forked from mbk-lab/rui_orig
Merge branch '0.9'
This commit is contained in:
commit
3c4315ed78
15
CHANGELOG.md
15
CHANGELOG.md
|
@ -1,3 +1,18 @@
|
||||||
|
# v0.9.0
|
||||||
|
|
||||||
|
* Requires go 1.18 or higher
|
||||||
|
* The "interface{}" type replaced by "any"
|
||||||
|
* Added SizeFunc interface and Function field to SizeUnit struct
|
||||||
|
* Added MaxSize, MinSize, SumSize, SubSize, MulSize, DivSize, ClampSize functions
|
||||||
|
* Added "list-row-gap", "list-column-gap", "accent-color", "tab-size", "overflow",
|
||||||
|
"arrow", "arrow-align", "arrow-size", "arrow-width", and "arrow-offset" properties
|
||||||
|
* Added "@ruiArrowSize" and "@ruiArrowWidth" constants to the default theme
|
||||||
|
* Added Transition, Transitions, and SetTransition functions to the ViewStyle interface
|
||||||
|
* Added GetListRowGap, GetListColumnGap, GetAccentColor, GetTabSize, GetOverflow, IsTimingFunctionValid, and GetTransitions functions
|
||||||
|
* Changed GetTransition functions
|
||||||
|
* Added the OpenURL function to the Session interface
|
||||||
|
* Changed the type of the second argument of all Get functions to "subviewID ...string" (previously "subviewID string")
|
||||||
|
|
||||||
# v0.8.0
|
# v0.8.0
|
||||||
|
|
||||||
* Added "loaded-event" and "error-event" events to ImageView
|
* Added "loaded-event" and "error-event" events to ImageView
|
||||||
|
|
475
README-ru.md
475
README-ru.md
File diff suppressed because it is too large
Load Diff
|
@ -14,7 +14,7 @@ type absoluteLayoutData struct {
|
||||||
// NewAbsoluteLayout create new AbsoluteLayout object and return it
|
// NewAbsoluteLayout create new AbsoluteLayout object and return it
|
||||||
func NewAbsoluteLayout(session Session, params Params) AbsoluteLayout {
|
func NewAbsoluteLayout(session Session, params Params) AbsoluteLayout {
|
||||||
view := new(absoluteLayoutData)
|
view := new(absoluteLayoutData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,8 @@ func newAbsoluteLayout(session Session) View {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initialize fields of ViewsContainer by default values
|
// Init initialize fields of ViewsContainer by default values
|
||||||
func (layout *absoluteLayoutData) Init(session Session) {
|
func (layout *absoluteLayoutData) init(session Session) {
|
||||||
layout.viewsContainerData.Init(session)
|
layout.viewsContainerData.init(session)
|
||||||
layout.tag = "AbsoluteLayout"
|
layout.tag = "AbsoluteLayout"
|
||||||
layout.systemClass = "ruiAbsoluteLayout"
|
layout.systemClass = "ruiAbsoluteLayout"
|
||||||
}
|
}
|
||||||
|
|
177
animation.go
177
animation.go
|
@ -55,16 +55,19 @@ const (
|
||||||
// The animation plays forwards each cycle. In other words, each time the animation cycles,
|
// The animation plays forwards each cycle. In other words, each time the animation cycles,
|
||||||
// the animation will reset to the beginning state and start over again. This is the default value.
|
// the animation will reset to the beginning state and start over again. This is the default value.
|
||||||
NormalAnimation = 0
|
NormalAnimation = 0
|
||||||
|
|
||||||
// ReverseAnimation is value of the "animation-direction" property.
|
// ReverseAnimation is value of the "animation-direction" property.
|
||||||
// The animation plays backwards each cycle. In other words, each time the animation cycles,
|
// The animation plays backwards each cycle. In other words, each time the animation cycles,
|
||||||
// the animation will reset to the end state and start over again. Animation steps are performed
|
// the animation will reset to the end state and start over again. Animation steps are performed
|
||||||
// backwards, and timing functions are also reversed.
|
// backwards, and timing functions are also reversed.
|
||||||
// For example, an "ease-in" timing function becomes "ease-out".
|
// For example, an "ease-in" timing function becomes "ease-out".
|
||||||
ReverseAnimation = 1
|
ReverseAnimation = 1
|
||||||
|
|
||||||
// AlternateAnimation is value of the "animation-direction" property.
|
// AlternateAnimation is value of the "animation-direction" property.
|
||||||
// The animation reverses direction each cycle, with the first iteration being played forwards.
|
// The animation reverses direction each cycle, with the first iteration being played forwards.
|
||||||
// The count to determine if a cycle is even or odd starts at one.
|
// The count to determine if a cycle is even or odd starts at one.
|
||||||
AlternateAnimation = 2
|
AlternateAnimation = 2
|
||||||
|
|
||||||
// AlternateReverseAnimation is value of the "animation-direction" property.
|
// AlternateReverseAnimation is value of the "animation-direction" property.
|
||||||
// The animation reverses direction each cycle, with the first iteration being played backwards.
|
// The animation reverses direction each cycle, with the first iteration being played backwards.
|
||||||
// The count to determine if a cycle is even or odd starts at one.
|
// The count to determine if a cycle is even or odd starts at one.
|
||||||
|
@ -107,11 +110,11 @@ type AnimatedProperty struct {
|
||||||
// Tag is the name of the property
|
// Tag is the name of the property
|
||||||
Tag string
|
Tag string
|
||||||
// From is the initial value of the property
|
// From is the initial value of the property
|
||||||
From interface{}
|
From any
|
||||||
// To is the final value of the property
|
// To is the final value of the property
|
||||||
To interface{}
|
To any
|
||||||
// KeyFrames is intermediate property values
|
// KeyFrames is intermediate property values
|
||||||
KeyFrames map[int]interface{}
|
KeyFrames map[int]any
|
||||||
}
|
}
|
||||||
|
|
||||||
type animationData struct {
|
type animationData struct {
|
||||||
|
@ -184,7 +187,7 @@ func (animation *animationData) normalizeTag(tag string) string {
|
||||||
return tag
|
return tag
|
||||||
}
|
}
|
||||||
|
|
||||||
func (animation *animationData) Set(tag string, value interface{}) bool {
|
func (animation *animationData) Set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
animation.Remove(tag)
|
animation.Remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -285,7 +288,7 @@ func (animation *animationData) Set(tag string, value interface{}) bool {
|
||||||
ErrorLogF(`key-frame "%d" is out of range`, n)
|
ErrorLogF(`key-frame "%d" is out of range`, n)
|
||||||
} else {
|
} else {
|
||||||
if result.KeyFrames == nil {
|
if result.KeyFrames == nil {
|
||||||
result.KeyFrames = map[int]interface{}{n: node.Text()}
|
result.KeyFrames = map[int]any{n: node.Text()}
|
||||||
} else {
|
} else {
|
||||||
result.KeyFrames[n] = node.Text()
|
result.KeyFrames[n] = node.Text()
|
||||||
}
|
}
|
||||||
|
@ -359,7 +362,7 @@ func (animation *animationData) Remove(tag string) {
|
||||||
delete(animation.properties, animation.normalizeTag(tag))
|
delete(animation.properties, animation.normalizeTag(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (animation *animationData) Get(tag string) interface{} {
|
func (animation *animationData) Get(tag string) any {
|
||||||
return animation.getRaw(animation.normalizeTag(tag))
|
return animation.getRaw(animation.normalizeTag(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,7 +400,7 @@ func (animation *animationData) animationCSS(session Session) string {
|
||||||
|
|
||||||
buffer.WriteString(animation.keyFramesName)
|
buffer.WriteString(animation.keyFramesName)
|
||||||
|
|
||||||
if duration, _ := floatProperty(animation, Duration, session, 1); duration > 0 {
|
if duration, ok := floatProperty(animation, Duration, session, 1); ok && duration > 0 {
|
||||||
buffer.WriteString(fmt.Sprintf(" %gs ", duration))
|
buffer.WriteString(fmt.Sprintf(" %gs ", duration))
|
||||||
} else {
|
} else {
|
||||||
buffer.WriteString(" 1s ")
|
buffer.WriteString(" 1s ")
|
||||||
|
@ -405,7 +408,7 @@ func (animation *animationData) animationCSS(session Session) string {
|
||||||
|
|
||||||
buffer.WriteString(animation.timingFunctionCSS(session))
|
buffer.WriteString(animation.timingFunctionCSS(session))
|
||||||
|
|
||||||
if delay, _ := floatProperty(animation, Delay, session, 0); delay > 0 {
|
if delay, ok := floatProperty(animation, Delay, session, 0); ok && delay > 0 {
|
||||||
buffer.WriteString(fmt.Sprintf(" %gs", delay))
|
buffer.WriteString(fmt.Sprintf(" %gs", delay))
|
||||||
} else {
|
} else {
|
||||||
buffer.WriteString(" 0s")
|
buffer.WriteString(" 0s")
|
||||||
|
@ -435,7 +438,7 @@ func (animation *animationData) animationCSS(session Session) string {
|
||||||
|
|
||||||
func (animation *animationData) transitionCSS(buffer *strings.Builder, session Session) {
|
func (animation *animationData) transitionCSS(buffer *strings.Builder, session Session) {
|
||||||
|
|
||||||
if duration, _ := floatProperty(animation, Duration, session, 1); duration > 0 {
|
if duration, ok := floatProperty(animation, Duration, session, 1); ok && duration > 0 {
|
||||||
buffer.WriteString(fmt.Sprintf(" %gs ", duration))
|
buffer.WriteString(fmt.Sprintf(" %gs ", duration))
|
||||||
} else {
|
} else {
|
||||||
buffer.WriteString(" 1s ")
|
buffer.WriteString(" 1s ")
|
||||||
|
@ -443,7 +446,7 @@ func (animation *animationData) transitionCSS(buffer *strings.Builder, session S
|
||||||
|
|
||||||
buffer.WriteString(animation.timingFunctionCSS(session))
|
buffer.WriteString(animation.timingFunctionCSS(session))
|
||||||
|
|
||||||
if delay, _ := floatProperty(animation, Delay, session, 0); delay > 0 {
|
if delay, ok := floatProperty(animation, Delay, session, 0); ok && delay > 0 {
|
||||||
buffer.WriteString(fmt.Sprintf(" %gs", delay))
|
buffer.WriteString(fmt.Sprintf(" %gs", delay))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -481,6 +484,8 @@ func (animation *animationData) writeTransitionString(tag string, buffer *string
|
||||||
buffer.WriteRune('"')
|
buffer.WriteRune('"')
|
||||||
buffer.WriteString(timingFunction)
|
buffer.WriteString(timingFunction)
|
||||||
buffer.WriteRune('"')
|
buffer.WriteRune('"')
|
||||||
|
} else {
|
||||||
|
buffer.WriteString(timingFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -490,14 +495,14 @@ func (animation *animationData) writeTransitionString(tag string, buffer *string
|
||||||
|
|
||||||
func (animation *animationData) timingFunctionCSS(session Session) string {
|
func (animation *animationData) timingFunctionCSS(session Session) string {
|
||||||
if timingFunction, ok := stringProperty(animation, TimingFunction, session); ok {
|
if timingFunction, ok := stringProperty(animation, TimingFunction, session); ok {
|
||||||
if timingFunction, ok = session.resolveConstants(timingFunction); ok && validateTimingFunction(timingFunction) {
|
if timingFunction, ok = session.resolveConstants(timingFunction); ok && isTimingFunctionValid(timingFunction) {
|
||||||
return timingFunction
|
return timingFunction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ("ease")
|
return ("ease")
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateTimingFunction(timingFunction string) bool {
|
func isTimingFunctionValid(timingFunction string) bool {
|
||||||
switch timingFunction {
|
switch timingFunction {
|
||||||
case "", EaseTiming, EaseInTiming, EaseOutTiming, EaseInOutTiming, LinearTiming:
|
case "", EaseTiming, EaseInTiming, EaseOutTiming, EaseInOutTiming, LinearTiming:
|
||||||
return true
|
return true
|
||||||
|
@ -529,6 +534,14 @@ func validateTimingFunction(timingFunction string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsTimingFunctionValid returns "true" if the "timingFunction" argument is the valid timing function.
|
||||||
|
func IsTimingFunctionValid(timingFunction string, session Session) bool {
|
||||||
|
if timingFunc, ok := session.resolveConstants(strings.Trim(timingFunction, " \t\n")); ok {
|
||||||
|
return isTimingFunctionValid(timingFunc)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (session *sessionData) registerAnimation(props []AnimatedProperty) string {
|
func (session *sessionData) registerAnimation(props []AnimatedProperty) string {
|
||||||
|
|
||||||
session.animationCounter++
|
session.animationCounter++
|
||||||
|
@ -602,7 +615,7 @@ func (session *sessionData) registerAnimation(props []AnimatedProperty) string {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *viewData) SetAnimated(tag string, value interface{}, animation Animation) bool {
|
func (view *viewData) SetAnimated(tag string, value any, animation Animation) bool {
|
||||||
if animation == nil {
|
if animation == nil {
|
||||||
return view.Set(tag, value)
|
return view.Set(tag, value)
|
||||||
}
|
}
|
||||||
|
@ -659,11 +672,29 @@ func (style *viewStyle) transitionCSS(session Session) string {
|
||||||
buffer := allocStringBuilder()
|
buffer := allocStringBuilder()
|
||||||
defer freeStringBuilder(buffer)
|
defer freeStringBuilder(buffer)
|
||||||
|
|
||||||
|
convert := map[string]string{
|
||||||
|
CellHeight: "grid-template-rows",
|
||||||
|
CellWidth: "grid-template-columns",
|
||||||
|
Row: "grid-row",
|
||||||
|
Column: "grid-column",
|
||||||
|
Clip: "clip-path",
|
||||||
|
Shadow: "box-shadow",
|
||||||
|
ColumnSeparator: "column-rule",
|
||||||
|
FontName: "font",
|
||||||
|
TextSize: "font-size",
|
||||||
|
TextLineThickness: "text-decoration-thickness",
|
||||||
|
}
|
||||||
|
|
||||||
for tag, animation := range style.transitions {
|
for tag, animation := range style.transitions {
|
||||||
if buffer.Len() > 0 {
|
if buffer.Len() > 0 {
|
||||||
buffer.WriteString(", ")
|
buffer.WriteString(", ")
|
||||||
}
|
}
|
||||||
buffer.WriteString(tag)
|
|
||||||
|
if cssTag, ok := convert[tag]; ok {
|
||||||
|
buffer.WriteString(cssTag)
|
||||||
|
} else {
|
||||||
|
buffer.WriteString(tag)
|
||||||
|
}
|
||||||
animation.transitionCSS(buffer, session)
|
animation.transitionCSS(buffer, session)
|
||||||
}
|
}
|
||||||
return buffer.String()
|
return buffer.String()
|
||||||
|
@ -673,18 +704,42 @@ func (view *viewData) updateTransitionCSS() {
|
||||||
updateCSSProperty(view.htmlID(), "transition", view.transitionCSS(view.Session()), view.Session())
|
updateCSSProperty(view.htmlID(), "transition", view.transitionCSS(view.Session()), view.Session())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *viewData) getTransitions() Params {
|
func (style *viewStyle) Transition(tag string) Animation {
|
||||||
result := Params{}
|
if style.transitions != nil {
|
||||||
for tag, animation := range view.transitions {
|
if anim, ok := style.transitions[tag]; ok {
|
||||||
|
return anim
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (style *viewStyle) Transitions() map[string]Animation {
|
||||||
|
result := map[string]Animation{}
|
||||||
|
for tag, animation := range style.transitions {
|
||||||
result[tag] = animation
|
result[tag] = animation
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (style *viewStyle) SetTransition(tag string, animation Animation) {
|
||||||
|
if animation == nil {
|
||||||
|
delete(style.transitions, tag)
|
||||||
|
} else {
|
||||||
|
style.transitions[tag] = animation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (view *viewData) SetTransition(tag string, animation Animation) {
|
||||||
|
view.viewStyle.SetTransition(tag, animation)
|
||||||
|
if view.created {
|
||||||
|
updateCSSProperty(view.htmlID(), "transition", view.transitionCSS(view.Session()), view.Session())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// SetAnimated sets the property with name "tag" of the "rootView" subview with "viewID" id by value. Result:
|
// SetAnimated sets the property with name "tag" of the "rootView" subview with "viewID" id by value. Result:
|
||||||
// true - success,
|
// true - success,
|
||||||
// false - error (incompatible type or invalid format of a string value, see AppLog).
|
// false - error (incompatible type or invalid format of a string value, see AppLog).
|
||||||
func SetAnimated(rootView View, viewID, tag string, value interface{}, animation Animation) bool {
|
func SetAnimated(rootView View, viewID, tag string, value any, animation Animation) bool {
|
||||||
if view := ViewByID(rootView, viewID); view != nil {
|
if view := ViewByID(rootView, viewID); view != nil {
|
||||||
return view.SetAnimated(tag, value, animation)
|
return view.SetAnimated(tag, value, animation)
|
||||||
}
|
}
|
||||||
|
@ -692,58 +747,60 @@ func SetAnimated(rootView View, viewID, tag string, value interface{}, animation
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsAnimationPaused returns "true" if an animation of the subview is paused, "false" otherwise.
|
// IsAnimationPaused returns "true" if an animation of the subview is paused, "false" otherwise.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func IsAnimationPaused(view View, subviewID string) bool {
|
func IsAnimationPaused(view View, subviewID ...string) bool {
|
||||||
|
return boolStyledProperty(view, subviewID, AnimationPaused, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTransitions returns the subview transitions. The result is always non-nil.
|
||||||
|
// If the second argument (subviewID) is not specified or it is "" then transitions of the first argument (view) is returned
|
||||||
|
func GetTransitions(view View, subviewID ...string) map[string]Animation {
|
||||||
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
|
view = ViewByID(view, subviewID[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
if view != nil {
|
||||||
|
return view.Transitions()
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string]Animation{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTransition returns the subview property transition. If there is no transition for the given property then nil is returned.
|
||||||
|
// If the second argument (subviewID) is not specified or it is "" then transitions of the first argument (view) is returned
|
||||||
|
func GetTransition(view View, subviewID, tag string) Animation {
|
||||||
if subviewID != "" {
|
if subviewID != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID)
|
||||||
}
|
}
|
||||||
|
|
||||||
if view != nil {
|
if view != nil {
|
||||||
if result, ok := boolStyledProperty(view, AnimationPaused); ok {
|
return view.Transition(tag)
|
||||||
return result
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTransition adds the transition for the subview property.
|
||||||
|
// If the second argument (subviewID) is not specified or it is "" then the transition is added to the first argument (view)
|
||||||
|
func AddTransition(view View, subviewID, tag string, animation Animation) bool {
|
||||||
|
if tag != "" {
|
||||||
|
if subviewID != "" {
|
||||||
|
view = ViewByID(view, subviewID)
|
||||||
|
}
|
||||||
|
|
||||||
|
if view != nil {
|
||||||
|
view.SetTransition(tag, animation)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTransition returns the subview transitions. The result is always non-nil.
|
|
||||||
// If the second argument (subviewID) is "" then transitions of the first argument (view) is returned
|
|
||||||
func GetTransition(view View, subviewID string) Params {
|
|
||||||
if subviewID != "" {
|
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
|
|
||||||
if view != nil {
|
|
||||||
return view.getTransitions()
|
|
||||||
}
|
|
||||||
|
|
||||||
return Params{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddTransition adds the transition for the subview property.
|
|
||||||
// If the second argument (subviewID) is "" then the transition is added to the first argument (view)
|
|
||||||
func AddTransition(view View, subviewID, tag string, animation Animation) bool {
|
|
||||||
if tag == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if subviewID != "" {
|
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
|
|
||||||
if view == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
transitions := view.getTransitions()
|
|
||||||
transitions[tag] = animation
|
|
||||||
return view.Set(Transition, transitions)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAnimation returns the subview animations. The result is always non-nil.
|
// GetAnimation returns the subview animations. The result is always non-nil.
|
||||||
// If the second argument (subviewID) is "" then transitions of the first argument (view) is returned
|
// If the second argument (subviewID) is not specified or it is "" then transitions of the first argument (view) is returned
|
||||||
func GetAnimation(view View, subviewID string) []Animation {
|
func GetAnimation(view View, subviewID ...string) []Animation {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
if view != nil {
|
if view != nil {
|
||||||
|
|
|
@ -51,131 +51,6 @@ const (
|
||||||
AnimationIterationEvent = "animation-iteration-event"
|
AnimationIterationEvent = "animation-iteration-event"
|
||||||
)
|
)
|
||||||
|
|
||||||
func valueToAnimationListeners(value interface{}) ([]func(View, string), bool) {
|
|
||||||
if value == nil {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
|
|
||||||
switch value := value.(type) {
|
|
||||||
case func(View, string):
|
|
||||||
return []func(View, string){value}, true
|
|
||||||
|
|
||||||
case func(string):
|
|
||||||
fn := func(_ View, event string) {
|
|
||||||
value(event)
|
|
||||||
}
|
|
||||||
return []func(View, string){fn}, true
|
|
||||||
|
|
||||||
case func(View):
|
|
||||||
fn := func(view View, _ string) {
|
|
||||||
value(view)
|
|
||||||
}
|
|
||||||
return []func(View, string){fn}, true
|
|
||||||
|
|
||||||
case func():
|
|
||||||
fn := func(View, string) {
|
|
||||||
value()
|
|
||||||
}
|
|
||||||
return []func(View, string){fn}, true
|
|
||||||
|
|
||||||
case []func(View, string):
|
|
||||||
if len(value) == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
for _, fn := range value {
|
|
||||||
if fn == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value, true
|
|
||||||
|
|
||||||
case []func(string):
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(View, string), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
listeners[i] = func(_ View, event string) {
|
|
||||||
v(event)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
|
|
||||||
case []func(View):
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(View, string), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
listeners[i] = func(view View, _ string) {
|
|
||||||
v(view)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
|
|
||||||
case []func():
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(View, string), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
listeners[i] = func(View, string) {
|
|
||||||
v()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(View, string), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
switch v := v.(type) {
|
|
||||||
case func(View, string):
|
|
||||||
listeners[i] = v
|
|
||||||
|
|
||||||
case func(string):
|
|
||||||
listeners[i] = func(_ View, event string) {
|
|
||||||
v(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
case func(View):
|
|
||||||
listeners[i] = func(view View, _ string) {
|
|
||||||
v(view)
|
|
||||||
}
|
|
||||||
|
|
||||||
case func():
|
|
||||||
listeners[i] = func(View, string) {
|
|
||||||
v()
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
var transitionEvents = map[string]struct{ jsEvent, jsFunc string }{
|
var transitionEvents = map[string]struct{ jsEvent, jsFunc string }{
|
||||||
TransitionRunEvent: {jsEvent: "ontransitionrun", jsFunc: "transitionRunEvent"},
|
TransitionRunEvent: {jsEvent: "ontransitionrun", jsFunc: "transitionRunEvent"},
|
||||||
TransitionStartEvent: {jsEvent: "ontransitionstart", jsFunc: "transitionStartEvent"},
|
TransitionStartEvent: {jsEvent: "ontransitionstart", jsFunc: "transitionStartEvent"},
|
||||||
|
@ -183,8 +58,8 @@ var transitionEvents = map[string]struct{ jsEvent, jsFunc string }{
|
||||||
TransitionCancelEvent: {jsEvent: "ontransitioncancel", jsFunc: "transitionCancelEvent"},
|
TransitionCancelEvent: {jsEvent: "ontransitioncancel", jsFunc: "transitionCancelEvent"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *viewData) setTransitionListener(tag string, value interface{}) bool {
|
func (view *viewData) setTransitionListener(tag string, value any) bool {
|
||||||
listeners, ok := valueToAnimationListeners(value)
|
listeners, ok := valueToEventListeners[View, string](value)
|
||||||
if !ok {
|
if !ok {
|
||||||
notCompatibleType(tag, value)
|
notCompatibleType(tag, value)
|
||||||
return false
|
return false
|
||||||
|
@ -212,20 +87,6 @@ func (view *viewData) removeTransitionListener(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAnimationListeners(view View, subviewID string, tag string) []func(View, string) {
|
|
||||||
if subviewID != "" {
|
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if value := view.Get(tag); value != nil {
|
|
||||||
if result, ok := value.([]func(View, string)); ok {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []func(View, string){}
|
|
||||||
}
|
|
||||||
|
|
||||||
func transitionEventsHtml(view View, buffer *strings.Builder) {
|
func transitionEventsHtml(view View, buffer *strings.Builder) {
|
||||||
for tag, js := range transitionEvents {
|
for tag, js := range transitionEvents {
|
||||||
if value := view.getRaw(tag); value != nil {
|
if value := view.getRaw(tag); value != nil {
|
||||||
|
@ -250,7 +111,7 @@ func (view *viewData) handleTransitionEvents(tag string, data DataObject) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, listener := range getAnimationListeners(view, "", tag) {
|
for _, listener := range getEventListeners[View, string](view, nil, tag) {
|
||||||
listener(view, property)
|
listener(view, property)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -263,8 +124,8 @@ var animationEvents = map[string]struct{ jsEvent, jsFunc string }{
|
||||||
AnimationCancelEvent: {jsEvent: "onanimationcancel", jsFunc: "animationCancelEvent"},
|
AnimationCancelEvent: {jsEvent: "onanimationcancel", jsFunc: "animationCancelEvent"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *viewData) setAnimationListener(tag string, value interface{}) bool {
|
func (view *viewData) setAnimationListener(tag string, value any) bool {
|
||||||
listeners, ok := valueToAnimationListeners(value)
|
listeners, ok := valueToEventListeners[View, string](value)
|
||||||
if !ok {
|
if !ok {
|
||||||
notCompatibleType(tag, value)
|
notCompatibleType(tag, value)
|
||||||
return false
|
return false
|
||||||
|
@ -303,10 +164,10 @@ func animationEventsHtml(view View, buffer *strings.Builder) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *viewData) handleAnimationEvents(tag string, data DataObject) {
|
func (view *viewData) handleAnimationEvents(tag string, data DataObject) {
|
||||||
if listeners := getAnimationListeners(view, "", tag); len(listeners) > 0 {
|
if listeners := getEventListeners[View, string](view, nil, tag); len(listeners) > 0 {
|
||||||
id := ""
|
id := ""
|
||||||
if name, ok := data.PropertyValue("name"); ok {
|
if name, ok := data.PropertyValue("name"); ok {
|
||||||
for _, animation := range GetAnimation(view, "") {
|
for _, animation := range GetAnimation(view) {
|
||||||
if name == animation.animationName() {
|
if name == animation.animationName() {
|
||||||
id, _ = stringProperty(animation, ID, view.Session())
|
id, _ = stringProperty(animation, ID, view.Session())
|
||||||
}
|
}
|
||||||
|
@ -320,56 +181,56 @@ func (view *viewData) handleAnimationEvents(tag string, data DataObject) {
|
||||||
|
|
||||||
// GetTransitionRunListeners returns the "transition-run-event" listener list.
|
// GetTransitionRunListeners returns the "transition-run-event" listener list.
|
||||||
// If there are no listeners then the empty list is returned.
|
// If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTransitionRunListeners(view View, subviewID string) []func(View, string) {
|
func GetTransitionRunListeners(view View, subviewID ...string) []func(View, string) {
|
||||||
return getAnimationListeners(view, subviewID, TransitionRunEvent)
|
return getEventListeners[View, string](view, subviewID, TransitionRunEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTransitionStartListeners returns the "transition-start-event" listener list.
|
// GetTransitionStartListeners returns the "transition-start-event" listener list.
|
||||||
// If there are no listeners then the empty list is returned.
|
// If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTransitionStartListeners(view View, subviewID string) []func(View, string) {
|
func GetTransitionStartListeners(view View, subviewID ...string) []func(View, string) {
|
||||||
return getAnimationListeners(view, subviewID, TransitionStartEvent)
|
return getEventListeners[View, string](view, subviewID, TransitionStartEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTransitionEndListeners returns the "transition-end-event" listener list.
|
// GetTransitionEndListeners returns the "transition-end-event" listener list.
|
||||||
// If there are no listeners then the empty list is returned.
|
// If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTransitionEndListeners(view View, subviewID string) []func(View, string) {
|
func GetTransitionEndListeners(view View, subviewID ...string) []func(View, string) {
|
||||||
return getAnimationListeners(view, subviewID, TransitionEndEvent)
|
return getEventListeners[View, string](view, subviewID, TransitionEndEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTransitionCancelListeners returns the "transition-cancel-event" listener list.
|
// GetTransitionCancelListeners returns the "transition-cancel-event" listener list.
|
||||||
// If there are no listeners then the empty list is returned.
|
// If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTransitionCancelListeners(view View, subviewID string) []func(View, string) {
|
func GetTransitionCancelListeners(view View, subviewID ...string) []func(View, string) {
|
||||||
return getAnimationListeners(view, subviewID, TransitionCancelEvent)
|
return getEventListeners[View, string](view, subviewID, TransitionCancelEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAnimationStartListeners returns the "animation-start-event" listener list.
|
// GetAnimationStartListeners returns the "animation-start-event" listener list.
|
||||||
// If there are no listeners then the empty list is returned.
|
// If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetAnimationStartListeners(view View, subviewID string) []func(View, string) {
|
func GetAnimationStartListeners(view View, subviewID ...string) []func(View, string) {
|
||||||
return getAnimationListeners(view, subviewID, AnimationStartEvent)
|
return getEventListeners[View, string](view, subviewID, AnimationStartEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAnimationEndListeners returns the "animation-end-event" listener list.
|
// GetAnimationEndListeners returns the "animation-end-event" listener list.
|
||||||
// If there are no listeners then the empty list is returned.
|
// If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetAnimationEndListeners(view View, subviewID string) []func(View, string) {
|
func GetAnimationEndListeners(view View, subviewID ...string) []func(View, string) {
|
||||||
return getAnimationListeners(view, subviewID, AnimationEndEvent)
|
return getEventListeners[View, string](view, subviewID, AnimationEndEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAnimationCancelListeners returns the "animation-cancel-event" listener list.
|
// GetAnimationCancelListeners returns the "animation-cancel-event" listener list.
|
||||||
// If there are no listeners then the empty list is returned.
|
// If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetAnimationCancelListeners(view View, subviewID string) []func(View, string) {
|
func GetAnimationCancelListeners(view View, subviewID ...string) []func(View, string) {
|
||||||
return getAnimationListeners(view, subviewID, AnimationCancelEvent)
|
return getEventListeners[View, string](view, subviewID, AnimationCancelEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAnimationIterationListeners returns the "animation-iteration-event" listener list.
|
// GetAnimationIterationListeners returns the "animation-iteration-event" listener list.
|
||||||
// If there are no listeners then the empty list is returned.
|
// If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetAnimationIterationListeners(view View, subviewID string) []func(View, string) {
|
func GetAnimationIterationListeners(view View, subviewID ...string) []func(View, string) {
|
||||||
return getAnimationListeners(view, subviewID, AnimationIterationEvent)
|
return getEventListeners[View, string](view, subviewID, AnimationIterationEvent)
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ func DebugLog(text string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// DebugLogF print the text to the debug log
|
// DebugLogF print the text to the debug log
|
||||||
func DebugLogF(format string, a ...interface{}) {
|
func DebugLogF(format string, a ...any) {
|
||||||
if debugLogFunc != nil {
|
if debugLogFunc != nil {
|
||||||
debugLogFunc(fmt.Sprintf(format, a...))
|
debugLogFunc(fmt.Sprintf(format, a...))
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ func ErrorLog(text string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrorLogF print the text to the error log
|
// ErrorLogF print the text to the error log
|
||||||
func ErrorLogF(format string, a ...interface{}) {
|
func ErrorLogF(format string, a ...any) {
|
||||||
lastError = fmt.Sprintf(format, a...)
|
lastError = fmt.Sprintf(format, a...)
|
||||||
if errorLogFunc != nil {
|
if errorLogFunc != nil {
|
||||||
errorLogFunc(lastError)
|
errorLogFunc(lastError)
|
||||||
|
|
|
@ -1793,6 +1793,7 @@ function imageLoaded(element, event) {
|
||||||
",natural-height=" + element.naturalHeight +
|
",natural-height=" + element.naturalHeight +
|
||||||
",current-src=\"" + element.currentSrc + "\"}";
|
",current-src=\"" + element.currentSrc + "\"}";
|
||||||
sendMessage(message);
|
sendMessage(message);
|
||||||
|
scanElementsSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
function imageError(element, event) {
|
function imageError(element, event) {
|
||||||
|
|
|
@ -59,7 +59,6 @@ ul:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.ruiRoot {
|
.ruiRoot {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
|
|
|
@ -11,7 +11,7 @@ type audioPlayerData struct {
|
||||||
// NewAudioPlayer create new MediaPlayer object and return it
|
// NewAudioPlayer create new MediaPlayer object and return it
|
||||||
func NewAudioPlayer(session Session, params Params) AudioPlayer {
|
func NewAudioPlayer(session Session, params Params) AudioPlayer {
|
||||||
view := new(audioPlayerData)
|
view := new(audioPlayerData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
view.tag = "AudioPlayer"
|
view.tag = "AudioPlayer"
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
|
@ -21,8 +21,8 @@ func newAudioPlayer(session Session) View {
|
||||||
return NewAudioPlayer(session, nil)
|
return NewAudioPlayer(session, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (player *audioPlayerData) Init(session Session) {
|
func (player *audioPlayerData) init(session Session) {
|
||||||
player.mediaPlayerData.Init(session)
|
player.mediaPlayerData.init(session)
|
||||||
player.tag = "AudioPlayer"
|
player.tag = "AudioPlayer"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,22 +81,22 @@ func createBackground(obj DataObject) BackgroundElement {
|
||||||
switch obj.Tag() {
|
switch obj.Tag() {
|
||||||
case "image":
|
case "image":
|
||||||
image := new(backgroundImage)
|
image := new(backgroundImage)
|
||||||
image.properties = map[string]interface{}{}
|
image.properties = map[string]any{}
|
||||||
result = image
|
result = image
|
||||||
|
|
||||||
case "linear-gradient":
|
case "linear-gradient":
|
||||||
gradient := new(backgroundLinearGradient)
|
gradient := new(backgroundLinearGradient)
|
||||||
gradient.properties = map[string]interface{}{}
|
gradient.properties = map[string]any{}
|
||||||
result = gradient
|
result = gradient
|
||||||
|
|
||||||
case "radial-gradient":
|
case "radial-gradient":
|
||||||
gradient := new(backgroundRadialGradient)
|
gradient := new(backgroundRadialGradient)
|
||||||
gradient.properties = map[string]interface{}{}
|
gradient.properties = map[string]any{}
|
||||||
result = gradient
|
result = gradient
|
||||||
|
|
||||||
case "conic-gradient":
|
case "conic-gradient":
|
||||||
gradient := new(backgroundConicGradient)
|
gradient := new(backgroundConicGradient)
|
||||||
gradient.properties = map[string]interface{}{}
|
gradient.properties = map[string]any{}
|
||||||
result = gradient
|
result = gradient
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -118,7 +118,7 @@ func createBackground(obj DataObject) BackgroundElement {
|
||||||
// NewBackgroundImage creates the new background image
|
// NewBackgroundImage creates the new background image
|
||||||
func NewBackgroundImage(params Params) BackgroundElement {
|
func NewBackgroundImage(params Params) BackgroundElement {
|
||||||
result := new(backgroundImage)
|
result := new(backgroundImage)
|
||||||
result.properties = map[string]interface{}{}
|
result.properties = map[string]any{}
|
||||||
for tag, value := range params {
|
for tag, value := range params {
|
||||||
result.Set(tag, value)
|
result.Set(tag, value)
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ func (image *backgroundImage) normalizeTag(tag string) string {
|
||||||
return tag
|
return tag
|
||||||
}
|
}
|
||||||
|
|
||||||
func (image *backgroundImage) Set(tag string, value interface{}) bool {
|
func (image *backgroundImage) Set(tag string, value any) bool {
|
||||||
tag = image.normalizeTag(tag)
|
tag = image.normalizeTag(tag)
|
||||||
switch tag {
|
switch tag {
|
||||||
case Attachment, Width, Height, Repeat, ImageHorizontalAlign, ImageVerticalAlign,
|
case Attachment, Width, Height, Repeat, ImageHorizontalAlign, ImageVerticalAlign,
|
||||||
|
@ -167,7 +167,7 @@ func (image *backgroundImage) Set(tag string, value interface{}) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (image *backgroundImage) Get(tag string) interface{} {
|
func (image *backgroundImage) Get(tag string) any {
|
||||||
return image.backgroundElement.Get(image.normalizeTag(tag))
|
return image.backgroundElement.Get(image.normalizeTag(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,9 +219,9 @@ func (image *backgroundImage) cssStyle(session Session) string {
|
||||||
|
|
||||||
if width.Type != Auto || height.Type != Auto {
|
if width.Type != Auto || height.Type != Auto {
|
||||||
buffer.WriteString(` / `)
|
buffer.WriteString(` / `)
|
||||||
buffer.WriteString(width.cssString("auto"))
|
buffer.WriteString(width.cssString("auto", session))
|
||||||
buffer.WriteRune(' ')
|
buffer.WriteRune(' ')
|
||||||
buffer.WriteString(height.cssString("auto"))
|
buffer.WriteString(height.cssString("auto", session))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,16 +12,16 @@ type backgroundConicGradient struct {
|
||||||
type BackgroundGradientAngle struct {
|
type BackgroundGradientAngle struct {
|
||||||
// Color - the color of the key angle. Must not be nil.
|
// Color - the color of the key angle. Must not be nil.
|
||||||
// Can take a value of Color type or string (color constant or textual description of the color)
|
// Can take a value of Color type or string (color constant or textual description of the color)
|
||||||
Color interface{}
|
Color any
|
||||||
// Angle - the key angle. Optional (may be nil).
|
// Angle - the key angle. Optional (may be nil).
|
||||||
// Can take a value of AngleUnit type or string (angle constant or textual description of the angle)
|
// Can take a value of AngleUnit type or string (angle constant or textual description of the angle)
|
||||||
Angle interface{}
|
Angle any
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBackgroundConicGradient creates the new background conic gradient
|
// NewBackgroundConicGradient creates the new background conic gradient
|
||||||
func NewBackgroundConicGradient(params Params) BackgroundElement {
|
func NewBackgroundConicGradient(params Params) BackgroundElement {
|
||||||
result := new(backgroundConicGradient)
|
result := new(backgroundConicGradient)
|
||||||
result.properties = map[string]interface{}{}
|
result.properties = map[string]any{}
|
||||||
for tag, value := range params {
|
for tag, value := range params {
|
||||||
result.Set(tag, value)
|
result.Set(tag, value)
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ func (gradient *backgroundConicGradient) normalizeTag(tag string) string {
|
||||||
return tag
|
return tag
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gradient *backgroundConicGradient) Set(tag string, value interface{}) bool {
|
func (gradient *backgroundConicGradient) Set(tag string, value any) bool {
|
||||||
tag = gradient.normalizeTag(tag)
|
tag = gradient.normalizeTag(tag)
|
||||||
switch tag {
|
switch tag {
|
||||||
case CenterX, CenterY, Repeating, From:
|
case CenterX, CenterY, Repeating, From:
|
||||||
|
@ -153,7 +153,7 @@ func (gradient *backgroundConicGradient) Set(tag string, value interface{}) bool
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gradient *backgroundConicGradient) stringToAngle(text string) (interface{}, bool) {
|
func (gradient *backgroundConicGradient) stringToAngle(text string) (any, bool) {
|
||||||
if text == "" {
|
if text == "" {
|
||||||
return nil, false
|
return nil, false
|
||||||
} else if text[0] == '@' {
|
} else if text[0] == '@' {
|
||||||
|
@ -216,7 +216,7 @@ func (gradient *backgroundConicGradient) parseGradientText(value string) []Backg
|
||||||
return vector
|
return vector
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gradient *backgroundConicGradient) setGradient(value interface{}) bool {
|
func (gradient *backgroundConicGradient) setGradient(value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
delete(gradient.properties, Gradient)
|
delete(gradient.properties, Gradient)
|
||||||
return true
|
return true
|
||||||
|
@ -262,7 +262,7 @@ func (gradient *backgroundConicGradient) setGradient(value interface{}) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gradient *backgroundConicGradient) Get(tag string) interface{} {
|
func (gradient *backgroundConicGradient) Get(tag string) any {
|
||||||
return gradient.backgroundElement.Get(gradient.normalizeTag(tag))
|
return gradient.backgroundElement.Get(gradient.normalizeTag(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,9 +316,9 @@ func (gradient *backgroundConicGradient) cssStyle(session Session) string {
|
||||||
buffer.WriteRune(' ')
|
buffer.WriteRune(' ')
|
||||||
}
|
}
|
||||||
buffer.WriteString("at ")
|
buffer.WriteString("at ")
|
||||||
buffer.WriteString(x.cssString("50%"))
|
buffer.WriteString(x.cssString("50%", session))
|
||||||
buffer.WriteString(" ")
|
buffer.WriteString(" ")
|
||||||
buffer.WriteString(y.cssString("50%"))
|
buffer.WriteString(y.cssString("50%", session))
|
||||||
comma = true
|
comma = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,10 +50,10 @@ const (
|
||||||
type BackgroundGradientPoint struct {
|
type BackgroundGradientPoint struct {
|
||||||
// Color - the color of the point. Must not be nil.
|
// Color - the color of the point. Must not be nil.
|
||||||
// Can take a value of Color type or string (color constant or textual description of the color)
|
// Can take a value of Color type or string (color constant or textual description of the color)
|
||||||
Color interface{}
|
Color any
|
||||||
// Pos - the distance from the start of the gradient straight line. Optional (may be nil).
|
// Pos - the distance from the start of the gradient straight line. Optional (may be nil).
|
||||||
// Can take a value of SizeUnit type or string (angle constant or textual description of the SizeUnit)
|
// Can take a value of SizeUnit type or string (angle constant or textual description of the SizeUnit)
|
||||||
Pos interface{}
|
Pos any
|
||||||
}
|
}
|
||||||
|
|
||||||
type backgroundGradient struct {
|
type backgroundGradient struct {
|
||||||
|
@ -71,7 +71,7 @@ type backgroundRadialGradient struct {
|
||||||
// NewBackgroundLinearGradient creates the new background linear gradient
|
// NewBackgroundLinearGradient creates the new background linear gradient
|
||||||
func NewBackgroundLinearGradient(params Params) BackgroundElement {
|
func NewBackgroundLinearGradient(params Params) BackgroundElement {
|
||||||
result := new(backgroundLinearGradient)
|
result := new(backgroundLinearGradient)
|
||||||
result.properties = map[string]interface{}{}
|
result.properties = map[string]any{}
|
||||||
for tag, value := range params {
|
for tag, value := range params {
|
||||||
result.Set(tag, value)
|
result.Set(tag, value)
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ func NewBackgroundLinearGradient(params Params) BackgroundElement {
|
||||||
// NewBackgroundRadialGradient creates the new background radial gradient
|
// NewBackgroundRadialGradient creates the new background radial gradient
|
||||||
func NewBackgroundRadialGradient(params Params) BackgroundElement {
|
func NewBackgroundRadialGradient(params Params) BackgroundElement {
|
||||||
result := new(backgroundRadialGradient)
|
result := new(backgroundRadialGradient)
|
||||||
result.properties = map[string]interface{}{}
|
result.properties = map[string]any{}
|
||||||
for tag, value := range params {
|
for tag, value := range params {
|
||||||
result.Set(tag, value)
|
result.Set(tag, value)
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ func (gradient *backgroundGradient) parseGradientText(value string) []Background
|
||||||
return points
|
return points
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gradient *backgroundGradient) Set(tag string, value interface{}) bool {
|
func (gradient *backgroundGradient) Set(tag string, value any) bool {
|
||||||
|
|
||||||
switch tag = strings.ToLower(tag); tag {
|
switch tag = strings.ToLower(tag); tag {
|
||||||
case Repeating:
|
case Repeating:
|
||||||
|
@ -261,19 +261,18 @@ func (gradient *backgroundGradient) writeGradient(session Session, buffer *strin
|
||||||
switch value := point.Pos.(type) {
|
switch value := point.Pos.(type) {
|
||||||
case string:
|
case string:
|
||||||
if value != "" {
|
if value != "" {
|
||||||
if value[0] == '@' {
|
if value, ok := session.resolveConstants(value); ok {
|
||||||
value, _ = session.Constant(value[1:])
|
if pos, ok := StringToSizeUnit(value); ok && pos.Type != Auto {
|
||||||
}
|
buffer.WriteRune(' ')
|
||||||
if pos, ok := StringToSizeUnit(value); ok && pos.Type != Auto {
|
buffer.WriteString(pos.cssString("", session))
|
||||||
buffer.WriteRune(' ')
|
}
|
||||||
buffer.WriteString(pos.cssString(""))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case SizeUnit:
|
case SizeUnit:
|
||||||
if value.Type != Auto {
|
if value.Type != Auto {
|
||||||
buffer.WriteRune(' ')
|
buffer.WriteRune(' ')
|
||||||
buffer.WriteString(value.cssString(""))
|
buffer.WriteString(value.cssString("", session))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -296,7 +295,7 @@ func (image *backgroundLinearGradient) Clone() BackgroundElement {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gradient *backgroundLinearGradient) Set(tag string, value interface{}) bool {
|
func (gradient *backgroundLinearGradient) Set(tag string, value any) bool {
|
||||||
if strings.ToLower(tag) == Direction {
|
if strings.ToLower(tag) == Direction {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case AngleUnit:
|
case AngleUnit:
|
||||||
|
@ -402,7 +401,7 @@ func (gradient *backgroundRadialGradient) normalizeTag(tag string) string {
|
||||||
return tag
|
return tag
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gradient *backgroundRadialGradient) Set(tag string, value interface{}) bool {
|
func (gradient *backgroundRadialGradient) Set(tag string, value any) bool {
|
||||||
tag = gradient.normalizeTag(tag)
|
tag = gradient.normalizeTag(tag)
|
||||||
switch tag {
|
switch tag {
|
||||||
case RadialGradientRadius:
|
case RadialGradientRadius:
|
||||||
|
@ -426,7 +425,7 @@ func (gradient *backgroundRadialGradient) Set(tag string, value interface{}) boo
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
case []interface{}:
|
case []any:
|
||||||
switch len(value) {
|
switch len(value) {
|
||||||
case 0:
|
case 0:
|
||||||
delete(gradient.properties, RadialGradientRadius)
|
delete(gradient.properties, RadialGradientRadius)
|
||||||
|
@ -477,7 +476,7 @@ func (gradient *backgroundRadialGradient) Set(tag string, value interface{}) boo
|
||||||
return gradient.backgroundGradient.Set(tag, value)
|
return gradient.backgroundGradient.Set(tag, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gradient *backgroundRadialGradient) Get(tag string) interface{} {
|
func (gradient *backgroundRadialGradient) Get(tag string) any {
|
||||||
return gradient.backgroundGradient.Get(gradient.normalizeTag(tag))
|
return gradient.backgroundGradient.Get(gradient.normalizeTag(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,9 +511,9 @@ func (gradient *backgroundRadialGradient) cssStyle(session Session) string {
|
||||||
if r, ok := StringToSizeUnit(text); ok && r.Type != Auto {
|
if r, ok := StringToSizeUnit(text); ok && r.Type != Auto {
|
||||||
buffer.WriteString("ellipse ")
|
buffer.WriteString("ellipse ")
|
||||||
shapeText = ""
|
shapeText = ""
|
||||||
buffer.WriteString(r.cssString(""))
|
buffer.WriteString(r.cssString("", session))
|
||||||
buffer.WriteString(" ")
|
buffer.WriteString(" ")
|
||||||
buffer.WriteString(r.cssString(""))
|
buffer.WriteString(r.cssString("", session))
|
||||||
buffer.WriteString(" ")
|
buffer.WriteString(" ")
|
||||||
} else {
|
} else {
|
||||||
ErrorLog(`Invalid radial gradient radius: ` + text)
|
ErrorLog(`Invalid radial gradient radius: ` + text)
|
||||||
|
@ -539,9 +538,9 @@ func (gradient *backgroundRadialGradient) cssStyle(session Session) string {
|
||||||
if value.Type != Auto {
|
if value.Type != Auto {
|
||||||
buffer.WriteString("ellipse ")
|
buffer.WriteString("ellipse ")
|
||||||
shapeText = ""
|
shapeText = ""
|
||||||
buffer.WriteString(value.cssString(""))
|
buffer.WriteString(value.cssString("", session))
|
||||||
buffer.WriteString(" ")
|
buffer.WriteString(" ")
|
||||||
buffer.WriteString(value.cssString(""))
|
buffer.WriteString(value.cssString("", session))
|
||||||
buffer.WriteString(" ")
|
buffer.WriteString(" ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -553,11 +552,11 @@ func (gradient *backgroundRadialGradient) cssStyle(session Session) string {
|
||||||
buffer.WriteString("ellipse ")
|
buffer.WriteString("ellipse ")
|
||||||
shapeText = ""
|
shapeText = ""
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
buffer.WriteString(value[i].cssString("50%"))
|
buffer.WriteString(value[i].cssString("50%", session))
|
||||||
buffer.WriteString(" ")
|
buffer.WriteString(" ")
|
||||||
}
|
}
|
||||||
|
|
||||||
case []interface{}:
|
case []any:
|
||||||
count := len(value)
|
count := len(value)
|
||||||
if count > 2 {
|
if count > 2 {
|
||||||
count = 2
|
count = 2
|
||||||
|
@ -568,13 +567,13 @@ func (gradient *backgroundRadialGradient) cssStyle(session Session) string {
|
||||||
if value[i] != nil {
|
if value[i] != nil {
|
||||||
switch value := value[i].(type) {
|
switch value := value[i].(type) {
|
||||||
case SizeUnit:
|
case SizeUnit:
|
||||||
buffer.WriteString(value.cssString("50%"))
|
buffer.WriteString(value.cssString("50%", session))
|
||||||
buffer.WriteString(" ")
|
buffer.WriteString(" ")
|
||||||
|
|
||||||
case string:
|
case string:
|
||||||
if text, ok := session.resolveConstants(value); ok {
|
if text, ok := session.resolveConstants(value); ok {
|
||||||
if size, err := stringToSizeUnit(text); err == nil {
|
if size, err := stringToSizeUnit(text); err == nil {
|
||||||
buffer.WriteString(size.cssString("50%"))
|
buffer.WriteString(size.cssString("50%", session))
|
||||||
buffer.WriteString(" ")
|
buffer.WriteString(" ")
|
||||||
} else {
|
} else {
|
||||||
buffer.WriteString("50% ")
|
buffer.WriteString("50% ")
|
||||||
|
@ -597,9 +596,9 @@ func (gradient *backgroundRadialGradient) cssStyle(session Session) string {
|
||||||
buffer.WriteString(shapeText)
|
buffer.WriteString(shapeText)
|
||||||
}
|
}
|
||||||
buffer.WriteString("at ")
|
buffer.WriteString("at ")
|
||||||
buffer.WriteString(x.cssString("50%"))
|
buffer.WriteString(x.cssString("50%", session))
|
||||||
buffer.WriteString(" ")
|
buffer.WriteString(" ")
|
||||||
buffer.WriteString(y.cssString("50%"))
|
buffer.WriteString(y.cssString("50%", session))
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.WriteString(", ")
|
buffer.WriteString(", ")
|
||||||
|
|
21
border.go
21
border.go
|
@ -64,9 +64,9 @@ type borderProperty struct {
|
||||||
propertyList
|
propertyList
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBorderProperty(value interface{}) BorderProperty {
|
func newBorderProperty(value any) BorderProperty {
|
||||||
border := new(borderProperty)
|
border := new(borderProperty)
|
||||||
border.properties = map[string]interface{}{}
|
border.properties = map[string]any{}
|
||||||
|
|
||||||
if value != nil {
|
if value != nil {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
|
@ -131,7 +131,7 @@ func newBorderProperty(value interface{}) BorderProperty {
|
||||||
// NewBorder creates the new BorderProperty
|
// NewBorder creates the new BorderProperty
|
||||||
func NewBorder(params Params) BorderProperty {
|
func NewBorder(params Params) BorderProperty {
|
||||||
border := new(borderProperty)
|
border := new(borderProperty)
|
||||||
border.properties = map[string]interface{}{}
|
border.properties = map[string]any{}
|
||||||
if params != nil {
|
if params != nil {
|
||||||
for _, tag := range []string{Style, Width, ColorTag, Left, Right, Top, Bottom,
|
for _, tag := range []string{Style, Width, ColorTag, Left, Right, Top, Bottom,
|
||||||
LeftStyle, RightStyle, TopStyle, BottomStyle,
|
LeftStyle, RightStyle, TopStyle, BottomStyle,
|
||||||
|
@ -213,7 +213,7 @@ func (border *borderProperty) writeString(buffer *strings.Builder, indent string
|
||||||
buffer.WriteString("_{ ")
|
buffer.WriteString("_{ ")
|
||||||
comma := false
|
comma := false
|
||||||
|
|
||||||
write := func(tag string, value interface{}) {
|
write := func(tag string, value any) {
|
||||||
if comma {
|
if comma {
|
||||||
buffer.WriteString(", ")
|
buffer.WriteString(", ")
|
||||||
}
|
}
|
||||||
|
@ -430,7 +430,7 @@ func (border *borderProperty) Remove(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (border *borderProperty) Set(tag string, value interface{}) bool {
|
func (border *borderProperty) Set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
border.Remove(tag)
|
border.Remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -512,7 +512,7 @@ func (border *borderProperty) Set(tag string, value interface{}) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (border *borderProperty) Get(tag string) interface{} {
|
func (border *borderProperty) Get(tag string) any {
|
||||||
tag = border.normalizeTag(tag)
|
tag = border.normalizeTag(tag)
|
||||||
|
|
||||||
if result, ok := border.properties[tag]; ok {
|
if result, ok := border.properties[tag]; ok {
|
||||||
|
@ -658,11 +658,14 @@ func (border *borderProperty) cssWidth(builder cssBuilder, session Session) {
|
||||||
borders.Top.Width == borders.Left.Width &&
|
borders.Top.Width == borders.Left.Width &&
|
||||||
borders.Top.Width == borders.Bottom.Width {
|
borders.Top.Width == borders.Bottom.Width {
|
||||||
if borders.Top.Width.Type != Auto {
|
if borders.Top.Width.Type != Auto {
|
||||||
builder.add("border-width", borders.Top.Width.cssString("0"))
|
builder.add("border-width", borders.Top.Width.cssString("0", session))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
builder.addValues("border-width", " ", borders.Top.Width.cssString("0"),
|
builder.addValues("border-width", " ",
|
||||||
borders.Right.Width.cssString("0"), borders.Bottom.Width.cssString("0"), borders.Left.Width.cssString("0"))
|
borders.Top.Width.cssString("0", session),
|
||||||
|
borders.Right.Width.cssString("0", session),
|
||||||
|
borders.Bottom.Width.cssString("0", session),
|
||||||
|
borders.Left.Width.cssString("0", session))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
39
bounds.go
39
bounds.go
|
@ -20,7 +20,7 @@ type boundsPropertyData struct {
|
||||||
// NewBoundsProperty creates the new BoundsProperty object
|
// NewBoundsProperty creates the new BoundsProperty object
|
||||||
func NewBoundsProperty(params Params) BoundsProperty {
|
func NewBoundsProperty(params Params) BoundsProperty {
|
||||||
bounds := new(boundsPropertyData)
|
bounds := new(boundsPropertyData)
|
||||||
bounds.properties = map[string]interface{}{}
|
bounds.properties = map[string]any{}
|
||||||
if params != nil {
|
if params != nil {
|
||||||
for _, tag := range []string{Top, Right, Bottom, Left} {
|
for _, tag := range []string{Top, Right, Bottom, Left} {
|
||||||
if value, ok := params[tag]; ok {
|
if value, ok := params[tag]; ok {
|
||||||
|
@ -79,7 +79,7 @@ func (bounds *boundsPropertyData) Remove(tag string) {
|
||||||
bounds.propertyList.Remove(bounds.normalizeTag(tag))
|
bounds.propertyList.Remove(bounds.normalizeTag(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bounds *boundsPropertyData) Set(tag string, value interface{}) bool {
|
func (bounds *boundsPropertyData) Set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
bounds.Remove(tag)
|
bounds.Remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -98,7 +98,7 @@ func (bounds *boundsPropertyData) Set(tag string, value interface{}) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bounds *boundsPropertyData) Get(tag string) interface{} {
|
func (bounds *boundsPropertyData) Get(tag string) any {
|
||||||
tag = bounds.normalizeTag(tag)
|
tag = bounds.normalizeTag(tag)
|
||||||
if value, ok := bounds.properties[tag]; ok {
|
if value, ok := bounds.properties[tag]; ok {
|
||||||
return value
|
return value
|
||||||
|
@ -213,22 +213,25 @@ func (bounds *Bounds) String() string {
|
||||||
bounds.Bottom.String() + "," + bounds.Left.String()
|
bounds.Bottom.String() + "," + bounds.Left.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bounds *Bounds) cssValue(tag string, builder cssBuilder) {
|
func (bounds *Bounds) cssValue(tag string, builder cssBuilder, session Session) {
|
||||||
if bounds.allFieldsEqual() {
|
if bounds.allFieldsEqual() {
|
||||||
builder.add(tag, bounds.Top.cssString("0"))
|
builder.add(tag, bounds.Top.cssString("0", session))
|
||||||
} else {
|
} else {
|
||||||
builder.addValues(tag, " ", bounds.Top.cssString("0"), bounds.Right.cssString("0"),
|
builder.addValues(tag, " ",
|
||||||
bounds.Bottom.cssString("0"), bounds.Left.cssString("0"))
|
bounds.Top.cssString("0", session),
|
||||||
|
bounds.Right.cssString("0", session),
|
||||||
|
bounds.Bottom.cssString("0", session),
|
||||||
|
bounds.Left.cssString("0", session))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bounds *Bounds) cssString() string {
|
func (bounds *Bounds) cssString(session Session) string {
|
||||||
var builder cssValueBuilder
|
var builder cssValueBuilder
|
||||||
bounds.cssValue("", &builder)
|
bounds.cssValue("", &builder, session)
|
||||||
return builder.finish()
|
return builder.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (properties *propertyList) setBounds(tag string, value interface{}) bool {
|
func (properties *propertyList) setBounds(tag string, value any) bool {
|
||||||
if !properties.setSimpleProperty(tag, value) {
|
if !properties.setSimpleProperty(tag, value) {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case string:
|
case string:
|
||||||
|
@ -260,6 +263,12 @@ func (properties *propertyList) setBounds(tag string, value interface{}) bool {
|
||||||
case SizeUnit:
|
case SizeUnit:
|
||||||
properties.properties[tag] = value
|
properties.properties[tag] = value
|
||||||
|
|
||||||
|
case float32:
|
||||||
|
properties.properties[tag] = Px(float64(value))
|
||||||
|
|
||||||
|
case float64:
|
||||||
|
properties.properties[tag] = Px(value)
|
||||||
|
|
||||||
case Bounds:
|
case Bounds:
|
||||||
bounds := NewBoundsProperty(nil)
|
bounds := NewBoundsProperty(nil)
|
||||||
if value.Top.Type != Auto {
|
if value.Top.Type != Auto {
|
||||||
|
@ -292,8 +301,12 @@ func (properties *propertyList) setBounds(tag string, value interface{}) bool {
|
||||||
properties.properties[tag] = bounds
|
properties.properties[tag] = bounds
|
||||||
|
|
||||||
default:
|
default:
|
||||||
notCompatibleType(tag, value)
|
if n, ok := isInt(value); ok {
|
||||||
return false
|
properties.properties[tag] = Px(float64(n))
|
||||||
|
} else {
|
||||||
|
notCompatibleType(tag, value)
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,7 +353,7 @@ func (properties *propertyList) removeBoundsSide(mainTag, sideTag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (properties *propertyList) setBoundsSide(mainTag, sideTag string, value interface{}) bool {
|
func (properties *propertyList) setBoundsSide(mainTag, sideTag string, value any) bool {
|
||||||
bounds := properties.boundsProperty(mainTag)
|
bounds := properties.boundsProperty(mainTag)
|
||||||
if bounds.Set(sideTag, value) {
|
if bounds.Set(sideTag, value) {
|
||||||
properties.properties[mainTag] = bounds
|
properties.properties[mainTag] = bounds
|
||||||
|
|
|
@ -592,7 +592,7 @@ func (canvas *canvasData) writeFont(name string, script *strings.Builder) {
|
||||||
|
|
||||||
func (canvas *canvasData) SetFont(name string, size SizeUnit) {
|
func (canvas *canvasData) SetFont(name string, size SizeUnit) {
|
||||||
canvas.script.WriteString("\nctx.font = '")
|
canvas.script.WriteString("\nctx.font = '")
|
||||||
canvas.script.WriteString(size.cssString("1em"))
|
canvas.script.WriteString(size.cssString("1rem", canvas.View().Session()))
|
||||||
canvas.writeFont(name, &canvas.script)
|
canvas.writeFont(name, &canvas.script)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -616,7 +616,7 @@ func (canvas *canvasData) setFontWithParams(name string, size SizeUnit, params F
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
script.WriteString(size.cssString("1em"))
|
script.WriteString(size.cssString("1rem", canvas.View().Session()))
|
||||||
switch params.LineHeight.Type {
|
switch params.LineHeight.Type {
|
||||||
case Auto:
|
case Auto:
|
||||||
|
|
||||||
|
@ -634,7 +634,7 @@ func (canvas *canvasData) setFontWithParams(name string, size SizeUnit, params F
|
||||||
|
|
||||||
default:
|
default:
|
||||||
script.WriteString("/")
|
script.WriteString("/")
|
||||||
script.WriteString(params.LineHeight.cssString(""))
|
script.WriteString(params.LineHeight.cssString("", canvas.View().Session()))
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.writeFont(name, script)
|
canvas.writeFont(name, script)
|
||||||
|
|
|
@ -21,7 +21,7 @@ type canvasViewData struct {
|
||||||
// NewCanvasView creates the new custom draw view
|
// NewCanvasView creates the new custom draw view
|
||||||
func NewCanvasView(session Session, params Params) CanvasView {
|
func NewCanvasView(session Session, params Params) CanvasView {
|
||||||
view := new(canvasViewData)
|
view := new(canvasViewData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -31,8 +31,8 @@ func newCanvasView(session Session) View {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initialize fields of ViewsContainer by default values
|
// Init initialize fields of ViewsContainer by default values
|
||||||
func (canvasView *canvasViewData) Init(session Session) {
|
func (canvasView *canvasViewData) init(session Session) {
|
||||||
canvasView.viewData.Init(session)
|
canvasView.viewData.init(session)
|
||||||
canvasView.tag = "CanvasView"
|
canvasView.tag = "CanvasView"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,11 +63,11 @@ func (canvasView *canvasViewData) remove(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvasView *canvasViewData) Set(tag string, value interface{}) bool {
|
func (canvasView *canvasViewData) Set(tag string, value any) bool {
|
||||||
return canvasView.set(canvasView.normalizeTag(tag), value)
|
return canvasView.set(canvasView.normalizeTag(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvasView *canvasViewData) set(tag string, value interface{}) bool {
|
func (canvasView *canvasViewData) set(tag string, value any) bool {
|
||||||
if tag == DrawFunction {
|
if tag == DrawFunction {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
canvasView.drawer = nil
|
canvasView.drawer = nil
|
||||||
|
@ -85,11 +85,11 @@ func (canvasView *canvasViewData) set(tag string, value interface{}) bool {
|
||||||
return canvasView.viewData.set(tag, value)
|
return canvasView.viewData.set(tag, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvasView *canvasViewData) Get(tag string) interface{} {
|
func (canvasView *canvasViewData) Get(tag string) any {
|
||||||
return canvasView.get(canvasView.normalizeTag(tag))
|
return canvasView.get(canvasView.normalizeTag(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvasView *canvasViewData) get(tag string) interface{} {
|
func (canvasView *canvasViewData) get(tag string) any {
|
||||||
if tag == DrawFunction {
|
if tag == DrawFunction {
|
||||||
return canvasView.drawer
|
return canvasView.drawer
|
||||||
}
|
}
|
||||||
|
|
122
checkbox.go
122
checkbox.go
|
@ -23,7 +23,7 @@ type checkboxData struct {
|
||||||
// NewCheckbox create new Checkbox object and return it
|
// NewCheckbox create new Checkbox object and return it
|
||||||
func NewCheckbox(session Session, params Params) Checkbox {
|
func NewCheckbox(session Session, params Params) Checkbox {
|
||||||
view := new(checkboxData)
|
view := new(checkboxData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
setInitParams(view, Params{
|
setInitParams(view, Params{
|
||||||
ClickEvent: checkboxClickListener,
|
ClickEvent: checkboxClickListener,
|
||||||
KeyDownEvent: checkboxKeyListener,
|
KeyDownEvent: checkboxKeyListener,
|
||||||
|
@ -36,8 +36,8 @@ func newCheckbox(session Session) View {
|
||||||
return NewCheckbox(session, nil)
|
return NewCheckbox(session, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (button *checkboxData) Init(session Session) {
|
func (button *checkboxData) init(session Session) {
|
||||||
button.viewsContainerData.Init(session)
|
button.viewsContainerData.init(session)
|
||||||
button.tag = "Checkbox"
|
button.tag = "Checkbox"
|
||||||
button.systemClass = "ruiGridLayout ruiCheckbox"
|
button.systemClass = "ruiGridLayout ruiCheckbox"
|
||||||
button.checkedListeners = []func(Checkbox, bool){}
|
button.checkedListeners = []func(Checkbox, bool){}
|
||||||
|
@ -51,7 +51,7 @@ func (button *checkboxData) Focusable() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (button *checkboxData) Get(tag string) interface{} {
|
func (button *checkboxData) Get(tag string) any {
|
||||||
switch strings.ToLower(tag) {
|
switch strings.ToLower(tag) {
|
||||||
case CheckboxChangedEvent:
|
case CheckboxChangedEvent:
|
||||||
return button.checkedListeners
|
return button.checkedListeners
|
||||||
|
@ -60,11 +60,11 @@ func (button *checkboxData) Get(tag string) interface{} {
|
||||||
return button.viewsContainerData.Get(tag)
|
return button.viewsContainerData.Get(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (button *checkboxData) Set(tag string, value interface{}) bool {
|
func (button *checkboxData) Set(tag string, value any) bool {
|
||||||
return button.set(tag, value)
|
return button.set(tag, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (button *checkboxData) set(tag string, value interface{}) bool {
|
func (button *checkboxData) set(tag string, value any) bool {
|
||||||
switch tag {
|
switch tag {
|
||||||
case CheckboxChangedEvent:
|
case CheckboxChangedEvent:
|
||||||
if !button.setChangedListener(value) {
|
if !button.setChangedListener(value) {
|
||||||
|
@ -194,80 +194,32 @@ func (button *checkboxData) changedCheckboxState(state bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkboxClickListener(view View) {
|
func checkboxClickListener(view View) {
|
||||||
view.Set(Checked, !IsCheckboxChecked(view, ""))
|
view.Set(Checked, !IsCheckboxChecked(view))
|
||||||
BlurView(view)
|
BlurView(view)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkboxKeyListener(view View, event KeyEvent) {
|
func checkboxKeyListener(view View, event KeyEvent) {
|
||||||
switch event.Code {
|
switch event.Code {
|
||||||
case "Enter", "Space":
|
case "Enter", "Space":
|
||||||
view.Set(Checked, !IsCheckboxChecked(view, ""))
|
view.Set(Checked, !IsCheckboxChecked(view))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (button *checkboxData) setChangedListener(value interface{}) bool {
|
func (button *checkboxData) setChangedListener(value any) bool {
|
||||||
if value == nil {
|
listeners, ok := valueToEventListeners[Checkbox, bool](value)
|
||||||
if len(button.checkedListeners) > 0 {
|
if !ok {
|
||||||
button.checkedListeners = []func(Checkbox, bool){}
|
return false
|
||||||
}
|
} else if listeners == nil {
|
||||||
return true
|
listeners = []func(Checkbox, bool){}
|
||||||
}
|
|
||||||
|
|
||||||
switch value := value.(type) {
|
|
||||||
case func(Checkbox, bool):
|
|
||||||
button.checkedListeners = []func(Checkbox, bool){value}
|
|
||||||
|
|
||||||
case func(bool):
|
|
||||||
fn := func(_ Checkbox, checked bool) {
|
|
||||||
value(checked)
|
|
||||||
}
|
|
||||||
button.checkedListeners = []func(Checkbox, bool){fn}
|
|
||||||
|
|
||||||
case []func(Checkbox, bool):
|
|
||||||
button.checkedListeners = value
|
|
||||||
|
|
||||||
case []func(bool):
|
|
||||||
listeners := make([]func(Checkbox, bool), len(value))
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
listeners[i] = func(_ Checkbox, checked bool) {
|
|
||||||
val(checked)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
button.checkedListeners = listeners
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
listeners := make([]func(Checkbox, bool), len(value))
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
switch val := val.(type) {
|
|
||||||
case func(Checkbox, bool):
|
|
||||||
listeners[i] = val
|
|
||||||
|
|
||||||
case func(bool):
|
|
||||||
listeners[i] = func(_ Checkbox, date bool) {
|
|
||||||
val(date)
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
button.checkedListeners = listeners
|
|
||||||
}
|
}
|
||||||
|
button.checkedListeners = listeners
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (button *checkboxData) cssStyle(self View, builder cssBuilder) {
|
func (button *checkboxData) cssStyle(self View, builder cssBuilder) {
|
||||||
session := button.Session()
|
session := button.Session()
|
||||||
vAlign, _ := enumStyledProperty(button, CheckboxVerticalAlign, LeftAlign)
|
vAlign := GetCheckboxVerticalAlign(button)
|
||||||
hAlign, _ := enumStyledProperty(button, CheckboxHorizontalAlign, TopAlign)
|
hAlign := GetCheckboxHorizontalAlign(button)
|
||||||
switch hAlign {
|
switch hAlign {
|
||||||
case CenterAlign:
|
case CenterAlign:
|
||||||
if vAlign == BottomAlign {
|
if vAlign == BottomAlign {
|
||||||
|
@ -284,7 +236,7 @@ func (button *checkboxData) cssStyle(self View, builder cssBuilder) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if gap, ok := sizeConstant(session, "ruiCheckboxGap"); ok && gap.Type != Auto && gap.Value > 0 {
|
if gap, ok := sizeConstant(session, "ruiCheckboxGap"); ok && gap.Type != Auto && gap.Value > 0 {
|
||||||
builder.add("gap", gap.cssString("0"))
|
builder.add("gap", gap.cssString("0", session))
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.add("align-items", "stretch")
|
builder.add("align-items", "stretch")
|
||||||
|
@ -294,8 +246,8 @@ func (button *checkboxData) cssStyle(self View, builder cssBuilder) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (button *checkboxData) htmlCheckbox(buffer *strings.Builder, checked bool) (int, int) {
|
func (button *checkboxData) htmlCheckbox(buffer *strings.Builder, checked bool) (int, int) {
|
||||||
vAlign, _ := enumStyledProperty(button, CheckboxVerticalAlign, LeftAlign)
|
vAlign := GetCheckboxVerticalAlign(button)
|
||||||
hAlign, _ := enumStyledProperty(button, CheckboxHorizontalAlign, TopAlign)
|
hAlign := GetCheckboxHorizontalAlign(button)
|
||||||
|
|
||||||
buffer.WriteString(`<div id="`)
|
buffer.WriteString(`<div id="`)
|
||||||
buffer.WriteString(button.htmlID())
|
buffer.WriteString(button.htmlID())
|
||||||
|
@ -339,7 +291,7 @@ func (button *checkboxData) htmlCheckbox(buffer *strings.Builder, checked bool)
|
||||||
|
|
||||||
func (button *checkboxData) htmlSubviews(self View, buffer *strings.Builder) {
|
func (button *checkboxData) htmlSubviews(self View, buffer *strings.Builder) {
|
||||||
|
|
||||||
vCheckboxAlign, hCheckboxAlign := button.htmlCheckbox(buffer, IsCheckboxChecked(button, ""))
|
vCheckboxAlign, hCheckboxAlign := button.htmlCheckbox(buffer, IsCheckboxChecked(button))
|
||||||
|
|
||||||
buffer.WriteString(`<div id="`)
|
buffer.WriteString(`<div id="`)
|
||||||
buffer.WriteString(button.htmlID())
|
buffer.WriteString(button.htmlID())
|
||||||
|
@ -370,7 +322,7 @@ func (button *checkboxData) htmlSubviews(self View, buffer *strings.Builder) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (button *checkboxData) cssHorizontalAlign() string {
|
func (button *checkboxData) cssHorizontalAlign() string {
|
||||||
align, _ := enumStyledProperty(button, HorizontalAlign, TopAlign)
|
align := GetHorizontalAlign(button)
|
||||||
values := enumProperties[CellHorizontalAlign].cssValues
|
values := enumProperties[CellHorizontalAlign].cssValues
|
||||||
if align >= 0 && align < len(values) {
|
if align >= 0 && align < len(values) {
|
||||||
return values[align]
|
return values[align]
|
||||||
|
@ -379,7 +331,7 @@ func (button *checkboxData) cssHorizontalAlign() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (button *checkboxData) cssVerticalAlign() string {
|
func (button *checkboxData) cssVerticalAlign() string {
|
||||||
align, _ := enumStyledProperty(button, VerticalAlign, TopAlign)
|
align := GetVerticalAlign(button)
|
||||||
values := enumProperties[CellVerticalAlign].cssValues
|
values := enumProperties[CellVerticalAlign].cssValues
|
||||||
if align >= 0 && align < len(values) {
|
if align >= 0 && align < len(values) {
|
||||||
return values[align]
|
return values[align]
|
||||||
|
@ -388,17 +340,19 @@ func (button *checkboxData) cssVerticalAlign() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsCheckboxChecked returns true if the Checkbox is checked, false otherwise.
|
// IsCheckboxChecked returns true if the Checkbox is checked, false otherwise.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func IsCheckboxChecked(view View, subviewID string) bool {
|
func IsCheckboxChecked(view View, subviewID ...string) bool {
|
||||||
if subviewID != "" {
|
return boolStyledProperty(view, subviewID, Checked, false)
|
||||||
view = ViewByID(view, subviewID)
|
}
|
||||||
}
|
|
||||||
if view != nil {
|
// GetCheckboxVerticalAlign return the vertical align of a Checkbox subview: TopAlign (0), BottomAlign (1), CenterAlign (2)
|
||||||
if checked := view.Get(Checked); checked != nil {
|
// If the second argument (subviewID) is not specified or it is "" then a left position of the first argument (view) is returned
|
||||||
if b, ok := checked.(bool); ok {
|
func GetCheckboxVerticalAlign(view View, subviewID ...string) int {
|
||||||
return b
|
return enumStyledProperty(view, subviewID, CheckboxVerticalAlign, LeftAlign, false)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
// GetCheckboxHorizontalAlign return the vertical align of a Checkbox subview: LeftAlign (0), RightAlign (1), CenterAlign (2)
|
||||||
return false
|
// If the second argument (subviewID) is not specified or it is "" then a left position of the first argument (view) is returned
|
||||||
|
func GetCheckboxHorizontalAlign(view View, subviewID ...string) int {
|
||||||
|
return enumStyledProperty(view, subviewID, CheckboxHorizontalAlign, TopAlign, false)
|
||||||
}
|
}
|
||||||
|
|
113
colorPicker.go
113
colorPicker.go
|
@ -23,7 +23,7 @@ type colorPickerData struct {
|
||||||
// NewColorPicker create new ColorPicker object and return it
|
// NewColorPicker create new ColorPicker object and return it
|
||||||
func NewColorPicker(session Session, params Params) ColorPicker {
|
func NewColorPicker(session Session, params Params) ColorPicker {
|
||||||
view := new(colorPickerData)
|
view := new(colorPickerData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,8 @@ func newColorPicker(session Session) View {
|
||||||
return NewColorPicker(session, nil)
|
return NewColorPicker(session, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *colorPickerData) Init(session Session) {
|
func (picker *colorPickerData) init(session Session) {
|
||||||
picker.viewData.Init(session)
|
picker.viewData.init(session)
|
||||||
picker.tag = "ColorPicker"
|
picker.tag = "ColorPicker"
|
||||||
picker.colorChangedListeners = []func(ColorPicker, Color){}
|
picker.colorChangedListeners = []func(ColorPicker, Color){}
|
||||||
picker.properties[Padding] = Px(0)
|
picker.properties[Padding] = Px(0)
|
||||||
|
@ -66,7 +66,7 @@ func (picker *colorPickerData) remove(tag string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case ColorPickerValue:
|
case ColorPickerValue:
|
||||||
oldColor := GetColorPickerValue(picker, "")
|
oldColor := GetColorPickerValue(picker)
|
||||||
delete(picker.properties, ColorPickerValue)
|
delete(picker.properties, ColorPickerValue)
|
||||||
picker.colorChanged(oldColor)
|
picker.colorChanged(oldColor)
|
||||||
|
|
||||||
|
@ -75,11 +75,11 @@ func (picker *colorPickerData) remove(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *colorPickerData) Set(tag string, value interface{}) bool {
|
func (picker *colorPickerData) Set(tag string, value any) bool {
|
||||||
return picker.set(picker.normalizeTag(tag), value)
|
return picker.set(picker.normalizeTag(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *colorPickerData) set(tag string, value interface{}) bool {
|
func (picker *colorPickerData) set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
picker.remove(tag)
|
picker.remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -87,62 +87,19 @@ func (picker *colorPickerData) set(tag string, value interface{}) bool {
|
||||||
|
|
||||||
switch tag {
|
switch tag {
|
||||||
case ColorChangedEvent:
|
case ColorChangedEvent:
|
||||||
switch value := value.(type) {
|
listeners, ok := valueToEventListeners[ColorPicker, Color](value)
|
||||||
case func(ColorPicker, Color):
|
if !ok {
|
||||||
picker.colorChangedListeners = []func(ColorPicker, Color){value}
|
notCompatibleType(tag, value)
|
||||||
|
return false
|
||||||
case func(Color):
|
} else if listeners == nil {
|
||||||
fn := func(_ ColorPicker, date Color) {
|
listeners = []func(ColorPicker, Color){}
|
||||||
value(date)
|
|
||||||
}
|
|
||||||
picker.colorChangedListeners = []func(ColorPicker, Color){fn}
|
|
||||||
|
|
||||||
case []func(ColorPicker, Color):
|
|
||||||
picker.colorChangedListeners = value
|
|
||||||
|
|
||||||
case []func(Color):
|
|
||||||
listeners := make([]func(ColorPicker, Color), len(value))
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
notCompatibleType(tag, val)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
listeners[i] = func(_ ColorPicker, date Color) {
|
|
||||||
val(date)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
picker.colorChangedListeners = listeners
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
listeners := make([]func(ColorPicker, Color), len(value))
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
notCompatibleType(tag, val)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
switch val := val.(type) {
|
|
||||||
case func(ColorPicker, Color):
|
|
||||||
listeners[i] = val
|
|
||||||
|
|
||||||
case func(Color):
|
|
||||||
listeners[i] = func(_ ColorPicker, date Color) {
|
|
||||||
val(date)
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
notCompatibleType(tag, val)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
picker.colorChangedListeners = listeners
|
|
||||||
}
|
}
|
||||||
|
picker.colorChangedListeners = listeners
|
||||||
picker.propertyChangedEvent(tag)
|
picker.propertyChangedEvent(tag)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
case ColorPickerValue:
|
case ColorPickerValue:
|
||||||
oldColor := GetColorPickerValue(picker, "")
|
oldColor := GetColorPickerValue(picker)
|
||||||
if picker.setColorProperty(ColorPickerValue, value) {
|
if picker.setColorProperty(ColorPickerValue, value) {
|
||||||
picker.colorChanged(oldColor)
|
picker.colorChanged(oldColor)
|
||||||
return true
|
return true
|
||||||
|
@ -155,7 +112,7 @@ func (picker *colorPickerData) set(tag string, value interface{}) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *colorPickerData) colorChanged(oldColor Color) {
|
func (picker *colorPickerData) colorChanged(oldColor Color) {
|
||||||
if newColor := GetColorPickerValue(picker, ""); oldColor != newColor {
|
if newColor := GetColorPickerValue(picker); oldColor != newColor {
|
||||||
if picker.created {
|
if picker.created {
|
||||||
picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), newColor.rgbString()))
|
picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), newColor.rgbString()))
|
||||||
}
|
}
|
||||||
|
@ -166,11 +123,11 @@ func (picker *colorPickerData) colorChanged(oldColor Color) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *colorPickerData) Get(tag string) interface{} {
|
func (picker *colorPickerData) Get(tag string) any {
|
||||||
return picker.get(picker.normalizeTag(tag))
|
return picker.get(picker.normalizeTag(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *colorPickerData) get(tag string) interface{} {
|
func (picker *colorPickerData) get(tag string) any {
|
||||||
switch tag {
|
switch tag {
|
||||||
case ColorChangedEvent:
|
case ColorChangedEvent:
|
||||||
return picker.colorChangedListeners
|
return picker.colorChangedListeners
|
||||||
|
@ -188,7 +145,7 @@ func (picker *colorPickerData) htmlProperties(self View, buffer *strings.Builder
|
||||||
picker.viewData.htmlProperties(self, buffer)
|
picker.viewData.htmlProperties(self, buffer)
|
||||||
|
|
||||||
buffer.WriteString(` type="color" value="`)
|
buffer.WriteString(` type="color" value="`)
|
||||||
buffer.WriteString(GetColorPickerValue(picker, "").rgbString())
|
buffer.WriteString(GetColorPickerValue(picker).rgbString())
|
||||||
buffer.WriteByte('"')
|
buffer.WriteByte('"')
|
||||||
|
|
||||||
buffer.WriteString(` oninput="editViewInputEvent(this)"`)
|
buffer.WriteString(` oninput="editViewInputEvent(this)"`)
|
||||||
|
@ -198,7 +155,7 @@ func (picker *colorPickerData) htmlProperties(self View, buffer *strings.Builder
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *colorPickerData) htmlDisabledProperties(self View, buffer *strings.Builder) {
|
func (picker *colorPickerData) htmlDisabledProperties(self View, buffer *strings.Builder) {
|
||||||
if IsDisabled(self, "") {
|
if IsDisabled(self) {
|
||||||
buffer.WriteString(` disabled`)
|
buffer.WriteString(` disabled`)
|
||||||
}
|
}
|
||||||
picker.viewData.htmlDisabledProperties(self, buffer)
|
picker.viewData.htmlDisabledProperties(self, buffer)
|
||||||
|
@ -208,7 +165,7 @@ func (picker *colorPickerData) handleCommand(self View, command string, data Dat
|
||||||
switch command {
|
switch command {
|
||||||
case "textChanged":
|
case "textChanged":
|
||||||
if text, ok := data.PropertyValue("text"); ok {
|
if text, ok := data.PropertyValue("text"); ok {
|
||||||
oldColor := GetColorPickerValue(picker, "")
|
oldColor := GetColorPickerValue(picker)
|
||||||
if color, ok := StringToColor(text); ok {
|
if color, ok := StringToColor(text); ok {
|
||||||
picker.properties[ColorPickerValue] = color
|
picker.properties[ColorPickerValue] = color
|
||||||
if color != oldColor {
|
if color != oldColor {
|
||||||
|
@ -225,16 +182,16 @@ func (picker *colorPickerData) handleCommand(self View, command string, data Dat
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetColorPickerValue returns the value of ColorPicker subview.
|
// GetColorPickerValue returns the value of ColorPicker subview.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetColorPickerValue(view View, subviewID string) Color {
|
func GetColorPickerValue(view View, subviewID ...string) Color {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view != nil {
|
if view != nil {
|
||||||
if result, ok := colorStyledProperty(view, ColorPickerValue); ok {
|
if value, ok := colorProperty(view, ColorPickerValue, view.Session()); ok {
|
||||||
return result
|
return value
|
||||||
}
|
}
|
||||||
for _, tag := range []string{Value, ColorTag} {
|
for _, tag := range []string{ColorPickerValue, Value, ColorTag} {
|
||||||
if value := valueFromStyle(view, tag); value != nil {
|
if value := valueFromStyle(view, tag); value != nil {
|
||||||
if result, ok := valueToColor(value, view.Session()); ok {
|
if result, ok := valueToColor(value, view.Session()); ok {
|
||||||
return result
|
return result
|
||||||
|
@ -247,17 +204,7 @@ func GetColorPickerValue(view View, subviewID string) Color {
|
||||||
|
|
||||||
// GetColorChangedListeners returns the ColorChangedListener list of an ColorPicker subview.
|
// GetColorChangedListeners returns the ColorChangedListener list of an ColorPicker subview.
|
||||||
// If there are no listeners then the empty list is returned
|
// If there are no listeners then the empty list is returned
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetColorChangedListeners(view View, subviewID string) []func(ColorPicker, Color) {
|
func GetColorChangedListeners(view View, subviewID ...string) []func(ColorPicker, Color) {
|
||||||
if subviewID != "" {
|
return getEventListeners[ColorPicker, Color](view, subviewID, ColorChangedEvent)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if value := view.Get(ColorChangedEvent); value != nil {
|
|
||||||
if listeners, ok := value.([]func(ColorPicker, Color)); ok {
|
|
||||||
return listeners
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []func(ColorPicker, Color){}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ type columnLayoutData struct {
|
||||||
// NewColumnLayout create new ColumnLayout object and return it
|
// NewColumnLayout create new ColumnLayout object and return it
|
||||||
func NewColumnLayout(session Session, params Params) ColumnLayout {
|
func NewColumnLayout(session Session, params Params) ColumnLayout {
|
||||||
view := new(columnLayoutData)
|
view := new(columnLayoutData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -57,8 +57,8 @@ func newColumnLayout(session Session) View {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initialize fields of ColumnLayout by default values
|
// Init initialize fields of ColumnLayout by default values
|
||||||
func (ColumnLayout *columnLayoutData) Init(session Session) {
|
func (ColumnLayout *columnLayoutData) init(session Session) {
|
||||||
ColumnLayout.viewsContainerData.Init(session)
|
ColumnLayout.viewsContainerData.init(session)
|
||||||
ColumnLayout.tag = "ColumnLayout"
|
ColumnLayout.tag = "ColumnLayout"
|
||||||
//ColumnLayout.systemClass = "ruiColumnLayout"
|
//ColumnLayout.systemClass = "ruiColumnLayout"
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ func (columnLayout *columnLayoutData) normalizeTag(tag string) string {
|
||||||
return tag
|
return tag
|
||||||
}
|
}
|
||||||
|
|
||||||
func (columnLayout *columnLayoutData) Get(tag string) interface{} {
|
func (columnLayout *columnLayoutData) Get(tag string) any {
|
||||||
return columnLayout.get(columnLayout.normalizeTag(tag))
|
return columnLayout.get(columnLayout.normalizeTag(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,11 +97,11 @@ func (columnLayout *columnLayoutData) remove(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (columnLayout *columnLayoutData) Set(tag string, value interface{}) bool {
|
func (columnLayout *columnLayoutData) Set(tag string, value any) bool {
|
||||||
return columnLayout.set(columnLayout.normalizeTag(tag), value)
|
return columnLayout.set(columnLayout.normalizeTag(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (columnLayout *columnLayoutData) set(tag string, value interface{}) bool {
|
func (columnLayout *columnLayoutData) set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
columnLayout.remove(tag)
|
columnLayout.remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -137,50 +137,26 @@ func (columnLayout *columnLayoutData) set(tag string, value interface{}) bool {
|
||||||
// GetColumnCount returns int value which specifies number of columns into which the content of
|
// GetColumnCount returns int value which specifies number of columns into which the content of
|
||||||
// ColumnLayout is break. If the return value is 0 then the number of columns is calculated
|
// ColumnLayout is break. If the return value is 0 then the number of columns is calculated
|
||||||
// based on the "column-width" property.
|
// based on the "column-width" property.
|
||||||
// If the second argument (subviewID) is "" then a top position of the first argument (view) is returned
|
// If the second argument (subviewID) is not specified or it is "" then a top position of the first argument (view) is returned
|
||||||
func GetColumnCount(view View, subviewID string) int {
|
func GetColumnCount(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return intStyledProperty(view, subviewID, ColumnCount, 0)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view == nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
result, _ := intStyledProperty(view, ColumnCount, 0)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetColumnWidth returns SizeUnit value which specifies the width of each column of ColumnLayout.
|
// GetColumnWidth returns SizeUnit value which specifies the width of each column of ColumnLayout.
|
||||||
// If the second argument (subviewID) is "" then a top position of the first argument (view) is returned
|
// If the second argument (subviewID) is not specified or it is "" then a top position of the first argument (view) is returned
|
||||||
func GetColumnWidth(view View, subviewID string) SizeUnit {
|
func GetColumnWidth(view View, subviewID ...string) SizeUnit {
|
||||||
if subviewID != "" {
|
return sizeStyledProperty(view, subviewID, ColumnWidth, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view == nil {
|
|
||||||
return AutoSize()
|
|
||||||
}
|
|
||||||
result, _ := sizeStyledProperty(view, ColumnWidth)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetColumnGap returns SizeUnit property which specifies the size of the gap (gutter) between columns of ColumnLayout.
|
// GetColumnGap returns SizeUnit property which specifies the size of the gap (gutter) between columns of ColumnLayout.
|
||||||
// If the second argument (subviewID) is "" then a top position of the first argument (view) is returned
|
// If the second argument (subviewID) is not specified or it is "" then a top position of the first argument (view) is returned
|
||||||
func GetColumnGap(view View, subviewID string) SizeUnit {
|
func GetColumnGap(view View, subviewID ...string) SizeUnit {
|
||||||
if subviewID != "" {
|
return sizeStyledProperty(view, subviewID, ColumnGap, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view == nil {
|
|
||||||
return AutoSize()
|
|
||||||
}
|
|
||||||
result, _ := sizeStyledProperty(view, ColumnGap)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetColumnSeparator returns ViewBorder struct which specifies the line drawn between
|
func getColumnSeparator(view View, subviewID []string) ViewBorder {
|
||||||
// columns in a multi-column ColumnLayout.
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
// If the second argument (subviewID) is "" then a top position of the first argument (view) is returned
|
view = ViewByID(view, subviewID[0])
|
||||||
func GetColumnSeparator(view View, subviewID string) ViewBorder {
|
|
||||||
if subviewID != "" {
|
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if view != nil {
|
if view != nil {
|
||||||
|
@ -199,27 +175,34 @@ func GetColumnSeparator(view View, subviewID string) ViewBorder {
|
||||||
return ViewBorder{}
|
return ViewBorder{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetColumnSeparator returns ViewBorder struct which specifies the line drawn between
|
||||||
|
// columns in a multi-column ColumnLayout.
|
||||||
|
// If the second argument (subviewID) is not specified or it is "" then a top position of the first argument (view) is returned
|
||||||
|
func GetColumnSeparator(view View, subviewID ...string) ViewBorder {
|
||||||
|
return getColumnSeparator(view, subviewID)
|
||||||
|
}
|
||||||
|
|
||||||
// ColumnSeparatorStyle returns int value which specifies the style of the line drawn between
|
// ColumnSeparatorStyle returns int value which specifies the style of the line drawn between
|
||||||
// columns in a multi-column layout.
|
// columns in a multi-column layout.
|
||||||
// Valid values are NoneLine (0), SolidLine (1), DashedLine (2), DottedLine (3), and DoubleLine (4).
|
// Valid values are NoneLine (0), SolidLine (1), DashedLine (2), DottedLine (3), and DoubleLine (4).
|
||||||
// If the second argument (subviewID) is "" then a top position of the first argument (view) is returned
|
// If the second argument (subviewID) is not specified or it is "" then a top position of the first argument (view) is returned
|
||||||
func GetColumnSeparatorStyle(view View, subviewID string) int {
|
func GetColumnSeparatorStyle(view View, subviewID ...string) int {
|
||||||
border := GetColumnSeparator(view, subviewID)
|
border := getColumnSeparator(view, subviewID)
|
||||||
return border.Style
|
return border.Style
|
||||||
}
|
}
|
||||||
|
|
||||||
// ColumnSeparatorWidth returns SizeUnit value which specifies the width of the line drawn between
|
// ColumnSeparatorWidth returns SizeUnit value which specifies the width of the line drawn between
|
||||||
// columns in a multi-column layout.
|
// columns in a multi-column layout.
|
||||||
// If the second argument (subviewID) is "" then a top position of the first argument (view) is returned
|
// If the second argument (subviewID) is not specified or it is "" then a top position of the first argument (view) is returned
|
||||||
func GetColumnSeparatorWidth(view View, subviewID string) SizeUnit {
|
func GetColumnSeparatorWidth(view View, subviewID ...string) SizeUnit {
|
||||||
border := GetColumnSeparator(view, subviewID)
|
border := getColumnSeparator(view, subviewID)
|
||||||
return border.Width
|
return border.Width
|
||||||
}
|
}
|
||||||
|
|
||||||
// ColumnSeparatorColor returns Color value which specifies the color of the line drawn between
|
// ColumnSeparatorColor returns Color value which specifies the color of the line drawn between
|
||||||
// columns in a multi-column layout.
|
// columns in a multi-column layout.
|
||||||
// If the second argument (subviewID) is "" then a top position of the first argument (view) is returned
|
// If the second argument (subviewID) is not specified or it is "" then a top position of the first argument (view) is returned
|
||||||
func GetColumnSeparatorColor(view View, subviewID string) Color {
|
func GetColumnSeparatorColor(view View, subviewID ...string) Color {
|
||||||
border := GetColumnSeparator(view, subviewID)
|
border := getColumnSeparator(view, subviewID)
|
||||||
return border.Color
|
return border.Color
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,11 +18,11 @@ type columnSeparatorProperty struct {
|
||||||
propertyList
|
propertyList
|
||||||
}
|
}
|
||||||
|
|
||||||
func newColumnSeparatorProperty(value interface{}) ColumnSeparatorProperty {
|
func newColumnSeparatorProperty(value any) ColumnSeparatorProperty {
|
||||||
|
|
||||||
if value == nil {
|
if value == nil {
|
||||||
separator := new(columnSeparatorProperty)
|
separator := new(columnSeparatorProperty)
|
||||||
separator.properties = map[string]interface{}{}
|
separator.properties = map[string]any{}
|
||||||
return separator
|
return separator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ func newColumnSeparatorProperty(value interface{}) ColumnSeparatorProperty {
|
||||||
|
|
||||||
case DataObject:
|
case DataObject:
|
||||||
separator := new(columnSeparatorProperty)
|
separator := new(columnSeparatorProperty)
|
||||||
separator.properties = map[string]interface{}{}
|
separator.properties = map[string]any{}
|
||||||
for _, tag := range []string{Style, Width, ColorTag} {
|
for _, tag := range []string{Style, Width, ColorTag} {
|
||||||
if val, ok := value.PropertyValue(tag); ok && val != "" {
|
if val, ok := value.PropertyValue(tag); ok && val != "" {
|
||||||
separator.set(tag, value)
|
separator.set(tag, value)
|
||||||
|
@ -42,7 +42,7 @@ func newColumnSeparatorProperty(value interface{}) ColumnSeparatorProperty {
|
||||||
|
|
||||||
case ViewBorder:
|
case ViewBorder:
|
||||||
separator := new(columnSeparatorProperty)
|
separator := new(columnSeparatorProperty)
|
||||||
separator.properties = map[string]interface{}{
|
separator.properties = map[string]any{
|
||||||
Style: value.Style,
|
Style: value.Style,
|
||||||
Width: value.Width,
|
Width: value.Width,
|
||||||
ColorTag: value.Color,
|
ColorTag: value.Color,
|
||||||
|
@ -57,7 +57,7 @@ func newColumnSeparatorProperty(value interface{}) ColumnSeparatorProperty {
|
||||||
// NewColumnSeparator creates the new ColumnSeparatorProperty
|
// NewColumnSeparator creates the new ColumnSeparatorProperty
|
||||||
func NewColumnSeparator(params Params) ColumnSeparatorProperty {
|
func NewColumnSeparator(params Params) ColumnSeparatorProperty {
|
||||||
separator := new(columnSeparatorProperty)
|
separator := new(columnSeparatorProperty)
|
||||||
separator.properties = map[string]interface{}{}
|
separator.properties = map[string]any{}
|
||||||
if params != nil {
|
if params != nil {
|
||||||
for _, tag := range []string{Style, Width, ColorTag} {
|
for _, tag := range []string{Style, Width, ColorTag} {
|
||||||
if value, ok := params[tag]; ok && value != nil {
|
if value, ok := params[tag]; ok && value != nil {
|
||||||
|
@ -117,7 +117,7 @@ func (separator *columnSeparatorProperty) Remove(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (separator *columnSeparatorProperty) Set(tag string, value interface{}) bool {
|
func (separator *columnSeparatorProperty) Set(tag string, value any) bool {
|
||||||
tag = separator.normalizeTag(tag)
|
tag = separator.normalizeTag(tag)
|
||||||
|
|
||||||
if value == nil {
|
if value == nil {
|
||||||
|
@ -140,7 +140,7 @@ func (separator *columnSeparatorProperty) Set(tag string, value interface{}) boo
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (separator *columnSeparatorProperty) Get(tag string) interface{} {
|
func (separator *columnSeparatorProperty) Get(tag string) any {
|
||||||
tag = separator.normalizeTag(tag)
|
tag = separator.normalizeTag(tag)
|
||||||
|
|
||||||
if result, ok := separator.properties[tag]; ok {
|
if result, ok := separator.properties[tag]; ok {
|
||||||
|
@ -167,8 +167,9 @@ func (separator *columnSeparatorProperty) cssValue(session Session) string {
|
||||||
buffer := allocStringBuilder()
|
buffer := allocStringBuilder()
|
||||||
defer freeStringBuilder(buffer)
|
defer freeStringBuilder(buffer)
|
||||||
|
|
||||||
if value.Width.Type != Auto && value.Width.Type != SizeInFraction && value.Width.Value > 0 {
|
if value.Width.Type != Auto && value.Width.Type != SizeInFraction &&
|
||||||
buffer.WriteString(value.Width.cssString(""))
|
(value.Width.Value > 0 || value.Width.Type == SizeFunction) {
|
||||||
|
buffer.WriteString(value.Width.cssString("", session))
|
||||||
}
|
}
|
||||||
|
|
||||||
styles := enumProperties[BorderStyle].cssValues
|
styles := enumProperties[BorderStyle].cssValues
|
||||||
|
|
|
@ -45,26 +45,26 @@ func (customView *CustomViewData) setTag(tag string) {
|
||||||
|
|
||||||
// Get returns a value of the property with name defined by the argument.
|
// Get returns a value of the property with name defined by the argument.
|
||||||
// The type of return value depends on the property. If the property is not set then nil is returned.
|
// The type of return value depends on the property. If the property is not set then nil is returned.
|
||||||
func (customView *CustomViewData) Get(tag string) interface{} {
|
func (customView *CustomViewData) Get(tag string) any {
|
||||||
return customView.superView.Get(tag)
|
return customView.superView.Get(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (customView *CustomViewData) getRaw(tag string) interface{} {
|
func (customView *CustomViewData) getRaw(tag string) any {
|
||||||
return customView.superView.getRaw(tag)
|
return customView.superView.getRaw(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (customView *CustomViewData) setRaw(tag string, value interface{}) {
|
func (customView *CustomViewData) setRaw(tag string, value any) {
|
||||||
customView.superView.setRaw(tag, value)
|
customView.superView.setRaw(tag, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set sets the value (second argument) of the property with name defined by the first argument.
|
// Set sets the value (second argument) of the property with name defined by the first argument.
|
||||||
// Return "true" if the value has been set, in the opposite case "false" are returned and
|
// Return "true" if the value has been set, in the opposite case "false" are returned and
|
||||||
// a description of the error is written to the log
|
// a description of the error is written to the log
|
||||||
func (customView *CustomViewData) Set(tag string, value interface{}) bool {
|
func (customView *CustomViewData) Set(tag string, value any) bool {
|
||||||
return customView.superView.Set(tag, value)
|
return customView.superView.Set(tag, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (customView *CustomViewData) SetAnimated(tag string, value interface{}, animation Animation) bool {
|
func (customView *CustomViewData) SetAnimated(tag string, value any, animation Animation) bool {
|
||||||
return customView.superView.SetAnimated(tag, value, animation)
|
return customView.superView.SetAnimated(tag, value, animation)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,10 +87,6 @@ func (customView *CustomViewData) Clear() {
|
||||||
customView.superView.Clear()
|
customView.superView.Clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initializes fields of View by default values
|
|
||||||
func (customView *CustomViewData) Init(session Session) {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (customView *CustomViewData) cssViewStyle(buffer cssBuilder, session Session) {
|
func (customView *CustomViewData) cssViewStyle(buffer cssBuilder, session Session) {
|
||||||
customView.superView.cssViewStyle(buffer, session)
|
customView.superView.cssViewStyle(buffer, session)
|
||||||
}
|
}
|
||||||
|
@ -264,9 +260,22 @@ func (customView *CustomViewData) setScroll(x, y, width, height float64) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (customView *CustomViewData) getTransitions() Params {
|
func (customView *CustomViewData) Transition(tag string) Animation {
|
||||||
if customView.superView != nil {
|
if customView.superView != nil {
|
||||||
return customView.superView.getTransitions()
|
return customView.superView.Transition(tag)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (customView *CustomViewData) Transitions() map[string]Animation {
|
||||||
|
if customView.superView != nil {
|
||||||
|
return customView.superView.Transitions()
|
||||||
|
}
|
||||||
|
return map[string]Animation{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (customView *CustomViewData) SetTransition(tag string, animation Animation) {
|
||||||
|
if customView.superView != nil {
|
||||||
|
customView.superView.SetTransition(tag, animation)
|
||||||
}
|
}
|
||||||
return Params{}
|
|
||||||
}
|
}
|
||||||
|
|
141
datePicker.go
141
datePicker.go
|
@ -29,7 +29,7 @@ type datePickerData struct {
|
||||||
// NewDatePicker create new DatePicker object and return it
|
// NewDatePicker create new DatePicker object and return it
|
||||||
func NewDatePicker(session Session, params Params) DatePicker {
|
func NewDatePicker(session Session, params Params) DatePicker {
|
||||||
view := new(datePickerData)
|
view := new(datePickerData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -38,8 +38,8 @@ func newDatePicker(session Session) View {
|
||||||
return NewDatePicker(session, nil)
|
return NewDatePicker(session, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *datePickerData) Init(session Session) {
|
func (picker *datePickerData) init(session Session) {
|
||||||
picker.viewData.Init(session)
|
picker.viewData.init(session)
|
||||||
picker.tag = "DatePicker"
|
picker.tag = "DatePicker"
|
||||||
picker.dateChangedListeners = []func(DatePicker, time.Time){}
|
picker.dateChangedListeners = []func(DatePicker, time.Time){}
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ func (picker *datePickerData) remove(tag string) {
|
||||||
case DatePickerValue:
|
case DatePickerValue:
|
||||||
if _, ok := picker.properties[DatePickerValue]; ok {
|
if _, ok := picker.properties[DatePickerValue]; ok {
|
||||||
delete(picker.properties, DatePickerValue)
|
delete(picker.properties, DatePickerValue)
|
||||||
date := GetDatePickerValue(picker, "")
|
date := GetDatePickerValue(picker)
|
||||||
if picker.created {
|
if picker.created {
|
||||||
picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), date.Format(dateFormat)))
|
picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), date.Format(dateFormat)))
|
||||||
}
|
}
|
||||||
|
@ -114,11 +114,11 @@ func (picker *datePickerData) remove(tag string) {
|
||||||
picker.propertyChangedEvent(tag)
|
picker.propertyChangedEvent(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *datePickerData) Set(tag string, value interface{}) bool {
|
func (picker *datePickerData) Set(tag string, value any) bool {
|
||||||
return picker.set(picker.normalizeTag(tag), value)
|
return picker.set(picker.normalizeTag(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *datePickerData) set(tag string, value interface{}) bool {
|
func (picker *datePickerData) set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
picker.remove(tag)
|
picker.remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -204,9 +204,9 @@ func (picker *datePickerData) set(tag string, value interface{}) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
case DatePickerStep:
|
case DatePickerStep:
|
||||||
oldStep := GetDatePickerStep(picker, "")
|
oldStep := GetDatePickerStep(picker)
|
||||||
if picker.setIntProperty(DatePickerStep, value) {
|
if picker.setIntProperty(DatePickerStep, value) {
|
||||||
if step := GetDatePickerStep(picker, ""); oldStep != step {
|
if step := GetDatePickerStep(picker); oldStep != step {
|
||||||
if picker.created {
|
if picker.created {
|
||||||
if step > 0 {
|
if step > 0 {
|
||||||
updateProperty(picker.htmlID(), Step, strconv.Itoa(step), picker.session)
|
updateProperty(picker.htmlID(), Step, strconv.Itoa(step), picker.session)
|
||||||
|
@ -220,7 +220,7 @@ func (picker *datePickerData) set(tag string, value interface{}) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
case DatePickerValue:
|
case DatePickerValue:
|
||||||
oldDate := GetDatePickerValue(picker, "")
|
oldDate := GetDatePickerValue(picker)
|
||||||
if date, ok := setTimeValue(DatePickerValue); ok {
|
if date, ok := setTimeValue(DatePickerValue); ok {
|
||||||
if date != oldDate {
|
if date != oldDate {
|
||||||
if picker.created {
|
if picker.created {
|
||||||
|
@ -235,57 +235,14 @@ func (picker *datePickerData) set(tag string, value interface{}) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
case DateChangedEvent:
|
case DateChangedEvent:
|
||||||
switch value := value.(type) {
|
listeners, ok := valueToEventListeners[DatePicker, time.Time](value)
|
||||||
case func(DatePicker, time.Time):
|
if !ok {
|
||||||
picker.dateChangedListeners = []func(DatePicker, time.Time){value}
|
notCompatibleType(tag, value)
|
||||||
|
return false
|
||||||
case func(time.Time):
|
} else if listeners == nil {
|
||||||
fn := func(_ DatePicker, date time.Time) {
|
listeners = []func(DatePicker, time.Time){}
|
||||||
value(date)
|
|
||||||
}
|
|
||||||
picker.dateChangedListeners = []func(DatePicker, time.Time){fn}
|
|
||||||
|
|
||||||
case []func(DatePicker, time.Time):
|
|
||||||
picker.dateChangedListeners = value
|
|
||||||
|
|
||||||
case []func(time.Time):
|
|
||||||
listeners := make([]func(DatePicker, time.Time), len(value))
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
notCompatibleType(tag, val)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
listeners[i] = func(_ DatePicker, date time.Time) {
|
|
||||||
val(date)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
picker.dateChangedListeners = listeners
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
listeners := make([]func(DatePicker, time.Time), len(value))
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
notCompatibleType(tag, val)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
switch val := val.(type) {
|
|
||||||
case func(DatePicker, time.Time):
|
|
||||||
listeners[i] = val
|
|
||||||
|
|
||||||
case func(time.Time):
|
|
||||||
listeners[i] = func(_ DatePicker, date time.Time) {
|
|
||||||
val(date)
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
notCompatibleType(tag, val)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
picker.dateChangedListeners = listeners
|
|
||||||
}
|
}
|
||||||
|
picker.dateChangedListeners = listeners
|
||||||
picker.propertyChangedEvent(tag)
|
picker.propertyChangedEvent(tag)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
@ -295,11 +252,11 @@ func (picker *datePickerData) set(tag string, value interface{}) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *datePickerData) Get(tag string) interface{} {
|
func (picker *datePickerData) Get(tag string) any {
|
||||||
return picker.get(picker.normalizeTag(tag))
|
return picker.get(picker.normalizeTag(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *datePickerData) get(tag string) interface{} {
|
func (picker *datePickerData) get(tag string) any {
|
||||||
switch tag {
|
switch tag {
|
||||||
case DateChangedEvent:
|
case DateChangedEvent:
|
||||||
return picker.dateChangedListeners
|
return picker.dateChangedListeners
|
||||||
|
@ -337,7 +294,7 @@ func (picker *datePickerData) htmlProperties(self View, buffer *strings.Builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.WriteString(` value="`)
|
buffer.WriteString(` value="`)
|
||||||
buffer.WriteString(GetDatePickerValue(picker, "").Format(dateFormat))
|
buffer.WriteString(GetDatePickerValue(picker).Format(dateFormat))
|
||||||
buffer.WriteByte('"')
|
buffer.WriteByte('"')
|
||||||
|
|
||||||
buffer.WriteString(` oninput="editViewInputEvent(this)"`)
|
buffer.WriteString(` oninput="editViewInputEvent(this)"`)
|
||||||
|
@ -347,7 +304,7 @@ func (picker *datePickerData) htmlProperties(self View, buffer *strings.Builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *datePickerData) htmlDisabledProperties(self View, buffer *strings.Builder) {
|
func (picker *datePickerData) htmlDisabledProperties(self View, buffer *strings.Builder) {
|
||||||
if IsDisabled(self, "") {
|
if IsDisabled(self) {
|
||||||
buffer.WriteString(` disabled`)
|
buffer.WriteString(` disabled`)
|
||||||
}
|
}
|
||||||
picker.viewData.htmlDisabledProperties(self, buffer)
|
picker.viewData.htmlDisabledProperties(self, buffer)
|
||||||
|
@ -358,7 +315,7 @@ func (picker *datePickerData) handleCommand(self View, command string, data Data
|
||||||
case "textChanged":
|
case "textChanged":
|
||||||
if text, ok := data.PropertyValue("text"); ok {
|
if text, ok := data.PropertyValue("text"); ok {
|
||||||
if value, err := time.Parse(dateFormat, text); err == nil {
|
if value, err := time.Parse(dateFormat, text); err == nil {
|
||||||
oldValue := GetDatePickerValue(picker, "")
|
oldValue := GetDatePickerValue(picker)
|
||||||
picker.properties[DatePickerValue] = value
|
picker.properties[DatePickerValue] = value
|
||||||
if value != oldValue {
|
if value != oldValue {
|
||||||
for _, listener := range picker.dateChangedListeners {
|
for _, listener := range picker.dateChangedListeners {
|
||||||
|
@ -374,7 +331,7 @@ func (picker *datePickerData) handleCommand(self View, command string, data Data
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDateProperty(view View, mainTag, shortTag string) (time.Time, bool) {
|
func getDateProperty(view View, mainTag, shortTag string) (time.Time, bool) {
|
||||||
valueToTime := func(value interface{}) (time.Time, bool) {
|
valueToTime := func(value any) (time.Time, bool) {
|
||||||
if value != nil {
|
if value != nil {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case time.Time:
|
case time.Time:
|
||||||
|
@ -408,10 +365,10 @@ func getDateProperty(view View, mainTag, shortTag string) (time.Time, bool) {
|
||||||
|
|
||||||
// GetDatePickerMin returns the min date of DatePicker subview and "true" as the second value if the min date is set,
|
// GetDatePickerMin returns the min date of DatePicker subview and "true" as the second value if the min date is set,
|
||||||
// "false" as the second value otherwise.
|
// "false" as the second value otherwise.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetDatePickerMin(view View, subviewID string) (time.Time, bool) {
|
func GetDatePickerMin(view View, subviewID ...string) (time.Time, bool) {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view != nil {
|
if view != nil {
|
||||||
return getDateProperty(view, DatePickerMin, Min)
|
return getDateProperty(view, DatePickerMin, Min)
|
||||||
|
@ -421,10 +378,10 @@ func GetDatePickerMin(view View, subviewID string) (time.Time, bool) {
|
||||||
|
|
||||||
// GetDatePickerMax returns the max date of DatePicker subview and "true" as the second value if the min date is set,
|
// GetDatePickerMax returns the max date of DatePicker subview and "true" as the second value if the min date is set,
|
||||||
// "false" as the second value otherwise.
|
// "false" as the second value otherwise.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetDatePickerMax(view View, subviewID string) (time.Time, bool) {
|
func GetDatePickerMax(view View, subviewID ...string) (time.Time, bool) {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view != nil {
|
if view != nil {
|
||||||
return getDateProperty(view, DatePickerMax, Max)
|
return getDateProperty(view, DatePickerMax, Max)
|
||||||
|
@ -433,24 +390,16 @@ func GetDatePickerMax(view View, subviewID string) (time.Time, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDatePickerStep returns the date changing step in days of DatePicker subview.
|
// GetDatePickerStep returns the date changing step in days of DatePicker subview.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetDatePickerStep(view View, subviewID string) int {
|
func GetDatePickerStep(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return intStyledProperty(view, subviewID, DatePickerStep, 0)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if result, _ := intStyledProperty(view, DatePickerStep, 0); result >= 0 {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDatePickerValue returns the date of DatePicker subview.
|
// GetDatePickerValue returns the date of DatePicker subview.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetDatePickerValue(view View, subviewID string) time.Time {
|
func GetDatePickerValue(view View, subviewID ...string) time.Time {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view == nil {
|
if view == nil {
|
||||||
return time.Now()
|
return time.Now()
|
||||||
|
@ -461,17 +410,7 @@ func GetDatePickerValue(view View, subviewID string) time.Time {
|
||||||
|
|
||||||
// GetDateChangedListeners returns the DateChangedListener list of an DatePicker subview.
|
// GetDateChangedListeners returns the DateChangedListener list of an DatePicker subview.
|
||||||
// If there are no listeners then the empty list is returned
|
// If there are no listeners then the empty list is returned
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetDateChangedListeners(view View, subviewID string) []func(DatePicker, time.Time) {
|
func GetDateChangedListeners(view View, subviewID ...string) []func(DatePicker, time.Time) {
|
||||||
if subviewID != "" {
|
return getEventListeners[DatePicker, time.Time](view, subviewID, DateChangedEvent)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if value := view.Get(DateChangedEvent); value != nil {
|
|
||||||
if listeners, ok := value.([]func(DatePicker, time.Time)); ok {
|
|
||||||
return listeners
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []func(DatePicker, time.Time){}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,8 @@ theme {
|
||||||
ruiTabHeight = 32px,
|
ruiTabHeight = 32px,
|
||||||
ruiTabBarPadding = 2px,
|
ruiTabBarPadding = 2px,
|
||||||
ruiTabRadius = 2px,
|
ruiTabRadius = 2px,
|
||||||
|
ruiArrowSize = 16px,
|
||||||
|
ruiArrowWidth = 16px,
|
||||||
},
|
},
|
||||||
constants:touch = _{
|
constants:touch = _{
|
||||||
ruiButtonHorizontalPadding = 20px,
|
ruiButtonHorizontalPadding = 20px,
|
||||||
|
@ -72,6 +74,7 @@ theme {
|
||||||
text-size = 10pt,
|
text-size = 10pt,
|
||||||
text-color = @ruiTextColor,
|
text-color = @ruiTextColor,
|
||||||
background-color = @ruiBackgroundColor,
|
background-color = @ruiBackgroundColor,
|
||||||
|
accent-color = @ruiHighlightColor,
|
||||||
},
|
},
|
||||||
ruiButton {
|
ruiButton {
|
||||||
align = center,
|
align = center,
|
||||||
|
@ -216,7 +219,6 @@ theme {
|
||||||
background-color = @ruiPopupBackgroundColor,
|
background-color = @ruiPopupBackgroundColor,
|
||||||
text-color = @ruiPopupTextColor,
|
text-color = @ruiPopupTextColor,
|
||||||
radius = 4px,
|
radius = 4px,
|
||||||
shadow = _{spread-radius=4px, blur=16px, color=@ruiPopupShadow },
|
|
||||||
},
|
},
|
||||||
ruiPopupTitle {
|
ruiPopupTitle {
|
||||||
background-color = @ruiPopupTitleColor,
|
background-color = @ruiPopupTitleColor,
|
||||||
|
|
|
@ -24,7 +24,7 @@ type detailsViewData struct {
|
||||||
// NewDetailsView create new DetailsView object and return it
|
// NewDetailsView create new DetailsView object and return it
|
||||||
func NewDetailsView(session Session, params Params) DetailsView {
|
func NewDetailsView(session Session, params Params) DetailsView {
|
||||||
view := new(detailsViewData)
|
view := new(detailsViewData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -34,8 +34,8 @@ func newDetailsView(session Session) View {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initialize fields of DetailsView by default values
|
// Init initialize fields of DetailsView by default values
|
||||||
func (detailsView *detailsViewData) Init(session Session) {
|
func (detailsView *detailsViewData) init(session Session) {
|
||||||
detailsView.viewsContainerData.Init(session)
|
detailsView.viewsContainerData.init(session)
|
||||||
detailsView.tag = "DetailsView"
|
detailsView.tag = "DetailsView"
|
||||||
//detailsView.systemClass = "ruiDetailsView"
|
//detailsView.systemClass = "ruiDetailsView"
|
||||||
}
|
}
|
||||||
|
@ -68,11 +68,11 @@ func (detailsView *detailsViewData) remove(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (detailsView *detailsViewData) Set(tag string, value interface{}) bool {
|
func (detailsView *detailsViewData) Set(tag string, value any) bool {
|
||||||
return detailsView.set(strings.ToLower(tag), value)
|
return detailsView.set(strings.ToLower(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (detailsView *detailsViewData) set(tag string, value interface{}) bool {
|
func (detailsView *detailsViewData) set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
detailsView.remove(tag)
|
detailsView.remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -110,7 +110,7 @@ func (detailsView *detailsViewData) set(tag string, value interface{}) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if detailsView.created {
|
if detailsView.created {
|
||||||
if IsDetailsExpanded(detailsView, "") {
|
if IsDetailsExpanded(detailsView) {
|
||||||
updateProperty(detailsView.htmlID(), "open", "", detailsView.Session())
|
updateProperty(detailsView.htmlID(), "open", "", detailsView.Session())
|
||||||
} else {
|
} else {
|
||||||
removeProperty(detailsView.htmlID(), "open", detailsView.Session())
|
removeProperty(detailsView.htmlID(), "open", detailsView.Session())
|
||||||
|
@ -133,11 +133,11 @@ func (detailsView *detailsViewData) set(tag string, value interface{}) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (detailsView *detailsViewData) Get(tag string) interface{} {
|
func (detailsView *detailsViewData) Get(tag string) any {
|
||||||
return detailsView.get(strings.ToLower(tag))
|
return detailsView.get(strings.ToLower(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (detailsView *detailsViewData) get(tag string) interface{} {
|
func (detailsView *detailsViewData) get(tag string) any {
|
||||||
return detailsView.viewsContainerData.get(tag)
|
return detailsView.viewsContainerData.get(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ func (detailsView *detailsViewData) htmlTag() string {
|
||||||
func (detailsView *detailsViewData) htmlProperties(self View, buffer *strings.Builder) {
|
func (detailsView *detailsViewData) htmlProperties(self View, buffer *strings.Builder) {
|
||||||
detailsView.viewsContainerData.htmlProperties(self, buffer)
|
detailsView.viewsContainerData.htmlProperties(self, buffer)
|
||||||
buffer.WriteString(` ontoggle="detailsEvent(this)"`)
|
buffer.WriteString(` ontoggle="detailsEvent(this)"`)
|
||||||
if IsDetailsExpanded(detailsView, "") {
|
if IsDetailsExpanded(detailsView) {
|
||||||
buffer.WriteString(` open`)
|
buffer.WriteString(` open`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,7 +157,7 @@ func (detailsView *detailsViewData) htmlSubviews(self View, buffer *strings.Buil
|
||||||
if value, ok := detailsView.properties[Summary]; ok {
|
if value, ok := detailsView.properties[Summary]; ok {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case string:
|
case string:
|
||||||
if !GetNotTranslate(detailsView, "") {
|
if !GetNotTranslate(detailsView) {
|
||||||
value, _ = detailsView.session.GetString(value)
|
value, _ = detailsView.session.GetString(value)
|
||||||
}
|
}
|
||||||
buffer.WriteString("<summary>")
|
buffer.WriteString("<summary>")
|
||||||
|
@ -186,10 +186,10 @@ func (detailsView *detailsViewData) handleCommand(self View, command string, dat
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDetailsSummary returns a value of the Summary property of DetailsView.
|
// GetDetailsSummary returns a value of the Summary property of DetailsView.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetDetailsSummary(view View, subviewID string) View {
|
func GetDetailsSummary(view View, subviewID ...string) View {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view != nil {
|
if view != nil {
|
||||||
if value := view.Get(Summary); value != nil {
|
if value := view.Get(Summary); value != nil {
|
||||||
|
@ -206,15 +206,7 @@ func GetDetailsSummary(view View, subviewID string) View {
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsDetailsExpanded returns a value of the Expanded property of DetailsView.
|
// IsDetailsExpanded returns a value of the Expanded property of DetailsView.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func IsDetailsExpanded(view View, subviewID string) bool {
|
func IsDetailsExpanded(view View, subviewID ...string) bool {
|
||||||
if subviewID != "" {
|
return boolStyledProperty(view, subviewID, Expanded, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if result, ok := boolStyledProperty(view, Expanded); ok {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
154
dropDownList.go
154
dropDownList.go
|
@ -6,6 +6,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DropDownEvent is the constant for "drop-down-event" property tag.
|
||||||
|
// The "drop-down-event" event occurs when a list item becomes selected.
|
||||||
|
// The main listener format: func(DropDownList, int), where the second argument is the item index.
|
||||||
const DropDownEvent = "drop-down-event"
|
const DropDownEvent = "drop-down-event"
|
||||||
|
|
||||||
// DropDownList - the interface of a drop-down list view
|
// DropDownList - the interface of a drop-down list view
|
||||||
|
@ -17,14 +20,14 @@ type DropDownList interface {
|
||||||
type dropDownListData struct {
|
type dropDownListData struct {
|
||||||
viewData
|
viewData
|
||||||
items []string
|
items []string
|
||||||
disabledItems []interface{}
|
disabledItems []any
|
||||||
dropDownListener []func(DropDownList, int)
|
dropDownListener []func(DropDownList, int)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDropDownList create new DropDownList object and return it
|
// NewDropDownList create new DropDownList object and return it
|
||||||
func NewDropDownList(session Session, params Params) DropDownList {
|
func NewDropDownList(session Session, params Params) DropDownList {
|
||||||
view := new(dropDownListData)
|
view := new(dropDownListData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -33,11 +36,11 @@ func newDropDownList(session Session) View {
|
||||||
return NewDropDownList(session, nil)
|
return NewDropDownList(session, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *dropDownListData) Init(session Session) {
|
func (list *dropDownListData) init(session Session) {
|
||||||
list.viewData.Init(session)
|
list.viewData.init(session)
|
||||||
list.tag = "DropDownList"
|
list.tag = "DropDownList"
|
||||||
list.items = []string{}
|
list.items = []string{}
|
||||||
list.disabledItems = []interface{}{}
|
list.disabledItems = []any{}
|
||||||
list.dropDownListener = []func(DropDownList, int){}
|
list.dropDownListener = []func(DropDownList, int){}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +69,7 @@ func (list *dropDownListData) remove(tag string) {
|
||||||
|
|
||||||
case DisabledItems:
|
case DisabledItems:
|
||||||
if len(list.disabledItems) > 0 {
|
if len(list.disabledItems) > 0 {
|
||||||
list.disabledItems = []interface{}{}
|
list.disabledItems = []any{}
|
||||||
if list.created {
|
if list.created {
|
||||||
updateInnerHTML(list.htmlID(), list.session)
|
updateInnerHTML(list.htmlID(), list.session)
|
||||||
}
|
}
|
||||||
|
@ -80,7 +83,7 @@ func (list *dropDownListData) remove(tag string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case Current:
|
case Current:
|
||||||
oldCurrent := GetCurrent(list, "")
|
oldCurrent := GetCurrent(list)
|
||||||
delete(list.properties, Current)
|
delete(list.properties, Current)
|
||||||
if oldCurrent != 0 {
|
if oldCurrent != 0 {
|
||||||
if list.created {
|
if list.created {
|
||||||
|
@ -95,11 +98,11 @@ func (list *dropDownListData) remove(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *dropDownListData) Set(tag string, value interface{}) bool {
|
func (list *dropDownListData) Set(tag string, value any) bool {
|
||||||
return list.set(strings.ToLower(tag), value)
|
return list.set(strings.ToLower(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *dropDownListData) set(tag string, value interface{}) bool {
|
func (list *dropDownListData) set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
list.remove(tag)
|
list.remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -113,15 +116,24 @@ func (list *dropDownListData) set(tag string, value interface{}) bool {
|
||||||
return list.setDisabledItems(value)
|
return list.setDisabledItems(value)
|
||||||
|
|
||||||
case DropDownEvent:
|
case DropDownEvent:
|
||||||
return list.setDropDownListener(value)
|
listeners, ok := valueToEventListeners[DropDownList, int](value)
|
||||||
|
if !ok {
|
||||||
|
notCompatibleType(tag, value)
|
||||||
|
return false
|
||||||
|
} else if listeners == nil {
|
||||||
|
listeners = []func(DropDownList, int){}
|
||||||
|
}
|
||||||
|
list.dropDownListener = listeners
|
||||||
|
list.propertyChangedEvent(tag)
|
||||||
|
return true
|
||||||
|
|
||||||
case Current:
|
case Current:
|
||||||
oldCurrent := GetCurrent(list, "")
|
oldCurrent := GetCurrent(list)
|
||||||
if !list.setIntProperty(Current, value) {
|
if !list.setIntProperty(Current, value) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if current := GetCurrent(list, ""); oldCurrent != current {
|
if current := GetCurrent(list); oldCurrent != current {
|
||||||
if list.created {
|
if list.created {
|
||||||
list.session.runScript(fmt.Sprintf(`selectDropDownListItem('%s', %d)`, list.htmlID(), current))
|
list.session.runScript(fmt.Sprintf(`selectDropDownListItem('%s', %d)`, list.htmlID(), current))
|
||||||
}
|
}
|
||||||
|
@ -133,7 +145,7 @@ func (list *dropDownListData) set(tag string, value interface{}) bool {
|
||||||
return list.viewData.set(tag, value)
|
return list.viewData.set(tag, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *dropDownListData) setItems(value interface{}) bool {
|
func (list *dropDownListData) setItems(value any) bool {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case string:
|
case string:
|
||||||
list.items = []string{value}
|
list.items = []string{value}
|
||||||
|
@ -155,7 +167,7 @@ func (list *dropDownListData) setItems(value interface{}) bool {
|
||||||
list.items[i] = str.String()
|
list.items[i] = str.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
case []interface{}:
|
case []any:
|
||||||
items := make([]string, 0, len(value))
|
items := make([]string, 0, len(value))
|
||||||
for _, v := range value {
|
for _, v := range value {
|
||||||
switch val := v.(type) {
|
switch val := v.(type) {
|
||||||
|
@ -206,16 +218,16 @@ func (list *dropDownListData) setItems(value interface{}) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *dropDownListData) setDisabledItems(value interface{}) bool {
|
func (list *dropDownListData) setDisabledItems(value any) bool {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case []int:
|
case []int:
|
||||||
list.disabledItems = make([]interface{}, len(value))
|
list.disabledItems = make([]any, len(value))
|
||||||
for i, n := range value {
|
for i, n := range value {
|
||||||
list.disabledItems[i] = n
|
list.disabledItems[i] = n
|
||||||
}
|
}
|
||||||
|
|
||||||
case []interface{}:
|
case []any:
|
||||||
disabledItems := make([]interface{}, len(value))
|
disabledItems := make([]any, len(value))
|
||||||
for i, val := range value {
|
for i, val := range value {
|
||||||
if val == nil {
|
if val == nil {
|
||||||
notCompatibleType(DisabledItems, value)
|
notCompatibleType(DisabledItems, value)
|
||||||
|
@ -248,7 +260,7 @@ func (list *dropDownListData) setDisabledItems(value interface{}) bool {
|
||||||
|
|
||||||
case string:
|
case string:
|
||||||
values := strings.Split(value, ",")
|
values := strings.Split(value, ",")
|
||||||
disabledItems := make([]interface{}, len(values))
|
disabledItems := make([]any, len(values))
|
||||||
for i, str := range values {
|
for i, str := range values {
|
||||||
str = strings.Trim(str, " ")
|
str = strings.Trim(str, " ")
|
||||||
if str == "" {
|
if str == "" {
|
||||||
|
@ -291,69 +303,11 @@ func (list *dropDownListData) setDisabledItems(value interface{}) bool {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *dropDownListData) setDropDownListener(value interface{}) bool {
|
func (list *dropDownListData) Get(tag string) any {
|
||||||
switch value := value.(type) {
|
|
||||||
case func(DropDownList, int):
|
|
||||||
list.dropDownListener = []func(DropDownList, int){value}
|
|
||||||
|
|
||||||
case func(int):
|
|
||||||
list.dropDownListener = []func(DropDownList, int){func(_ DropDownList, index int) {
|
|
||||||
value(index)
|
|
||||||
}}
|
|
||||||
|
|
||||||
case []func(DropDownList, int):
|
|
||||||
list.dropDownListener = value
|
|
||||||
|
|
||||||
case []func(int):
|
|
||||||
listeners := make([]func(DropDownList, int), len(value))
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
notCompatibleType(DropDownEvent, value)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
listeners[i] = func(_ DropDownList, index int) {
|
|
||||||
val(index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list.dropDownListener = listeners
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
listeners := make([]func(DropDownList, int), len(value))
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
notCompatibleType(DropDownEvent, value)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
switch val := val.(type) {
|
|
||||||
case func(DropDownList, int):
|
|
||||||
listeners[i] = val
|
|
||||||
|
|
||||||
case func(int):
|
|
||||||
listeners[i] = func(_ DropDownList, index int) {
|
|
||||||
val(index)
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
notCompatibleType(DropDownEvent, value)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list.dropDownListener = listeners
|
|
||||||
|
|
||||||
default:
|
|
||||||
notCompatibleType(DropDownEvent, value)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
list.propertyChangedEvent(DropDownEvent)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (list *dropDownListData) Get(tag string) interface{} {
|
|
||||||
return list.get(strings.ToLower(tag))
|
return list.get(strings.ToLower(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *dropDownListData) get(tag string) interface{} {
|
func (list *dropDownListData) get(tag string) any {
|
||||||
switch tag {
|
switch tag {
|
||||||
case Items:
|
case Items:
|
||||||
return list.items
|
return list.items
|
||||||
|
@ -382,9 +336,9 @@ func (list *dropDownListData) htmlTag() string {
|
||||||
|
|
||||||
func (list *dropDownListData) htmlSubviews(self View, buffer *strings.Builder) {
|
func (list *dropDownListData) htmlSubviews(self View, buffer *strings.Builder) {
|
||||||
if list.items != nil {
|
if list.items != nil {
|
||||||
current := GetCurrent(list, "")
|
current := GetCurrent(list)
|
||||||
notTranslate := GetNotTranslate(list, "")
|
notTranslate := GetNotTranslate(list)
|
||||||
disabledItems := GetDropDownDisabledItems(list, "")
|
disabledItems := GetDropDownDisabledItems(list)
|
||||||
for i, item := range list.items {
|
for i, item := range list.items {
|
||||||
disabled := false
|
disabled := false
|
||||||
for _, index := range disabledItems {
|
for _, index := range disabledItems {
|
||||||
|
@ -418,7 +372,7 @@ func (list *dropDownListData) htmlProperties(self View, buffer *strings.Builder)
|
||||||
|
|
||||||
func (list *dropDownListData) htmlDisabledProperties(self View, buffer *strings.Builder) {
|
func (list *dropDownListData) htmlDisabledProperties(self View, buffer *strings.Builder) {
|
||||||
list.viewData.htmlDisabledProperties(self, buffer)
|
list.viewData.htmlDisabledProperties(self, buffer)
|
||||||
if IsDisabled(list, "") {
|
if IsDisabled(list) {
|
||||||
buffer.WriteString(`disabled`)
|
buffer.WriteString(`disabled`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -435,7 +389,7 @@ func (list *dropDownListData) handleCommand(self View, command string, data Data
|
||||||
case "itemSelected":
|
case "itemSelected":
|
||||||
if text, ok := data.PropertyValue("number"); ok {
|
if text, ok := data.PropertyValue("number"); ok {
|
||||||
if number, err := strconv.Atoi(text); err == nil {
|
if number, err := strconv.Atoi(text); err == nil {
|
||||||
if GetCurrent(list, "") != number && number >= 0 && number < len(list.items) {
|
if GetCurrent(list) != number && number >= 0 && number < len(list.items) {
|
||||||
list.properties[Current] = number
|
list.properties[Current] = number
|
||||||
list.onSelectedItemChanged(number)
|
list.onSelectedItemChanged(number)
|
||||||
}
|
}
|
||||||
|
@ -450,19 +404,17 @@ func (list *dropDownListData) handleCommand(self View, command string, data Data
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDropDownListeners(view View) []func(DropDownList, int) {
|
// GetDropDownListeners returns the "drop-down-event" listener list. If there are no listeners then the empty list is returned.
|
||||||
if value := view.Get(DropDownEvent); value != nil {
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
if listeners, ok := value.([]func(DropDownList, int)); ok {
|
func GetDropDownListeners(view View, subviewID ...string) []func(DropDownList, int) {
|
||||||
return listeners
|
return getEventListeners[DropDownList, int](view, subviewID, DropDownEvent)
|
||||||
}
|
|
||||||
}
|
|
||||||
return []func(DropDownList, int){}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// func GetDropDownItems return the view items list
|
// GetDropDownItems return the DropDownList items list.
|
||||||
func GetDropDownItems(view View, subviewID string) []string {
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
if subviewID != "" {
|
func GetDropDownItems(view View, subviewID ...string) []string {
|
||||||
view = ViewByID(view, subviewID)
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view != nil {
|
if view != nil {
|
||||||
if list, ok := view.(DropDownList); ok {
|
if list, ok := view.(DropDownList); ok {
|
||||||
|
@ -472,14 +424,16 @@ func GetDropDownItems(view View, subviewID string) []string {
|
||||||
return []string{}
|
return []string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// func GetDropDownDisabledItems return the list of disabled item indexes
|
// GetDropDownDisabledItems return the list of DropDownList disabled item indexes.
|
||||||
func GetDropDownDisabledItems(view View, subviewID string) []int {
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
if subviewID != "" {
|
func GetDropDownDisabledItems(view View, subviewID ...string) []int {
|
||||||
view = ViewByID(view, subviewID)
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
if view != nil {
|
if view != nil {
|
||||||
if value := view.Get(DisabledItems); value != nil {
|
if value := view.Get(DisabledItems); value != nil {
|
||||||
if values, ok := value.([]interface{}); ok {
|
if values, ok := value.([]any); ok {
|
||||||
count := len(values)
|
count := len(values)
|
||||||
if count > 0 {
|
if count > 0 {
|
||||||
result := make([]int, 0, count)
|
result := make([]int, 0, count)
|
||||||
|
|
279
editView.go
279
editView.go
|
@ -48,7 +48,7 @@ type editViewData struct {
|
||||||
// NewEditView create new EditView object and return it
|
// NewEditView create new EditView object and return it
|
||||||
func NewEditView(session Session, params Params) EditView {
|
func NewEditView(session Session, params Params) EditView {
|
||||||
view := new(editViewData)
|
view := new(editViewData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -57,8 +57,8 @@ func newEditView(session Session) View {
|
||||||
return NewEditView(session, nil)
|
return NewEditView(session, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (edit *editViewData) Init(session Session) {
|
func (edit *editViewData) init(session Session) {
|
||||||
edit.viewData.Init(session)
|
edit.viewData.init(session)
|
||||||
edit.textChangeListeners = []func(EditView, string){}
|
edit.textChangeListeners = []func(EditView, string){}
|
||||||
edit.tag = "EditView"
|
edit.tag = "EditView"
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ func (edit *editViewData) remove(tag string) {
|
||||||
|
|
||||||
case Text:
|
case Text:
|
||||||
if exists {
|
if exists {
|
||||||
oldText := GetText(edit, "")
|
oldText := GetText(edit)
|
||||||
delete(edit.properties, tag)
|
delete(edit.properties, tag)
|
||||||
if oldText != "" {
|
if oldText != "" {
|
||||||
edit.textChanged("")
|
edit.textChanged("")
|
||||||
|
@ -144,7 +144,7 @@ func (edit *editViewData) remove(tag string) {
|
||||||
|
|
||||||
case EditViewPattern:
|
case EditViewPattern:
|
||||||
if exists {
|
if exists {
|
||||||
oldText := GetEditViewPattern(edit, "")
|
oldText := GetEditViewPattern(edit)
|
||||||
delete(edit.properties, tag)
|
delete(edit.properties, tag)
|
||||||
if oldText != "" {
|
if oldText != "" {
|
||||||
if edit.created {
|
if edit.created {
|
||||||
|
@ -156,7 +156,7 @@ func (edit *editViewData) remove(tag string) {
|
||||||
|
|
||||||
case EditViewType:
|
case EditViewType:
|
||||||
if exists {
|
if exists {
|
||||||
oldType := GetEditViewType(edit, "")
|
oldType := GetEditViewType(edit)
|
||||||
delete(edit.properties, tag)
|
delete(edit.properties, tag)
|
||||||
if oldType != 0 {
|
if oldType != 0 {
|
||||||
if edit.created {
|
if edit.created {
|
||||||
|
@ -168,10 +168,10 @@ func (edit *editViewData) remove(tag string) {
|
||||||
|
|
||||||
case EditWrap:
|
case EditWrap:
|
||||||
if exists {
|
if exists {
|
||||||
oldWrap := IsEditViewWrap(edit, "")
|
oldWrap := IsEditViewWrap(edit)
|
||||||
delete(edit.properties, tag)
|
delete(edit.properties, tag)
|
||||||
if GetEditViewType(edit, "") == MultiLineText {
|
if GetEditViewType(edit) == MultiLineText {
|
||||||
if wrap := IsEditViewWrap(edit, ""); wrap != oldWrap {
|
if wrap := IsEditViewWrap(edit); wrap != oldWrap {
|
||||||
if edit.created {
|
if edit.created {
|
||||||
if wrap {
|
if wrap {
|
||||||
updateProperty(edit.htmlID(), "wrap", "soft", edit.session)
|
updateProperty(edit.htmlID(), "wrap", "soft", edit.session)
|
||||||
|
@ -190,11 +190,11 @@ func (edit *editViewData) remove(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (edit *editViewData) Set(tag string, value interface{}) bool {
|
func (edit *editViewData) Set(tag string, value any) bool {
|
||||||
return edit.set(edit.normalizeTag(tag), value)
|
return edit.set(edit.normalizeTag(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (edit *editViewData) set(tag string, value interface{}) bool {
|
func (edit *editViewData) set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
edit.remove(tag)
|
edit.remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -202,13 +202,13 @@ func (edit *editViewData) set(tag string, value interface{}) bool {
|
||||||
|
|
||||||
switch tag {
|
switch tag {
|
||||||
case Text:
|
case Text:
|
||||||
oldText := GetText(edit, "")
|
oldText := GetText(edit)
|
||||||
if text, ok := value.(string); ok {
|
if text, ok := value.(string); ok {
|
||||||
edit.properties[Text] = text
|
edit.properties[Text] = text
|
||||||
if text = GetText(edit, ""); oldText != text {
|
if text = GetText(edit); oldText != text {
|
||||||
edit.textChanged(text)
|
edit.textChanged(text)
|
||||||
if edit.created {
|
if edit.created {
|
||||||
if GetEditViewType(edit, "") == MultiLineText {
|
if GetEditViewType(edit) == MultiLineText {
|
||||||
updateInnerHTML(edit.htmlID(), edit.Session())
|
updateInnerHTML(edit.htmlID(), edit.Session())
|
||||||
} else {
|
} else {
|
||||||
text = strings.ReplaceAll(text, `"`, `\"`)
|
text = strings.ReplaceAll(text, `"`, `\"`)
|
||||||
|
@ -224,10 +224,10 @@ func (edit *editViewData) set(tag string, value interface{}) bool {
|
||||||
return false
|
return false
|
||||||
|
|
||||||
case Hint:
|
case Hint:
|
||||||
oldText := GetHint(edit, "")
|
oldText := GetHint(edit)
|
||||||
if text, ok := value.(string); ok {
|
if text, ok := value.(string); ok {
|
||||||
edit.properties[Hint] = text
|
edit.properties[Hint] = text
|
||||||
if text = GetHint(edit, ""); oldText != text {
|
if text = GetHint(edit); oldText != text {
|
||||||
if edit.created {
|
if edit.created {
|
||||||
if text != "" {
|
if text != "" {
|
||||||
updateProperty(edit.htmlID(), "placeholder", text, edit.session)
|
updateProperty(edit.htmlID(), "placeholder", text, edit.session)
|
||||||
|
@ -242,9 +242,9 @@ func (edit *editViewData) set(tag string, value interface{}) bool {
|
||||||
return false
|
return false
|
||||||
|
|
||||||
case MaxLength:
|
case MaxLength:
|
||||||
oldMaxLength := GetMaxLength(edit, "")
|
oldMaxLength := GetMaxLength(edit)
|
||||||
if edit.setIntProperty(MaxLength, value) {
|
if edit.setIntProperty(MaxLength, value) {
|
||||||
if maxLength := GetMaxLength(edit, ""); maxLength != oldMaxLength {
|
if maxLength := GetMaxLength(edit); maxLength != oldMaxLength {
|
||||||
if edit.created {
|
if edit.created {
|
||||||
if maxLength > 0 {
|
if maxLength > 0 {
|
||||||
updateProperty(edit.htmlID(), "maxlength", strconv.Itoa(maxLength), edit.session)
|
updateProperty(edit.htmlID(), "maxlength", strconv.Itoa(maxLength), edit.session)
|
||||||
|
@ -261,7 +261,7 @@ func (edit *editViewData) set(tag string, value interface{}) bool {
|
||||||
case ReadOnly:
|
case ReadOnly:
|
||||||
if edit.setBoolProperty(ReadOnly, value) {
|
if edit.setBoolProperty(ReadOnly, value) {
|
||||||
if edit.created {
|
if edit.created {
|
||||||
if IsReadOnly(edit, "") {
|
if IsReadOnly(edit) {
|
||||||
updateProperty(edit.htmlID(), ReadOnly, "", edit.session)
|
updateProperty(edit.htmlID(), ReadOnly, "", edit.session)
|
||||||
} else {
|
} else {
|
||||||
removeProperty(edit.htmlID(), ReadOnly, edit.session)
|
removeProperty(edit.htmlID(), ReadOnly, edit.session)
|
||||||
|
@ -275,7 +275,7 @@ func (edit *editViewData) set(tag string, value interface{}) bool {
|
||||||
case Spellcheck:
|
case Spellcheck:
|
||||||
if edit.setBoolProperty(Spellcheck, value) {
|
if edit.setBoolProperty(Spellcheck, value) {
|
||||||
if edit.created {
|
if edit.created {
|
||||||
updateBoolProperty(edit.htmlID(), Spellcheck, IsSpellcheck(edit, ""), edit.session)
|
updateBoolProperty(edit.htmlID(), Spellcheck, IsSpellcheck(edit), edit.session)
|
||||||
}
|
}
|
||||||
edit.propertyChangedEvent(tag)
|
edit.propertyChangedEvent(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -283,10 +283,10 @@ func (edit *editViewData) set(tag string, value interface{}) bool {
|
||||||
return false
|
return false
|
||||||
|
|
||||||
case EditViewPattern:
|
case EditViewPattern:
|
||||||
oldText := GetEditViewPattern(edit, "")
|
oldText := GetEditViewPattern(edit)
|
||||||
if text, ok := value.(string); ok {
|
if text, ok := value.(string); ok {
|
||||||
edit.properties[EditViewPattern] = text
|
edit.properties[EditViewPattern] = text
|
||||||
if text = GetEditViewPattern(edit, ""); oldText != text {
|
if text = GetEditViewPattern(edit); oldText != text {
|
||||||
if edit.created {
|
if edit.created {
|
||||||
if text != "" {
|
if text != "" {
|
||||||
updateProperty(edit.htmlID(), Pattern, text, edit.session)
|
updateProperty(edit.htmlID(), Pattern, text, edit.session)
|
||||||
|
@ -301,9 +301,9 @@ func (edit *editViewData) set(tag string, value interface{}) bool {
|
||||||
return false
|
return false
|
||||||
|
|
||||||
case EditViewType:
|
case EditViewType:
|
||||||
oldType := GetEditViewType(edit, "")
|
oldType := GetEditViewType(edit)
|
||||||
if edit.setEnumProperty(EditViewType, value, enumProperties[EditViewType].values) {
|
if edit.setEnumProperty(EditViewType, value, enumProperties[EditViewType].values) {
|
||||||
if GetEditViewType(edit, "") != oldType {
|
if GetEditViewType(edit) != oldType {
|
||||||
if edit.created {
|
if edit.created {
|
||||||
updateInnerHTML(edit.parentHTMLID(), edit.session)
|
updateInnerHTML(edit.parentHTMLID(), edit.session)
|
||||||
}
|
}
|
||||||
|
@ -314,10 +314,10 @@ func (edit *editViewData) set(tag string, value interface{}) bool {
|
||||||
return false
|
return false
|
||||||
|
|
||||||
case EditWrap:
|
case EditWrap:
|
||||||
oldWrap := IsEditViewWrap(edit, "")
|
oldWrap := IsEditViewWrap(edit)
|
||||||
if edit.setBoolProperty(EditWrap, value) {
|
if edit.setBoolProperty(EditWrap, value) {
|
||||||
if GetEditViewType(edit, "") == MultiLineText {
|
if GetEditViewType(edit) == MultiLineText {
|
||||||
if wrap := IsEditViewWrap(edit, ""); wrap != oldWrap {
|
if wrap := IsEditViewWrap(edit); wrap != oldWrap {
|
||||||
if edit.created {
|
if edit.created {
|
||||||
if wrap {
|
if wrap {
|
||||||
updateProperty(edit.htmlID(), "wrap", "soft", edit.session)
|
updateProperty(edit.htmlID(), "wrap", "soft", edit.session)
|
||||||
|
@ -333,80 +333,34 @@ func (edit *editViewData) set(tag string, value interface{}) bool {
|
||||||
return false
|
return false
|
||||||
|
|
||||||
case EditTextChangedEvent:
|
case EditTextChangedEvent:
|
||||||
ok := edit.setChangeListeners(value)
|
listeners, ok := valueToEventListeners[EditView, string](value)
|
||||||
if !ok {
|
if !ok {
|
||||||
notCompatibleType(tag, value)
|
notCompatibleType(tag, value)
|
||||||
|
return false
|
||||||
|
} else if listeners == nil {
|
||||||
|
listeners = []func(EditView, string){}
|
||||||
}
|
}
|
||||||
|
edit.textChangeListeners = listeners
|
||||||
edit.propertyChangedEvent(tag)
|
edit.propertyChangedEvent(tag)
|
||||||
return ok
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return edit.viewData.set(tag, value)
|
return edit.viewData.set(tag, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (edit *editViewData) setChangeListeners(value interface{}) bool {
|
func (edit *editViewData) Get(tag string) any {
|
||||||
switch value := value.(type) {
|
|
||||||
case func(EditView, string):
|
|
||||||
edit.textChangeListeners = []func(EditView, string){value}
|
|
||||||
|
|
||||||
case func(string):
|
|
||||||
fn := func(_ EditView, text string) {
|
|
||||||
value(text)
|
|
||||||
}
|
|
||||||
edit.textChangeListeners = []func(EditView, string){fn}
|
|
||||||
|
|
||||||
case []func(EditView, string):
|
|
||||||
edit.textChangeListeners = value
|
|
||||||
|
|
||||||
case []func(string):
|
|
||||||
listeners := make([]func(EditView, string), len(value))
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
listeners[i] = func(_ EditView, text string) {
|
|
||||||
v(text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
edit.textChangeListeners = listeners
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
listeners := make([]func(EditView, string), len(value))
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
switch v := v.(type) {
|
|
||||||
case func(EditView, string):
|
|
||||||
listeners[i] = v
|
|
||||||
|
|
||||||
case func(string):
|
|
||||||
listeners[i] = func(_ EditView, text string) {
|
|
||||||
v(text)
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
edit.textChangeListeners = listeners
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (edit *editViewData) Get(tag string) interface{} {
|
|
||||||
return edit.get(edit.normalizeTag(tag))
|
return edit.get(edit.normalizeTag(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (edit *editViewData) get(tag string) interface{} {
|
func (edit *editViewData) get(tag string) any {
|
||||||
|
if tag == EditTextChangedEvent {
|
||||||
|
return edit.textChangeListeners
|
||||||
|
}
|
||||||
return edit.viewData.get(tag)
|
return edit.viewData.get(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (edit *editViewData) AppendText(text string) {
|
func (edit *editViewData) AppendText(text string) {
|
||||||
if GetEditViewType(edit, "") == MultiLineText {
|
if GetEditViewType(edit) == MultiLineText {
|
||||||
if value := edit.getRaw(Text); value != nil {
|
if value := edit.getRaw(Text); value != nil {
|
||||||
if textValue, ok := value.(string); ok {
|
if textValue, ok := value.(string); ok {
|
||||||
textValue += text
|
textValue += text
|
||||||
|
@ -425,7 +379,7 @@ func (edit *editViewData) AppendText(text string) {
|
||||||
}
|
}
|
||||||
edit.set(Text, text)
|
edit.set(Text, text)
|
||||||
} else {
|
} else {
|
||||||
edit.set(Text, GetText(edit, "")+text)
|
edit.set(Text, GetText(edit)+text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,7 +391,7 @@ func (edit *editViewData) textChanged(newText string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (edit *editViewData) htmlTag() string {
|
func (edit *editViewData) htmlTag() string {
|
||||||
if GetEditViewType(edit, "") == MultiLineText {
|
if GetEditViewType(edit) == MultiLineText {
|
||||||
return "textarea"
|
return "textarea"
|
||||||
}
|
}
|
||||||
return "input"
|
return "input"
|
||||||
|
@ -447,14 +401,14 @@ func (edit *editViewData) htmlProperties(self View, buffer *strings.Builder) {
|
||||||
edit.viewData.htmlProperties(self, buffer)
|
edit.viewData.htmlProperties(self, buffer)
|
||||||
|
|
||||||
writeSpellcheck := func() {
|
writeSpellcheck := func() {
|
||||||
if spellcheck := IsSpellcheck(edit, ""); spellcheck {
|
if spellcheck := IsSpellcheck(edit); spellcheck {
|
||||||
buffer.WriteString(` spellcheck="true"`)
|
buffer.WriteString(` spellcheck="true"`)
|
||||||
} else {
|
} else {
|
||||||
buffer.WriteString(` spellcheck="false"`)
|
buffer.WriteString(` spellcheck="false"`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
editType := GetEditViewType(edit, "")
|
editType := GetEditViewType(edit)
|
||||||
switch editType {
|
switch editType {
|
||||||
case SingleLineText:
|
case SingleLineText:
|
||||||
buffer.WriteString(` type="text" inputmode="text"`)
|
buffer.WriteString(` type="text" inputmode="text"`)
|
||||||
|
@ -476,7 +430,7 @@ func (edit *editViewData) htmlProperties(self View, buffer *strings.Builder) {
|
||||||
buffer.WriteString(` type="tel" inputmode="tel"`)
|
buffer.WriteString(` type="tel" inputmode="tel"`)
|
||||||
|
|
||||||
case MultiLineText:
|
case MultiLineText:
|
||||||
if IsEditViewWrap(edit, "") {
|
if IsEditViewWrap(edit) {
|
||||||
buffer.WriteString(` wrap="soft"`)
|
buffer.WriteString(` wrap="soft"`)
|
||||||
} else {
|
} else {
|
||||||
buffer.WriteString(` wrap="off"`)
|
buffer.WriteString(` wrap="off"`)
|
||||||
|
@ -484,11 +438,11 @@ func (edit *editViewData) htmlProperties(self View, buffer *strings.Builder) {
|
||||||
writeSpellcheck()
|
writeSpellcheck()
|
||||||
}
|
}
|
||||||
|
|
||||||
if IsReadOnly(edit, "") {
|
if IsReadOnly(edit) {
|
||||||
buffer.WriteString(` readonly`)
|
buffer.WriteString(` readonly`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if maxLength := GetMaxLength(edit, ""); maxLength > 0 {
|
if maxLength := GetMaxLength(edit); maxLength > 0 {
|
||||||
buffer.WriteString(` maxlength="`)
|
buffer.WriteString(` maxlength="`)
|
||||||
buffer.WriteString(strconv.Itoa(maxLength))
|
buffer.WriteString(strconv.Itoa(maxLength))
|
||||||
buffer.WriteByte('"')
|
buffer.WriteByte('"')
|
||||||
|
@ -501,21 +455,21 @@ func (edit *editViewData) htmlProperties(self View, buffer *strings.Builder) {
|
||||||
return textToJS(text)
|
return textToJS(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
if hint := GetHint(edit, ""); hint != "" {
|
if hint := GetHint(edit); hint != "" {
|
||||||
buffer.WriteString(` placeholder="`)
|
buffer.WriteString(` placeholder="`)
|
||||||
buffer.WriteString(convertText(hint))
|
buffer.WriteString(convertText(hint))
|
||||||
buffer.WriteByte('"')
|
buffer.WriteByte('"')
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.WriteString(` oninput="editViewInputEvent(this)"`)
|
buffer.WriteString(` oninput="editViewInputEvent(this)"`)
|
||||||
if pattern := GetEditViewPattern(edit, ""); pattern != "" {
|
if pattern := GetEditViewPattern(edit); pattern != "" {
|
||||||
buffer.WriteString(` pattern="`)
|
buffer.WriteString(` pattern="`)
|
||||||
buffer.WriteString(convertText(pattern))
|
buffer.WriteString(convertText(pattern))
|
||||||
buffer.WriteByte('"')
|
buffer.WriteByte('"')
|
||||||
}
|
}
|
||||||
|
|
||||||
if editType != MultiLineText {
|
if editType != MultiLineText {
|
||||||
if text := GetText(edit, ""); text != "" {
|
if text := GetText(edit); text != "" {
|
||||||
buffer.WriteString(` value="`)
|
buffer.WriteString(` value="`)
|
||||||
buffer.WriteString(convertText(text))
|
buffer.WriteString(convertText(text))
|
||||||
buffer.WriteByte('"')
|
buffer.WriteByte('"')
|
||||||
|
@ -524,25 +478,25 @@ func (edit *editViewData) htmlProperties(self View, buffer *strings.Builder) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (edit *editViewData) htmlDisabledProperties(self View, buffer *strings.Builder) {
|
func (edit *editViewData) htmlDisabledProperties(self View, buffer *strings.Builder) {
|
||||||
if IsDisabled(self, "") {
|
if IsDisabled(self) {
|
||||||
buffer.WriteString(` disabled`)
|
buffer.WriteString(` disabled`)
|
||||||
}
|
}
|
||||||
edit.viewData.htmlDisabledProperties(self, buffer)
|
edit.viewData.htmlDisabledProperties(self, buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (edit *editViewData) htmlSubviews(self View, buffer *strings.Builder) {
|
func (edit *editViewData) htmlSubviews(self View, buffer *strings.Builder) {
|
||||||
if GetEditViewType(edit, "") == MultiLineText {
|
if GetEditViewType(edit) == MultiLineText {
|
||||||
buffer.WriteString(textToJS(GetText(edit, "")))
|
buffer.WriteString(textToJS(GetText(edit)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (edit *editViewData) handleCommand(self View, command string, data DataObject) bool {
|
func (edit *editViewData) handleCommand(self View, command string, data DataObject) bool {
|
||||||
switch command {
|
switch command {
|
||||||
case "textChanged":
|
case "textChanged":
|
||||||
oldText := GetText(edit, "")
|
oldText := GetText(edit)
|
||||||
if text, ok := data.PropertyValue("text"); ok {
|
if text, ok := data.PropertyValue("text"); ok {
|
||||||
edit.properties[Text] = text
|
edit.properties[Text] = text
|
||||||
if text := GetText(edit, ""); text != oldText {
|
if text := GetText(edit); text != oldText {
|
||||||
edit.textChanged(text)
|
edit.textChanged(text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -553,10 +507,10 @@ func (edit *editViewData) handleCommand(self View, command string, data DataObje
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetText returns a text of the EditView subview.
|
// GetText returns a text of the EditView subview.
|
||||||
// If the second argument (subviewID) is "" then a text of the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a text of the first argument (view) is returned.
|
||||||
func GetText(view View, subviewID string) string {
|
func GetText(view View, subviewID ...string) string {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view != nil {
|
if view != nil {
|
||||||
if value := view.getRaw(Text); value != nil {
|
if value := view.getRaw(Text); value != nil {
|
||||||
|
@ -569,10 +523,10 @@ func GetText(view View, subviewID string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHint returns a hint text of the subview.
|
// GetHint returns a hint text of the subview.
|
||||||
// If the second argument (subviewID) is "" then a text of the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a text of the first argument (view) is returned.
|
||||||
func GetHint(view View, subviewID string) string {
|
func GetHint(view View, subviewID ...string) string {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view != nil {
|
if view != nil {
|
||||||
if text, ok := stringProperty(view, Hint, view.Session()); ok {
|
if text, ok := stringProperty(view, Hint, view.Session()); ok {
|
||||||
|
@ -590,82 +544,41 @@ func GetHint(view View, subviewID string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMaxLength returns a maximal lenght of EditView. If a maximal lenght is not limited then 0 is returned
|
// GetMaxLength returns a maximal lenght of EditView. If a maximal lenght is not limited then 0 is returned
|
||||||
// If the second argument (subviewID) is "" then a value of the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value of the first argument (view) is returned.
|
||||||
func GetMaxLength(view View, subviewID string) int {
|
func GetMaxLength(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return intStyledProperty(view, subviewID, MaxLength, 0)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if result, ok := intStyledProperty(view, MaxLength, 0); ok {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsReadOnly returns the true if a EditView works in read only mode.
|
// IsReadOnly returns the true if a EditView works in read only mode.
|
||||||
// If the second argument (subviewID) is "" then a value of the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value of the first argument (view) is returned.
|
||||||
func IsReadOnly(view View, subviewID string) bool {
|
func IsReadOnly(view View, subviewID ...string) bool {
|
||||||
if subviewID != "" {
|
return boolStyledProperty(view, subviewID, ReadOnly, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if result, ok := boolStyledProperty(view, ReadOnly); ok {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsSpellcheck returns a value of the Spellcheck property of EditView.
|
// IsSpellcheck returns a value of the Spellcheck property of EditView.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func IsSpellcheck(view View, subviewID string) bool {
|
func IsSpellcheck(view View, subviewID ...string) bool {
|
||||||
if subviewID != "" {
|
return boolStyledProperty(view, subviewID, Spellcheck, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if spellcheck, ok := boolStyledProperty(view, Spellcheck); ok {
|
|
||||||
return spellcheck
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTextChangedListeners returns the TextChangedListener list of an EditView or MultiLineEditView subview.
|
// GetTextChangedListeners returns the TextChangedListener list of an EditView or MultiLineEditView subview.
|
||||||
// If there are no listeners then the empty list is returned
|
// If there are no listeners then the empty list is returned
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTextChangedListeners(view View, subviewID string) []func(EditView, string) {
|
func GetTextChangedListeners(view View, subviewID ...string) []func(EditView, string) {
|
||||||
if subviewID != "" {
|
return getEventListeners[EditView, string](view, subviewID, EditTextChangedEvent)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if value := view.Get(EditTextChangedEvent); value != nil {
|
|
||||||
if result, ok := value.([]func(EditView, string)); ok {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []func(EditView, string){}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEditViewType returns a value of the Type property of EditView.
|
// GetEditViewType returns a value of the Type property of EditView.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetEditViewType(view View, subviewID string) int {
|
func GetEditViewType(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return enumStyledProperty(view, subviewID, EditViewType, SingleLineText, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view == nil {
|
|
||||||
return SingleLineText
|
|
||||||
}
|
|
||||||
t, _ := enumStyledProperty(view, EditViewType, SingleLineText)
|
|
||||||
return t
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEditViewPattern returns a value of the Pattern property of EditView.
|
// GetEditViewPattern returns a value of the Pattern property of EditView.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetEditViewPattern(view View, subviewID string) string {
|
func GetEditViewPattern(view View, subviewID ...string) string {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view != nil {
|
if view != nil {
|
||||||
if pattern, ok := stringProperty(view, EditViewPattern, view.Session()); ok {
|
if pattern, ok := stringProperty(view, EditViewPattern, view.Session()); ok {
|
||||||
|
@ -683,22 +596,13 @@ func GetEditViewPattern(view View, subviewID string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsEditViewWrap returns a value of the EditWrap property of MultiLineEditView.
|
// IsEditViewWrap returns a value of the EditWrap property of MultiLineEditView.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func IsEditViewWrap(view View, subviewID string) bool {
|
func IsEditViewWrap(view View, subviewID ...string) bool {
|
||||||
if subviewID != "" {
|
return boolStyledProperty(view, subviewID, EditWrap, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if wrap, ok := boolStyledProperty(view, EditWrap); ok {
|
|
||||||
return wrap
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppendEditText appends the text to the EditView content.
|
// AppendEditText appends the text to the EditView content.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func AppendEditText(view View, subviewID string, text string) {
|
func AppendEditText(view View, subviewID string, text string) {
|
||||||
if subviewID != "" {
|
if subviewID != "" {
|
||||||
if edit := EditViewByID(view, subviewID); edit != nil {
|
if edit := EditViewByID(view, subviewID); edit != nil {
|
||||||
|
@ -713,14 +617,7 @@ func AppendEditText(view View, subviewID string, text string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCaretColor returns the color of the text input carret.
|
// GetCaretColor returns the color of the text input carret.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetCaretColor(view View, subviewID string) Color {
|
func GetCaretColor(view View, subviewID ...string) Color {
|
||||||
if subviewID != "" {
|
return colorStyledProperty(view, subviewID, CaretColor, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view == nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
t, _ := colorStyledProperty(view, CaretColor)
|
|
||||||
return t
|
|
||||||
}
|
}
|
||||||
|
|
120
filePicker.go
120
filePicker.go
|
@ -72,7 +72,7 @@ func (file *FileInfo) initBy(node DataValue) {
|
||||||
// NewFilePicker create new FilePicker object and return it
|
// NewFilePicker create new FilePicker object and return it
|
||||||
func NewFilePicker(session Session, params Params) FilePicker {
|
func NewFilePicker(session Session, params Params) FilePicker {
|
||||||
view := new(filePickerData)
|
view := new(filePickerData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -81,8 +81,8 @@ func newFilePicker(session Session) View {
|
||||||
return NewFilePicker(session, nil)
|
return NewFilePicker(session, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *filePickerData) Init(session Session) {
|
func (picker *filePickerData) init(session Session) {
|
||||||
picker.viewData.Init(session)
|
picker.viewData.init(session)
|
||||||
picker.tag = "FilePicker"
|
picker.tag = "FilePicker"
|
||||||
picker.files = []FileInfo{}
|
picker.files = []FileInfo{}
|
||||||
picker.loader = map[int]func(FileInfo, []byte){}
|
picker.loader = map[int]func(FileInfo, []byte){}
|
||||||
|
@ -139,11 +139,11 @@ func (picker *filePickerData) remove(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *filePickerData) Set(tag string, value interface{}) bool {
|
func (picker *filePickerData) Set(tag string, value any) bool {
|
||||||
return picker.set(strings.ToLower(tag), value)
|
return picker.set(strings.ToLower(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *filePickerData) set(tag string, value interface{}) bool {
|
func (picker *filePickerData) set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
picker.remove(tag)
|
picker.remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -151,57 +151,14 @@ func (picker *filePickerData) set(tag string, value interface{}) bool {
|
||||||
|
|
||||||
switch tag {
|
switch tag {
|
||||||
case FileSelectedEvent:
|
case FileSelectedEvent:
|
||||||
switch value := value.(type) {
|
listeners, ok := valueToEventListeners[FilePicker, []FileInfo](value)
|
||||||
case func(FilePicker, []FileInfo):
|
if !ok {
|
||||||
picker.fileSelectedListeners = []func(FilePicker, []FileInfo){value}
|
notCompatibleType(tag, value)
|
||||||
|
return false
|
||||||
case func([]FileInfo):
|
} else if listeners == nil {
|
||||||
fn := func(_ FilePicker, files []FileInfo) {
|
listeners = []func(FilePicker, []FileInfo){}
|
||||||
value(files)
|
|
||||||
}
|
|
||||||
picker.fileSelectedListeners = []func(FilePicker, []FileInfo){fn}
|
|
||||||
|
|
||||||
case []func(FilePicker, []FileInfo):
|
|
||||||
picker.fileSelectedListeners = value
|
|
||||||
|
|
||||||
case []func([]FileInfo):
|
|
||||||
listeners := make([]func(FilePicker, []FileInfo), len(value))
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
notCompatibleType(tag, val)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
listeners[i] = func(_ FilePicker, files []FileInfo) {
|
|
||||||
val(files)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
picker.fileSelectedListeners = listeners
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
listeners := make([]func(FilePicker, []FileInfo), len(value))
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
notCompatibleType(tag, val)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
switch val := val.(type) {
|
|
||||||
case func(FilePicker, []FileInfo):
|
|
||||||
listeners[i] = val
|
|
||||||
|
|
||||||
case func([]FileInfo):
|
|
||||||
listeners[i] = func(_ FilePicker, files []FileInfo) {
|
|
||||||
val(files)
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
notCompatibleType(tag, val)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
picker.fileSelectedListeners = listeners
|
|
||||||
}
|
}
|
||||||
|
picker.fileSelectedListeners = listeners
|
||||||
picker.propertyChangedEvent(tag)
|
picker.propertyChangedEvent(tag)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
@ -294,7 +251,7 @@ func (picker *filePickerData) htmlProperties(self View, buffer *strings.Builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.WriteString(` type="file"`)
|
buffer.WriteString(` type="file"`)
|
||||||
if multiple, ok := boolStyledProperty(picker, Multiple); ok && multiple {
|
if IsMultipleFilePicker(picker) {
|
||||||
buffer.WriteString(` multiple`)
|
buffer.WriteString(` multiple`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,7 +262,7 @@ func (picker *filePickerData) htmlProperties(self View, buffer *strings.Builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *filePickerData) htmlDisabledProperties(self View, buffer *strings.Builder) {
|
func (picker *filePickerData) htmlDisabledProperties(self View, buffer *strings.Builder) {
|
||||||
if IsDisabled(self, "") {
|
if IsDisabled(self) {
|
||||||
buffer.WriteString(` disabled`)
|
buffer.WriteString(` disabled`)
|
||||||
}
|
}
|
||||||
picker.viewData.htmlDisabledProperties(self, buffer)
|
picker.viewData.htmlDisabledProperties(self, buffer)
|
||||||
|
@ -377,9 +334,14 @@ func (picker *filePickerData) handleCommand(self View, command string, data Data
|
||||||
|
|
||||||
// GetFilePickerFiles returns the list of FilePicker selected files
|
// GetFilePickerFiles returns the list of FilePicker selected files
|
||||||
// If there are no files selected then an empty slice is returned (the result is always not nil)
|
// If there are no files selected then an empty slice is returned (the result is always not nil)
|
||||||
// If the second argument (subviewID) is "" then selected files of the first argument (view) is returned
|
// If the second argument (subviewID) is not specified or it is "" then selected files of the first argument (view) is returned
|
||||||
func GetFilePickerFiles(view View, subviewID string) []FileInfo {
|
func GetFilePickerFiles(view View, subviewID ...string) []FileInfo {
|
||||||
if picker := FilePickerByID(view, subviewID); picker != nil {
|
subview := ""
|
||||||
|
if len(subviewID) > 0 {
|
||||||
|
subview = subviewID[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if picker := FilePickerByID(view, subview); picker != nil {
|
||||||
return picker.Files()
|
return picker.Files()
|
||||||
}
|
}
|
||||||
return []FileInfo{}
|
return []FileInfo{}
|
||||||
|
@ -395,24 +357,16 @@ func LoadFilePickerFile(view View, subviewID string, file FileInfo, result func(
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsMultipleFilePicker returns "true" if multiple files can be selected in the FilePicker, "false" otherwise.
|
// IsMultipleFilePicker returns "true" if multiple files can be selected in the FilePicker, "false" otherwise.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func IsMultipleFilePicker(view View, subviewID string) bool {
|
func IsMultipleFilePicker(view View, subviewID ...string) bool {
|
||||||
if subviewID != "" {
|
return boolStyledProperty(view, subviewID, Multiple, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if result, ok := boolStyledProperty(view, Multiple); ok {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFilePickerAccept returns sets the list of allowed file extensions or MIME types.
|
// GetFilePickerAccept returns sets the list of allowed file extensions or MIME types.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetFilePickerAccept(view View, subviewID string) []string {
|
func GetFilePickerAccept(view View, subviewID ...string) []string {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view != nil {
|
if view != nil {
|
||||||
accept, ok := stringProperty(view, Accept, view.Session())
|
accept, ok := stringProperty(view, Accept, view.Session())
|
||||||
|
@ -434,17 +388,7 @@ func GetFilePickerAccept(view View, subviewID string) []string {
|
||||||
|
|
||||||
// GetFileSelectedListeners returns the "file-selected-event" listener list.
|
// GetFileSelectedListeners returns the "file-selected-event" listener list.
|
||||||
// If there are no listeners then the empty list is returned.
|
// If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetFileSelectedListeners(view View, subviewID string) []func(FilePicker, []FileInfo) {
|
func GetFileSelectedListeners(view View, subviewID ...string) []func(FilePicker, []FileInfo) {
|
||||||
if subviewID != "" {
|
return getEventListeners[FilePicker, []FileInfo](view, subviewID, FileSelectedEvent)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if value := view.Get(FileSelectedEvent); value != nil {
|
|
||||||
if result, ok := value.([]func(FilePicker, []FileInfo)); ok {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []func(FilePicker, []FileInfo){}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,22 +20,22 @@ const (
|
||||||
LostFocusEvent = "lost-focus-event"
|
LostFocusEvent = "lost-focus-event"
|
||||||
)
|
)
|
||||||
|
|
||||||
func valueToFocusListeners(value interface{}) ([]func(View), bool) {
|
func valueToNoParamListeners[V any](value any) ([]func(V), bool) {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return nil, true
|
return nil, true
|
||||||
}
|
}
|
||||||
|
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case func(View):
|
case func(V):
|
||||||
return []func(View){value}, true
|
return []func(V){value}, true
|
||||||
|
|
||||||
case func():
|
case func():
|
||||||
fn := func(View) {
|
fn := func(V) {
|
||||||
value()
|
value()
|
||||||
}
|
}
|
||||||
return []func(View){fn}, true
|
return []func(V){fn}, true
|
||||||
|
|
||||||
case []func(View):
|
case []func(V):
|
||||||
if len(value) == 0 {
|
if len(value) == 0 {
|
||||||
return nil, true
|
return nil, true
|
||||||
}
|
}
|
||||||
|
@ -51,33 +51,33 @@ func valueToFocusListeners(value interface{}) ([]func(View), bool) {
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
return nil, true
|
return nil, true
|
||||||
}
|
}
|
||||||
listeners := make([]func(View), count)
|
listeners := make([]func(V), count)
|
||||||
for i, v := range value {
|
for i, v := range value {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
listeners[i] = func(View) {
|
listeners[i] = func(V) {
|
||||||
v()
|
v()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return listeners, true
|
return listeners, true
|
||||||
|
|
||||||
case []interface{}:
|
case []any:
|
||||||
count := len(value)
|
count := len(value)
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
return nil, true
|
return nil, true
|
||||||
}
|
}
|
||||||
listeners := make([]func(View), count)
|
listeners := make([]func(V), count)
|
||||||
for i, v := range value {
|
for i, v := range value {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
switch v := v.(type) {
|
switch v := v.(type) {
|
||||||
case func(View):
|
case func(V):
|
||||||
listeners[i] = v
|
listeners[i] = v
|
||||||
|
|
||||||
case func():
|
case func():
|
||||||
listeners[i] = func(View) {
|
listeners[i] = func(V) {
|
||||||
v()
|
v()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,8 +96,8 @@ var focusEvents = map[string]struct{ jsEvent, jsFunc string }{
|
||||||
LostFocusEvent: {jsEvent: "onblur", jsFunc: "blurEvent"},
|
LostFocusEvent: {jsEvent: "onblur", jsFunc: "blurEvent"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *viewData) setFocusListener(tag string, value interface{}) bool {
|
func (view *viewData) setFocusListener(tag string, value any) bool {
|
||||||
listeners, ok := valueToFocusListeners(value)
|
listeners, ok := valueToNoParamListeners[View](value)
|
||||||
if !ok {
|
if !ok {
|
||||||
notCompatibleType(tag, value)
|
notCompatibleType(tag, value)
|
||||||
return false
|
return false
|
||||||
|
@ -125,10 +125,11 @@ func (view *viewData) removeFocusListener(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getFocusListeners(view View, subviewID string, tag string) []func(View) {
|
func getFocusListeners(view View, subviewID []string, tag string) []func(View) {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
if view != nil {
|
if view != nil {
|
||||||
if value := view.Get(tag); value != nil {
|
if value := view.Get(tag); value != nil {
|
||||||
if result, ok := value.([]func(View)); ok {
|
if result, ok := value.([]func(View)); ok {
|
||||||
|
@ -148,13 +149,13 @@ func focusEventsHtml(view View, buffer *strings.Builder) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFocusListeners returns a FocusListener list. If there are no listeners then the empty list is returned
|
// GetFocusListeners returns a FocusListener list. If there are no listeners then the empty list is returned
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetFocusListeners(view View, subviewID string) []func(View) {
|
func GetFocusListeners(view View, subviewID ...string) []func(View) {
|
||||||
return getFocusListeners(view, subviewID, FocusEvent)
|
return getFocusListeners(view, subviewID, FocusEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLostFocusListeners returns a LostFocusListener list. If there are no listeners then the empty list is returned
|
// GetLostFocusListeners returns a LostFocusListener list. If there are no listeners then the empty list is returned
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetLostFocusListeners(view View, subviewID string) []func(View) {
|
func GetLostFocusListeners(view View, subviewID ...string) []func(View) {
|
||||||
return getFocusListeners(view, subviewID, LostFocusEvent)
|
return getFocusListeners(view, subviewID, LostFocusEvent)
|
||||||
}
|
}
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -1,5 +1,5 @@
|
||||||
module github.com/anoshenko/rui
|
module github.com/anoshenko/rui
|
||||||
|
|
||||||
go 1.17
|
go 1.18
|
||||||
|
|
||||||
require github.com/gorilla/websocket v1.5.0
|
require github.com/gorilla/websocket v1.5.0
|
||||||
|
|
128
gridLayout.go
128
gridLayout.go
|
@ -17,7 +17,7 @@ type gridLayoutData struct {
|
||||||
// NewGridLayout create new GridLayout object and return it
|
// NewGridLayout create new GridLayout object and return it
|
||||||
func NewGridLayout(session Session, params Params) GridLayout {
|
func NewGridLayout(session Session, params Params) GridLayout {
|
||||||
view := new(gridLayoutData)
|
view := new(gridLayoutData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -27,8 +27,8 @@ func newGridLayout(session Session) View {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initialize fields of GridLayout by default values
|
// Init initialize fields of GridLayout by default values
|
||||||
func (gridLayout *gridLayoutData) Init(session Session) {
|
func (gridLayout *gridLayoutData) init(session Session) {
|
||||||
gridLayout.viewsContainerData.Init(session)
|
gridLayout.viewsContainerData.init(session)
|
||||||
gridLayout.tag = "GridLayout"
|
gridLayout.tag = "GridLayout"
|
||||||
gridLayout.systemClass = "ruiGridLayout"
|
gridLayout.systemClass = "ruiGridLayout"
|
||||||
}
|
}
|
||||||
|
@ -37,15 +37,17 @@ func (gridLayout *gridLayoutData) String() string {
|
||||||
return getViewString(gridLayout)
|
return getViewString(gridLayout)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (style *viewStyle) setGridCellSize(tag string, value interface{}) bool {
|
func (style *viewStyle) setGridCellSize(tag string, value any) bool {
|
||||||
setValues := func(values []string) bool {
|
setValues := func(values []string) bool {
|
||||||
count := len(values)
|
count := len(values)
|
||||||
if count > 1 {
|
if count > 1 {
|
||||||
sizes := make([]interface{}, count)
|
sizes := make([]any, count)
|
||||||
for i, val := range values {
|
for i, val := range values {
|
||||||
val = strings.Trim(val, " \t\n\r")
|
val = strings.Trim(val, " \t\n\r")
|
||||||
if isConstantName(val) {
|
if isConstantName(val) {
|
||||||
sizes[i] = val
|
sizes[i] = val
|
||||||
|
} else if fn := parseSizeFunc(val); fn != nil {
|
||||||
|
sizes[i] = SizeUnit{Type: SizeFunction, Function: fn}
|
||||||
} else if size, err := stringToSizeUnit(val); err == nil {
|
} else if size, err := stringToSizeUnit(val); err == nil {
|
||||||
sizes[i] = size
|
sizes[i] = size
|
||||||
} else {
|
} else {
|
||||||
|
@ -99,13 +101,13 @@ func (style *viewStyle) setGridCellSize(tag string, value interface{}) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
case []interface{}:
|
case []any:
|
||||||
count := len(value)
|
count := len(value)
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
invalidPropertyValue(tag, value)
|
invalidPropertyValue(tag, value)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
sizes := make([]interface{}, count)
|
sizes := make([]any, count)
|
||||||
for i, val := range value {
|
for i, val := range value {
|
||||||
switch val := val.(type) {
|
switch val := val.(type) {
|
||||||
case SizeUnit:
|
case SizeUnit:
|
||||||
|
@ -145,7 +147,7 @@ func (style *viewStyle) gridCellSizesCSS(tag string, session Session) string {
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
if cellSize[0].Type != Auto {
|
if cellSize[0].Type != Auto {
|
||||||
return `repeat(auto-fill, ` + cellSize[0].cssString(`auto`) + `)`
|
return `repeat(auto-fill, ` + cellSize[0].cssString(`auto`, session) + `)`
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -161,14 +163,14 @@ func (style *viewStyle) gridCellSizesCSS(tag string, session Session) string {
|
||||||
}
|
}
|
||||||
if !allAuto {
|
if !allAuto {
|
||||||
if allEqual {
|
if allEqual {
|
||||||
return fmt.Sprintf(`repeat(%d, %s)`, len(cellSize), cellSize[0].cssString(`auto`))
|
return fmt.Sprintf(`repeat(%d, %s)`, len(cellSize), cellSize[0].cssString(`auto`, session))
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer := allocStringBuilder()
|
buffer := allocStringBuilder()
|
||||||
defer freeStringBuilder(buffer)
|
defer freeStringBuilder(buffer)
|
||||||
for _, size := range cellSize {
|
for _, size := range cellSize {
|
||||||
buffer.WriteRune(' ')
|
buffer.WriteRune(' ')
|
||||||
buffer.WriteString(size.cssString(`auto`))
|
buffer.WriteString(size.cssString(`auto`, session))
|
||||||
}
|
}
|
||||||
return buffer.String()
|
return buffer.String()
|
||||||
}
|
}
|
||||||
|
@ -195,14 +197,14 @@ func (gridLayout *gridLayoutData) normalizeTag(tag string) string {
|
||||||
return tag
|
return tag
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gridLayout *gridLayoutData) Get(tag string) interface{} {
|
func (gridLayout *gridLayoutData) Get(tag string) any {
|
||||||
return gridLayout.get(gridLayout.normalizeTag(tag))
|
return gridLayout.get(gridLayout.normalizeTag(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gridLayout *gridLayoutData) get(tag string) interface{} {
|
func (gridLayout *gridLayoutData) get(tag string) any {
|
||||||
if tag == Gap {
|
if tag == Gap {
|
||||||
rowGap := GetGridRowGap(gridLayout, "")
|
rowGap := GetGridRowGap(gridLayout)
|
||||||
columnGap := GetGridColumnGap(gridLayout, "")
|
columnGap := GetGridColumnGap(gridLayout)
|
||||||
if rowGap.Equal(columnGap) {
|
if rowGap.Equal(columnGap) {
|
||||||
return rowGap
|
return rowGap
|
||||||
}
|
}
|
||||||
|
@ -239,22 +241,18 @@ func (gridLayout *gridLayoutData) remove(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gridLayout *gridLayoutData) Set(tag string, value interface{}) bool {
|
func (gridLayout *gridLayoutData) Set(tag string, value any) bool {
|
||||||
return gridLayout.set(gridLayout.normalizeTag(tag), value)
|
return gridLayout.set(gridLayout.normalizeTag(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gridLayout *gridLayoutData) set(tag string, value interface{}) bool {
|
func (gridLayout *gridLayoutData) set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
gridLayout.remove(tag)
|
gridLayout.remove(tag)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if tag == Gap {
|
if tag == Gap {
|
||||||
if gridLayout.set(GridRowGap, value) && gridLayout.set(GridColumnGap, value) {
|
return gridLayout.set(GridRowGap, value) && gridLayout.set(GridColumnGap, value)
|
||||||
gridLayout.propertyChangedEvent(Gap)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if gridLayout.viewsContainerData.set(tag, value) {
|
if gridLayout.viewsContainerData.set(tag, value) {
|
||||||
|
@ -285,7 +283,7 @@ func gridCellSizes(properties Properties, tag string, session Session) []SizeUni
|
||||||
case SizeUnit:
|
case SizeUnit:
|
||||||
return []SizeUnit{value}
|
return []SizeUnit{value}
|
||||||
|
|
||||||
case []interface{}:
|
case []any:
|
||||||
result := make([]SizeUnit, len(value))
|
result := make([]SizeUnit, len(value))
|
||||||
for i, val := range value {
|
for i, val := range value {
|
||||||
result[i] = AutoSize()
|
result[i] = AutoSize()
|
||||||
|
@ -323,53 +321,29 @@ func (gridLayout *gridLayoutData) cssStyle(self View, builder cssBuilder) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// GetCellVerticalAlign returns the vertical align of a GridLayout cell content: TopAlign (0), BottomAlign (1), CenterAlign (2), StretchAlign (3)
|
// GetCellVerticalAlign returns the vertical align of a GridLayout cell content: TopAlign (0), BottomAlign (1), CenterAlign (2), StretchAlign (3)
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetCellVerticalAlign(view View, subviewID string) int {
|
func GetCellVerticalAlign(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return enumStyledProperty(view, subviewID, CellVerticalAlign, StretchAlign, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if align, ok := enumStyledProperty(view, CellVerticalAlign, StretchAlign); ok {
|
|
||||||
return align
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return StretchAlign
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCellHorizontalAlign returns the vertical align of a GridLayout cell content: LeftAlign (0), RightAlign (1), CenterAlign (2), StretchAlign (3)
|
// GetCellHorizontalAlign returns the vertical align of a GridLayout cell content: LeftAlign (0), RightAlign (1), CenterAlign (2), StretchAlign (3)
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetCellHorizontalAlign(view View, subviewID string) int {
|
func GetCellHorizontalAlign(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return enumStyledProperty(view, subviewID, CellHorizontalAlign, StretchAlign, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if align, ok := enumStyledProperty(view, CellHorizontalAlign, StretchAlign); ok {
|
|
||||||
return align
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return StretchAlign
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetGridAutoFlow returns the value of the "grid-auto-flow" property
|
// GetGridAutoFlow returns the value of the "grid-auto-flow" property
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetGridAutoFlow(view View, subviewID string) int {
|
func GetGridAutoFlow(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return enumStyledProperty(view, subviewID, GridAutoFlow, 0, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if align, ok := enumStyledProperty(view, GridAutoFlow, 0); ok {
|
|
||||||
return align
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCellWidth returns the width of a GridLayout cell. If the result is an empty array, then the width is not set.
|
// GetCellWidth returns the width of a GridLayout cell. If the result is an empty array, then the width is not set.
|
||||||
// If the result is a single value array, then the width of all cell is equal.
|
// If the result is a single value array, then the width of all cell is equal.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetCellWidth(view View, subviewID string) []SizeUnit {
|
func GetCellWidth(view View, subviewID ...string) []SizeUnit {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view != nil {
|
if view != nil {
|
||||||
return gridCellSizes(view, CellWidth, view.Session())
|
return gridCellSizes(view, CellWidth, view.Session())
|
||||||
|
@ -379,10 +353,10 @@ func GetCellWidth(view View, subviewID string) []SizeUnit {
|
||||||
|
|
||||||
// GetCellHeight returns the height of a GridLayout cell. If the result is an empty array, then the height is not set.
|
// GetCellHeight returns the height of a GridLayout cell. If the result is an empty array, then the height is not set.
|
||||||
// If the result is a single value array, then the height of all cell is equal.
|
// If the result is a single value array, then the height of all cell is equal.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetCellHeight(view View, subviewID string) []SizeUnit {
|
func GetCellHeight(view View, subviewID ...string) []SizeUnit {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view != nil {
|
if view != nil {
|
||||||
return gridCellSizes(view, CellHeight, view.Session())
|
return gridCellSizes(view, CellHeight, view.Session())
|
||||||
|
@ -391,29 +365,13 @@ func GetCellHeight(view View, subviewID string) []SizeUnit {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetGridRowGap returns the gap between GridLayout rows.
|
// GetGridRowGap returns the gap between GridLayout rows.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetGridRowGap(view View, subviewID string) SizeUnit {
|
func GetGridRowGap(view View, subviewID ...string) SizeUnit {
|
||||||
if subviewID != "" {
|
return sizeStyledProperty(view, subviewID, GridRowGap, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if result, ok := sizeStyledProperty(view, GridRowGap); ok {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return AutoSize()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetGridColumnGap returns the gap between GridLayout columns.
|
// GetGridColumnGap returns the gap between GridLayout columns.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetGridColumnGap(view View, subviewID string) SizeUnit {
|
func GetGridColumnGap(view View, subviewID ...string) SizeUnit {
|
||||||
if subviewID != "" {
|
return sizeStyledProperty(view, subviewID, GridColumnGap, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if result, ok := sizeStyledProperty(view, GridColumnGap); ok {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return AutoSize()
|
|
||||||
}
|
}
|
||||||
|
|
152
imageView.go
152
imageView.go
|
@ -54,7 +54,7 @@ type imageViewData struct {
|
||||||
// NewImageView create new ImageView object and return it
|
// NewImageView create new ImageView object and return it
|
||||||
func NewImageView(session Session, params Params) ImageView {
|
func NewImageView(session Session, params Params) ImageView {
|
||||||
view := new(imageViewData)
|
view := new(imageViewData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -64,8 +64,8 @@ func newImageView(session Session) View {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initialize fields of imageView by default values
|
// Init initialize fields of imageView by default values
|
||||||
func (imageView *imageViewData) Init(session Session) {
|
func (imageView *imageViewData) init(session Session) {
|
||||||
imageView.viewData.Init(session)
|
imageView.viewData.init(session)
|
||||||
imageView.tag = "ImageView"
|
imageView.tag = "ImageView"
|
||||||
//imageView.systemClass = "ruiImageView"
|
//imageView.systemClass = "ruiImageView"
|
||||||
|
|
||||||
|
@ -114,82 +114,11 @@ func (imageView *imageViewData) remove(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (imageView *imageViewData) Set(tag string, value interface{}) bool {
|
func (imageView *imageViewData) Set(tag string, value any) bool {
|
||||||
return imageView.set(imageView.normalizeTag(tag), value)
|
return imageView.set(imageView.normalizeTag(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func valueToImageListeners(value interface{}) ([]func(ImageView), bool) {
|
func (imageView *imageViewData) set(tag string, value any) bool {
|
||||||
if value == nil {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
|
|
||||||
switch value := value.(type) {
|
|
||||||
case func(ImageView):
|
|
||||||
return []func(ImageView){value}, true
|
|
||||||
|
|
||||||
case func():
|
|
||||||
fn := func(ImageView) {
|
|
||||||
value()
|
|
||||||
}
|
|
||||||
return []func(ImageView){fn}, true
|
|
||||||
|
|
||||||
case []func(ImageView):
|
|
||||||
if len(value) == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
for _, fn := range value {
|
|
||||||
if fn == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value, true
|
|
||||||
|
|
||||||
case []func():
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(ImageView), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
listeners[i] = func(ImageView) {
|
|
||||||
v()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(ImageView), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
switch v := v.(type) {
|
|
||||||
case func(ImageView):
|
|
||||||
listeners[i] = v
|
|
||||||
|
|
||||||
case func():
|
|
||||||
listeners[i] = func(ImageView) {
|
|
||||||
v()
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (imageView *imageViewData) set(tag string, value interface{}) bool {
|
|
||||||
if value == nil {
|
if value == nil {
|
||||||
imageView.remove(tag)
|
imageView.remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -228,8 +157,12 @@ func (imageView *imageViewData) set(tag string, value interface{}) bool {
|
||||||
notCompatibleType(tag, value)
|
notCompatibleType(tag, value)
|
||||||
|
|
||||||
case LoadedEvent, ErrorEvent:
|
case LoadedEvent, ErrorEvent:
|
||||||
if listeners, ok := valueToImageListeners(value); ok {
|
if listeners, ok := valueToNoParamListeners[ImageView](value); ok {
|
||||||
imageView.properties[tag] = listeners
|
if listeners == nil {
|
||||||
|
delete(imageView.properties, tag)
|
||||||
|
} else {
|
||||||
|
imageView.properties[tag] = listeners
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +181,7 @@ func (imageView *imageViewData) set(tag string, value interface{}) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (imageView *imageViewData) Get(tag string) interface{} {
|
func (imageView *imageViewData) Get(tag string) any {
|
||||||
return imageView.viewData.get(imageView.normalizeTag(tag))
|
return imageView.viewData.get(imageView.normalizeTag(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,7 +244,7 @@ func (imageView *imageViewData) htmlProperties(self View, buffer *strings.Builde
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if text := GetImageViewAltText(imageView, ""); text != "" {
|
if text := GetImageViewAltText(imageView); text != "" {
|
||||||
buffer.WriteString(` alt="`)
|
buffer.WriteString(` alt="`)
|
||||||
buffer.WriteString(textToJS(text))
|
buffer.WriteString(textToJS(text))
|
||||||
buffer.WriteString(`"`)
|
buffer.WriteString(`"`)
|
||||||
|
@ -333,8 +266,8 @@ func (imageView *imageViewData) cssStyle(self View, builder cssBuilder) {
|
||||||
builder.add("object-fit", "none")
|
builder.add("object-fit", "none")
|
||||||
}
|
}
|
||||||
|
|
||||||
vAlign := GetImageViewVerticalAlign(imageView, "")
|
vAlign := GetImageViewVerticalAlign(imageView)
|
||||||
hAlign := GetImageViewHorizontalAlign(imageView, "")
|
hAlign := GetImageViewHorizontalAlign(imageView)
|
||||||
if vAlign != CenterAlign || hAlign != CenterAlign {
|
if vAlign != CenterAlign || hAlign != CenterAlign {
|
||||||
var position string
|
var position string
|
||||||
switch hAlign {
|
switch hAlign {
|
||||||
|
@ -390,10 +323,10 @@ func (imageView *imageViewData) CurrentSource() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetImageViewSource returns the image URL of an ImageView subview.
|
// GetImageViewSource returns the image URL of an ImageView subview.
|
||||||
// If the second argument (subviewID) is "" then a left position of the first argument (view) is returned
|
// If the second argument (subviewID) is not specified or it is "" then a left position of the first argument (view) is returned
|
||||||
func GetImageViewSource(view View, subviewID string) string {
|
func GetImageViewSource(view View, subviewID ...string) string {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
if view != nil {
|
if view != nil {
|
||||||
|
@ -406,10 +339,10 @@ func GetImageViewSource(view View, subviewID string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetImageViewAltText returns an alternative text description of an ImageView subview.
|
// GetImageViewAltText returns an alternative text description of an ImageView subview.
|
||||||
// If the second argument (subviewID) is "" then a left position of the first argument (view) is returned
|
// If the second argument (subviewID) is not specified or it is "" then a left position of the first argument (view) is returned
|
||||||
func GetImageViewAltText(view View, subviewID string) string {
|
func GetImageViewAltText(view View, subviewID ...string) string {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
if view != nil {
|
if view != nil {
|
||||||
|
@ -425,40 +358,19 @@ func GetImageViewAltText(view View, subviewID string) string {
|
||||||
|
|
||||||
// GetImageViewFit returns how the content of a replaced ImageView subview:
|
// GetImageViewFit returns how the content of a replaced ImageView subview:
|
||||||
// NoneFit (0), ContainFit (1), CoverFit (2), FillFit (3), or ScaleDownFit (4).
|
// NoneFit (0), ContainFit (1), CoverFit (2), FillFit (3), or ScaleDownFit (4).
|
||||||
// If the second argument (subviewID) is "" then a left position of the first argument (view) is returned
|
// If the second argument (subviewID) is not specified or it is "" then a left position of the first argument (view) is returned
|
||||||
func GetImageViewFit(view View, subviewID string) int {
|
func GetImageViewFit(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return enumStyledProperty(view, subviewID, Fit, NoneFit, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
|
|
||||||
if value, ok := enumStyledProperty(view, Fit, NoneFit); ok {
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetImageViewVerticalAlign return the vertical align of an ImageView subview: TopAlign (0), BottomAlign (1), CenterAlign (2)
|
// GetImageViewVerticalAlign return the vertical align of an ImageView subview: TopAlign (0), BottomAlign (1), CenterAlign (2)
|
||||||
// If the second argument (subviewID) is "" then a left position of the first argument (view) is returned
|
// If the second argument (subviewID) is not specified or it is "" then a left position of the first argument (view) is returned
|
||||||
func GetImageViewVerticalAlign(view View, subviewID string) int {
|
func GetImageViewVerticalAlign(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return enumStyledProperty(view, subviewID, ImageVerticalAlign, LeftAlign, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
|
|
||||||
if align, ok := enumStyledProperty(view, ImageVerticalAlign, LeftAlign); ok {
|
|
||||||
return align
|
|
||||||
}
|
|
||||||
return CenterAlign
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetImageViewHorizontalAlign return the vertical align of an ImageView subview: LeftAlign (0), RightAlign (1), CenterAlign (2)
|
// GetImageViewHorizontalAlign return the vertical align of an ImageView subview: LeftAlign (0), RightAlign (1), CenterAlign (2)
|
||||||
// If the second argument (subviewID) is "" then a left position of the first argument (view) is returned
|
// If the second argument (subviewID) is not specified or it is "" then a left position of the first argument (view) is returned
|
||||||
func GetImageViewHorizontalAlign(view View, subviewID string) int {
|
func GetImageViewHorizontalAlign(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return enumStyledProperty(view, subviewID, ImageHorizontalAlign, LeftAlign, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
|
|
||||||
if align, ok := enumStyledProperty(view, ImageHorizontalAlign, LeftAlign); ok {
|
|
||||||
return align
|
|
||||||
}
|
|
||||||
return CenterAlign
|
|
||||||
}
|
}
|
||||||
|
|
133
keyEvents.go
133
keyEvents.go
|
@ -50,34 +50,52 @@ type KeyEvent struct {
|
||||||
MetaKey bool
|
MetaKey bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func valueToKeyListeners(value interface{}) ([]func(View, KeyEvent), bool) {
|
func (event *KeyEvent) init(data DataObject) {
|
||||||
|
getBool := func(tag string) bool {
|
||||||
|
if value, ok := data.PropertyValue(tag); ok && value == "1" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
event.Key, _ = data.PropertyValue("key")
|
||||||
|
event.Code, _ = data.PropertyValue("code")
|
||||||
|
event.TimeStamp = getTimeStamp(data)
|
||||||
|
event.Repeat = getBool("repeat")
|
||||||
|
event.CtrlKey = getBool("ctrlKey")
|
||||||
|
event.ShiftKey = getBool("shiftKey")
|
||||||
|
event.AltKey = getBool("altKey")
|
||||||
|
event.MetaKey = getBool("metaKey")
|
||||||
|
}
|
||||||
|
|
||||||
|
func valueToEventListeners[V View, E any](value any) ([]func(V, E), bool) {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return nil, true
|
return nil, true
|
||||||
}
|
}
|
||||||
|
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case func(View, KeyEvent):
|
case func(V, E):
|
||||||
return []func(View, KeyEvent){value}, true
|
return []func(V, E){value}, true
|
||||||
|
|
||||||
case func(KeyEvent):
|
case func(E):
|
||||||
fn := func(_ View, event KeyEvent) {
|
fn := func(_ V, event E) {
|
||||||
value(event)
|
value(event)
|
||||||
}
|
}
|
||||||
return []func(View, KeyEvent){fn}, true
|
return []func(V, E){fn}, true
|
||||||
|
|
||||||
case func(View):
|
case func(V):
|
||||||
fn := func(view View, _ KeyEvent) {
|
fn := func(view V, _ E) {
|
||||||
value(view)
|
value(view)
|
||||||
}
|
}
|
||||||
return []func(View, KeyEvent){fn}, true
|
return []func(V, E){fn}, true
|
||||||
|
|
||||||
case func():
|
case func():
|
||||||
fn := func(View, KeyEvent) {
|
fn := func(V, E) {
|
||||||
value()
|
value()
|
||||||
}
|
}
|
||||||
return []func(View, KeyEvent){fn}, true
|
return []func(V, E){fn}, true
|
||||||
|
|
||||||
case []func(View, KeyEvent):
|
case []func(V, E):
|
||||||
if len(value) == 0 {
|
if len(value) == 0 {
|
||||||
return nil, true
|
return nil, true
|
||||||
}
|
}
|
||||||
|
@ -88,33 +106,33 @@ func valueToKeyListeners(value interface{}) ([]func(View, KeyEvent), bool) {
|
||||||
}
|
}
|
||||||
return value, true
|
return value, true
|
||||||
|
|
||||||
case []func(KeyEvent):
|
case []func(E):
|
||||||
count := len(value)
|
count := len(value)
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
return nil, true
|
return nil, true
|
||||||
}
|
}
|
||||||
listeners := make([]func(View, KeyEvent), count)
|
listeners := make([]func(V, E), count)
|
||||||
for i, v := range value {
|
for i, v := range value {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
listeners[i] = func(_ View, event KeyEvent) {
|
listeners[i] = func(_ V, event E) {
|
||||||
v(event)
|
v(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return listeners, true
|
return listeners, true
|
||||||
|
|
||||||
case []func(View):
|
case []func(V):
|
||||||
count := len(value)
|
count := len(value)
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
return nil, true
|
return nil, true
|
||||||
}
|
}
|
||||||
listeners := make([]func(View, KeyEvent), count)
|
listeners := make([]func(V, E), count)
|
||||||
for i, v := range value {
|
for i, v := range value {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
listeners[i] = func(view View, _ KeyEvent) {
|
listeners[i] = func(view V, _ E) {
|
||||||
v(view)
|
v(view)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,43 +143,43 @@ func valueToKeyListeners(value interface{}) ([]func(View, KeyEvent), bool) {
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
return nil, true
|
return nil, true
|
||||||
}
|
}
|
||||||
listeners := make([]func(View, KeyEvent), count)
|
listeners := make([]func(V, E), count)
|
||||||
for i, v := range value {
|
for i, v := range value {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
listeners[i] = func(View, KeyEvent) {
|
listeners[i] = func(V, E) {
|
||||||
v()
|
v()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return listeners, true
|
return listeners, true
|
||||||
|
|
||||||
case []interface{}:
|
case []any:
|
||||||
count := len(value)
|
count := len(value)
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
return nil, true
|
return nil, true
|
||||||
}
|
}
|
||||||
listeners := make([]func(View, KeyEvent), count)
|
listeners := make([]func(V, E), count)
|
||||||
for i, v := range value {
|
for i, v := range value {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
switch v := v.(type) {
|
switch v := v.(type) {
|
||||||
case func(View, KeyEvent):
|
case func(V, E):
|
||||||
listeners[i] = v
|
listeners[i] = v
|
||||||
|
|
||||||
case func(KeyEvent):
|
case func(E):
|
||||||
listeners[i] = func(_ View, event KeyEvent) {
|
listeners[i] = func(_ V, event E) {
|
||||||
v(event)
|
v(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
case func(View):
|
case func(V):
|
||||||
listeners[i] = func(view View, _ KeyEvent) {
|
listeners[i] = func(view V, _ E) {
|
||||||
v(view)
|
v(view)
|
||||||
}
|
}
|
||||||
|
|
||||||
case func():
|
case func():
|
||||||
listeners[i] = func(View, KeyEvent) {
|
listeners[i] = func(V, E) {
|
||||||
v()
|
v()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,8 +198,8 @@ var keyEvents = map[string]struct{ jsEvent, jsFunc string }{
|
||||||
KeyUpEvent: {jsEvent: "onkeyup", jsFunc: "keyUpEvent"},
|
KeyUpEvent: {jsEvent: "onkeyup", jsFunc: "keyUpEvent"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *viewData) setKeyListener(tag string, value interface{}) bool {
|
func (view *viewData) setKeyListener(tag string, value any) bool {
|
||||||
listeners, ok := valueToKeyListeners(value)
|
listeners, ok := valueToEventListeners[View, KeyEvent](value)
|
||||||
if !ok {
|
if !ok {
|
||||||
notCompatibleType(tag, value)
|
notCompatibleType(tag, value)
|
||||||
return false
|
return false
|
||||||
|
@ -209,67 +227,48 @@ func (view *viewData) removeKeyListener(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getKeyListeners(view View, subviewID string, tag string) []func(View, KeyEvent) {
|
func getEventListeners[V View, E any](view View, subviewID []string, tag string) []func(V, E) {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view != nil {
|
if view != nil {
|
||||||
if value := view.Get(tag); value != nil {
|
if value := view.Get(tag); value != nil {
|
||||||
if result, ok := value.([]func(View, KeyEvent)); ok {
|
if result, ok := value.([]func(V, E)); ok {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return []func(View, KeyEvent){}
|
return []func(V, E){}
|
||||||
}
|
}
|
||||||
|
|
||||||
func keyEventsHtml(view View, buffer *strings.Builder) {
|
func keyEventsHtml(view View, buffer *strings.Builder) {
|
||||||
for tag, js := range keyEvents {
|
for tag, js := range keyEvents {
|
||||||
if listeners := getKeyListeners(view, "", tag); len(listeners) > 0 {
|
if listeners := getEventListeners[View, KeyEvent](view, nil, tag); len(listeners) > 0 {
|
||||||
buffer.WriteString(js.jsEvent + `="` + js.jsFunc + `(this, event)" `)
|
buffer.WriteString(js.jsEvent + `="` + js.jsFunc + `(this, event)" `)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleKeyEvents(view View, tag string, data DataObject) {
|
func handleKeyEvents(view View, tag string, data DataObject) {
|
||||||
listeners := getKeyListeners(view, "", tag)
|
listeners := getEventListeners[View, KeyEvent](view, nil, tag)
|
||||||
if len(listeners) == 0 {
|
if len(listeners) > 0 {
|
||||||
return
|
var event KeyEvent
|
||||||
}
|
event.init(data)
|
||||||
|
|
||||||
getBool := func(tag string) bool {
|
for _, listener := range listeners {
|
||||||
if value, ok := data.PropertyValue(tag); ok && value == "1" {
|
listener(view, event)
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
key, _ := data.PropertyValue("key")
|
|
||||||
code, _ := data.PropertyValue("code")
|
|
||||||
event := KeyEvent{
|
|
||||||
TimeStamp: getTimeStamp(data),
|
|
||||||
Key: key,
|
|
||||||
Code: code,
|
|
||||||
Repeat: getBool("repeat"),
|
|
||||||
CtrlKey: getBool("ctrlKey"),
|
|
||||||
ShiftKey: getBool("shiftKey"),
|
|
||||||
AltKey: getBool("altKey"),
|
|
||||||
MetaKey: getBool("metaKey"),
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, listener := range listeners {
|
|
||||||
listener(view, event)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetKeyDownListeners returns the "key-down-event" listener list. If there are no listeners then the empty list is returned.
|
// GetKeyDownListeners returns the "key-down-event" listener list. If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetKeyDownListeners(view View, subviewID string) []func(View, KeyEvent) {
|
func GetKeyDownListeners(view View, subviewID ...string) []func(View, KeyEvent) {
|
||||||
return getKeyListeners(view, subviewID, KeyDownEvent)
|
return getEventListeners[View, KeyEvent](view, subviewID, KeyDownEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetKeyUpListeners returns the "key-up-event" listener list. If there are no listeners then the empty list is returned.
|
// GetKeyUpListeners returns the "key-up-event" listener list. If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetKeyUpListeners(view View, subviewID string) []func(View, KeyEvent) {
|
func GetKeyUpListeners(view View, subviewID ...string) []func(View, KeyEvent) {
|
||||||
return getKeyListeners(view, subviewID, KeyUpEvent)
|
return getEventListeners[View, KeyEvent](view, subviewID, KeyUpEvent)
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@ func (adapter *viewListAdapter) ListItem(index int, session Session) View {
|
||||||
|
|
||||||
func (adapter *viewListAdapter) IsListItemEnabled(index int) bool {
|
func (adapter *viewListAdapter) IsListItemEnabled(index int) bool {
|
||||||
if index >= 0 && index < len(adapter.items) {
|
if index >= 0 && index < len(adapter.items) {
|
||||||
return !IsDisabled(adapter.items[index], "")
|
return !IsDisabled(adapter.items[index])
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
100
listLayout.go
100
listLayout.go
|
@ -33,7 +33,7 @@ type listLayoutData struct {
|
||||||
// NewListLayout create new ListLayout object and return it
|
// NewListLayout create new ListLayout object and return it
|
||||||
func NewListLayout(session Session, params Params) ListLayout {
|
func NewListLayout(session Session, params Params) ListLayout {
|
||||||
view := new(listLayoutData)
|
view := new(listLayoutData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -43,8 +43,8 @@ func newListLayout(session Session) View {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initialize fields of ViewsAlignContainer by default values
|
// Init initialize fields of ViewsAlignContainer by default values
|
||||||
func (listLayout *listLayoutData) Init(session Session) {
|
func (listLayout *listLayoutData) init(session Session) {
|
||||||
listLayout.viewsContainerData.Init(session)
|
listLayout.viewsContainerData.init(session)
|
||||||
listLayout.tag = "ListLayout"
|
listLayout.tag = "ListLayout"
|
||||||
listLayout.systemClass = "ruiListLayout"
|
listLayout.systemClass = "ruiListLayout"
|
||||||
}
|
}
|
||||||
|
@ -58,19 +58,41 @@ func (listLayout *listLayoutData) normalizeTag(tag string) string {
|
||||||
switch tag {
|
switch tag {
|
||||||
case "wrap":
|
case "wrap":
|
||||||
tag = ListWrap
|
tag = ListWrap
|
||||||
|
|
||||||
|
case "row-gap":
|
||||||
|
return ListRowGap
|
||||||
|
|
||||||
|
case ColumnGap:
|
||||||
|
return ListColumnGap
|
||||||
}
|
}
|
||||||
return tag
|
return tag
|
||||||
}
|
}
|
||||||
|
|
||||||
func (listLayout *listLayoutData) Get(tag string) interface{} {
|
func (listLayout *listLayoutData) Get(tag string) any {
|
||||||
return listLayout.get(listLayout.normalizeTag(tag))
|
return listLayout.get(listLayout.normalizeTag(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (listLayout *listLayoutData) get(tag string) any {
|
||||||
|
if tag == Gap {
|
||||||
|
if rowGap := GetListRowGap(listLayout); rowGap.Equal(GetListColumnGap(listLayout)) {
|
||||||
|
return rowGap
|
||||||
|
}
|
||||||
|
return AutoSize()
|
||||||
|
}
|
||||||
|
|
||||||
|
return listLayout.viewsContainerData.get(tag)
|
||||||
|
}
|
||||||
|
|
||||||
func (listLayout *listLayoutData) Remove(tag string) {
|
func (listLayout *listLayoutData) Remove(tag string) {
|
||||||
listLayout.remove(listLayout.normalizeTag(tag))
|
listLayout.remove(listLayout.normalizeTag(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (listLayout *listLayoutData) remove(tag string) {
|
func (listLayout *listLayoutData) remove(tag string) {
|
||||||
|
if tag == Gap {
|
||||||
|
listLayout.remove(ListRowGap)
|
||||||
|
listLayout.remove(ListColumnGap)
|
||||||
|
return
|
||||||
|
}
|
||||||
listLayout.viewsContainerData.remove(tag)
|
listLayout.viewsContainerData.remove(tag)
|
||||||
if listLayout.created {
|
if listLayout.created {
|
||||||
switch tag {
|
switch tag {
|
||||||
|
@ -80,16 +102,20 @@ func (listLayout *listLayoutData) remove(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (listLayout *listLayoutData) Set(tag string, value interface{}) bool {
|
func (listLayout *listLayoutData) Set(tag string, value any) bool {
|
||||||
return listLayout.set(listLayout.normalizeTag(tag), value)
|
return listLayout.set(listLayout.normalizeTag(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (listLayout *listLayoutData) set(tag string, value interface{}) bool {
|
func (listLayout *listLayoutData) set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
listLayout.remove(tag)
|
listLayout.remove(tag)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if tag == Gap {
|
||||||
|
return listLayout.set(ListRowGap, value) && listLayout.set(ListColumnGap, value)
|
||||||
|
}
|
||||||
|
|
||||||
if listLayout.viewsContainerData.set(tag, value) {
|
if listLayout.viewsContainerData.set(tag, value) {
|
||||||
if listLayout.created {
|
if listLayout.created {
|
||||||
switch tag {
|
switch tag {
|
||||||
|
@ -113,38 +139,24 @@ func (listLayout *listLayoutData) htmlSubviews(self View, buffer *strings.Builde
|
||||||
|
|
||||||
// GetListVerticalAlign returns the vertical align of a ListLayout or ListView sibview:
|
// GetListVerticalAlign returns the vertical align of a ListLayout or ListView sibview:
|
||||||
// TopAlign (0), BottomAlign (1), CenterAlign (2), or StretchAlign (3)
|
// TopAlign (0), BottomAlign (1), CenterAlign (2), or StretchAlign (3)
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetListVerticalAlign(view View, subviewID string) int {
|
func GetListVerticalAlign(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return enumStyledProperty(view, subviewID, VerticalAlign, TopAlign, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view == nil {
|
|
||||||
return LeftAlign
|
|
||||||
}
|
|
||||||
result, _ := enumProperty(view, VerticalAlign, view.Session(), 0)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetListHorizontalAlign returns the vertical align of a ListLayout or ListView subview:
|
// GetListHorizontalAlign returns the vertical align of a ListLayout or ListView subview:
|
||||||
// LeftAlign (0), RightAlign (1), CenterAlign (2), or StretchAlign (3)
|
// LeftAlign (0), RightAlign (1), CenterAlign (2), or StretchAlign (3)
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetListHorizontalAlign(view View, subviewID string) int {
|
func GetListHorizontalAlign(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return enumStyledProperty(view, subviewID, HorizontalAlign, LeftAlign, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view == nil {
|
|
||||||
return TopAlign
|
|
||||||
}
|
|
||||||
result, _ := enumProperty(view, HorizontalAlign, view.Session(), 0)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetListOrientation returns the orientation of a ListLayout or ListView subview:
|
// GetListOrientation returns the orientation of a ListLayout or ListView subview:
|
||||||
// TopDownOrientation (0), StartToEndOrientation (1), BottomUpOrientation (2), or EndToStartOrientation (3)
|
// TopDownOrientation (0), StartToEndOrientation (1), BottomUpOrientation (2), or EndToStartOrientation (3)
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetListOrientation(view View, subviewID string) int {
|
func GetListOrientation(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
if view != nil {
|
if view != nil {
|
||||||
|
@ -163,16 +175,20 @@ func GetListOrientation(view View, subviewID string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetListWrap returns the wrap type of a ListLayout or ListView subview:
|
// GetListWrap returns the wrap type of a ListLayout or ListView subview:
|
||||||
// WrapOff (0), WrapOn (1), or WrapReverse (2)
|
// ListWrapOff (0), ListWrapOn (1), or ListWrapReverse (2)
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetListWrap(view View, subviewID string) int {
|
func GetListWrap(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return enumStyledProperty(view, subviewID, ListWrap, ListWrapOff, false)
|
||||||
view = ViewByID(view, subviewID)
|
}
|
||||||
}
|
|
||||||
if view != nil {
|
// GetListRowGap returns the gap between ListLayout or ListView rows.
|
||||||
if result, ok := enumStyledProperty(view, ListWrap, 0); ok {
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
return result
|
func GetListRowGap(view View, subviewID ...string) SizeUnit {
|
||||||
}
|
return sizeStyledProperty(view, subviewID, ListRowGap, false)
|
||||||
}
|
}
|
||||||
return ListWrapOff
|
|
||||||
|
// GetListColumnGap returns the gap between ListLayout or ListView columns.
|
||||||
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
|
func GetListColumnGap(view View, subviewID ...string) SizeUnit {
|
||||||
|
return sizeStyledProperty(view, subviewID, ListColumnGap, false)
|
||||||
}
|
}
|
||||||
|
|
513
listView.go
513
listView.go
|
@ -69,7 +69,7 @@ type listViewData struct {
|
||||||
// NewListView creates the new list view
|
// NewListView creates the new list view
|
||||||
func NewListView(session Session, params Params) ListView {
|
func NewListView(session Session, params Params) ListView {
|
||||||
view := new(listViewData)
|
view := new(listViewData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -79,8 +79,8 @@ func newListView(session Session) View {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initialize fields of ViewsContainer by default values
|
// Init initialize fields of ViewsContainer by default values
|
||||||
func (listView *listViewData) Init(session Session) {
|
func (listView *listViewData) init(session Session) {
|
||||||
listView.viewData.Init(session)
|
listView.viewData.init(session)
|
||||||
listView.tag = "ListView"
|
listView.tag = "ListView"
|
||||||
listView.systemClass = "ruiListView"
|
listView.systemClass = "ruiListView"
|
||||||
listView.items = []View{}
|
listView.items = []View{}
|
||||||
|
@ -110,6 +110,12 @@ func (listView *listViewData) normalizeTag(tag string) string {
|
||||||
|
|
||||||
case "wrap":
|
case "wrap":
|
||||||
tag = ListWrap
|
tag = ListWrap
|
||||||
|
|
||||||
|
case "row-gap":
|
||||||
|
return ListRowGap
|
||||||
|
|
||||||
|
case ColumnGap:
|
||||||
|
return ListColumnGap
|
||||||
}
|
}
|
||||||
return tag
|
return tag
|
||||||
}
|
}
|
||||||
|
@ -120,6 +126,10 @@ func (listView *listViewData) Remove(tag string) {
|
||||||
|
|
||||||
func (listView *listViewData) remove(tag string) {
|
func (listView *listViewData) remove(tag string) {
|
||||||
switch tag {
|
switch tag {
|
||||||
|
case Gap:
|
||||||
|
listView.remove(ListRowGap)
|
||||||
|
listView.remove(ListColumnGap)
|
||||||
|
|
||||||
case Checked:
|
case Checked:
|
||||||
if len(listView.checkedItem) > 0 {
|
if len(listView.checkedItem) > 0 {
|
||||||
listView.checkedItem = []int{}
|
listView.checkedItem = []int{}
|
||||||
|
@ -148,7 +158,7 @@ func (listView *listViewData) remove(tag string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case Current:
|
case Current:
|
||||||
current := GetCurrent(listView, "")
|
current := GetCurrent(listView)
|
||||||
delete(listView.properties, tag)
|
delete(listView.properties, tag)
|
||||||
if listView.created {
|
if listView.created {
|
||||||
updateInnerHTML(listView.htmlID(), listView.session)
|
updateInnerHTML(listView.htmlID(), listView.session)
|
||||||
|
@ -193,41 +203,53 @@ func (listView *listViewData) remove(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (listView *listViewData) Set(tag string, value interface{}) bool {
|
func (listView *listViewData) Set(tag string, value any) bool {
|
||||||
return listView.set(listView.normalizeTag(tag), value)
|
return listView.set(listView.normalizeTag(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (listView *listViewData) set(tag string, value interface{}) bool {
|
func (listView *listViewData) set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
listView.remove(tag)
|
listView.remove(tag)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
switch tag {
|
switch tag {
|
||||||
|
case Gap:
|
||||||
|
return listView.set(ListRowGap, value) && listView.set(ListColumnGap, value)
|
||||||
|
|
||||||
case ListItemClickedEvent:
|
case ListItemClickedEvent:
|
||||||
listeners := listView.valueToItemListeners(value)
|
listeners, ok := valueToEventListeners[ListView, int](value)
|
||||||
if listeners == nil {
|
if !ok {
|
||||||
notCompatibleType(tag, value)
|
notCompatibleType(tag, value)
|
||||||
return false
|
return false
|
||||||
|
} else if listeners == nil {
|
||||||
|
listeners = []func(ListView, int){}
|
||||||
}
|
}
|
||||||
listView.clickedListeners = listeners
|
listView.clickedListeners = listeners
|
||||||
listView.propertyChangedEvent(tag)
|
listView.propertyChangedEvent(tag)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
case ListItemSelectedEvent:
|
case ListItemSelectedEvent:
|
||||||
listeners := listView.valueToItemListeners(value)
|
listeners, ok := valueToEventListeners[ListView, int](value)
|
||||||
if listeners == nil {
|
if !ok {
|
||||||
notCompatibleType(tag, value)
|
notCompatibleType(tag, value)
|
||||||
return false
|
return false
|
||||||
|
} else if listeners == nil {
|
||||||
|
listeners = []func(ListView, int){}
|
||||||
}
|
}
|
||||||
listView.selectedListeners = listeners
|
listView.selectedListeners = listeners
|
||||||
listView.propertyChangedEvent(tag)
|
listView.propertyChangedEvent(tag)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
case ListItemCheckedEvent:
|
case ListItemCheckedEvent:
|
||||||
if !listView.setItemCheckedEvent(value) {
|
listeners, ok := valueToEventListeners[ListView, []int](value)
|
||||||
|
if !ok {
|
||||||
|
notCompatibleType(tag, value)
|
||||||
return false
|
return false
|
||||||
|
} else if listeners == nil {
|
||||||
|
listeners = []func(ListView, []int){}
|
||||||
}
|
}
|
||||||
|
listView.checkedListeners = listeners
|
||||||
listView.propertyChangedEvent(tag)
|
listView.propertyChangedEvent(tag)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
@ -242,11 +264,11 @@ func (listView *listViewData) set(tag string, value interface{}) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
case Current:
|
case Current:
|
||||||
oldCurrent := GetCurrent(listView, "")
|
oldCurrent := GetCurrent(listView)
|
||||||
if !listView.setIntProperty(Current, value) {
|
if !listView.setIntProperty(Current, value) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
current := GetCurrent(listView, "")
|
current := GetCurrent(listView)
|
||||||
if oldCurrent == current {
|
if oldCurrent == current {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -255,7 +277,7 @@ func (listView *listViewData) set(tag string, value interface{}) bool {
|
||||||
listener(listView, current)
|
listener(listView, current)
|
||||||
}
|
}
|
||||||
|
|
||||||
case Orientation, ListWrap, VerticalAlign, HorizontalAlign, Style, StyleDisabled, ItemWidth, ItemHeight:
|
case Orientation, ListWrap, ListRowGap, ListColumnGap, VerticalAlign, HorizontalAlign, Style, StyleDisabled, ItemWidth, ItemHeight:
|
||||||
result := listView.viewData.set(tag, value)
|
result := listView.viewData.set(tag, value)
|
||||||
if result && listView.created {
|
if result && listView.created {
|
||||||
updateInnerHTML(listView.htmlID(), listView.session)
|
updateInnerHTML(listView.htmlID(), listView.session)
|
||||||
|
@ -288,67 +310,18 @@ func (listView *listViewData) set(tag string, value interface{}) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (listView *listViewData) setItemCheckedEvent(value interface{}) bool {
|
func (listView *listViewData) Get(tag string) any {
|
||||||
switch value := value.(type) {
|
|
||||||
case func(ListView, []int):
|
|
||||||
listView.checkedListeners = []func(ListView, []int){value}
|
|
||||||
|
|
||||||
case func([]int):
|
|
||||||
fn := func(_ ListView, date []int) {
|
|
||||||
value(date)
|
|
||||||
}
|
|
||||||
listView.checkedListeners = []func(ListView, []int){fn}
|
|
||||||
|
|
||||||
case []func(ListView, []int):
|
|
||||||
listView.checkedListeners = value
|
|
||||||
|
|
||||||
case []func([]int):
|
|
||||||
listeners := make([]func(ListView, []int), len(value))
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
notCompatibleType(ListItemCheckedEvent, val)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
listeners[i] = func(_ ListView, date []int) {
|
|
||||||
val(date)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
listView.checkedListeners = listeners
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
listeners := make([]func(ListView, []int), len(value))
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
notCompatibleType(ListItemCheckedEvent, val)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
switch val := val.(type) {
|
|
||||||
case func(ListView, []int):
|
|
||||||
listeners[i] = val
|
|
||||||
|
|
||||||
case func([]int):
|
|
||||||
listeners[i] = func(_ ListView, checked []int) {
|
|
||||||
val(checked)
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
notCompatibleType(ListItemCheckedEvent, val)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
listView.checkedListeners = listeners
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (listView *listViewData) Get(tag string) interface{} {
|
|
||||||
return listView.get(listView.normalizeTag(tag))
|
return listView.get(listView.normalizeTag(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (listView *listViewData) get(tag string) interface{} {
|
func (listView *listViewData) get(tag string) any {
|
||||||
switch tag {
|
switch tag {
|
||||||
|
case Gap:
|
||||||
|
if rowGap := GetListRowGap(listView); rowGap.Equal(GetListColumnGap(listView)) {
|
||||||
|
return rowGap
|
||||||
|
}
|
||||||
|
return AutoSize()
|
||||||
|
|
||||||
case ListItemClickedEvent:
|
case ListItemClickedEvent:
|
||||||
return listView.clickedListeners
|
return listView.clickedListeners
|
||||||
|
|
||||||
|
@ -376,7 +349,7 @@ func (listView *listViewData) get(tag string) interface{} {
|
||||||
return listView.viewData.get(tag)
|
return listView.viewData.get(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (listView *listViewData) setItems(value interface{}) bool {
|
func (listView *listViewData) setItems(value any) bool {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case []string:
|
case []string:
|
||||||
listView.adapter = NewTextListAdapter(value, nil)
|
listView.adapter = NewTextListAdapter(value, nil)
|
||||||
|
@ -412,7 +385,7 @@ func (listView *listViewData) setItems(value interface{}) bool {
|
||||||
listView.adapter = NewTextListAdapter(items, nil)
|
listView.adapter = NewTextListAdapter(items, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
case []interface{}:
|
case []any:
|
||||||
items := make([]View, len(value))
|
items := make([]View, len(value))
|
||||||
for i, val := range value {
|
for i, val := range value {
|
||||||
switch value := val.(type) {
|
switch value := val.(type) {
|
||||||
|
@ -460,62 +433,7 @@ func (listView *listViewData) setItems(value interface{}) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (listView *listViewData) valueToItemListeners(value interface{}) []func(ListView, int) {
|
func (listView *listViewData) setChecked(value any) bool {
|
||||||
if value == nil {
|
|
||||||
return []func(ListView, int){}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch value := value.(type) {
|
|
||||||
case func(ListView, int):
|
|
||||||
return []func(ListView, int){value}
|
|
||||||
|
|
||||||
case func(int):
|
|
||||||
fn := func(_ ListView, index int) {
|
|
||||||
value(index)
|
|
||||||
}
|
|
||||||
return []func(ListView, int){fn}
|
|
||||||
|
|
||||||
case []func(ListView, int):
|
|
||||||
return value
|
|
||||||
|
|
||||||
case []func(int):
|
|
||||||
listeners := make([]func(ListView, int), len(value))
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
listeners[i] = func(_ ListView, index int) {
|
|
||||||
val(index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
listeners := make([]func(ListView, int), len(value))
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
switch val := val.(type) {
|
|
||||||
case func(ListView, int):
|
|
||||||
listeners[i] = val
|
|
||||||
|
|
||||||
case func(int):
|
|
||||||
listeners[i] = func(_ ListView, index int) {
|
|
||||||
val(index)
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (listView *listViewData) setChecked(value interface{}) bool {
|
|
||||||
var checked []int
|
var checked []int
|
||||||
if value == nil {
|
if value == nil {
|
||||||
checked = []int{}
|
checked = []int{}
|
||||||
|
@ -544,7 +462,7 @@ func (listView *listViewData) setChecked(value interface{}) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch GetListViewCheckbox(listView, "") {
|
switch GetListViewCheckbox(listView) {
|
||||||
case SingleCheckbox:
|
case SingleCheckbox:
|
||||||
count := len(checked)
|
count := len(checked)
|
||||||
if count > 1 {
|
if count > 1 {
|
||||||
|
@ -628,14 +546,14 @@ func (listView *listViewData) getItemFrames() []Frame {
|
||||||
|
|
||||||
func (listView *listViewData) itemAlign(self View, buffer *strings.Builder) {
|
func (listView *listViewData) itemAlign(self View, buffer *strings.Builder) {
|
||||||
values := enumProperties[ItemHorizontalAlign].cssValues
|
values := enumProperties[ItemHorizontalAlign].cssValues
|
||||||
if hAlign := GetListItemHorizontalAlign(listView, ""); hAlign >= 0 && hAlign < len(values) {
|
if hAlign := GetListItemHorizontalAlign(listView); hAlign >= 0 && hAlign < len(values) {
|
||||||
buffer.WriteString(" justify-items: ")
|
buffer.WriteString(" justify-items: ")
|
||||||
buffer.WriteString(values[hAlign])
|
buffer.WriteString(values[hAlign])
|
||||||
buffer.WriteRune(';')
|
buffer.WriteRune(';')
|
||||||
}
|
}
|
||||||
|
|
||||||
values = enumProperties[ItemVerticalAlign].cssValues
|
values = enumProperties[ItemVerticalAlign].cssValues
|
||||||
if vAlign := GetListItemVerticalAlign(listView, ""); vAlign >= 0 && vAlign < len(values) {
|
if vAlign := GetListItemVerticalAlign(listView); vAlign >= 0 && vAlign < len(values) {
|
||||||
buffer.WriteString(" align-items: ")
|
buffer.WriteString(" align-items: ")
|
||||||
buffer.WriteString(values[vAlign])
|
buffer.WriteString(values[vAlign])
|
||||||
buffer.WriteRune(';')
|
buffer.WriteRune(';')
|
||||||
|
@ -643,15 +561,15 @@ func (listView *listViewData) itemAlign(self View, buffer *strings.Builder) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (listView *listViewData) itemSize(self View, buffer *strings.Builder) {
|
func (listView *listViewData) itemSize(self View, buffer *strings.Builder) {
|
||||||
if itemWidth := GetListItemWidth(listView, ""); itemWidth.Type != Auto {
|
if itemWidth := GetListItemWidth(listView); itemWidth.Type != Auto {
|
||||||
buffer.WriteString(` min-width: `)
|
buffer.WriteString(` min-width: `)
|
||||||
buffer.WriteString(itemWidth.cssString(""))
|
buffer.WriteString(itemWidth.cssString("", listView.Session()))
|
||||||
buffer.WriteRune(';')
|
buffer.WriteRune(';')
|
||||||
}
|
}
|
||||||
|
|
||||||
if itemHeight := GetListItemHeight(listView, ""); itemHeight.Type != Auto {
|
if itemHeight := GetListItemHeight(listView); itemHeight.Type != Auto {
|
||||||
buffer.WriteString(` min-height: `)
|
buffer.WriteString(` min-height: `)
|
||||||
buffer.WriteString(itemHeight.cssString(""))
|
buffer.WriteString(itemHeight.cssString("", listView.Session()))
|
||||||
buffer.WriteRune(';')
|
buffer.WriteRune(';')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -741,7 +659,7 @@ func (listView *listViewData) checkboxItemDiv(self View, checkbox, hCheckboxAlig
|
||||||
|
|
||||||
if gap, ok := sizeConstant(listView.session, "ruiCheckboxGap"); ok && gap.Type != Auto {
|
if gap, ok := sizeConstant(listView.session, "ruiCheckboxGap"); ok && gap.Type != Auto {
|
||||||
itemStyleBuilder.WriteString(` grid-gap: `)
|
itemStyleBuilder.WriteString(` grid-gap: `)
|
||||||
itemStyleBuilder.WriteString(gap.cssString("auto"))
|
itemStyleBuilder.WriteString(gap.cssString("auto", listView.Session()))
|
||||||
itemStyleBuilder.WriteRune(';')
|
itemStyleBuilder.WriteRune(';')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -801,14 +719,14 @@ func (listView *listViewData) checkboxSubviews(self View, buffer *strings.Builde
|
||||||
count := listView.adapter.ListSize()
|
count := listView.adapter.ListSize()
|
||||||
listViewID := listView.htmlID()
|
listViewID := listView.htmlID()
|
||||||
|
|
||||||
hCheckboxAlign := GetListViewCheckboxHorizontalAlign(listView, "")
|
hCheckboxAlign := GetListViewCheckboxHorizontalAlign(listView)
|
||||||
vCheckboxAlign := GetListViewCheckboxVerticalAlign(listView, "")
|
vCheckboxAlign := GetListViewCheckboxVerticalAlign(listView)
|
||||||
|
|
||||||
itemDiv := listView.checkboxItemDiv(self, checkbox, hCheckboxAlign, vCheckboxAlign)
|
itemDiv := listView.checkboxItemDiv(self, checkbox, hCheckboxAlign, vCheckboxAlign)
|
||||||
onDiv, offDiv, contentDiv := listView.getDivs(self, checkbox, hCheckboxAlign, vCheckboxAlign)
|
onDiv, offDiv, contentDiv := listView.getDivs(self, checkbox, hCheckboxAlign, vCheckboxAlign)
|
||||||
|
|
||||||
current := GetCurrent(listView, "")
|
current := GetCurrent(listView)
|
||||||
checkedItems := GetListViewCheckedItems(listView, "")
|
checkedItems := GetListViewCheckedItems(listView)
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
buffer.WriteString(`<div id="`)
|
buffer.WriteString(`<div id="`)
|
||||||
buffer.WriteString(listViewID)
|
buffer.WriteString(listViewID)
|
||||||
|
@ -864,7 +782,7 @@ func (listView *listViewData) noneCheckboxSubviews(self View, buffer *strings.Bu
|
||||||
itemStyleBuilder.WriteString(`" onclick="listItemClickEvent(this, event)"`)
|
itemStyleBuilder.WriteString(`" onclick="listItemClickEvent(this, event)"`)
|
||||||
itemStyle := itemStyleBuilder.String()
|
itemStyle := itemStyleBuilder.String()
|
||||||
|
|
||||||
current := GetCurrent(listView, "")
|
current := GetCurrent(listView)
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
buffer.WriteString(`<div id="`)
|
buffer.WriteString(`<div id="`)
|
||||||
buffer.WriteString(listViewID)
|
buffer.WriteString(listViewID)
|
||||||
|
@ -893,9 +811,9 @@ func (listView *listViewData) noneCheckboxSubviews(self View, buffer *strings.Bu
|
||||||
|
|
||||||
func (listView *listViewData) updateCheckboxItem(index int, checked bool) {
|
func (listView *listViewData) updateCheckboxItem(index int, checked bool) {
|
||||||
|
|
||||||
checkbox := GetListViewCheckbox(listView, "")
|
checkbox := GetListViewCheckbox(listView)
|
||||||
hCheckboxAlign := GetListViewCheckboxHorizontalAlign(listView, "")
|
hCheckboxAlign := GetListViewCheckboxHorizontalAlign(listView)
|
||||||
vCheckboxAlign := GetListViewCheckboxVerticalAlign(listView, "")
|
vCheckboxAlign := GetListViewCheckboxVerticalAlign(listView)
|
||||||
onDiv, offDiv, contentDiv := listView.getDivs(listView, checkbox, hCheckboxAlign, vCheckboxAlign)
|
onDiv, offDiv, contentDiv := listView.getDivs(listView, checkbox, hCheckboxAlign, vCheckboxAlign)
|
||||||
|
|
||||||
buffer := allocStringBuilder()
|
buffer := allocStringBuilder()
|
||||||
|
@ -937,7 +855,7 @@ func (listView *listViewData) htmlProperties(self View, buffer *strings.Builder)
|
||||||
buffer.WriteString(`" data-bluritemstyle="`)
|
buffer.WriteString(`" data-bluritemstyle="`)
|
||||||
buffer.WriteString(listView.currentInactiveStyle())
|
buffer.WriteString(listView.currentInactiveStyle())
|
||||||
buffer.WriteString(`"`)
|
buffer.WriteString(`"`)
|
||||||
current := GetCurrent(listView, "")
|
current := GetCurrent(listView)
|
||||||
if listView.adapter != nil && current >= 0 && current < listView.adapter.ListSize() {
|
if listView.adapter != nil && current >= 0 && current < listView.adapter.ListSize() {
|
||||||
buffer.WriteString(` data-current="`)
|
buffer.WriteString(` data-current="`)
|
||||||
buffer.WriteString(listView.htmlID())
|
buffer.WriteString(listView.htmlID())
|
||||||
|
@ -953,8 +871,8 @@ func (listView *listViewData) htmlProperties(self View, buffer *strings.Builder)
|
||||||
func (listView *listViewData) cssStyle(self View, builder cssBuilder) {
|
func (listView *listViewData) cssStyle(self View, builder cssBuilder) {
|
||||||
listView.viewData.cssStyle(self, builder)
|
listView.viewData.cssStyle(self, builder)
|
||||||
|
|
||||||
if GetListWrap(listView, "") != WrapOff {
|
if GetListWrap(listView) != WrapOff {
|
||||||
switch GetListOrientation(listView, "") {
|
switch GetListOrientation(listView) {
|
||||||
case TopDownOrientation, BottomUpOrientation:
|
case TopDownOrientation, BottomUpOrientation:
|
||||||
builder.add(`max-height`, `100%`)
|
builder.add(`max-height`, `100%`)
|
||||||
default:
|
default:
|
||||||
|
@ -976,8 +894,20 @@ func (listView *listViewData) htmlSubviews(self View, buffer *strings.Builder) {
|
||||||
|
|
||||||
buffer.WriteString(`<div style="display: flex; align-content: stretch;`)
|
buffer.WriteString(`<div style="display: flex; align-content: stretch;`)
|
||||||
|
|
||||||
wrap := GetListWrap(listView, "")
|
if gap := GetListRowGap(listView); gap.Type != Auto {
|
||||||
orientation := GetListOrientation(listView, "")
|
buffer.WriteString(` row-gap: `)
|
||||||
|
buffer.WriteString(gap.cssString("0", listView.Session()))
|
||||||
|
buffer.WriteRune(';')
|
||||||
|
}
|
||||||
|
|
||||||
|
if gap := GetListColumnGap(listView); gap.Type != Auto {
|
||||||
|
buffer.WriteString(` column-gap: `)
|
||||||
|
buffer.WriteString(gap.cssString("0", listView.Session()))
|
||||||
|
buffer.WriteRune(';')
|
||||||
|
}
|
||||||
|
|
||||||
|
wrap := GetListWrap(listView)
|
||||||
|
orientation := GetListOrientation(listView)
|
||||||
rows := (orientation == StartToEndOrientation || orientation == EndToStartOrientation)
|
rows := (orientation == StartToEndOrientation || orientation == EndToStartOrientation)
|
||||||
|
|
||||||
if rows {
|
if rows {
|
||||||
|
@ -1018,29 +948,27 @@ func (listView *listViewData) htmlSubviews(self View, buffer *strings.Builder) {
|
||||||
}
|
}
|
||||||
|
|
||||||
value := ""
|
value := ""
|
||||||
if align, ok := enumStyledProperty(listView, HorizontalAlign, LeftAlign); ok {
|
switch GetListHorizontalAlign(listView) {
|
||||||
switch align {
|
case LeftAlign:
|
||||||
case LeftAlign:
|
if (!rows && wrap == ListWrapReverse) || orientation == EndToStartOrientation {
|
||||||
if (!rows && wrap == ListWrapReverse) || orientation == EndToStartOrientation {
|
value = `flex-end`
|
||||||
value = `flex-end`
|
} else {
|
||||||
} else {
|
value = `flex-start`
|
||||||
value = `flex-start`
|
}
|
||||||
}
|
case RightAlign:
|
||||||
case RightAlign:
|
if (!rows && wrap == ListWrapReverse) || orientation == EndToStartOrientation {
|
||||||
if (!rows && wrap == ListWrapReverse) || orientation == EndToStartOrientation {
|
value = `flex-start`
|
||||||
value = `flex-start`
|
} else {
|
||||||
} else {
|
value = `flex-end`
|
||||||
value = `flex-end`
|
}
|
||||||
}
|
case CenterAlign:
|
||||||
case CenterAlign:
|
value = `center`
|
||||||
value = `center`
|
|
||||||
|
|
||||||
case StretchAlign:
|
case StretchAlign:
|
||||||
if rows {
|
if rows {
|
||||||
value = `space-between`
|
value = `space-between`
|
||||||
} else {
|
} else {
|
||||||
value = `stretch`
|
value = `stretch`
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1053,29 +981,27 @@ func (listView *listViewData) htmlSubviews(self View, buffer *strings.Builder) {
|
||||||
}
|
}
|
||||||
|
|
||||||
value = ""
|
value = ""
|
||||||
if align, ok := enumStyledProperty(listView, VerticalAlign, TopAlign); ok {
|
switch GetListVerticalAlign(listView) {
|
||||||
switch align {
|
case TopAlign:
|
||||||
case TopAlign:
|
if (rows && wrap == ListWrapReverse) || orientation == BottomUpOrientation {
|
||||||
if (rows && wrap == ListWrapReverse) || orientation == BottomUpOrientation {
|
value = `flex-end`
|
||||||
value = `flex-end`
|
} else {
|
||||||
} else {
|
value = `flex-start`
|
||||||
value = `flex-start`
|
}
|
||||||
}
|
case BottomAlign:
|
||||||
case BottomAlign:
|
if (rows && wrap == ListWrapReverse) || orientation == BottomUpOrientation {
|
||||||
if (rows && wrap == ListWrapReverse) || orientation == BottomUpOrientation {
|
value = `flex-start`
|
||||||
value = `flex-start`
|
} else {
|
||||||
} else {
|
value = `flex-end`
|
||||||
value = `flex-end`
|
}
|
||||||
}
|
case CenterAlign:
|
||||||
case CenterAlign:
|
value = `center`
|
||||||
value = `center`
|
|
||||||
|
|
||||||
case StretchAlign:
|
case StretchAlign:
|
||||||
if rows {
|
if rows {
|
||||||
value = `stretch`
|
value = `stretch`
|
||||||
} else {
|
} else {
|
||||||
value = `space-between`
|
value = `space-between`
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1089,7 +1015,7 @@ func (listView *listViewData) htmlSubviews(self View, buffer *strings.Builder) {
|
||||||
|
|
||||||
buffer.WriteString(`">`)
|
buffer.WriteString(`">`)
|
||||||
|
|
||||||
checkbox := GetListViewCheckbox(listView, "")
|
checkbox := GetListViewCheckbox(listView)
|
||||||
if checkbox == NoneCheckbox {
|
if checkbox == NoneCheckbox {
|
||||||
listView.noneCheckboxSubviews(self, buffer)
|
listView.noneCheckboxSubviews(self, buffer)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1130,9 +1056,9 @@ func (listView *listViewData) handleCommand(self View, command string, data Data
|
||||||
}
|
}
|
||||||
|
|
||||||
func (listView *listViewData) onItemClick() {
|
func (listView *listViewData) onItemClick() {
|
||||||
current := GetCurrent(listView, "")
|
current := GetCurrent(listView)
|
||||||
if current >= 0 && !IsDisabled(listView, "") {
|
if current >= 0 && !IsDisabled(listView) {
|
||||||
checkbox := GetListViewCheckbox(listView, "")
|
checkbox := GetListViewCheckbox(listView)
|
||||||
m:
|
m:
|
||||||
switch checkbox {
|
switch checkbox {
|
||||||
case SingleCheckbox:
|
case SingleCheckbox:
|
||||||
|
@ -1191,121 +1117,67 @@ func (listView *listViewData) onItemResize(self View, index string, x, y, width,
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetVerticalAlign return the vertical align of a list: TopAlign (0), BottomAlign (1), CenterAlign (2), StretchAlign (3)
|
// GetVerticalAlign return the vertical align of a list: TopAlign (0), BottomAlign (1), CenterAlign (2), StretchAlign (3)
|
||||||
func GetVerticalAlign(view View) int {
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
if align, ok := enumProperty(view, VerticalAlign, view.Session(), TopAlign); ok {
|
func GetVerticalAlign(view View, subviewID ...string) int {
|
||||||
return align
|
return enumStyledProperty(view, subviewID, VerticalAlign, TopAlign, false)
|
||||||
}
|
|
||||||
return TopAlign
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHorizontalAlign return the vertical align of a list: LeftAlign (0), RightAlign (1), CenterAlign (2), StretchAlign (3)
|
// GetHorizontalAlign return the vertical align of a list/checkbox: LeftAlign (0), RightAlign (1), CenterAlign (2), StretchAlign (3)
|
||||||
func GetHorizontalAlign(view View) int {
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
if align, ok := enumProperty(view, HorizontalAlign, view.Session(), LeftAlign); ok {
|
func GetHorizontalAlign(view View, subviewID ...string) int {
|
||||||
return align
|
return enumStyledProperty(view, subviewID, HorizontalAlign, LeftAlign, false)
|
||||||
}
|
|
||||||
return LeftAlign
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetListItemClickedListeners returns a ListItemClickedListener of the ListView.
|
// GetListItemClickedListeners returns a ListItemClickedListener of the ListView.
|
||||||
// If there are no listeners then the empty list is returned
|
// If there are no listeners then the empty list is returned
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetListItemClickedListeners(view View, subviewID string) []func(ListView, int) {
|
func GetListItemClickedListeners(view View, subviewID ...string) []func(ListView, int) {
|
||||||
if subviewID != "" {
|
return getEventListeners[ListView, int](view, subviewID, ListItemClickedEvent)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if value := view.Get(ListItemClickedEvent); value != nil {
|
|
||||||
if result, ok := value.([]func(ListView, int)); ok {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []func(ListView, int){}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetListItemSelectedListeners returns a ListItemSelectedListener of the ListView.
|
// GetListItemSelectedListeners returns a ListItemSelectedListener of the ListView.
|
||||||
// If there are no listeners then the empty list is returned
|
// If there are no listeners then the empty list is returned
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetListItemSelectedListeners(view View, subviewID string) []func(ListView, int) {
|
func GetListItemSelectedListeners(view View, subviewID ...string) []func(ListView, int) {
|
||||||
if subviewID != "" {
|
return getEventListeners[ListView, int](view, subviewID, ListItemSelectedEvent)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if value := view.Get(ListItemSelectedEvent); value != nil {
|
|
||||||
if result, ok := value.([]func(ListView, int)); ok {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []func(ListView, int){}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetListItemCheckedListeners returns a ListItemCheckedListener of the ListView.
|
// GetListItemCheckedListeners returns a ListItemCheckedListener of the ListView.
|
||||||
// If there are no listeners then the empty list is returned
|
// If there are no listeners then the empty list is returned
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetListItemCheckedListeners(view View, subviewID string) []func(ListView, []int) {
|
func GetListItemCheckedListeners(view View, subviewID ...string) []func(ListView, []int) {
|
||||||
if subviewID != "" {
|
return getEventListeners[ListView, []int](view, subviewID, ListItemCheckedEvent)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if value := view.Get(ListItemCheckedEvent); value != nil {
|
|
||||||
if result, ok := value.([]func(ListView, []int)); ok {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []func(ListView, []int){}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetListItemWidth returns the width of a ListView item.
|
// GetListItemWidth returns the width of a ListView item.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetListItemWidth(view View, subviewID string) SizeUnit {
|
func GetListItemWidth(view View, subviewID ...string) SizeUnit {
|
||||||
if subviewID != "" {
|
return sizeStyledProperty(view, subviewID, ItemWidth, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
result, _ := sizeProperty(view, ItemWidth, view.Session())
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
return AutoSize()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetListItemHeight returns the height of a ListView item.
|
// GetListItemHeight returns the height of a ListView item.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetListItemHeight(view View, subviewID string) SizeUnit {
|
func GetListItemHeight(view View, subviewID ...string) SizeUnit {
|
||||||
if subviewID != "" {
|
return sizeStyledProperty(view, subviewID, ItemHeight, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
result, _ := sizeProperty(view, ItemHeight, view.Session())
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
return AutoSize()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetListViewCheckbox returns the ListView checkbox type: NoneCheckbox (0), SingleCheckbox (1), or MultipleCheckbox (2).
|
// GetListViewCheckbox returns the ListView checkbox type: NoneCheckbox (0), SingleCheckbox (1), or MultipleCheckbox (2).
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetListViewCheckbox(view View, subviewID string) int {
|
func GetListViewCheckbox(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return enumStyledProperty(view, subviewID, ItemCheckbox, 0, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
result, _ := enumProperty(view, ItemCheckbox, view.Session(), 0)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetListViewCheckedItems returns the array of ListView checked items.
|
// GetListViewCheckedItems returns the array of ListView checked items.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetListViewCheckedItems(view View, subviewID string) []int {
|
func GetListViewCheckedItems(view View, subviewID ...string) []int {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
if view != nil {
|
if view != nil {
|
||||||
if listView, ok := view.(ListView); ok {
|
if listView, ok := view.(ListView); ok {
|
||||||
checkedItems := listView.getCheckedItems()
|
checkedItems := listView.getCheckedItems()
|
||||||
switch GetListViewCheckbox(view, "") {
|
switch GetListViewCheckbox(view) {
|
||||||
case NoneCheckbox:
|
case NoneCheckbox:
|
||||||
return []int{}
|
return []int{}
|
||||||
|
|
||||||
|
@ -1334,66 +1206,34 @@ func IsListViewCheckedItem(view View, subviewID string, index int) bool {
|
||||||
|
|
||||||
// GetListViewCheckboxVerticalAlign returns the vertical align of the ListView checkbox:
|
// GetListViewCheckboxVerticalAlign returns the vertical align of the ListView checkbox:
|
||||||
// TopAlign (0), BottomAlign (1), CenterAlign (2)
|
// TopAlign (0), BottomAlign (1), CenterAlign (2)
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetListViewCheckboxVerticalAlign(view View, subviewID string) int {
|
func GetListViewCheckboxVerticalAlign(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return enumStyledProperty(view, subviewID, CheckboxVerticalAlign, TopAlign, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if align, ok := enumProperty(view, CheckboxVerticalAlign, view.Session(), TopAlign); ok {
|
|
||||||
return align
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TopAlign
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetListViewCheckboxHorizontalAlign returns the horizontal align of the ListView checkbox:
|
// GetListViewCheckboxHorizontalAlign returns the horizontal align of the ListView checkbox:
|
||||||
// LeftAlign (0), RightAlign (1), CenterAlign (2)
|
// LeftAlign (0), RightAlign (1), CenterAlign (2)
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetListViewCheckboxHorizontalAlign(view View, subviewID string) int {
|
func GetListViewCheckboxHorizontalAlign(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return enumStyledProperty(view, subviewID, CheckboxHorizontalAlign, LeftAlign, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if align, ok := enumProperty(view, CheckboxHorizontalAlign, view.Session(), LeftAlign); ok {
|
|
||||||
return align
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return LeftAlign
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetListItemVerticalAlign returns the vertical align of the ListView item content:
|
// GetListItemVerticalAlign returns the vertical align of the ListView item content:
|
||||||
// TopAlign (0), BottomAlign (1), CenterAlign (2)
|
// TopAlign (0), BottomAlign (1), CenterAlign (2)
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetListItemVerticalAlign(view View, subviewID string) int {
|
func GetListItemVerticalAlign(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return enumStyledProperty(view, subviewID, ItemVerticalAlign, TopAlign, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if align, ok := enumProperty(view, ItemVerticalAlign, view.Session(), TopAlign); ok {
|
|
||||||
return align
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TopAlign
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ItemHorizontalAlign returns the horizontal align of the ListView item content:
|
// ItemHorizontalAlign returns the horizontal align of the ListView item content:
|
||||||
// LeftAlign (0), RightAlign (1), CenterAlign (2), StretchAlign (3)
|
// LeftAlign (0), RightAlign (1), CenterAlign (2), StretchAlign (3)
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetListItemHorizontalAlign(view View, subviewID string) int {
|
func GetListItemHorizontalAlign(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return enumStyledProperty(view, subviewID, ItemHorizontalAlign, LeftAlign, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if align, ok := enumProperty(view, ItemHorizontalAlign, view.Session(), LeftAlign); ok {
|
|
||||||
return align
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return LeftAlign
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetListItemFrame - returns the location and size of the ListView item in pixels.
|
// GetListItemFrame - returns the location and size of the ListView item in pixels.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetListItemFrame(view View, subviewID string, index int) Frame {
|
func GetListItemFrame(view View, subviewID string, index int) Frame {
|
||||||
if subviewID != "" {
|
if subviewID != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID)
|
||||||
|
@ -1410,10 +1250,10 @@ func GetListItemFrame(view View, subviewID string, index int) Frame {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetListViewAdapter - returns the ListView adapter.
|
// GetListViewAdapter - returns the ListView adapter.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetListViewAdapter(view View, subviewID string) ListAdapter {
|
func GetListViewAdapter(view View, subviewID ...string) ListAdapter {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view != nil {
|
if view != nil {
|
||||||
if value := view.Get(Items); value != nil {
|
if value := view.Get(Items); value != nil {
|
||||||
|
@ -1426,11 +1266,12 @@ func GetListViewAdapter(view View, subviewID string) ListAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReloadListViewData updates ListView content
|
// ReloadListViewData updates ListView content
|
||||||
// If the second argument (subviewID) is "" then content the first argument (view) is updated.
|
// If the second argument (subviewID) is not specified or it is "" then content the first argument (view) is updated.
|
||||||
func ReloadListViewData(view View, subviewID string) {
|
func ReloadListViewData(view View, subviewID ...string) {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
if view != nil {
|
if view != nil {
|
||||||
if listView, ok := view.(ListView); ok {
|
if listView, ok := view.(ListView); ok {
|
||||||
listView.ReloadListViewData()
|
listView.ReloadListViewData()
|
||||||
|
|
214
mediaPlayer.go
214
mediaPlayer.go
|
@ -163,8 +163,8 @@ type MediaSource struct {
|
||||||
MimeType string
|
MimeType string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (player *mediaPlayerData) Init(session Session) {
|
func (player *mediaPlayerData) init(session Session) {
|
||||||
player.viewData.Init(session)
|
player.viewData.init(session)
|
||||||
player.tag = "MediaPlayer"
|
player.tag = "MediaPlayer"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,11 +185,11 @@ func (player *mediaPlayerData) remove(tag string) {
|
||||||
player.propertyChanged(tag)
|
player.propertyChanged(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (player *mediaPlayerData) Set(tag string, value interface{}) bool {
|
func (player *mediaPlayerData) Set(tag string, value any) bool {
|
||||||
return player.set(strings.ToLower(tag), value)
|
return player.set(strings.ToLower(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (player *mediaPlayerData) set(tag string, value interface{}) bool {
|
func (player *mediaPlayerData) set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
player.remove(tag)
|
player.remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -205,7 +205,7 @@ func (player *mediaPlayerData) set(tag string, value interface{}) bool {
|
||||||
case AbortEvent, CanPlayEvent, CanPlayThroughEvent, CompleteEvent, EmptiedEvent, LoadStartEvent,
|
case AbortEvent, CanPlayEvent, CanPlayThroughEvent, CompleteEvent, EmptiedEvent, LoadStartEvent,
|
||||||
EndedEvent, LoadedDataEvent, LoadedMetadataEvent, PauseEvent, PlayEvent, PlayingEvent,
|
EndedEvent, LoadedDataEvent, LoadedMetadataEvent, PauseEvent, PlayEvent, PlayingEvent,
|
||||||
ProgressEvent, SeekedEvent, SeekingEvent, StalledEvent, SuspendEvent, WaitingEvent:
|
ProgressEvent, SeekedEvent, SeekingEvent, StalledEvent, SuspendEvent, WaitingEvent:
|
||||||
if listeners, ok := valueToPlayerListeners(value); ok {
|
if listeners, ok := valueToNoParamListeners[MediaPlayer](value); ok {
|
||||||
if listeners == nil {
|
if listeners == nil {
|
||||||
delete(player.properties, tag)
|
delete(player.properties, tag)
|
||||||
} else {
|
} else {
|
||||||
|
@ -218,7 +218,7 @@ func (player *mediaPlayerData) set(tag string, value interface{}) bool {
|
||||||
notCompatibleType(tag, value)
|
notCompatibleType(tag, value)
|
||||||
|
|
||||||
case DurationChangedEvent, RateChangedEvent, TimeUpdateEvent, VolumeChangedEvent:
|
case DurationChangedEvent, RateChangedEvent, TimeUpdateEvent, VolumeChangedEvent:
|
||||||
if listeners, ok := valueToPlayerTimeListeners(value); ok {
|
if listeners, ok := valueToEventListeners[MediaPlayer, float64](value); ok {
|
||||||
if listeners == nil {
|
if listeners == nil {
|
||||||
delete(player.properties, tag)
|
delete(player.properties, tag)
|
||||||
} else {
|
} else {
|
||||||
|
@ -257,7 +257,7 @@ func (player *mediaPlayerData) set(tag string, value interface{}) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (player *mediaPlayerData) setSource(value interface{}) bool {
|
func (player *mediaPlayerData) setSource(value any) bool {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case string:
|
case string:
|
||||||
src := MediaSource{Url: value, MimeType: ""}
|
src := MediaSource{Url: value, MimeType: ""}
|
||||||
|
@ -311,203 +311,7 @@ func (player *mediaPlayerData) setSource(value interface{}) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func valueToPlayerListeners(value interface{}) ([]func(MediaPlayer), bool) {
|
func valueToPlayerErrorListeners(value any) ([]func(MediaPlayer, int, string), bool) {
|
||||||
if value == nil {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
|
|
||||||
switch value := value.(type) {
|
|
||||||
case func(MediaPlayer):
|
|
||||||
return []func(MediaPlayer){value}, true
|
|
||||||
|
|
||||||
case func():
|
|
||||||
fn := func(MediaPlayer) {
|
|
||||||
value()
|
|
||||||
}
|
|
||||||
return []func(MediaPlayer){fn}, true
|
|
||||||
|
|
||||||
case []func(MediaPlayer):
|
|
||||||
if len(value) == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
for _, fn := range value {
|
|
||||||
if fn == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value, true
|
|
||||||
|
|
||||||
case []func():
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(MediaPlayer), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
listeners[i] = func(MediaPlayer) {
|
|
||||||
v()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(MediaPlayer), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
switch v := v.(type) {
|
|
||||||
case func(MediaPlayer):
|
|
||||||
listeners[i] = v
|
|
||||||
|
|
||||||
case func():
|
|
||||||
listeners[i] = func(MediaPlayer) {
|
|
||||||
v()
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func valueToPlayerTimeListeners(value interface{}) ([]func(MediaPlayer, float64), bool) {
|
|
||||||
if value == nil {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
|
|
||||||
switch value := value.(type) {
|
|
||||||
case func(MediaPlayer, float64):
|
|
||||||
return []func(MediaPlayer, float64){value}, true
|
|
||||||
|
|
||||||
case func(float64):
|
|
||||||
fn := func(_ MediaPlayer, time float64) {
|
|
||||||
value(time)
|
|
||||||
}
|
|
||||||
return []func(MediaPlayer, float64){fn}, true
|
|
||||||
|
|
||||||
case func(MediaPlayer):
|
|
||||||
fn := func(player MediaPlayer, _ float64) {
|
|
||||||
value(player)
|
|
||||||
}
|
|
||||||
return []func(MediaPlayer, float64){fn}, true
|
|
||||||
|
|
||||||
case func():
|
|
||||||
fn := func(MediaPlayer, float64) {
|
|
||||||
value()
|
|
||||||
}
|
|
||||||
return []func(MediaPlayer, float64){fn}, true
|
|
||||||
|
|
||||||
case []func(MediaPlayer, float64):
|
|
||||||
if len(value) == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
for _, fn := range value {
|
|
||||||
if fn == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value, true
|
|
||||||
|
|
||||||
case []func(float64):
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(MediaPlayer, float64), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
listeners[i] = func(_ MediaPlayer, time float64) {
|
|
||||||
v(time)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
|
|
||||||
case []func(MediaPlayer):
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(MediaPlayer, float64), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
listeners[i] = func(player MediaPlayer, _ float64) {
|
|
||||||
v(player)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
|
|
||||||
case []func():
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(MediaPlayer, float64), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
listeners[i] = func(MediaPlayer, float64) {
|
|
||||||
v()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(MediaPlayer, float64), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
switch v := v.(type) {
|
|
||||||
case func(MediaPlayer, float64):
|
|
||||||
listeners[i] = v
|
|
||||||
|
|
||||||
case func(float64):
|
|
||||||
listeners[i] = func(_ MediaPlayer, time float64) {
|
|
||||||
v(time)
|
|
||||||
}
|
|
||||||
|
|
||||||
case func(MediaPlayer):
|
|
||||||
listeners[i] = func(player MediaPlayer, _ float64) {
|
|
||||||
v(player)
|
|
||||||
}
|
|
||||||
|
|
||||||
case func():
|
|
||||||
listeners[i] = func(MediaPlayer, float64) {
|
|
||||||
v()
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func valueToPlayerErrorListeners(value interface{}) ([]func(MediaPlayer, int, string), bool) {
|
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return nil, true
|
return nil, true
|
||||||
}
|
}
|
||||||
|
@ -593,7 +397,7 @@ func valueToPlayerErrorListeners(value interface{}) ([]func(MediaPlayer, int, st
|
||||||
}
|
}
|
||||||
return listeners, true
|
return listeners, true
|
||||||
|
|
||||||
case []interface{}:
|
case []any:
|
||||||
count := len(value)
|
count := len(value)
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
return nil, true
|
return nil, true
|
||||||
|
|
207
mouseEvents.go
207
mouseEvents.go
|
@ -144,131 +144,6 @@ type MouseEvent struct {
|
||||||
MetaKey bool
|
MetaKey bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func valueToMouseListeners(value interface{}) ([]func(View, MouseEvent), bool) {
|
|
||||||
if value == nil {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
|
|
||||||
switch value := value.(type) {
|
|
||||||
case func(View, MouseEvent):
|
|
||||||
return []func(View, MouseEvent){value}, true
|
|
||||||
|
|
||||||
case func(MouseEvent):
|
|
||||||
fn := func(_ View, event MouseEvent) {
|
|
||||||
value(event)
|
|
||||||
}
|
|
||||||
return []func(View, MouseEvent){fn}, true
|
|
||||||
|
|
||||||
case func(View):
|
|
||||||
fn := func(view View, _ MouseEvent) {
|
|
||||||
value(view)
|
|
||||||
}
|
|
||||||
return []func(View, MouseEvent){fn}, true
|
|
||||||
|
|
||||||
case func():
|
|
||||||
fn := func(View, MouseEvent) {
|
|
||||||
value()
|
|
||||||
}
|
|
||||||
return []func(View, MouseEvent){fn}, true
|
|
||||||
|
|
||||||
case []func(View, MouseEvent):
|
|
||||||
if len(value) == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
for _, fn := range value {
|
|
||||||
if fn == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value, true
|
|
||||||
|
|
||||||
case []func(MouseEvent):
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(View, MouseEvent), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
listeners[i] = func(_ View, event MouseEvent) {
|
|
||||||
v(event)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
|
|
||||||
case []func(View):
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(View, MouseEvent), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
listeners[i] = func(view View, _ MouseEvent) {
|
|
||||||
v(view)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
|
|
||||||
case []func():
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(View, MouseEvent), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
listeners[i] = func(View, MouseEvent) {
|
|
||||||
v()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(View, MouseEvent), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
switch v := v.(type) {
|
|
||||||
case func(View, MouseEvent):
|
|
||||||
listeners[i] = v
|
|
||||||
|
|
||||||
case func(MouseEvent):
|
|
||||||
listeners[i] = func(_ View, event MouseEvent) {
|
|
||||||
v(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
case func(View):
|
|
||||||
listeners[i] = func(view View, _ MouseEvent) {
|
|
||||||
v(view)
|
|
||||||
}
|
|
||||||
|
|
||||||
case func():
|
|
||||||
listeners[i] = func(View, MouseEvent) {
|
|
||||||
v()
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
var mouseEvents = map[string]struct{ jsEvent, jsFunc string }{
|
var mouseEvents = map[string]struct{ jsEvent, jsFunc string }{
|
||||||
ClickEvent: {jsEvent: "onclick", jsFunc: "clickEvent"},
|
ClickEvent: {jsEvent: "onclick", jsFunc: "clickEvent"},
|
||||||
DoubleClickEvent: {jsEvent: "ondblclick", jsFunc: "doubleClickEvent"},
|
DoubleClickEvent: {jsEvent: "ondblclick", jsFunc: "doubleClickEvent"},
|
||||||
|
@ -280,8 +155,8 @@ var mouseEvents = map[string]struct{ jsEvent, jsFunc string }{
|
||||||
ContextMenuEvent: {jsEvent: "oncontextmenu", jsFunc: "contextMenuEvent"},
|
ContextMenuEvent: {jsEvent: "oncontextmenu", jsFunc: "contextMenuEvent"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *viewData) setMouseListener(tag string, value interface{}) bool {
|
func (view *viewData) setMouseListener(tag string, value any) bool {
|
||||||
listeners, ok := valueToMouseListeners(value)
|
listeners, ok := valueToEventListeners[View, MouseEvent](value)
|
||||||
if !ok {
|
if !ok {
|
||||||
notCompatibleType(tag, value)
|
notCompatibleType(tag, value)
|
||||||
return false
|
return false
|
||||||
|
@ -309,20 +184,6 @@ func (view *viewData) removeMouseListener(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getMouseListeners(view View, subviewID string, tag string) []func(View, MouseEvent) {
|
|
||||||
if subviewID != "" {
|
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if value := view.Get(tag); value != nil {
|
|
||||||
if result, ok := value.([]func(View, MouseEvent)); ok {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []func(View, MouseEvent){}
|
|
||||||
}
|
|
||||||
|
|
||||||
func mouseEventsHtml(view View, buffer *strings.Builder) {
|
func mouseEventsHtml(view View, buffer *strings.Builder) {
|
||||||
for tag, js := range mouseEvents {
|
for tag, js := range mouseEvents {
|
||||||
if value := view.getRaw(tag); value != nil {
|
if value := view.getRaw(tag); value != nil {
|
||||||
|
@ -363,64 +224,62 @@ func (event *MouseEvent) init(data DataObject) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMouseEvents(view View, tag string, data DataObject) {
|
func handleMouseEvents(view View, tag string, data DataObject) {
|
||||||
listeners := getMouseListeners(view, "", tag)
|
listeners := getEventListeners[View, MouseEvent](view, nil, tag)
|
||||||
if len(listeners) == 0 {
|
if len(listeners) > 0 {
|
||||||
return
|
var event MouseEvent
|
||||||
}
|
event.init(data)
|
||||||
|
|
||||||
var event MouseEvent
|
for _, listener := range listeners {
|
||||||
event.init(data)
|
listener(view, event)
|
||||||
|
}
|
||||||
for _, listener := range listeners {
|
|
||||||
listener(view, event)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetClickListeners returns the "click-event" listener list. If there are no listeners then the empty list is returned.
|
// GetClickListeners returns the "click-event" listener list. If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetClickListeners(view View, subviewID string) []func(View, MouseEvent) {
|
func GetClickListeners(view View, subviewID ...string) []func(View, MouseEvent) {
|
||||||
return getMouseListeners(view, subviewID, ClickEvent)
|
return getEventListeners[View, MouseEvent](view, subviewID, ClickEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDoubleClickListeners returns the "double-click-event" listener list. If there are no listeners then the empty list is returned.
|
// GetDoubleClickListeners returns the "double-click-event" listener list. If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetDoubleClickListeners(view View, subviewID string) []func(View, MouseEvent) {
|
func GetDoubleClickListeners(view View, subviewID ...string) []func(View, MouseEvent) {
|
||||||
return getMouseListeners(view, subviewID, DoubleClickEvent)
|
return getEventListeners[View, MouseEvent](view, subviewID, DoubleClickEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetContextMenuListeners returns the "context-menu" listener list.
|
// GetContextMenuListeners returns the "context-menu" listener list.
|
||||||
// If there are no listeners then the empty list is returned.
|
// If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetContextMenuListeners(view View, subviewID string) []func(View, MouseEvent) {
|
func GetContextMenuListeners(view View, subviewID ...string) []func(View, MouseEvent) {
|
||||||
return getMouseListeners(view, subviewID, ContextMenuEvent)
|
return getEventListeners[View, MouseEvent](view, subviewID, ContextMenuEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMouseDownListeners returns the "mouse-down" listener list. If there are no listeners then the empty list is returned.
|
// GetMouseDownListeners returns the "mouse-down" listener list. If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetMouseDownListeners(view View, subviewID string) []func(View, MouseEvent) {
|
func GetMouseDownListeners(view View, subviewID ...string) []func(View, MouseEvent) {
|
||||||
return getMouseListeners(view, subviewID, MouseDown)
|
return getEventListeners[View, MouseEvent](view, subviewID, MouseDown)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMouseUpListeners returns the "mouse-up" listener list. If there are no listeners then the empty list is returned.
|
// GetMouseUpListeners returns the "mouse-up" listener list. If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetMouseUpListeners(view View, subviewID string) []func(View, MouseEvent) {
|
func GetMouseUpListeners(view View, subviewID ...string) []func(View, MouseEvent) {
|
||||||
return getMouseListeners(view, subviewID, MouseUp)
|
return getEventListeners[View, MouseEvent](view, subviewID, MouseUp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMouseMoveListeners returns the "mouse-move" listener list. If there are no listeners then the empty list is returned.
|
// GetMouseMoveListeners returns the "mouse-move" listener list. If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetMouseMoveListeners(view View, subviewID string) []func(View, MouseEvent) {
|
func GetMouseMoveListeners(view View, subviewID ...string) []func(View, MouseEvent) {
|
||||||
return getMouseListeners(view, subviewID, MouseMove)
|
return getEventListeners[View, MouseEvent](view, subviewID, MouseMove)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMouseOverListeners returns the "mouse-over" listener list. If there are no listeners then the empty list is returned.
|
// GetMouseOverListeners returns the "mouse-over" listener list. If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetMouseOverListeners(view View, subviewID string) []func(View, MouseEvent) {
|
func GetMouseOverListeners(view View, subviewID ...string) []func(View, MouseEvent) {
|
||||||
return getMouseListeners(view, subviewID, MouseOver)
|
return getEventListeners[View, MouseEvent](view, subviewID, MouseOver)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMouseOutListeners returns the "mouse-out" listener list. If there are no listeners then the empty list is returned.
|
// GetMouseOutListeners returns the "mouse-out" listener list. If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetMouseOutListeners(view View, subviewID string) []func(View, MouseEvent) {
|
func GetMouseOutListeners(view View, subviewID ...string) []func(View, MouseEvent) {
|
||||||
return getMouseListeners(view, subviewID, MouseOut)
|
return getEventListeners[View, MouseEvent](view, subviewID, MouseOut)
|
||||||
}
|
}
|
||||||
|
|
223
numberPicker.go
223
numberPicker.go
|
@ -36,7 +36,7 @@ type numberPickerData struct {
|
||||||
// NewNumberPicker create new NumberPicker object and return it
|
// NewNumberPicker create new NumberPicker object and return it
|
||||||
func NewNumberPicker(session Session, params Params) NumberPicker {
|
func NewNumberPicker(session Session, params Params) NumberPicker {
|
||||||
view := new(numberPickerData)
|
view := new(numberPickerData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -45,8 +45,8 @@ func newNumberPicker(session Session) View {
|
||||||
return NewNumberPicker(session, nil)
|
return NewNumberPicker(session, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *numberPickerData) Init(session Session) {
|
func (picker *numberPickerData) init(session Session) {
|
||||||
picker.viewData.Init(session)
|
picker.viewData.init(session)
|
||||||
picker.tag = "NumberPicker"
|
picker.tag = "NumberPicker"
|
||||||
picker.numberChangedListeners = []func(NumberPicker, float64){}
|
picker.numberChangedListeners = []func(NumberPicker, float64){}
|
||||||
}
|
}
|
||||||
|
@ -87,11 +87,11 @@ func (picker *numberPickerData) remove(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *numberPickerData) Set(tag string, value interface{}) bool {
|
func (picker *numberPickerData) Set(tag string, value any) bool {
|
||||||
return picker.set(picker.normalizeTag(tag), value)
|
return picker.set(picker.normalizeTag(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *numberPickerData) set(tag string, value interface{}) bool {
|
func (picker *numberPickerData) set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
picker.remove(tag)
|
picker.remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -99,65 +99,28 @@ func (picker *numberPickerData) set(tag string, value interface{}) bool {
|
||||||
|
|
||||||
switch tag {
|
switch tag {
|
||||||
case NumberChangedEvent:
|
case NumberChangedEvent:
|
||||||
switch value := value.(type) {
|
listeners, ok := valueToEventListeners[NumberPicker, float64](value)
|
||||||
case func(NumberPicker, float64):
|
if !ok {
|
||||||
picker.numberChangedListeners = []func(NumberPicker, float64){value}
|
notCompatibleType(tag, value)
|
||||||
|
return false
|
||||||
case func(float64):
|
} else if listeners == nil {
|
||||||
fn := func(_ NumberPicker, newValue float64) {
|
listeners = []func(NumberPicker, float64){}
|
||||||
value(newValue)
|
|
||||||
}
|
|
||||||
picker.numberChangedListeners = []func(NumberPicker, float64){fn}
|
|
||||||
|
|
||||||
case []func(NumberPicker, float64):
|
|
||||||
picker.numberChangedListeners = value
|
|
||||||
|
|
||||||
case []func(float64):
|
|
||||||
listeners := make([]func(NumberPicker, float64), len(value))
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
notCompatibleType(tag, val)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
listeners[i] = func(_ NumberPicker, newValue float64) {
|
|
||||||
val(newValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
picker.numberChangedListeners = listeners
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
listeners := make([]func(NumberPicker, float64), len(value))
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
notCompatibleType(tag, val)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
switch val := val.(type) {
|
|
||||||
case func(NumberPicker, float64):
|
|
||||||
listeners[i] = val
|
|
||||||
|
|
||||||
default:
|
|
||||||
notCompatibleType(tag, val)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
picker.numberChangedListeners = listeners
|
|
||||||
}
|
}
|
||||||
|
picker.numberChangedListeners = listeners
|
||||||
picker.propertyChangedEvent(tag)
|
picker.propertyChangedEvent(tag)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
case NumberPickerValue:
|
case NumberPickerValue:
|
||||||
oldValue := GetNumberPickerValue(picker, "")
|
oldValue := GetNumberPickerValue(picker)
|
||||||
min, max := GetNumberPickerMinMax(picker, "")
|
min, max := GetNumberPickerMinMax(picker)
|
||||||
if picker.setFloatProperty(NumberPickerValue, value, min, max) {
|
if picker.setFloatProperty(NumberPickerValue, value, min, max) {
|
||||||
if newValue := GetNumberPickerValue(picker, ""); oldValue != newValue {
|
if f, ok := floatProperty(picker, NumberPickerValue, picker.Session(), min); ok && f != oldValue {
|
||||||
|
newValue, _ := floatTextProperty(picker, NumberPickerValue, picker.Session(), min)
|
||||||
if picker.created {
|
if picker.created {
|
||||||
picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%f')`, picker.htmlID(), newValue))
|
picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), newValue))
|
||||||
}
|
}
|
||||||
for _, listener := range picker.numberChangedListeners {
|
for _, listener := range picker.numberChangedListeners {
|
||||||
listener(picker, newValue)
|
listener(picker, f)
|
||||||
}
|
}
|
||||||
picker.propertyChangedEvent(tag)
|
picker.propertyChangedEvent(tag)
|
||||||
}
|
}
|
||||||
|
@ -177,29 +140,29 @@ func (picker *numberPickerData) propertyChanged(tag string) {
|
||||||
if picker.created {
|
if picker.created {
|
||||||
switch tag {
|
switch tag {
|
||||||
case NumberPickerType:
|
case NumberPickerType:
|
||||||
if GetNumberPickerType(picker, "") == NumberSlider {
|
if GetNumberPickerType(picker) == NumberSlider {
|
||||||
updateProperty(picker.htmlID(), "type", "range", picker.session)
|
updateProperty(picker.htmlID(), "type", "range", picker.session)
|
||||||
} else {
|
} else {
|
||||||
updateProperty(picker.htmlID(), "type", "number", picker.session)
|
updateProperty(picker.htmlID(), "type", "number", picker.session)
|
||||||
}
|
}
|
||||||
|
|
||||||
case NumberPickerMin:
|
case NumberPickerMin:
|
||||||
min, _ := GetNumberPickerMinMax(picker, "")
|
min, _ := GetNumberPickerMinMax(picker)
|
||||||
updateProperty(picker.htmlID(), Min, strconv.FormatFloat(min, 'f', -1, 32), picker.session)
|
updateProperty(picker.htmlID(), Min, strconv.FormatFloat(min, 'f', -1, 32), picker.session)
|
||||||
|
|
||||||
case NumberPickerMax:
|
case NumberPickerMax:
|
||||||
_, max := GetNumberPickerMinMax(picker, "")
|
_, max := GetNumberPickerMinMax(picker)
|
||||||
updateProperty(picker.htmlID(), Max, strconv.FormatFloat(max, 'f', -1, 32), picker.session)
|
updateProperty(picker.htmlID(), Max, strconv.FormatFloat(max, 'f', -1, 32), picker.session)
|
||||||
|
|
||||||
case NumberPickerStep:
|
case NumberPickerStep:
|
||||||
if step := GetNumberPickerStep(picker, ""); step > 0 {
|
if step := GetNumberPickerStep(picker); step > 0 {
|
||||||
updateProperty(picker.htmlID(), Step, strconv.FormatFloat(step, 'f', -1, 32), picker.session)
|
updateProperty(picker.htmlID(), Step, strconv.FormatFloat(step, 'f', -1, 32), picker.session)
|
||||||
} else {
|
} else {
|
||||||
updateProperty(picker.htmlID(), Step, "any", picker.session)
|
updateProperty(picker.htmlID(), Step, "any", picker.session)
|
||||||
}
|
}
|
||||||
|
|
||||||
case NumberPickerValue:
|
case NumberPickerValue:
|
||||||
value := GetNumberPickerValue(picker, "")
|
value := GetNumberPickerValue(picker)
|
||||||
picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%f')`, picker.htmlID(), value))
|
picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%f')`, picker.htmlID(), value))
|
||||||
for _, listener := range picker.numberChangedListeners {
|
for _, listener := range picker.numberChangedListeners {
|
||||||
listener(picker, value)
|
listener(picker, value)
|
||||||
|
@ -208,11 +171,11 @@ func (picker *numberPickerData) propertyChanged(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *numberPickerData) Get(tag string) interface{} {
|
func (picker *numberPickerData) Get(tag string) any {
|
||||||
return picker.get(picker.normalizeTag(tag))
|
return picker.get(picker.normalizeTag(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *numberPickerData) get(tag string) interface{} {
|
func (picker *numberPickerData) get(tag string) any {
|
||||||
switch tag {
|
switch tag {
|
||||||
case NumberChangedEvent:
|
case NumberChangedEvent:
|
||||||
return picker.numberChangedListeners
|
return picker.numberChangedListeners
|
||||||
|
@ -229,13 +192,13 @@ func (picker *numberPickerData) htmlTag() string {
|
||||||
func (picker *numberPickerData) htmlProperties(self View, buffer *strings.Builder) {
|
func (picker *numberPickerData) htmlProperties(self View, buffer *strings.Builder) {
|
||||||
picker.viewData.htmlProperties(self, buffer)
|
picker.viewData.htmlProperties(self, buffer)
|
||||||
|
|
||||||
if GetNumberPickerType(picker, "") == NumberSlider {
|
if GetNumberPickerType(picker) == NumberSlider {
|
||||||
buffer.WriteString(` type="range"`)
|
buffer.WriteString(` type="range"`)
|
||||||
} else {
|
} else {
|
||||||
buffer.WriteString(` type="number"`)
|
buffer.WriteString(` type="number"`)
|
||||||
}
|
}
|
||||||
|
|
||||||
min, max := GetNumberPickerMinMax(picker, "")
|
min, max := GetNumberPickerMinMax(picker)
|
||||||
if min != math.Inf(-1) {
|
if min != math.Inf(-1) {
|
||||||
buffer.WriteString(` min="`)
|
buffer.WriteString(` min="`)
|
||||||
buffer.WriteString(strconv.FormatFloat(min, 'f', -1, 64))
|
buffer.WriteString(strconv.FormatFloat(min, 'f', -1, 64))
|
||||||
|
@ -248,7 +211,7 @@ func (picker *numberPickerData) htmlProperties(self View, buffer *strings.Builde
|
||||||
buffer.WriteByte('"')
|
buffer.WriteByte('"')
|
||||||
}
|
}
|
||||||
|
|
||||||
step := GetNumberPickerStep(picker, "")
|
step := GetNumberPickerStep(picker)
|
||||||
if step != 0 {
|
if step != 0 {
|
||||||
buffer.WriteString(` step="`)
|
buffer.WriteString(` step="`)
|
||||||
buffer.WriteString(strconv.FormatFloat(step, 'f', -1, 64))
|
buffer.WriteString(strconv.FormatFloat(step, 'f', -1, 64))
|
||||||
|
@ -258,14 +221,14 @@ func (picker *numberPickerData) htmlProperties(self View, buffer *strings.Builde
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.WriteString(` value="`)
|
buffer.WriteString(` value="`)
|
||||||
buffer.WriteString(strconv.FormatFloat(GetNumberPickerValue(picker, ""), 'f', -1, 64))
|
buffer.WriteString(strconv.FormatFloat(GetNumberPickerValue(picker), 'f', -1, 64))
|
||||||
buffer.WriteByte('"')
|
buffer.WriteByte('"')
|
||||||
|
|
||||||
buffer.WriteString(` oninput="editViewInputEvent(this)"`)
|
buffer.WriteString(` oninput="editViewInputEvent(this)"`)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *numberPickerData) htmlDisabledProperties(self View, buffer *strings.Builder) {
|
func (picker *numberPickerData) htmlDisabledProperties(self View, buffer *strings.Builder) {
|
||||||
if IsDisabled(self, "") {
|
if IsDisabled(self) {
|
||||||
buffer.WriteString(` disabled`)
|
buffer.WriteString(` disabled`)
|
||||||
}
|
}
|
||||||
picker.viewData.htmlDisabledProperties(self, buffer)
|
picker.viewData.htmlDisabledProperties(self, buffer)
|
||||||
|
@ -276,8 +239,8 @@ func (picker *numberPickerData) handleCommand(self View, command string, data Da
|
||||||
case "textChanged":
|
case "textChanged":
|
||||||
if text, ok := data.PropertyValue("text"); ok {
|
if text, ok := data.PropertyValue("text"); ok {
|
||||||
if value, err := strconv.ParseFloat(text, 32); err == nil {
|
if value, err := strconv.ParseFloat(text, 32); err == nil {
|
||||||
oldValue := GetNumberPickerValue(picker, "")
|
oldValue := GetNumberPickerValue(picker)
|
||||||
picker.properties[NumberPickerValue] = value
|
picker.properties[NumberPickerValue] = text
|
||||||
if value != oldValue {
|
if value != oldValue {
|
||||||
for _, listener := range picker.numberChangedListeners {
|
for _, listener := range picker.numberChangedListeners {
|
||||||
listener(picker, value)
|
listener(picker, value)
|
||||||
|
@ -294,70 +257,50 @@ func (picker *numberPickerData) handleCommand(self View, command string, data Da
|
||||||
// GetNumberPickerType returns the type of NumberPicker subview. Valid values:
|
// GetNumberPickerType returns the type of NumberPicker subview. Valid values:
|
||||||
// NumberEditor (0) - NumberPicker is presented by editor (default type);
|
// NumberEditor (0) - NumberPicker is presented by editor (default type);
|
||||||
// NumberSlider (1) - NumberPicker is presented by slider.
|
// NumberSlider (1) - NumberPicker is presented by slider.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetNumberPickerType(view View, subviewID string) int {
|
func GetNumberPickerType(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return enumStyledProperty(view, subviewID, NumberPickerType, NumberEditor, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view == nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
t, _ := enumStyledProperty(view, NumberPickerType, NumberEditor)
|
|
||||||
return t
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNumberPickerMinMax returns the min and max value of NumberPicker subview.
|
// GetNumberPickerMinMax returns the min and max value of NumberPicker subview.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetNumberPickerMinMax(view View, subviewID string) (float64, float64) {
|
func GetNumberPickerMinMax(view View, subviewID ...string) (float64, float64) {
|
||||||
if subviewID != "" {
|
var pickerType int
|
||||||
view = ViewByID(view, subviewID)
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
|
pickerType = GetNumberPickerType(view, subviewID[0])
|
||||||
|
} else {
|
||||||
|
pickerType = GetNumberPickerType(view)
|
||||||
}
|
}
|
||||||
if view != nil {
|
|
||||||
t, _ := enumStyledProperty(view, NumberPickerType, NumberEditor)
|
|
||||||
var defMin, defMax float64
|
|
||||||
|
|
||||||
if t == NumberSlider {
|
var defMin, defMax float64
|
||||||
defMin = 0
|
if pickerType == NumberSlider {
|
||||||
defMax = 1
|
defMin = 0
|
||||||
} else {
|
defMax = 1
|
||||||
defMin = math.Inf(-1)
|
} else {
|
||||||
defMax = math.Inf(1)
|
defMin = math.Inf(-1)
|
||||||
}
|
defMax = math.Inf(1)
|
||||||
min, ok := floatStyledProperty(view, NumberPickerMin, defMin)
|
|
||||||
if !ok {
|
|
||||||
min, _ = floatStyledProperty(view, Min, defMin)
|
|
||||||
}
|
|
||||||
|
|
||||||
max, ok := floatStyledProperty(view, NumberPickerMax, defMax)
|
|
||||||
if !ok {
|
|
||||||
max, _ = floatStyledProperty(view, Max, defMax)
|
|
||||||
}
|
|
||||||
|
|
||||||
if min > max {
|
|
||||||
return max, min
|
|
||||||
}
|
|
||||||
return min, max
|
|
||||||
}
|
}
|
||||||
return 0, 1
|
|
||||||
|
min := floatStyledProperty(view, subviewID, NumberPickerMin, defMin)
|
||||||
|
max := floatStyledProperty(view, subviewID, NumberPickerMax, defMax)
|
||||||
|
|
||||||
|
if min > max {
|
||||||
|
return max, min
|
||||||
|
}
|
||||||
|
return min, max
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNumberPickerStep returns the value changing step of NumberPicker subview.
|
// GetNumberPickerStep returns the value changing step of NumberPicker subview.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetNumberPickerStep(view View, subviewID string) float64 {
|
func GetNumberPickerStep(view View, subviewID ...string) float64 {
|
||||||
if subviewID != "" {
|
var max float64
|
||||||
view = ViewByID(view, subviewID)
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
}
|
_, max = GetNumberPickerMinMax(view, subviewID[0])
|
||||||
if view == nil {
|
} else {
|
||||||
return 0
|
_, max = GetNumberPickerMinMax(view)
|
||||||
}
|
}
|
||||||
|
|
||||||
result, ok := floatStyledProperty(view, NumberPickerStep, 0)
|
result := floatStyledProperty(view, subviewID, NumberPickerStep, 0)
|
||||||
if !ok {
|
|
||||||
result, _ = floatStyledProperty(view, Step, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, max := GetNumberPickerMinMax(view, "")
|
|
||||||
if result > max {
|
if result > max {
|
||||||
return max
|
return max
|
||||||
}
|
}
|
||||||
|
@ -365,36 +308,22 @@ func GetNumberPickerStep(view View, subviewID string) float64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNumberPickerValue returns the value of NumberPicker subview.
|
// GetNumberPickerValue returns the value of NumberPicker subview.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetNumberPickerValue(view View, subviewID string) float64 {
|
func GetNumberPickerValue(view View, subviewID ...string) float64 {
|
||||||
if subviewID != "" {
|
var min float64
|
||||||
view = ViewByID(view, subviewID)
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
}
|
min, _ = GetNumberPickerMinMax(view, subviewID[0])
|
||||||
if view == nil {
|
} else {
|
||||||
return 0
|
min, _ = GetNumberPickerMinMax(view)
|
||||||
}
|
}
|
||||||
|
|
||||||
min, _ := GetNumberPickerMinMax(view, "")
|
result := floatStyledProperty(view, subviewID, NumberPickerValue, min)
|
||||||
result, ok := floatStyledProperty(view, NumberPickerValue, min)
|
|
||||||
if !ok {
|
|
||||||
result, _ = floatStyledProperty(view, Value, min)
|
|
||||||
}
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNumberChangedListeners returns the NumberChangedListener list of an NumberPicker subview.
|
// GetNumberChangedListeners returns the NumberChangedListener list of an NumberPicker subview.
|
||||||
// If there are no listeners then the empty list is returned
|
// If there are no listeners then the empty list is returned
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetNumberChangedListeners(view View, subviewID string) []func(NumberPicker, float64) {
|
func GetNumberChangedListeners(view View, subviewID ...string) []func(NumberPicker, float64) {
|
||||||
if subviewID != "" {
|
return getEventListeners[NumberPicker, float64](view, subviewID, NumberChangedEvent)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if value := view.Get(NumberChangedEvent); value != nil {
|
|
||||||
if listeners, ok := value.([]func(NumberPicker, float64)); ok {
|
|
||||||
return listeners
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []func(NumberPicker, float64){}
|
|
||||||
}
|
}
|
||||||
|
|
16
outline.go
16
outline.go
|
@ -18,7 +18,7 @@ type outlinePropertyData struct {
|
||||||
|
|
||||||
func NewOutlineProperty(params Params) OutlineProperty {
|
func NewOutlineProperty(params Params) OutlineProperty {
|
||||||
outline := new(outlinePropertyData)
|
outline := new(outlinePropertyData)
|
||||||
outline.properties = map[string]interface{}{}
|
outline.properties = map[string]any{}
|
||||||
for tag, value := range params {
|
for tag, value := range params {
|
||||||
outline.Set(tag, value)
|
outline.Set(tag, value)
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ func (outline *outlinePropertyData) Remove(tag string) {
|
||||||
delete(outline.properties, outline.normalizeTag(tag))
|
delete(outline.properties, outline.normalizeTag(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (outline *outlinePropertyData) Set(tag string, value interface{}) bool {
|
func (outline *outlinePropertyData) Set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
outline.Remove(tag)
|
outline.Remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -85,7 +85,7 @@ func (outline *outlinePropertyData) Set(tag string, value interface{}) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (outline *outlinePropertyData) Get(tag string) interface{} {
|
func (outline *outlinePropertyData) Get(tag string) any {
|
||||||
return outline.propertyList.Get(outline.normalizeTag(tag))
|
return outline.propertyList.Get(outline.normalizeTag(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,18 +103,18 @@ type ViewOutline struct {
|
||||||
Width SizeUnit
|
Width SizeUnit
|
||||||
}
|
}
|
||||||
|
|
||||||
func (outline ViewOutline) cssValue(builder cssBuilder) {
|
func (outline ViewOutline) cssValue(builder cssBuilder, session Session) {
|
||||||
values := enumProperties[BorderStyle].cssValues
|
values := enumProperties[BorderStyle].cssValues
|
||||||
if outline.Style > 0 && outline.Style < len(values) && outline.Color.Alpha() > 0 &&
|
if outline.Style > 0 && outline.Style < len(values) && outline.Color.Alpha() > 0 &&
|
||||||
outline.Width.Type != Auto && outline.Width.Type != SizeInFraction &&
|
outline.Width.Type != Auto && outline.Width.Type != SizeInFraction &&
|
||||||
outline.Width.Type != SizeInPercent && outline.Width.Value > 0 {
|
outline.Width.Type != SizeInPercent && outline.Width.Value > 0 {
|
||||||
builder.addValues("outline", " ", outline.Width.cssString("0"), values[outline.Style], outline.Color.cssString())
|
builder.addValues("outline", " ", outline.Width.cssString("0", session), values[outline.Style], outline.Color.cssString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (outline ViewOutline) cssString() string {
|
func (outline ViewOutline) cssString(session Session) string {
|
||||||
var builder cssValueBuilder
|
var builder cssValueBuilder
|
||||||
outline.cssValue(&builder)
|
outline.cssValue(&builder, session)
|
||||||
return builder.finish()
|
return builder.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ func getOutline(properties Properties) OutlineProperty {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (style *viewStyle) setOutline(value interface{}) bool {
|
func (style *viewStyle) setOutline(value any) bool {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case OutlineProperty:
|
case OutlineProperty:
|
||||||
style.properties[Outline] = value
|
style.properties[Outline] = value
|
||||||
|
|
10
params.go
10
params.go
|
@ -3,25 +3,25 @@ package rui
|
||||||
import "sort"
|
import "sort"
|
||||||
|
|
||||||
// Params defines a type of a parameters list
|
// Params defines a type of a parameters list
|
||||||
type Params map[string]interface{}
|
type Params map[string]any
|
||||||
|
|
||||||
func (params Params) Get(tag string) interface{} {
|
func (params Params) Get(tag string) any {
|
||||||
return params.getRaw(tag)
|
return params.getRaw(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (params Params) getRaw(tag string) interface{} {
|
func (params Params) getRaw(tag string) any {
|
||||||
if value, ok := params[tag]; ok {
|
if value, ok := params[tag]; ok {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (params Params) Set(tag string, value interface{}) bool {
|
func (params Params) Set(tag string, value any) bool {
|
||||||
params.setRaw(tag, value)
|
params.setRaw(tag, value)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (params Params) setRaw(tag string, value interface{}) {
|
func (params Params) setRaw(tag string, value any) {
|
||||||
if value != nil {
|
if value != nil {
|
||||||
params[tag] = value
|
params[tag] = value
|
||||||
} else {
|
} else {
|
||||||
|
|
181
pointerEvents.go
181
pointerEvents.go
|
@ -87,131 +87,6 @@ type PointerEvent struct {
|
||||||
IsPrimary bool
|
IsPrimary bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func valueToPointerListeners(value interface{}) ([]func(View, PointerEvent), bool) {
|
|
||||||
if value == nil {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
|
|
||||||
switch value := value.(type) {
|
|
||||||
case func(View, PointerEvent):
|
|
||||||
return []func(View, PointerEvent){value}, true
|
|
||||||
|
|
||||||
case func(PointerEvent):
|
|
||||||
fn := func(_ View, event PointerEvent) {
|
|
||||||
value(event)
|
|
||||||
}
|
|
||||||
return []func(View, PointerEvent){fn}, true
|
|
||||||
|
|
||||||
case func(View):
|
|
||||||
fn := func(view View, _ PointerEvent) {
|
|
||||||
value(view)
|
|
||||||
}
|
|
||||||
return []func(View, PointerEvent){fn}, true
|
|
||||||
|
|
||||||
case func():
|
|
||||||
fn := func(View, PointerEvent) {
|
|
||||||
value()
|
|
||||||
}
|
|
||||||
return []func(View, PointerEvent){fn}, true
|
|
||||||
|
|
||||||
case []func(View, PointerEvent):
|
|
||||||
if len(value) == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
for _, fn := range value {
|
|
||||||
if fn == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value, true
|
|
||||||
|
|
||||||
case []func(PointerEvent):
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(View, PointerEvent), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
listeners[i] = func(_ View, event PointerEvent) {
|
|
||||||
v(event)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
|
|
||||||
case []func(View):
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(View, PointerEvent), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
listeners[i] = func(view View, _ PointerEvent) {
|
|
||||||
v(view)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
|
|
||||||
case []func():
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(View, PointerEvent), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
listeners[i] = func(View, PointerEvent) {
|
|
||||||
v()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(View, PointerEvent), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
switch v := v.(type) {
|
|
||||||
case func(View, PointerEvent):
|
|
||||||
listeners[i] = v
|
|
||||||
|
|
||||||
case func(PointerEvent):
|
|
||||||
listeners[i] = func(_ View, event PointerEvent) {
|
|
||||||
v(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
case func(View):
|
|
||||||
listeners[i] = func(view View, _ PointerEvent) {
|
|
||||||
v(view)
|
|
||||||
}
|
|
||||||
|
|
||||||
case func():
|
|
||||||
listeners[i] = func(View, PointerEvent) {
|
|
||||||
v()
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
var pointerEvents = map[string]struct{ jsEvent, jsFunc string }{
|
var pointerEvents = map[string]struct{ jsEvent, jsFunc string }{
|
||||||
PointerDown: {jsEvent: "onpointerdown", jsFunc: "pointerDownEvent"},
|
PointerDown: {jsEvent: "onpointerdown", jsFunc: "pointerDownEvent"},
|
||||||
PointerUp: {jsEvent: "onpointerup", jsFunc: "pointerUpEvent"},
|
PointerUp: {jsEvent: "onpointerup", jsFunc: "pointerUpEvent"},
|
||||||
|
@ -221,8 +96,8 @@ var pointerEvents = map[string]struct{ jsEvent, jsFunc string }{
|
||||||
PointerOver: {jsEvent: "onpointerover", jsFunc: "pointerOverEvent"},
|
PointerOver: {jsEvent: "onpointerover", jsFunc: "pointerOverEvent"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *viewData) setPointerListener(tag string, value interface{}) bool {
|
func (view *viewData) setPointerListener(tag string, value any) bool {
|
||||||
listeners, ok := valueToPointerListeners(value)
|
listeners, ok := valueToEventListeners[View, PointerEvent](value)
|
||||||
if !ok {
|
if !ok {
|
||||||
notCompatibleType(tag, value)
|
notCompatibleType(tag, value)
|
||||||
return false
|
return false
|
||||||
|
@ -250,20 +125,6 @@ func (view *viewData) removePointerListener(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPointerListeners(view View, subviewID string, tag string) []func(View, PointerEvent) {
|
|
||||||
if subviewID != "" {
|
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if value := view.Get(tag); value != nil {
|
|
||||||
if result, ok := value.([]func(View, PointerEvent)); ok {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []func(View, PointerEvent){}
|
|
||||||
}
|
|
||||||
|
|
||||||
func pointerEventsHtml(view View, buffer *strings.Builder) {
|
func pointerEventsHtml(view View, buffer *strings.Builder) {
|
||||||
for tag, js := range pointerEvents {
|
for tag, js := range pointerEvents {
|
||||||
if value := view.getRaw(tag); value != nil {
|
if value := view.getRaw(tag); value != nil {
|
||||||
|
@ -291,7 +152,7 @@ func (event *PointerEvent) init(data DataObject) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func handlePointerEvents(view View, tag string, data DataObject) {
|
func handlePointerEvents(view View, tag string, data DataObject) {
|
||||||
listeners := getPointerListeners(view, "", tag)
|
listeners := getEventListeners[View, PointerEvent](view, nil, tag)
|
||||||
if len(listeners) == 0 {
|
if len(listeners) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -305,37 +166,37 @@ func handlePointerEvents(view View, tag string, data DataObject) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPointerDownListeners returns the "pointer-down" listener list. If there are no listeners then the empty list is returned.
|
// GetPointerDownListeners returns the "pointer-down" listener list. If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetPointerDownListeners(view View, subviewID string) []func(View, PointerEvent) {
|
func GetPointerDownListeners(view View, subviewID ...string) []func(View, PointerEvent) {
|
||||||
return getPointerListeners(view, subviewID, PointerDown)
|
return getEventListeners[View, PointerEvent](view, subviewID, PointerDown)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPointerUpListeners returns the "pointer-up" listener list. If there are no listeners then the empty list is returned.
|
// GetPointerUpListeners returns the "pointer-up" listener list. If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetPointerUpListeners(view View, subviewID string) []func(View, PointerEvent) {
|
func GetPointerUpListeners(view View, subviewID ...string) []func(View, PointerEvent) {
|
||||||
return getPointerListeners(view, subviewID, PointerUp)
|
return getEventListeners[View, PointerEvent](view, subviewID, PointerUp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPointerMoveListeners returns the "pointer-move" listener list. If there are no listeners then the empty list is returned.
|
// GetPointerMoveListeners returns the "pointer-move" listener list. If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetPointerMoveListeners(view View, subviewID string) []func(View, PointerEvent) {
|
func GetPointerMoveListeners(view View, subviewID ...string) []func(View, PointerEvent) {
|
||||||
return getPointerListeners(view, subviewID, PointerMove)
|
return getEventListeners[View, PointerEvent](view, subviewID, PointerMove)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPointerCancelListeners returns the "pointer-cancel" listener list. If there are no listeners then the empty list is returned.
|
// GetPointerCancelListeners returns the "pointer-cancel" listener list. If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetPointerCancelListeners(view View, subviewID string) []func(View, PointerEvent) {
|
func GetPointerCancelListeners(view View, subviewID ...string) []func(View, PointerEvent) {
|
||||||
return getPointerListeners(view, subviewID, PointerCancel)
|
return getEventListeners[View, PointerEvent](view, subviewID, PointerCancel)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPointerOverListeners returns the "pointer-over" listener list. If there are no listeners then the empty list is returned.
|
// GetPointerOverListeners returns the "pointer-over" listener list. If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetPointerOverListeners(view View, subviewID string) []func(View, PointerEvent) {
|
func GetPointerOverListeners(view View, subviewID ...string) []func(View, PointerEvent) {
|
||||||
return getPointerListeners(view, subviewID, PointerOver)
|
return getEventListeners[View, PointerEvent](view, subviewID, PointerOver)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPointerOutListeners returns the "pointer-out" listener list. If there are no listeners then the empty list is returned.
|
// GetPointerOutListeners returns the "pointer-out" listener list. If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetPointerOutListeners(view View, subviewID string) []func(View, PointerEvent) {
|
func GetPointerOutListeners(view View, subviewID ...string) []func(View, PointerEvent) {
|
||||||
return getPointerListeners(view, subviewID, PointerOut)
|
return getEventListeners[View, PointerEvent](view, subviewID, PointerOut)
|
||||||
}
|
}
|
||||||
|
|
520
popup.go
520
popup.go
|
@ -1,6 +1,8 @@
|
||||||
package rui
|
package rui
|
||||||
|
|
||||||
import "strings"
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Title is the constant for the "title" property tag.
|
// Title is the constant for the "title" property tag.
|
||||||
|
@ -36,6 +38,46 @@ const (
|
||||||
// It occurs after the Popup disappears from the screen.
|
// It occurs after the Popup disappears from the screen.
|
||||||
// The main listener for this event has the following format: func(Popup)
|
// The main listener for this event has the following format: func(Popup)
|
||||||
DismissEvent = "dismiss-event"
|
DismissEvent = "dismiss-event"
|
||||||
|
|
||||||
|
// Arrow is the constant for the "arrow" property tag.
|
||||||
|
// Using the "popup-arrow" int property you can add ...
|
||||||
|
Arrow = "arrow"
|
||||||
|
|
||||||
|
// ArrowAlign is the constant for the "arrow-align" property tag.
|
||||||
|
// The "arrow-align" int property is used for set the horizontal alignment of the Popup arrow.
|
||||||
|
// Valid values: LeftAlign (0), RightAlign (1), TopAlign (0), BottomAlign (1), CenterAlign (2)
|
||||||
|
ArrowAlign = "arrow-align"
|
||||||
|
|
||||||
|
// ArrowSize is the constant for the "arrow-size" property tag.
|
||||||
|
// The "arrow-size" SizeUnit property is used for set the size (length) of the Popup arrow.
|
||||||
|
ArrowSize = "arrow-size"
|
||||||
|
|
||||||
|
// ArrowWidth is the constant for the "arrow-width" property tag.
|
||||||
|
// The "arrow-width" SizeUnit property is used for set the width of the Popup arrow.
|
||||||
|
ArrowWidth = "arrow-width"
|
||||||
|
|
||||||
|
// ArrowOffset is the constant for the "arrow-offset" property tag.
|
||||||
|
// The "arrow-offset" SizeUnit property is used for set the offset of the Popup arrow.
|
||||||
|
ArrowOffset = "arrow-offset"
|
||||||
|
|
||||||
|
// NoneArrow is value of the popup "arrow" property: no arrow
|
||||||
|
NoneArrow = 0
|
||||||
|
|
||||||
|
// TopArrow is value of the popup "arrow" property:
|
||||||
|
// Arrow at the top side of the pop-up window
|
||||||
|
TopArrow = 1
|
||||||
|
|
||||||
|
// RightArrow is value of the popup "arrow" property:
|
||||||
|
// Arrow on the right side of the pop-up window
|
||||||
|
RightArrow = 2
|
||||||
|
|
||||||
|
// BottomArrow is value of the popup "arrow" property:
|
||||||
|
// Arrow at the bottom of the pop-up window
|
||||||
|
BottomArrow = 3
|
||||||
|
|
||||||
|
// LeftArrow is value of the popup "arrow" property:
|
||||||
|
// Arrow on the left side of the pop-up window
|
||||||
|
LeftArrow = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
// PopupButton describes a button that will be placed at the bottom of the window.
|
// PopupButton describes a button that will be placed at the bottom of the window.
|
||||||
|
@ -65,152 +107,388 @@ type popupManager struct {
|
||||||
popups []Popup
|
popups []Popup
|
||||||
}
|
}
|
||||||
|
|
||||||
func (popup *popupData) init(view View, params Params) {
|
type popupArrow struct {
|
||||||
|
column, row int
|
||||||
|
location, align int
|
||||||
|
size, width, off SizeUnit
|
||||||
|
}
|
||||||
|
|
||||||
|
func (arrow *popupArrow) fixOff(popupView View) {
|
||||||
|
if arrow.align == CenterAlign && arrow.off.Type == Auto {
|
||||||
|
r := GetRadius(popupView)
|
||||||
|
switch arrow.location {
|
||||||
|
case TopArrow:
|
||||||
|
switch arrow.align {
|
||||||
|
case LeftAlign:
|
||||||
|
arrow.off = r.TopLeftX
|
||||||
|
|
||||||
|
case RightAlign:
|
||||||
|
arrow.off = r.TopRightX
|
||||||
|
}
|
||||||
|
|
||||||
|
case BottomArrow:
|
||||||
|
switch arrow.align {
|
||||||
|
case LeftAlign:
|
||||||
|
arrow.off = r.BottomLeftX
|
||||||
|
|
||||||
|
case RightAlign:
|
||||||
|
arrow.off = r.BottomRightX
|
||||||
|
}
|
||||||
|
|
||||||
|
case RightArrow:
|
||||||
|
switch arrow.align {
|
||||||
|
case TopAlign:
|
||||||
|
arrow.off = r.TopRightY
|
||||||
|
|
||||||
|
case BottomAlign:
|
||||||
|
arrow.off = r.BottomRightY
|
||||||
|
}
|
||||||
|
|
||||||
|
case LeftArrow:
|
||||||
|
switch arrow.align {
|
||||||
|
case TopAlign:
|
||||||
|
arrow.off = r.TopLeftY
|
||||||
|
|
||||||
|
case BottomAlign:
|
||||||
|
arrow.off = r.BottomLeftY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (arrow *popupArrow) createView(popupView View) View {
|
||||||
|
session := popupView.Session()
|
||||||
|
|
||||||
|
defaultSize := func(constTag string, defValue SizeUnit) SizeUnit {
|
||||||
|
if value, ok := session.Constant(constTag); ok {
|
||||||
|
if size, ok := StringToSizeUnit(value); ok && size.Type != Auto && size.Value != 0 {
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defValue
|
||||||
|
}
|
||||||
|
|
||||||
|
if arrow.size.Type == Auto || arrow.size.Value == 0 {
|
||||||
|
arrow.size = defaultSize("ruiArrowSize", Px(16))
|
||||||
|
}
|
||||||
|
|
||||||
|
if arrow.width.Type == Auto || arrow.width.Value == 0 {
|
||||||
|
arrow.width = defaultSize("ruiArrowWidth", Px(16))
|
||||||
|
}
|
||||||
|
|
||||||
|
params := Params{BackgroundColor: GetBackgroundColor(popupView)}
|
||||||
|
|
||||||
|
if shadow := GetViewShadows(popupView); shadow != nil {
|
||||||
|
params[Shadow] = shadow
|
||||||
|
}
|
||||||
|
|
||||||
|
if filter := GetBackdropFilter(popupView); filter != nil {
|
||||||
|
params[BackdropFilter] = filter
|
||||||
|
}
|
||||||
|
|
||||||
|
switch arrow.location {
|
||||||
|
case TopArrow:
|
||||||
|
params[Row] = 0
|
||||||
|
params[Column] = 1
|
||||||
|
params[Clip] = PolygonClip([]any{"0%", "100%", "50%", "0%", "100%", "100%"})
|
||||||
|
params[Width] = arrow.width
|
||||||
|
params[Height] = arrow.size
|
||||||
|
|
||||||
|
case RightArrow:
|
||||||
|
params[Row] = 1
|
||||||
|
params[Column] = 0
|
||||||
|
params[Clip] = PolygonClip([]any{"0%", "0%", "100%", "50%", "0%", "100%"})
|
||||||
|
params[Width] = arrow.size
|
||||||
|
params[Height] = arrow.width
|
||||||
|
|
||||||
|
case BottomArrow:
|
||||||
|
params[Row] = 0
|
||||||
|
params[Column] = 1
|
||||||
|
params[Clip] = PolygonClip([]any{"0%", "0%", "50%", "100%", "100%", "0%"})
|
||||||
|
params[Width] = arrow.width
|
||||||
|
params[Height] = arrow.size
|
||||||
|
|
||||||
|
case LeftArrow:
|
||||||
|
params[Row] = 1
|
||||||
|
params[Column] = 0
|
||||||
|
params[Clip] = PolygonClip([]any{"100%", "0%", "0%", "50%", "100%", "100%"})
|
||||||
|
params[Width] = arrow.size
|
||||||
|
params[Height] = arrow.width
|
||||||
|
}
|
||||||
|
|
||||||
|
arrowView := NewView(session, params)
|
||||||
|
|
||||||
|
params = Params{
|
||||||
|
Row: arrow.row,
|
||||||
|
Column: arrow.column,
|
||||||
|
Content: arrowView,
|
||||||
|
}
|
||||||
|
|
||||||
|
arrow.fixOff(popupView)
|
||||||
|
|
||||||
|
switch arrow.location {
|
||||||
|
case TopArrow, BottomArrow:
|
||||||
|
cellWidth := make([]SizeUnit, 3)
|
||||||
|
switch arrow.align {
|
||||||
|
case LeftAlign:
|
||||||
|
cellWidth[0] = arrow.off
|
||||||
|
cellWidth[2] = Fr(1)
|
||||||
|
|
||||||
|
case RightAlign:
|
||||||
|
cellWidth[0] = Fr(1)
|
||||||
|
cellWidth[2] = arrow.off
|
||||||
|
|
||||||
|
default:
|
||||||
|
cellWidth[0] = Fr(1)
|
||||||
|
cellWidth[2] = Fr(1)
|
||||||
|
if arrow.off.Type != Auto && arrow.off.Value != 0 {
|
||||||
|
arrowView.Set(MarginLeft, arrow.off)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
params[CellWidth] = cellWidth
|
||||||
|
|
||||||
|
case RightArrow, LeftArrow:
|
||||||
|
cellHeight := make([]SizeUnit, 3)
|
||||||
|
switch arrow.align {
|
||||||
|
case TopAlign:
|
||||||
|
cellHeight[0] = arrow.off
|
||||||
|
cellHeight[2] = Fr(1)
|
||||||
|
|
||||||
|
case BottomAlign:
|
||||||
|
cellHeight[0] = Fr(1)
|
||||||
|
cellHeight[2] = arrow.off
|
||||||
|
|
||||||
|
default:
|
||||||
|
cellHeight[0] = Fr(1)
|
||||||
|
cellHeight[2] = Fr(1)
|
||||||
|
if arrow.off.Type != Auto && arrow.off.Value != 0 {
|
||||||
|
arrowView.Set(MarginTop, arrow.off)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
params[CellHeight] = cellHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewGridLayout(session, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (popup *popupData) init(view View, popupParams Params) {
|
||||||
popup.view = view
|
popup.view = view
|
||||||
session := view.Session()
|
session := view.Session()
|
||||||
|
|
||||||
if params == nil {
|
columnCount := 3
|
||||||
params = Params{}
|
rowCount := 3
|
||||||
|
popupRow := 1
|
||||||
|
popupColumn := 1
|
||||||
|
arrow := popupArrow{
|
||||||
|
row: 1,
|
||||||
|
column: 1,
|
||||||
|
align: CenterAlign,
|
||||||
}
|
}
|
||||||
|
|
||||||
popup.dismissListener = []func(Popup){}
|
switch arrow.location, _ = enumProperty(popupParams, Arrow, session, NoneArrow); arrow.location {
|
||||||
if value, ok := params[DismissEvent]; ok && value != nil {
|
case TopArrow:
|
||||||
switch value := value.(type) {
|
rowCount = 4
|
||||||
case func(Popup):
|
popupRow = 2
|
||||||
popup.dismissListener = []func(Popup){value}
|
|
||||||
|
|
||||||
case func():
|
case BottomArrow:
|
||||||
popup.dismissListener = []func(Popup){
|
rowCount = 4
|
||||||
func(_ Popup) {
|
arrow.row = 2
|
||||||
value()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
case []func(Popup):
|
case LeftArrow:
|
||||||
for _, fn := range value {
|
columnCount = 4
|
||||||
if fn != nil {
|
popupColumn = 2
|
||||||
popup.dismissListener = append(popup.dismissListener, fn)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case []func():
|
case RightArrow:
|
||||||
for _, fn := range value {
|
columnCount = 4
|
||||||
if fn != nil {
|
arrow.column = 2
|
||||||
popup.dismissListener = append(popup.dismissListener, func(_ Popup) {
|
|
||||||
fn()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case []interface{}:
|
default:
|
||||||
for _, val := range value {
|
|
||||||
if val != nil {
|
|
||||||
switch fn := val.(type) {
|
|
||||||
case func(Popup):
|
|
||||||
popup.dismissListener = append(popup.dismissListener, fn)
|
|
||||||
|
|
||||||
case func():
|
|
||||||
popup.dismissListener = append(popup.dismissListener, func(_ Popup) {
|
|
||||||
fn()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var title View = nil
|
cellWidth := make([]SizeUnit, columnCount)
|
||||||
titleStyle := "ruiPopupTitle"
|
switch hAlign, _ := enumProperty(popupParams, HorizontalAlign, session, CenterAlign); hAlign {
|
||||||
closeButton, _ := boolProperty(params, CloseButton, session)
|
case LeftAlign:
|
||||||
outsideClose, _ := boolProperty(params, OutsideClose, session)
|
cellWidth[columnCount-1] = Fr(1)
|
||||||
vAlign, _ := enumProperty(params, VerticalAlign, session, CenterAlign)
|
|
||||||
hAlign, _ := enumProperty(params, HorizontalAlign, session, CenterAlign)
|
|
||||||
|
|
||||||
buttons := []PopupButton{}
|
case RightAlign:
|
||||||
if value, ok := params[Buttons]; ok && value != nil {
|
cellWidth[0] = Fr(1)
|
||||||
switch value := value.(type) {
|
|
||||||
case PopupButton:
|
|
||||||
buttons = []PopupButton{value}
|
|
||||||
|
|
||||||
case []PopupButton:
|
default:
|
||||||
buttons = value
|
cellWidth[0] = Fr(1)
|
||||||
}
|
cellWidth[columnCount-1] = Fr(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
popupView := NewGridLayout(view.Session(), Params{
|
cellHeight := make([]SizeUnit, rowCount)
|
||||||
|
switch vAlign, _ := enumProperty(popupParams, VerticalAlign, session, CenterAlign); vAlign {
|
||||||
|
case LeftAlign:
|
||||||
|
cellHeight[rowCount-1] = Fr(1)
|
||||||
|
|
||||||
|
case RightAlign:
|
||||||
|
cellHeight[0] = Fr(1)
|
||||||
|
|
||||||
|
default:
|
||||||
|
cellHeight[0] = Fr(1)
|
||||||
|
cellHeight[rowCount-1] = Fr(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
layerParams := Params{
|
||||||
|
Style: "ruiPopupLayer",
|
||||||
|
MaxWidth: Percent(100),
|
||||||
|
MaxHeight: Percent(100),
|
||||||
|
CellWidth: cellWidth,
|
||||||
|
CellHeight: cellHeight,
|
||||||
|
}
|
||||||
|
|
||||||
|
params := Params{
|
||||||
Style: "ruiPopup",
|
Style: "ruiPopup",
|
||||||
|
Row: popupRow,
|
||||||
|
Column: popupColumn,
|
||||||
MaxWidth: Percent(100),
|
MaxWidth: Percent(100),
|
||||||
MaxHeight: Percent(100),
|
MaxHeight: Percent(100),
|
||||||
CellVerticalAlign: StretchAlign,
|
CellVerticalAlign: StretchAlign,
|
||||||
CellHorizontalAlign: StretchAlign,
|
CellHorizontalAlign: StretchAlign,
|
||||||
ClickEvent: func(View) {},
|
ClickEvent: func(View) {},
|
||||||
})
|
Shadow: NewShadowWithParams(Params{
|
||||||
|
SpreadRadius: Px(4),
|
||||||
|
Blur: Px(16),
|
||||||
|
ColorTag: "@ruiPopupShadow",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
for tag, value := range params {
|
var closeButton View = nil
|
||||||
switch tag {
|
outsideClose := false
|
||||||
case Title:
|
buttons := []PopupButton{}
|
||||||
switch value := value.(type) {
|
titleStyle := "ruiPopupTitle"
|
||||||
case string:
|
var title View = nil
|
||||||
title = NewTextView(view.Session(), Params{Text: value})
|
|
||||||
|
|
||||||
case View:
|
for tag, value := range popupParams {
|
||||||
title = value
|
if value != nil {
|
||||||
|
switch tag {
|
||||||
|
case VerticalAlign, HorizontalAlign, Arrow, Row, Column:
|
||||||
|
// Do nothing
|
||||||
|
|
||||||
|
case Margin:
|
||||||
|
layerParams[Padding] = value
|
||||||
|
|
||||||
|
case MarginLeft:
|
||||||
|
layerParams[PaddingLeft] = value
|
||||||
|
|
||||||
|
case MarginRight:
|
||||||
|
layerParams[PaddingRight] = value
|
||||||
|
|
||||||
|
case MarginTop:
|
||||||
|
layerParams[PaddingTop] = value
|
||||||
|
|
||||||
|
case MarginBottom:
|
||||||
|
layerParams[PaddingBottom] = value
|
||||||
|
|
||||||
|
case CloseButton:
|
||||||
|
closeButton = NewGridLayout(session, Params{
|
||||||
|
Column: 1,
|
||||||
|
Height: "@ruiPopupTitleHeight",
|
||||||
|
Width: "@ruiPopupTitleHeight",
|
||||||
|
CellHorizontalAlign: CenterAlign,
|
||||||
|
CellVerticalAlign: CenterAlign,
|
||||||
|
TextSize: Px(20),
|
||||||
|
Content: "✕",
|
||||||
|
NotTranslate: true,
|
||||||
|
ClickEvent: func(View) {
|
||||||
|
popup.Dismiss()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
case OutsideClose:
|
||||||
|
outsideClose, _ = boolProperty(popupParams, OutsideClose, session)
|
||||||
|
|
||||||
|
case Buttons:
|
||||||
|
switch value := value.(type) {
|
||||||
|
case PopupButton:
|
||||||
|
buttons = []PopupButton{value}
|
||||||
|
|
||||||
|
case []PopupButton:
|
||||||
|
buttons = value
|
||||||
|
}
|
||||||
|
|
||||||
|
case Title:
|
||||||
|
switch value := value.(type) {
|
||||||
|
case string:
|
||||||
|
title = NewTextView(view.Session(), Params{Text: value})
|
||||||
|
|
||||||
|
case View:
|
||||||
|
title = value
|
||||||
|
|
||||||
|
default:
|
||||||
|
notCompatibleType(Title, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
case TitleStyle:
|
||||||
|
switch value := value.(type) {
|
||||||
|
case string:
|
||||||
|
titleStyle = value
|
||||||
|
|
||||||
|
default:
|
||||||
|
notCompatibleType(TitleStyle, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
case DismissEvent:
|
||||||
|
if listeners, ok := valueToNoParamListeners[Popup](value); ok {
|
||||||
|
if listeners != nil {
|
||||||
|
popup.dismissListener = listeners
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
notCompatibleType(tag, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
case ArrowAlign:
|
||||||
|
switch text := value.(type) {
|
||||||
|
case string:
|
||||||
|
switch text {
|
||||||
|
case "top":
|
||||||
|
value = "left"
|
||||||
|
|
||||||
|
case "bottom":
|
||||||
|
value = "right"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arrow.align, _ = enumProperty(popupParams, ArrowAlign, session, CenterAlign)
|
||||||
|
|
||||||
|
case ArrowSize:
|
||||||
|
arrow.size, _ = sizeProperty(popupParams, ArrowSize, session)
|
||||||
|
|
||||||
|
case ArrowOffset:
|
||||||
|
arrow.off, _ = sizeProperty(popupParams, ArrowOffset, session)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
notCompatibleType(Title, value)
|
params[tag] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
case TitleStyle:
|
|
||||||
switch value := value.(type) {
|
|
||||||
case string:
|
|
||||||
titleStyle = value
|
|
||||||
|
|
||||||
default:
|
|
||||||
notCompatibleType(TitleStyle, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
case CloseButton, OutsideClose, VerticalAlign, HorizontalAlign, Buttons:
|
|
||||||
// do nothing
|
|
||||||
|
|
||||||
default:
|
|
||||||
popupView.Set(tag, value)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var cellHeight []SizeUnit
|
popupView := NewGridLayout(view.Session(), params)
|
||||||
|
|
||||||
|
var popupCellHeight []SizeUnit
|
||||||
viewRow := 0
|
viewRow := 0
|
||||||
if title != nil || closeButton {
|
if title != nil || closeButton != nil {
|
||||||
viewRow = 1
|
titleContent := []View{}
|
||||||
titleHeight, _ := sizeConstant(popup.Session(), "ruiPopupTitleHeight")
|
if title != nil {
|
||||||
titleView := NewGridLayout(session, Params{
|
titleContent = append(titleContent, title)
|
||||||
|
}
|
||||||
|
if closeButton != nil {
|
||||||
|
titleContent = append(titleContent, closeButton)
|
||||||
|
}
|
||||||
|
popupView.Append(NewGridLayout(session, Params{
|
||||||
Row: 0,
|
Row: 0,
|
||||||
Style: titleStyle,
|
Style: titleStyle,
|
||||||
CellWidth: []SizeUnit{Fr(1), titleHeight},
|
CellWidth: []any{Fr(1), AutoSize()},
|
||||||
CellVerticalAlign: CenterAlign,
|
CellVerticalAlign: CenterAlign,
|
||||||
PaddingLeft: Px(12),
|
PaddingLeft: Px(12),
|
||||||
})
|
Content: titleContent,
|
||||||
if title != nil {
|
}))
|
||||||
titleView.Append(title)
|
|
||||||
}
|
|
||||||
if closeButton {
|
|
||||||
titleView.Append(NewGridLayout(session, Params{
|
|
||||||
Column: 1,
|
|
||||||
Height: titleHeight,
|
|
||||||
Width: titleHeight,
|
|
||||||
CellHorizontalAlign: CenterAlign,
|
|
||||||
CellVerticalAlign: CenterAlign,
|
|
||||||
TextSize: Px(20),
|
|
||||||
Content: "✕",
|
|
||||||
ClickEvent: func(View) {
|
|
||||||
popup.Dismiss()
|
|
||||||
},
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
popupView.Append(titleView)
|
viewRow = 1
|
||||||
cellHeight = []SizeUnit{AutoSize(), Fr(1)}
|
popupCellHeight = []SizeUnit{AutoSize(), Fr(1)}
|
||||||
} else {
|
} else {
|
||||||
cellHeight = []SizeUnit{Fr(1)}
|
popupCellHeight = []SizeUnit{Fr(1)}
|
||||||
}
|
}
|
||||||
|
|
||||||
view.Set(Row, viewRow)
|
view.Set(Row, viewRow)
|
||||||
|
@ -218,7 +496,7 @@ func (popup *popupData) init(view View, params Params) {
|
||||||
|
|
||||||
if buttonCount := len(buttons); buttonCount > 0 {
|
if buttonCount := len(buttons); buttonCount > 0 {
|
||||||
buttonsAlign, _ := enumProperty(params, ButtonsAlign, session, RightAlign)
|
buttonsAlign, _ := enumProperty(params, ButtonsAlign, session, RightAlign)
|
||||||
cellHeight = append(cellHeight, AutoSize())
|
popupCellHeight = append(popupCellHeight, AutoSize())
|
||||||
gap, _ := sizeConstant(session, "ruiPopupButtonGap")
|
gap, _ := sizeConstant(session, "ruiPopupButtonGap")
|
||||||
cellWidth := []SizeUnit{}
|
cellWidth := []SizeUnit{}
|
||||||
for i := 0; i < buttonCount; i++ {
|
for i := 0; i < buttonCount; i++ {
|
||||||
|
@ -256,16 +534,16 @@ func (popup *popupData) init(view View, params Params) {
|
||||||
Content: buttonsPanel,
|
Content: buttonsPanel,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
popupView.Set(CellHeight, cellHeight)
|
|
||||||
|
|
||||||
popup.layerView = NewGridLayout(session, Params{
|
popupView.Set(CellHeight, popupCellHeight)
|
||||||
Style: "ruiPopupLayer",
|
|
||||||
CellVerticalAlign: vAlign,
|
if arrow.location != NoneArrow {
|
||||||
CellHorizontalAlign: hAlign,
|
layerParams[Content] = []View{popupView, arrow.createView(popupView)}
|
||||||
Content: NewColumnLayout(session, Params{Content: popupView}),
|
} else {
|
||||||
MaxWidth: Percent(100),
|
layerParams[Content] = []View{popupView}
|
||||||
MaxHeight: Percent(100),
|
}
|
||||||
})
|
|
||||||
|
popup.layerView = NewGridLayout(session, layerParams)
|
||||||
|
|
||||||
if outsideClose {
|
if outsideClose {
|
||||||
popup.layerView.Set(ClickEvent, func(View) {
|
popup.layerView.Set(ClickEvent, func(View) {
|
||||||
|
|
|
@ -103,19 +103,22 @@ func ShowCancellableQuestion(title, text string, session Session, onYes func(),
|
||||||
}
|
}
|
||||||
|
|
||||||
type popupMenuData struct {
|
type popupMenuData struct {
|
||||||
items []string
|
items []string
|
||||||
session Session
|
disabled []int
|
||||||
popup Popup
|
session Session
|
||||||
result func(int)
|
popup Popup
|
||||||
|
result func(int)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (popup *popupMenuData) itemClick(list ListView, n int) {
|
func (popup *popupMenuData) itemClick(list ListView, n int) {
|
||||||
if popup.popup != nil {
|
if popup.IsListItemEnabled(n) {
|
||||||
popup.popup.Dismiss()
|
if popup.popup != nil {
|
||||||
popup.popup = nil
|
popup.popup.Dismiss()
|
||||||
}
|
popup.popup = nil
|
||||||
if popup.result != nil {
|
}
|
||||||
popup.result(n)
|
if popup.result != nil {
|
||||||
|
popup.result(n)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,6 +134,13 @@ func (popup *popupMenuData) ListItem(index int, session Session) View {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (popup *popupMenuData) IsListItemEnabled(index int) bool {
|
func (popup *popupMenuData) IsListItemEnabled(index int) bool {
|
||||||
|
if popup.disabled != nil {
|
||||||
|
for _, n := range popup.disabled {
|
||||||
|
if index == n {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,13 +175,18 @@ func ShowMenu(session Session, params Params) Popup {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
value, ok = params[PopupMenuResult]
|
if value, ok := params[PopupMenuResult]; ok && value != nil {
|
||||||
if ok && value != nil {
|
|
||||||
if result, ok := value.(func(int)); ok {
|
if result, ok := value.(func(int)); ok {
|
||||||
data.result = result
|
data.result = result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if value, ok := params[DisabledItems]; ok && value != nil {
|
||||||
|
if value, ok := value.([]int); ok {
|
||||||
|
data.disabled = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
listView := NewListView(session, Params{
|
listView := NewListView(session, Params{
|
||||||
Items: adapter,
|
Items: adapter,
|
||||||
Orientation: TopDownOrientation,
|
Orientation: TopDownOrientation,
|
||||||
|
@ -181,7 +196,7 @@ func ShowMenu(session Session, params Params) Popup {
|
||||||
popupParams := Params{}
|
popupParams := Params{}
|
||||||
for tag, value := range params {
|
for tag, value := range params {
|
||||||
switch tag {
|
switch tag {
|
||||||
case Items, PopupMenuResult:
|
case Items, PopupMenuResult, DisabledItems:
|
||||||
// do nothing
|
// do nothing
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -22,7 +22,7 @@ type progressBarData struct {
|
||||||
// NewProgressBar create new ProgressBar object and return it
|
// NewProgressBar create new ProgressBar object and return it
|
||||||
func NewProgressBar(session Session, params Params) ProgressBar {
|
func NewProgressBar(session Session, params Params) ProgressBar {
|
||||||
view := new(progressBarData)
|
view := new(progressBarData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -31,8 +31,8 @@ func newProgressBar(session Session) View {
|
||||||
return NewProgressBar(session, nil)
|
return NewProgressBar(session, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (progress *progressBarData) Init(session Session) {
|
func (progress *progressBarData) init(session Session) {
|
||||||
progress.viewData.Init(session)
|
progress.viewData.init(session)
|
||||||
progress.tag = "ProgressBar"
|
progress.tag = "ProgressBar"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,19 +65,19 @@ func (progress *progressBarData) propertyChanged(tag string) {
|
||||||
if progress.created {
|
if progress.created {
|
||||||
switch tag {
|
switch tag {
|
||||||
case ProgressBarMax:
|
case ProgressBarMax:
|
||||||
updateProperty(progress.htmlID(), Max, strconv.FormatFloat(GetProgressBarMax(progress, ""), 'f', -1, 32), progress.session)
|
updateProperty(progress.htmlID(), Max, strconv.FormatFloat(GetProgressBarMax(progress), 'f', -1, 32), progress.session)
|
||||||
|
|
||||||
case ProgressBarValue:
|
case ProgressBarValue:
|
||||||
updateProperty(progress.htmlID(), Value, strconv.FormatFloat(GetProgressBarValue(progress, ""), 'f', -1, 32), progress.session)
|
updateProperty(progress.htmlID(), Value, strconv.FormatFloat(GetProgressBarValue(progress), 'f', -1, 32), progress.session)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (progress *progressBarData) Set(tag string, value interface{}) bool {
|
func (progress *progressBarData) Set(tag string, value any) bool {
|
||||||
return progress.set(progress.normalizeTag(tag), value)
|
return progress.set(progress.normalizeTag(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (progress *progressBarData) set(tag string, value interface{}) bool {
|
func (progress *progressBarData) set(tag string, value any) bool {
|
||||||
if progress.viewData.set(tag, value) {
|
if progress.viewData.set(tag, value) {
|
||||||
progress.propertyChanged(tag)
|
progress.propertyChanged(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -85,7 +85,7 @@ func (progress *progressBarData) set(tag string, value interface{}) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (progress *progressBarData) Get(tag string) interface{} {
|
func (progress *progressBarData) Get(tag string) any {
|
||||||
return progress.get(progress.normalizeTag(tag))
|
return progress.get(progress.normalizeTag(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,44 +97,22 @@ func (progress *progressBarData) htmlProperties(self View, buffer *strings.Build
|
||||||
progress.viewData.htmlProperties(self, buffer)
|
progress.viewData.htmlProperties(self, buffer)
|
||||||
|
|
||||||
buffer.WriteString(` max="`)
|
buffer.WriteString(` max="`)
|
||||||
buffer.WriteString(strconv.FormatFloat(GetProgressBarMax(progress, ""), 'f', -1, 64))
|
buffer.WriteString(strconv.FormatFloat(GetProgressBarMax(progress), 'f', -1, 64))
|
||||||
buffer.WriteByte('"')
|
buffer.WriteByte('"')
|
||||||
|
|
||||||
buffer.WriteString(` value="`)
|
buffer.WriteString(` value="`)
|
||||||
buffer.WriteString(strconv.FormatFloat(GetProgressBarValue(progress, ""), 'f', -1, 64))
|
buffer.WriteString(strconv.FormatFloat(GetProgressBarValue(progress), 'f', -1, 64))
|
||||||
buffer.WriteByte('"')
|
buffer.WriteByte('"')
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetProgressBarMax returns the max value of ProgressBar subview.
|
// GetProgressBarMax returns the max value of ProgressBar subview.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetProgressBarMax(view View, subviewID string) float64 {
|
func GetProgressBarMax(view View, subviewID ...string) float64 {
|
||||||
if subviewID != "" {
|
return floatStyledProperty(view, subviewID, ProgressBarMax, 1)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view == nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
result, ok := floatStyledProperty(view, ProgressBarMax, 1)
|
|
||||||
if !ok {
|
|
||||||
result, _ = floatStyledProperty(view, Max, 1)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetProgressBarValue returns the value of ProgressBar subview.
|
// GetProgressBarValue returns the value of ProgressBar subview.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetProgressBarValue(view View, subviewID string) float64 {
|
func GetProgressBarValue(view View, subviewID ...string) float64 {
|
||||||
if subviewID != "" {
|
return floatStyledProperty(view, subviewID, ProgressBarValue, 0)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view == nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
result, ok := floatStyledProperty(view, ProgressBarValue, 0)
|
|
||||||
if !ok {
|
|
||||||
result, _ = floatStyledProperty(view, Value, 0)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,13 +9,13 @@ import (
|
||||||
type Properties interface {
|
type Properties interface {
|
||||||
// Get returns a value of the property with name defined by the argument.
|
// Get returns a value of the property with name defined by the argument.
|
||||||
// The type of return value depends on the property. If the property is not set then nil is returned.
|
// The type of return value depends on the property. If the property is not set then nil is returned.
|
||||||
Get(tag string) interface{}
|
Get(tag string) any
|
||||||
getRaw(tag string) interface{}
|
getRaw(tag string) any
|
||||||
// Set sets the value (second argument) of the property with name defined by the first argument.
|
// Set sets the value (second argument) of the property with name defined by the first argument.
|
||||||
// Return "true" if the value has been set, in the opposite case "false" are returned and
|
// Return "true" if the value has been set, in the opposite case "false" are returned and
|
||||||
// a description of the error is written to the log
|
// a description of the error is written to the log
|
||||||
Set(tag string, value interface{}) bool
|
Set(tag string, value any) bool
|
||||||
setRaw(tag string, value interface{})
|
setRaw(tag string, value any)
|
||||||
// Remove removes the property with name defined by the argument
|
// Remove removes the property with name defined by the argument
|
||||||
Remove(tag string)
|
Remove(tag string)
|
||||||
// Clear removes all properties
|
// Clear removes all properties
|
||||||
|
@ -25,25 +25,25 @@ type Properties interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type propertyList struct {
|
type propertyList struct {
|
||||||
properties map[string]interface{}
|
properties map[string]any
|
||||||
}
|
}
|
||||||
|
|
||||||
func (properties *propertyList) init() {
|
func (properties *propertyList) init() {
|
||||||
properties.properties = map[string]interface{}{}
|
properties.properties = map[string]any{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (properties *propertyList) Get(tag string) interface{} {
|
func (properties *propertyList) Get(tag string) any {
|
||||||
return properties.getRaw(strings.ToLower(tag))
|
return properties.getRaw(strings.ToLower(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (properties *propertyList) getRaw(tag string) interface{} {
|
func (properties *propertyList) getRaw(tag string) any {
|
||||||
if value, ok := properties.properties[tag]; ok {
|
if value, ok := properties.properties[tag]; ok {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (properties *propertyList) setRaw(tag string, value interface{}) {
|
func (properties *propertyList) setRaw(tag string, value any) {
|
||||||
properties.properties[tag] = value
|
properties.properties[tag] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ func (properties *propertyList) remove(tag string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (properties *propertyList) Clear() {
|
func (properties *propertyList) Clear() {
|
||||||
properties.properties = map[string]interface{}{}
|
properties.properties = map[string]any{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (properties *propertyList) AllTags() []string {
|
func (properties *propertyList) AllTags() []string {
|
||||||
|
|
|
@ -32,49 +32,49 @@ func TestProperties(t *testing.T) {
|
||||||
t.Error(`list.Get("name") is not string`)
|
t.Error(`list.Get("name") is not string`)
|
||||||
}
|
}
|
||||||
|
|
||||||
sizeValues := []interface{}{"@small", "auto", "10px", Pt(20), AutoSize()}
|
sizeValues := []any{"@small", "auto", "10px", Pt(20), AutoSize()}
|
||||||
for _, value := range sizeValues {
|
for _, value := range sizeValues {
|
||||||
if !list.setSizeProperty("size", value) {
|
if !list.setSizeProperty("size", value) {
|
||||||
t.Errorf(`setSizeProperty("size", %v) fail`, value)
|
t.Errorf(`setSizeProperty("size", %v) fail`, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
failSizeValues := []interface{}{"@small,big", "abc", "10", Color(20), 100}
|
failSizeValues := []any{"@small,big", "abc", "10", Color(20), 100}
|
||||||
for _, value := range failSizeValues {
|
for _, value := range failSizeValues {
|
||||||
if list.setSizeProperty("size", value) {
|
if list.setSizeProperty("size", value) {
|
||||||
t.Errorf(`setSizeProperty("size", %v) success`, value)
|
t.Errorf(`setSizeProperty("size", %v) success`, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
angleValues := []interface{}{"@angle", "2pi", "π", "3deg", "60°", Rad(1.5), Deg(45), 1, 1.5}
|
angleValues := []any{"@angle", "2pi", "π", "3deg", "60°", Rad(1.5), Deg(45), 1, 1.5}
|
||||||
for _, value := range angleValues {
|
for _, value := range angleValues {
|
||||||
if !list.setAngleProperty("angle", value) {
|
if !list.setAngleProperty("angle", value) {
|
||||||
t.Errorf(`setAngleProperty("angle", %v) fail`, value)
|
t.Errorf(`setAngleProperty("angle", %v) fail`, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
failAngleValues := []interface{}{"@angle,2", "pi32", "deg", "60°x", Color(0xFFFFFFFF)}
|
failAngleValues := []any{"@angle,2", "pi32", "deg", "60°x", Color(0xFFFFFFFF)}
|
||||||
for _, value := range failAngleValues {
|
for _, value := range failAngleValues {
|
||||||
if list.setAngleProperty("angle", value) {
|
if list.setAngleProperty("angle", value) {
|
||||||
t.Errorf(`setAngleProperty("angle", %v) success`, value)
|
t.Errorf(`setAngleProperty("angle", %v) success`, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
colorValues := []interface{}{"@color", "#FF234567", "#234567", "rgba(30%, 128, 0.5, .25)", "rgb(30%, 128, 0.5)", Color(0xFFFFFFFF), 0xFFFFFFFF, White}
|
colorValues := []any{"@color", "#FF234567", "#234567", "rgba(30%, 128, 0.5, .25)", "rgb(30%, 128, 0.5)", Color(0xFFFFFFFF), 0xFFFFFFFF, White}
|
||||||
for _, color := range colorValues {
|
for _, color := range colorValues {
|
||||||
if !list.setColorProperty("color", color) {
|
if !list.setColorProperty("color", color) {
|
||||||
t.Errorf(`list.setColorProperty("color", %v) fail`, color)
|
t.Errorf(`list.setColorProperty("color", %v) fail`, color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
failColorValues := []interface{}{"@color|2", "#FF234567FF", "#TT234567", "rgba(500%, 128, 10.5, .25)", 10.6}
|
failColorValues := []any{"@color|2", "#FF234567FF", "#TT234567", "rgba(500%, 128, 10.5, .25)", 10.6}
|
||||||
for _, color := range failColorValues {
|
for _, color := range failColorValues {
|
||||||
if list.setColorProperty("color", color) {
|
if list.setColorProperty("color", color) {
|
||||||
t.Errorf(`list.setColorProperty("color", %v) success`, color)
|
t.Errorf(`list.setColorProperty("color", %v) success`, color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enumValues := []interface{}{"@enum", "inherit", "on", Inherit, 2}
|
enumValues := []any{"@enum", "inherit", "on", Inherit, 2}
|
||||||
inheritOffOn := inheritOffOnValues()
|
inheritOffOn := inheritOffOnValues()
|
||||||
for _, value := range enumValues {
|
for _, value := range enumValues {
|
||||||
if !list.setEnumProperty("enum", value, inheritOffOn) {
|
if !list.setEnumProperty("enum", value, inheritOffOn) {
|
||||||
|
@ -82,56 +82,56 @@ func TestProperties(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
failEnumValues := []interface{}{"@enum 13", "inherit2", "onn", -1, 10}
|
failEnumValues := []any{"@enum 13", "inherit2", "onn", -1, 10}
|
||||||
for _, value := range failEnumValues {
|
for _, value := range failEnumValues {
|
||||||
if list.setEnumProperty("enum", value, inheritOffOn) {
|
if list.setEnumProperty("enum", value, inheritOffOn) {
|
||||||
t.Errorf(`list.setEnumProperty("enum", %v, %v) success`, value, inheritOffOn)
|
t.Errorf(`list.setEnumProperty("enum", %v, %v) success`, value, inheritOffOn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolValues := []interface{}{"@bool", "true", "yes ", "on", " 1", "false", "no", "off", "0", 0, 1, false, true}
|
boolValues := []any{"@bool", "true", "yes ", "on", " 1", "false", "no", "off", "0", 0, 1, false, true}
|
||||||
for _, value := range boolValues {
|
for _, value := range boolValues {
|
||||||
if !list.setBoolProperty("bool", value) {
|
if !list.setBoolProperty("bool", value) {
|
||||||
t.Errorf(`list.setBoolProperty("bool", %v) fail`, value)
|
t.Errorf(`list.setBoolProperty("bool", %v) fail`, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
failBoolValues := []interface{}{"@bool,2", "tr", "ys", "10", -1, 10, 0.8}
|
failBoolValues := []any{"@bool,2", "tr", "ys", "10", -1, 10, 0.8}
|
||||||
for _, value := range failBoolValues {
|
for _, value := range failBoolValues {
|
||||||
if list.setBoolProperty("bool", value) {
|
if list.setBoolProperty("bool", value) {
|
||||||
t.Errorf(`list.setBoolProperty("bool", %v) success`, value)
|
t.Errorf(`list.setBoolProperty("bool", %v) success`, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
intValues := []interface{}{"@int", " 100", "-10 ", 0, 250}
|
intValues := []any{"@int", " 100", "-10 ", 0, 250}
|
||||||
for _, value := range intValues {
|
for _, value := range intValues {
|
||||||
if !list.setIntProperty("int", value) {
|
if !list.setIntProperty("int", value) {
|
||||||
t.Errorf(`list.setIntProperty("int", %v) fail`, value)
|
t.Errorf(`list.setIntProperty("int", %v) fail`, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
failIntValues := []interface{}{"@int|10", "100i", "-1.0 ", 0.0}
|
failIntValues := []any{"@int|10", "100i", "-1.0 ", 0.0}
|
||||||
for _, value := range failIntValues {
|
for _, value := range failIntValues {
|
||||||
if list.setIntProperty("int", value) {
|
if list.setIntProperty("int", value) {
|
||||||
t.Errorf(`list.setIntProperty("int", %v) success`, value)
|
t.Errorf(`list.setIntProperty("int", %v) success`, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
floatValues := []interface{}{"@float", " 100.25", "-1.5e12 ", uint(0), 250, float32(10.2), float64(0)}
|
floatValues := []any{"@float", " 100.25", "-1.5e12 ", uint(0), 250, float32(10.2), float64(0)}
|
||||||
for _, value := range floatValues {
|
for _, value := range floatValues {
|
||||||
if !list.setFloatProperty("float", value) {
|
if !list.setFloatProperty("float", value) {
|
||||||
t.Errorf(`list.setFloatProperty("float", %v) fail`, value)
|
t.Errorf(`list.setFloatProperty("float", %v) fail`, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
failFloatValues := []interface{}{"@float|2", " 100.25i", "-1.5ee12 ", "abc"}
|
failFloatValues := []any{"@float|2", " 100.25i", "-1.5ee12 ", "abc"}
|
||||||
for _, value := range failFloatValues {
|
for _, value := range failFloatValues {
|
||||||
if list.setFloatProperty("float", value) {
|
if list.setFloatProperty("float", value) {
|
||||||
t.Errorf(`list.setFloatProperty("float", %v) success`, value)
|
t.Errorf(`list.setFloatProperty("float", %v) success`, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boundsValues := []interface{}{"@bounds", "10px,20pt,@bottom,0", Em(2), []interface{}{"@top", Px(10), AutoSize(), "14pt"}}
|
boundsValues := []any{"@bounds", "10px,20pt,@bottom,0", Em(2), []any{"@top", Px(10), AutoSize(), "14pt"}}
|
||||||
for _, value := range boundsValues {
|
for _, value := range boundsValues {
|
||||||
if !list.setBoundsProperty("margin", value) {
|
if !list.setBoundsProperty("margin", value) {
|
||||||
t.Errorf(`list.setBoundsProperty("margin", %v) fail`, value)
|
t.Errorf(`list.setBoundsProperty("margin", %v) fail`, value)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package rui
|
package rui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -31,16 +32,29 @@ func imageProperty(properties Properties, tag string, session Session) (string,
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
func valueToSizeUnit(value interface{}, session Session) (SizeUnit, bool) {
|
func valueToSizeUnit(value any, session Session) (SizeUnit, bool) {
|
||||||
if value != nil {
|
if value != nil {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case SizeUnit:
|
case SizeUnit:
|
||||||
return value, true
|
return value, true
|
||||||
|
|
||||||
|
case SizeFunc:
|
||||||
|
return SizeUnit{Type: SizeFunction, Function: value}, true
|
||||||
|
|
||||||
case string:
|
case string:
|
||||||
if text, ok := session.resolveConstants(value); ok {
|
if text, ok := session.resolveConstants(value); ok {
|
||||||
return StringToSizeUnit(text)
|
return StringToSizeUnit(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case float64:
|
||||||
|
return Px(value), true
|
||||||
|
|
||||||
|
case float32:
|
||||||
|
return Px(float64(value)), true
|
||||||
|
}
|
||||||
|
|
||||||
|
if n, ok := isInt(value); ok {
|
||||||
|
return Px(float64(n)), true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +81,7 @@ func angleProperty(properties Properties, tag string, session Session) (AngleUni
|
||||||
return AngleUnit{Type: 0, Value: 0}, false
|
return AngleUnit{Type: 0, Value: 0}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func valueToColor(value interface{}, session Session) (Color, bool) {
|
func valueToColor(value any, session Session) (Color, bool) {
|
||||||
if value != nil {
|
if value != nil {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case Color:
|
case Color:
|
||||||
|
@ -88,7 +102,7 @@ func colorProperty(properties Properties, tag string, session Session) (Color, b
|
||||||
return valueToColor(properties.getRaw(tag), session)
|
return valueToColor(properties.getRaw(tag), session)
|
||||||
}
|
}
|
||||||
|
|
||||||
func valueToEnum(value interface{}, tag string, session Session, defaultValue int) (int, bool) {
|
func valueToEnum(value any, tag string, session Session, defaultValue int) (int, bool) {
|
||||||
if value != nil {
|
if value != nil {
|
||||||
values := enumProperties[tag].values
|
values := enumProperties[tag].values
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
|
@ -155,7 +169,7 @@ func enumProperty(properties Properties, tag string, session Session, defaultVal
|
||||||
return valueToEnum(properties.getRaw(tag), tag, session, defaultValue)
|
return valueToEnum(properties.getRaw(tag), tag, session, defaultValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
func valueToBool(value interface{}, session Session) (bool, bool) {
|
func valueToBool(value any, session Session) (bool, bool) {
|
||||||
if value != nil {
|
if value != nil {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case bool:
|
case bool:
|
||||||
|
@ -184,7 +198,7 @@ func boolProperty(properties Properties, tag string, session Session) (bool, boo
|
||||||
return valueToBool(properties.getRaw(tag), session)
|
return valueToBool(properties.getRaw(tag), session)
|
||||||
}
|
}
|
||||||
|
|
||||||
func valueToInt(value interface{}, session Session, defaultValue int) (int, bool) {
|
func valueToInt(value any, session Session, defaultValue int) (int, bool) {
|
||||||
if value != nil {
|
if value != nil {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case string:
|
case string:
|
||||||
|
@ -214,7 +228,7 @@ func intProperty(properties Properties, tag string, session Session, defaultValu
|
||||||
return valueToInt(properties.getRaw(tag), session, defaultValue)
|
return valueToInt(properties.getRaw(tag), session, defaultValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
func valueToFloat(value interface{}, session Session, defaultValue float64) (float64, bool) {
|
func valueToFloat(value any, session Session, defaultValue float64) (float64, bool) {
|
||||||
if value != nil {
|
if value != nil {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case float64:
|
case float64:
|
||||||
|
@ -238,7 +252,31 @@ func floatProperty(properties Properties, tag string, session Session, defaultVa
|
||||||
return valueToFloat(properties.getRaw(tag), session, defaultValue)
|
return valueToFloat(properties.getRaw(tag), session, defaultValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
func valueToRange(value interface{}, session Session) (Range, bool) {
|
func valueToFloatText(value any, session Session, defaultValue float64) (string, bool) {
|
||||||
|
if value != nil {
|
||||||
|
switch value := value.(type) {
|
||||||
|
case float64:
|
||||||
|
return fmt.Sprintf("%g", value), true
|
||||||
|
|
||||||
|
case string:
|
||||||
|
if text, ok := session.resolveConstants(value); ok {
|
||||||
|
if _, err := strconv.ParseFloat(text, 64); err != nil {
|
||||||
|
ErrorLog(err.Error())
|
||||||
|
return fmt.Sprintf("%g", defaultValue), false
|
||||||
|
}
|
||||||
|
return text, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%g", defaultValue), false
|
||||||
|
}
|
||||||
|
|
||||||
|
func floatTextProperty(properties Properties, tag string, session Session, defaultValue float64) (string, bool) {
|
||||||
|
return valueToFloatText(properties.getRaw(tag), session, defaultValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
func valueToRange(value any, session Session) (Range, bool) {
|
||||||
if value != nil {
|
if value != nil {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case Range:
|
case Range:
|
||||||
|
|
|
@ -45,6 +45,12 @@ const (
|
||||||
// Opacity is the degree to which content behind an element is hidden, and is the opposite of transparency.
|
// Opacity is the degree to which content behind an element is hidden, and is the opposite of transparency.
|
||||||
Opacity = "opacity"
|
Opacity = "opacity"
|
||||||
|
|
||||||
|
// Overflow is the constant for the "overflow" property tag.
|
||||||
|
// The "overflow" int property sets the desired behavior for an element's overflow — i.e.
|
||||||
|
// when an element's content is too big to fit in its block formatting context — in both directions.
|
||||||
|
// Valid values: OverflowHidden (0), OverflowVisible (1), OverflowScroll (2), OverflowAuto (3)
|
||||||
|
Overflow = "overflow"
|
||||||
|
|
||||||
// Row is the constant for the "row" property tag.
|
// Row is the constant for the "row" property tag.
|
||||||
Row = "row"
|
Row = "row"
|
||||||
|
|
||||||
|
@ -141,6 +147,10 @@ const (
|
||||||
// The "padding-bottom" SizeUnit property sets the height of the padding area to the bottom of a view.
|
// The "padding-bottom" SizeUnit property sets the height of the padding area to the bottom of a view.
|
||||||
PaddingBottom = "padding-bottom"
|
PaddingBottom = "padding-bottom"
|
||||||
|
|
||||||
|
// AccentColor is the constant for the "accent-color" property tag.
|
||||||
|
// The "accent-color" property sets sets the accent color for UI controls generated by some elements.
|
||||||
|
AccentColor = "accent-color"
|
||||||
|
|
||||||
// BackgroundColor is the constant for the "background-color" property tag.
|
// BackgroundColor is the constant for the "background-color" property tag.
|
||||||
// The "background-color" property sets the background color of a view.
|
// The "background-color" property sets the background color of a view.
|
||||||
BackgroundColor = "background-color"
|
BackgroundColor = "background-color"
|
||||||
|
@ -314,20 +324,20 @@ const (
|
||||||
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
|
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
|
||||||
Underline = "underline"
|
Underline = "underline"
|
||||||
|
|
||||||
// TextLineThickness is the constant for the "text-decoration-thickness" property tag.
|
// TextLineThickness is the constant for the "text-line-thickness" property tag.
|
||||||
// The "text-decoration-thickness" SizeUnit property sets the stroke thickness of the decoration line that
|
// The "text-line-thickness" SizeUnit property sets the stroke thickness of the decoration line that
|
||||||
// is used on text in an element, such as a line-through, underline, or overline.
|
// is used on text in an element, such as a line-through, underline, or overline.
|
||||||
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
|
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
|
||||||
TextLineThickness = "text-line-thickness"
|
TextLineThickness = "text-line-thickness"
|
||||||
|
|
||||||
// TextLineStyle is the constant for the "text-decoration-style" property tag.
|
// TextLineStyle is the constant for the "text-line-style" property tag.
|
||||||
// The "text-decoration-style" int property sets the style of the lines specified by "text-decoration" property.
|
// The "text-line-style" int property sets the style of the lines specified by "text-decoration" property.
|
||||||
// The style applies to all lines that are set with "text-decoration" property.
|
// The style applies to all lines that are set with "text-decoration" property.
|
||||||
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
|
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
|
||||||
TextLineStyle = "text-line-style"
|
TextLineStyle = "text-line-style"
|
||||||
|
|
||||||
// TextLineColor is the constant for the "text-decoration-color" property tag.
|
// TextLineColor is the constant for the "text-line-color" property tag.
|
||||||
// The "text-decoration-color" Color property sets the color of the lines specified by "text-decoration" property.
|
// The "text-line-color" Color property sets the color of the lines specified by "text-decoration" property.
|
||||||
// The color applies to all lines that are set with "text-decoration" property.
|
// The color applies to all lines that are set with "text-decoration" property.
|
||||||
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
|
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
|
||||||
TextLineColor = "text-line-color"
|
TextLineColor = "text-line-color"
|
||||||
|
@ -349,6 +359,11 @@ const (
|
||||||
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
|
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
|
||||||
TextShadow = "text-shadow"
|
TextShadow = "text-shadow"
|
||||||
|
|
||||||
|
// TabSize is the constant for the "tab-size" property tag.
|
||||||
|
// The "tab-size" int property sets the width of tab characters (U+0009) in spaces.
|
||||||
|
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
|
||||||
|
TabSize = "tab-size"
|
||||||
|
|
||||||
// LetterSpacing is the constant for the "letter-spacing" property tag.
|
// LetterSpacing is the constant for the "letter-spacing" property tag.
|
||||||
// The "letter-spacing" SizeUnit property sets the horizontal spacing behavior between text characters.
|
// The "letter-spacing" SizeUnit property sets the horizontal spacing behavior between text characters.
|
||||||
// This value is added to the natural spacing between characters while rendering the text.
|
// This value is added to the natural spacing between characters while rendering the text.
|
||||||
|
@ -553,9 +568,19 @@ const (
|
||||||
// Orientation is the constant for the "orientation" property tag.
|
// Orientation is the constant for the "orientation" property tag.
|
||||||
Orientation = "orientation"
|
Orientation = "orientation"
|
||||||
|
|
||||||
// Gap is the constant for the "gap" property tag.
|
// Gap is t he constant for the "gap" property tag.
|
||||||
Gap = "gap"
|
Gap = "gap"
|
||||||
|
|
||||||
|
// ListRowGap is the constant for the "list-row-gap" property tag.
|
||||||
|
// The "list-row-gap" SizeUnit properties allow to set the distance between the rows of the ListLayout or ListView.
|
||||||
|
// The default is 0px.
|
||||||
|
ListRowGap = "list-row-gap"
|
||||||
|
|
||||||
|
// ListColumnGap is the constant for the "list-column-gap" property tag.
|
||||||
|
// The "list-column-gap" SizeUnit properties allow to set the distance between the columns of the GridLayout or ListView.
|
||||||
|
// The default is 0px.
|
||||||
|
ListColumnGap = "list-column-gap"
|
||||||
|
|
||||||
// Text is the constant for the "text" property tag.
|
// Text is the constant for the "text" property tag.
|
||||||
Text = "text"
|
Text = "text"
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,7 @@ var boolProperties = []string{
|
||||||
|
|
||||||
var intProperties = []string{
|
var intProperties = []string{
|
||||||
ZIndex,
|
ZIndex,
|
||||||
|
TabSize,
|
||||||
HeadHeight,
|
HeadHeight,
|
||||||
FootHeight,
|
FootHeight,
|
||||||
RowSpan,
|
RowSpan,
|
||||||
|
@ -109,6 +110,8 @@ var sizeProperties = map[string]string{
|
||||||
WordSpacing: WordSpacing,
|
WordSpacing: WordSpacing,
|
||||||
LineHeight: LineHeight,
|
LineHeight: LineHeight,
|
||||||
TextLineThickness: "text-decoration-thickness",
|
TextLineThickness: "text-decoration-thickness",
|
||||||
|
ListRowGap: "row-gap",
|
||||||
|
ListColumnGap: "column-gap",
|
||||||
GridRowGap: GridRowGap,
|
GridRowGap: GridRowGap,
|
||||||
GridColumnGap: GridColumnGap,
|
GridColumnGap: GridColumnGap,
|
||||||
ColumnWidth: ColumnWidth,
|
ColumnWidth: ColumnWidth,
|
||||||
|
@ -179,6 +182,11 @@ var enumProperties = map[string]struct {
|
||||||
"",
|
"",
|
||||||
[]string{"visible", "invisible", "gone"},
|
[]string{"visible", "invisible", "gone"},
|
||||||
},
|
},
|
||||||
|
Overflow: {
|
||||||
|
[]string{"hidden", "visible", "scroll", "auto"},
|
||||||
|
Overflow,
|
||||||
|
[]string{"hidden", "visible", "scroll", "auto"},
|
||||||
|
},
|
||||||
TextAlign: {
|
TextAlign: {
|
||||||
[]string{"left", "right", "center", "justify"},
|
[]string{"left", "right", "center", "justify"},
|
||||||
TextAlign,
|
TextAlign,
|
||||||
|
@ -304,6 +312,11 @@ var enumProperties = map[string]struct {
|
||||||
"",
|
"",
|
||||||
[]string{"left", "right", "center", "stretch"},
|
[]string{"left", "right", "center", "stretch"},
|
||||||
},
|
},
|
||||||
|
ArrowAlign: {
|
||||||
|
[]string{"left", "right", "center"},
|
||||||
|
"",
|
||||||
|
[]string{"left", "right", "center"},
|
||||||
|
},
|
||||||
CellVerticalAlign: {
|
CellVerticalAlign: {
|
||||||
[]string{"top", "bottom", "center", "stretch"},
|
[]string{"top", "bottom", "center", "stretch"},
|
||||||
"align-items",
|
"align-items",
|
||||||
|
@ -429,13 +442,18 @@ var enumProperties = map[string]struct {
|
||||||
"resize",
|
"resize",
|
||||||
[]string{"none", "both", "horizontal", "vertical"},
|
[]string{"none", "both", "horizontal", "vertical"},
|
||||||
},
|
},
|
||||||
|
Arrow: {
|
||||||
|
[]string{"none", "top", "right", "bottom", "left"},
|
||||||
|
"",
|
||||||
|
[]string{"none", "top", "right", "bottom", "left"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func notCompatibleType(tag string, value interface{}) {
|
func notCompatibleType(tag string, value any) {
|
||||||
ErrorLogF(`"%T" type not compatible with "%s" property`, value, tag)
|
ErrorLogF(`"%T" type not compatible with "%s" property`, value, tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func invalidPropertyValue(tag string, value interface{}) {
|
func invalidPropertyValue(tag string, value any) {
|
||||||
ErrorLogF(`Invalid value "%v" of "%s" property`, value, tag)
|
ErrorLogF(`Invalid value "%v" of "%s" property`, value, tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,7 +475,7 @@ func isConstantName(text string) bool {
|
||||||
return !strings.ContainsAny(text, ",;|\"'`+(){}[]<>/\\*&%! \t\n\r")
|
return !strings.ContainsAny(text, ",;|\"'`+(){}[]<>/\\*&%! \t\n\r")
|
||||||
}
|
}
|
||||||
|
|
||||||
func isInt(value interface{}) (int, bool) {
|
func isInt(value any) (int, bool) {
|
||||||
var n int
|
var n int
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case int:
|
case int:
|
||||||
|
@ -497,7 +515,7 @@ func isInt(value interface{}) (int, bool) {
|
||||||
return n, true
|
return n, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (properties *propertyList) setSimpleProperty(tag string, value interface{}) bool {
|
func (properties *propertyList) setSimpleProperty(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
delete(properties.properties, tag)
|
delete(properties.properties, tag)
|
||||||
return true
|
return true
|
||||||
|
@ -515,19 +533,26 @@ func (properties *propertyList) setSimpleProperty(tag string, value interface{})
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (properties *propertyList) setSizeProperty(tag string, value interface{}) bool {
|
func (properties *propertyList) setSizeProperty(tag string, value any) bool {
|
||||||
if !properties.setSimpleProperty(tag, value) {
|
if !properties.setSimpleProperty(tag, value) {
|
||||||
var size SizeUnit
|
var size SizeUnit
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case string:
|
case string:
|
||||||
var ok bool
|
var ok bool
|
||||||
if size, ok = StringToSizeUnit(value); !ok {
|
if fn := parseSizeFunc(value); fn != nil {
|
||||||
|
size.Type = SizeFunction
|
||||||
|
size.Function = fn
|
||||||
|
} else if size, ok = StringToSizeUnit(value); !ok {
|
||||||
invalidPropertyValue(tag, value)
|
invalidPropertyValue(tag, value)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case SizeUnit:
|
case SizeUnit:
|
||||||
size = value
|
size = value
|
||||||
|
|
||||||
|
case SizeFunc:
|
||||||
|
size.Type = SizeFunction
|
||||||
|
size.Function = value
|
||||||
|
|
||||||
case float32:
|
case float32:
|
||||||
size.Type = SizeInPixel
|
size.Type = SizeInPixel
|
||||||
size.Value = float64(value)
|
size.Value = float64(value)
|
||||||
|
@ -556,7 +581,7 @@ func (properties *propertyList) setSizeProperty(tag string, value interface{}) b
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (properties *propertyList) setAngleProperty(tag string, value interface{}) bool {
|
func (properties *propertyList) setAngleProperty(tag string, value any) bool {
|
||||||
if !properties.setSimpleProperty(tag, value) {
|
if !properties.setSimpleProperty(tag, value) {
|
||||||
var angle AngleUnit
|
var angle AngleUnit
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
|
@ -589,7 +614,7 @@ func (properties *propertyList) setAngleProperty(tag string, value interface{})
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (properties *propertyList) setColorProperty(tag string, value interface{}) bool {
|
func (properties *propertyList) setColorProperty(tag string, value any) bool {
|
||||||
if !properties.setSimpleProperty(tag, value) {
|
if !properties.setSimpleProperty(tag, value) {
|
||||||
var result Color
|
var result Color
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
|
@ -621,7 +646,7 @@ func (properties *propertyList) setColorProperty(tag string, value interface{})
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (properties *propertyList) setEnumProperty(tag string, value interface{}, values []string) bool {
|
func (properties *propertyList) setEnumProperty(tag string, value any, values []string) bool {
|
||||||
if !properties.setSimpleProperty(tag, value) {
|
if !properties.setSimpleProperty(tag, value) {
|
||||||
var n int
|
var n int
|
||||||
if text, ok := value.(string); ok {
|
if text, ok := value.(string); ok {
|
||||||
|
@ -646,7 +671,7 @@ func (properties *propertyList) setEnumProperty(tag string, value interface{}, v
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (properties *propertyList) setBoolProperty(tag string, value interface{}) bool {
|
func (properties *propertyList) setBoolProperty(tag string, value any) bool {
|
||||||
if !properties.setSimpleProperty(tag, value) {
|
if !properties.setSimpleProperty(tag, value) {
|
||||||
if text, ok := value.(string); ok {
|
if text, ok := value.(string); ok {
|
||||||
switch strings.ToLower(strings.Trim(text, " \t")) {
|
switch strings.ToLower(strings.Trim(text, " \t")) {
|
||||||
|
@ -683,7 +708,7 @@ func (properties *propertyList) setBoolProperty(tag string, value interface{}) b
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (properties *propertyList) setIntProperty(tag string, value interface{}) bool {
|
func (properties *propertyList) setIntProperty(tag string, value any) bool {
|
||||||
if !properties.setSimpleProperty(tag, value) {
|
if !properties.setSimpleProperty(tag, value) {
|
||||||
if text, ok := value.(string); ok {
|
if text, ok := value.(string); ok {
|
||||||
n, err := strconv.Atoi(strings.Trim(text, " \t"))
|
n, err := strconv.Atoi(strings.Trim(text, " \t"))
|
||||||
|
@ -704,7 +729,7 @@ func (properties *propertyList) setIntProperty(tag string, value interface{}) bo
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (properties *propertyList) setFloatProperty(tag string, value interface{}, min, max float64) bool {
|
func (properties *propertyList) setFloatProperty(tag string, value any, min, max float64) bool {
|
||||||
if !properties.setSimpleProperty(tag, value) {
|
if !properties.setSimpleProperty(tag, value) {
|
||||||
f := float64(0)
|
f := float64(0)
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
|
@ -715,6 +740,12 @@ func (properties *propertyList) setFloatProperty(tag string, value interface{},
|
||||||
ErrorLog(err.Error())
|
ErrorLog(err.Error())
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if f < min || f > max {
|
||||||
|
ErrorLogF(`"%T" out of range of "%s" property`, value, tag)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
properties.properties[tag] = value
|
||||||
|
return true
|
||||||
|
|
||||||
case float32:
|
case float32:
|
||||||
f = float64(value)
|
f = float64(value)
|
||||||
|
@ -742,11 +773,11 @@ func (properties *propertyList) setFloatProperty(tag string, value interface{},
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (properties *propertyList) Set(tag string, value interface{}) bool {
|
func (properties *propertyList) Set(tag string, value any) bool {
|
||||||
return properties.set(strings.ToLower(tag), value)
|
return properties.set(strings.ToLower(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (properties *propertyList) set(tag string, value interface{}) bool {
|
func (properties *propertyList) set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
delete(properties.properties, tag)
|
delete(properties.properties, tag)
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -3,29 +3,57 @@ package rui
|
||||||
const (
|
const (
|
||||||
// Visible - default value of the view Visibility property: View is visible
|
// Visible - default value of the view Visibility property: View is visible
|
||||||
Visible = 0
|
Visible = 0
|
||||||
|
|
||||||
// Invisible - value of the view Visibility property: View is invisible but takes place
|
// Invisible - value of the view Visibility property: View is invisible but takes place
|
||||||
Invisible = 1
|
Invisible = 1
|
||||||
|
|
||||||
// Gone - value of the view Visibility property: View is invisible and does not take place
|
// Gone - value of the view Visibility property: View is invisible and does not take place
|
||||||
Gone = 2
|
Gone = 2
|
||||||
|
|
||||||
|
// OverflowHidden - value of the view "overflow" property:
|
||||||
|
// Content is clipped if necessary to fit the padding box. No scrollbars are provided,
|
||||||
|
// and no support for allowing the user to scroll (such as by dragging or using a scroll wheel) is allowed.
|
||||||
|
// The content can be scrolled programmatically, so the element is still a scroll container.
|
||||||
|
OverflowHidden = 0
|
||||||
|
|
||||||
|
// OverflowVisible - value of the view "overflow" property:
|
||||||
|
// Content is not clipped and may be rendered outside the padding box.
|
||||||
|
OverflowVisible = 1
|
||||||
|
|
||||||
|
// OverflowScroll - value of the view "overflow" property:
|
||||||
|
// Content is clipped if necessary to fit the padding box. Browsers always display scrollbars whether or
|
||||||
|
// not any content is actually clipped, preventing scrollbars from appearing or disappearing as content changes.
|
||||||
|
OverflowScroll = 2
|
||||||
|
|
||||||
|
// OverflowAuto - value of the view "overflow" property:
|
||||||
|
// Depends on the browser user agent. If content fits inside the padding box, it looks the same as OverflowVisible,
|
||||||
|
// but still establishes a new block formatting context. Desktop browsers provide scrollbars if content overflows.
|
||||||
|
OverflowAuto = 3
|
||||||
|
|
||||||
// NoneTextTransform - not transform text
|
// NoneTextTransform - not transform text
|
||||||
NoneTextTransform = 0
|
NoneTextTransform = 0
|
||||||
|
|
||||||
// CapitalizeTextTransform - capitalize text
|
// CapitalizeTextTransform - capitalize text
|
||||||
CapitalizeTextTransform = 1
|
CapitalizeTextTransform = 1
|
||||||
|
|
||||||
// LowerCaseTextTransform - transform text to lower case
|
// LowerCaseTextTransform - transform text to lower case
|
||||||
LowerCaseTextTransform = 2
|
LowerCaseTextTransform = 2
|
||||||
|
|
||||||
// UpperCaseTextTransform - transform text to upper case
|
// UpperCaseTextTransform - transform text to upper case
|
||||||
UpperCaseTextTransform = 3
|
UpperCaseTextTransform = 3
|
||||||
|
|
||||||
// HorizontalTopToBottom - content flows horizontally from left to right, vertically from top to bottom.
|
// HorizontalTopToBottom - content flows horizontally from left to right, vertically from top to bottom.
|
||||||
// The next horizontal line is positioned below the previous line.
|
// The next horizontal line is positioned below the previous line.
|
||||||
HorizontalTopToBottom = 0
|
HorizontalTopToBottom = 0
|
||||||
|
|
||||||
// HorizontalBottomToTop - content flows horizontally from left to right, vertically from bottom to top.
|
// HorizontalBottomToTop - content flows horizontally from left to right, vertically from bottom to top.
|
||||||
// The next horizontal line is positioned above the previous line.
|
// The next horizontal line is positioned above the previous line.
|
||||||
HorizontalBottomToTop = 1
|
HorizontalBottomToTop = 1
|
||||||
|
|
||||||
// VerticalRightToLeft - content flows vertically from top to bottom, horizontally from right to left.
|
// VerticalRightToLeft - content flows vertically from top to bottom, horizontally from right to left.
|
||||||
// The next vertical line is positioned to the left of the previous line.
|
// The next vertical line is positioned to the left of the previous line.
|
||||||
VerticalRightToLeft = 2
|
VerticalRightToLeft = 2
|
||||||
|
|
||||||
// VerticalLeftToRight - content flows vertically from top to bottom, horizontally from left to right.
|
// VerticalLeftToRight - content flows vertically from top to bottom, horizontally from left to right.
|
||||||
// The next vertical line is positioned to the right of the previous line.
|
// The next vertical line is positioned to the right of the previous line.
|
||||||
VerticalLeftToRight = 3
|
VerticalLeftToRight = 3
|
||||||
|
@ -33,6 +61,7 @@ const (
|
||||||
// MixedTextOrientation - rotates the characters of horizontal scripts 90° clockwise.
|
// MixedTextOrientation - rotates the characters of horizontal scripts 90° clockwise.
|
||||||
// Lays out the characters of vertical scripts naturally. Default value.
|
// Lays out the characters of vertical scripts naturally. Default value.
|
||||||
MixedTextOrientation = 0
|
MixedTextOrientation = 0
|
||||||
|
|
||||||
// UprightTextOrientation - lays out the characters of horizontal scripts naturally (upright),
|
// UprightTextOrientation - lays out the characters of horizontal scripts naturally (upright),
|
||||||
// as well as the glyphs for vertical scripts. Note that this keyword causes all characters
|
// as well as the glyphs for vertical scripts. Note that this keyword causes all characters
|
||||||
// to be considered as left-to-right: the used value of "text-direction" is forced to be "left-to-right".
|
// to be considered as left-to-right: the used value of "text-direction" is forced to be "left-to-right".
|
||||||
|
@ -40,62 +69,84 @@ const (
|
||||||
|
|
||||||
// SystemTextDirection - direction of a text and other elements defined by system. This is the default value.
|
// SystemTextDirection - direction of a text and other elements defined by system. This is the default value.
|
||||||
SystemTextDirection = 0
|
SystemTextDirection = 0
|
||||||
|
|
||||||
// LeftToRightDirection - text and other elements go from left to right.
|
// LeftToRightDirection - text and other elements go from left to right.
|
||||||
LeftToRightDirection = 1
|
LeftToRightDirection = 1
|
||||||
|
|
||||||
//RightToLeftDirection - text and other elements go from right to left.
|
//RightToLeftDirection - text and other elements go from right to left.
|
||||||
RightToLeftDirection = 2
|
RightToLeftDirection = 2
|
||||||
|
|
||||||
// ThinFont - the value of "text-weight" property: the thin (hairline) text weight
|
// ThinFont - the value of "text-weight" property: the thin (hairline) text weight
|
||||||
ThinFont = 1
|
ThinFont = 1
|
||||||
|
|
||||||
// ExtraLightFont - the value of "text-weight" property: the extra light (ultra light) text weight
|
// ExtraLightFont - the value of "text-weight" property: the extra light (ultra light) text weight
|
||||||
ExtraLightFont = 2
|
ExtraLightFont = 2
|
||||||
|
|
||||||
// LightFont - the value of "text-weight" property: the light text weight
|
// LightFont - the value of "text-weight" property: the light text weight
|
||||||
LightFont = 3
|
LightFont = 3
|
||||||
|
|
||||||
// NormalFont - the value of "text-weight" property (default value): the normal text weight
|
// NormalFont - the value of "text-weight" property (default value): the normal text weight
|
||||||
NormalFont = 4
|
NormalFont = 4
|
||||||
|
|
||||||
// MediumFont - the value of "text-weight" property: the medium text weight
|
// MediumFont - the value of "text-weight" property: the medium text weight
|
||||||
MediumFont = 5
|
MediumFont = 5
|
||||||
|
|
||||||
// SemiBoldFont - the value of "text-weight" property: the semi bold (demi bold) text weight
|
// SemiBoldFont - the value of "text-weight" property: the semi bold (demi bold) text weight
|
||||||
SemiBoldFont = 6
|
SemiBoldFont = 6
|
||||||
|
|
||||||
// BoldFont - the value of "text-weight" property: the bold text weight
|
// BoldFont - the value of "text-weight" property: the bold text weight
|
||||||
BoldFont = 7
|
BoldFont = 7
|
||||||
|
|
||||||
// ExtraBoldFont - the value of "text-weight" property: the extra bold (ultra bold) text weight
|
// ExtraBoldFont - the value of "text-weight" property: the extra bold (ultra bold) text weight
|
||||||
ExtraBoldFont = 8
|
ExtraBoldFont = 8
|
||||||
|
|
||||||
// BlackFont - the value of "text-weight" property: the black (heavy) text weight
|
// BlackFont - the value of "text-weight" property: the black (heavy) text weight
|
||||||
BlackFont = 9
|
BlackFont = 9
|
||||||
|
|
||||||
// TopAlign - top vertical-align for the "vertical-align" property
|
// TopAlign - top vertical-align for the "vertical-align" property
|
||||||
TopAlign = 0
|
TopAlign = 0
|
||||||
|
|
||||||
// BottomAlign - bottom vertical-align for the "vertical-align" property
|
// BottomAlign - bottom vertical-align for the "vertical-align" property
|
||||||
BottomAlign = 1
|
BottomAlign = 1
|
||||||
|
|
||||||
// LeftAlign - the left horizontal-align for the "horizontal-align" property
|
// LeftAlign - the left horizontal-align for the "horizontal-align" property
|
||||||
LeftAlign = 0
|
LeftAlign = 0
|
||||||
|
|
||||||
// RightAlign - the right horizontal-align for the "horizontal-align" property
|
// RightAlign - the right horizontal-align for the "horizontal-align" property
|
||||||
RightAlign = 1
|
RightAlign = 1
|
||||||
|
|
||||||
// CenterAlign - the center horizontal/vertical-align for the "horizontal-align"/"vertical-align" property
|
// CenterAlign - the center horizontal/vertical-align for the "horizontal-align"/"vertical-align" property
|
||||||
CenterAlign = 2
|
CenterAlign = 2
|
||||||
|
|
||||||
// StretchAlign - the stretch horizontal/vertical-align for the "horizontal-align"/"vertical-align" property
|
// StretchAlign - the stretch horizontal/vertical-align for the "horizontal-align"/"vertical-align" property
|
||||||
StretchAlign = 3
|
StretchAlign = 3
|
||||||
|
|
||||||
// JustifyAlign - the justify text align for "text-align" property
|
// JustifyAlign - the justify text align for "text-align" property
|
||||||
JustifyAlign = 3
|
JustifyAlign = 3
|
||||||
|
|
||||||
// BaselineAlign - the baseline cell-vertical-align for the "cell-vertical-align" property
|
// BaselineAlign - the baseline cell-vertical-align for the "cell-vertical-align" property
|
||||||
BaselineAlign = 4
|
BaselineAlign = 4
|
||||||
|
|
||||||
// WhiteSpaceNormal - sequences of white space are collapsed. Newline characters in the source
|
// WhiteSpaceNormal - sequences of white space are collapsed. Newline characters in the source
|
||||||
// are handled the same as other white space. Lines are broken as necessary to fill line boxes.
|
// are handled the same as other white space. Lines are broken as necessary to fill line boxes.
|
||||||
WhiteSpaceNormal = 0
|
WhiteSpaceNormal = 0
|
||||||
|
|
||||||
// WhiteSpaceNowrap - collapses white space as for normal, but suppresses line breaks (text wrapping)
|
// WhiteSpaceNowrap - collapses white space as for normal, but suppresses line breaks (text wrapping)
|
||||||
// within the source.
|
// within the source.
|
||||||
WhiteSpaceNowrap = 1
|
WhiteSpaceNowrap = 1
|
||||||
|
|
||||||
// WhiteSpacePre - sequences of white space are preserved. Lines are only broken at newline
|
// WhiteSpacePre - sequences of white space are preserved. Lines are only broken at newline
|
||||||
// characters in the source and at <br> elements.
|
// characters in the source and at <br> elements.
|
||||||
WhiteSpacePre = 2
|
WhiteSpacePre = 2
|
||||||
|
|
||||||
// WhiteSpacePreWrap - Sequences of white space are preserved. Lines are broken at newline
|
// WhiteSpacePreWrap - Sequences of white space are preserved. Lines are broken at newline
|
||||||
// characters, at <br>, and as necessary to fill line boxes.
|
// characters, at <br>, and as necessary to fill line boxes.
|
||||||
WhiteSpacePreWrap = 3
|
WhiteSpacePreWrap = 3
|
||||||
|
|
||||||
// WhiteSpacePreLine - sequences of white space are collapsed. Lines are broken at newline characters,
|
// WhiteSpacePreLine - sequences of white space are collapsed. Lines are broken at newline characters,
|
||||||
// at <br>, and as necessary to fill line boxes.
|
// at <br>, and as necessary to fill line boxes.
|
||||||
WhiteSpacePreLine = 4
|
WhiteSpacePreLine = 4
|
||||||
|
|
||||||
// WhiteSpaceBreakSpaces - the behavior is identical to that of WhiteSpacePreWrap, except that:
|
// WhiteSpaceBreakSpaces - the behavior is identical to that of WhiteSpacePreWrap, except that:
|
||||||
// * Any sequence of preserved white space always takes up space, including at the end of the line.
|
// * Any sequence of preserved white space always takes up space, including at the end of the line.
|
||||||
// * A line breaking opportunity exists after every preserved white space character, including between white space characters.
|
// * A line breaking opportunity exists after every preserved white space character, including between white space characters.
|
||||||
|
@ -104,12 +155,15 @@ const (
|
||||||
|
|
||||||
// WordBreakNormal - use the default line break rule.
|
// WordBreakNormal - use the default line break rule.
|
||||||
WordBreakNormal = 0
|
WordBreakNormal = 0
|
||||||
|
|
||||||
// WordBreakAll - to prevent overflow, word breaks should be inserted between any two characters
|
// WordBreakAll - to prevent overflow, word breaks should be inserted between any two characters
|
||||||
// (excluding Chinese/Japanese/Korean text).
|
// (excluding Chinese/Japanese/Korean text).
|
||||||
WordBreakAll = 1
|
WordBreakAll = 1
|
||||||
|
|
||||||
// WordBreakKeepAll - word breaks should not be used for Chinese/Japanese/Korean (CJK) text.
|
// WordBreakKeepAll - word breaks should not be used for Chinese/Japanese/Korean (CJK) text.
|
||||||
// Non-CJK text behavior is the same as for normal.
|
// Non-CJK text behavior is the same as for normal.
|
||||||
WordBreakKeepAll = 2
|
WordBreakKeepAll = 2
|
||||||
|
|
||||||
// WordBreakWord - when the block boundaries are exceeded, the remaining whole words can be split
|
// WordBreakWord - when the block boundaries are exceeded, the remaining whole words can be split
|
||||||
// in an arbitrary place, unless a more suitable place for the line break is found.
|
// in an arbitrary place, unless a more suitable place for the line break is found.
|
||||||
WordBreakWord = 3
|
WordBreakWord = 3
|
||||||
|
@ -117,6 +171,7 @@ const (
|
||||||
// TextOverflowClip - truncate the text at the limit of the content area, therefore the truncation
|
// TextOverflowClip - truncate the text at the limit of the content area, therefore the truncation
|
||||||
// can happen in the middle of a character.
|
// can happen in the middle of a character.
|
||||||
TextOverflowClip = 0
|
TextOverflowClip = 0
|
||||||
|
|
||||||
// TextOverflowEllipsis - display an ellipsis ('…', U+2026 HORIZONTAL ELLIPSIS) to represent clipped text.
|
// TextOverflowEllipsis - display an ellipsis ('…', U+2026 HORIZONTAL ELLIPSIS) to represent clipped text.
|
||||||
// The ellipsis is displayed inside the content area, decreasing the amount of text displayed.
|
// The ellipsis is displayed inside the content area, decreasing the amount of text displayed.
|
||||||
// If there is not enough space to display the ellipsis, it is clipped.
|
// If there is not enough space to display the ellipsis, it is clipped.
|
||||||
|
@ -124,87 +179,111 @@ const (
|
||||||
|
|
||||||
// DefaultSemantics - default value of the view Semantic property
|
// DefaultSemantics - default value of the view Semantic property
|
||||||
DefaultSemantics = 0
|
DefaultSemantics = 0
|
||||||
|
|
||||||
// ArticleSemantics - value of the view Semantic property: view represents a self-contained
|
// ArticleSemantics - value of the view Semantic property: view represents a self-contained
|
||||||
// composition in a document, page, application, or site, which is intended to be
|
// composition in a document, page, application, or site, which is intended to be
|
||||||
// independently distributable or reusable (e.g., in syndication)
|
// independently distributable or reusable (e.g., in syndication)
|
||||||
ArticleSemantics = 1
|
ArticleSemantics = 1
|
||||||
|
|
||||||
// SectionSemantics - value of the view Semantic property: view represents
|
// SectionSemantics - value of the view Semantic property: view represents
|
||||||
// a generic standalone section of a document, which doesn't have a more specific
|
// a generic standalone section of a document, which doesn't have a more specific
|
||||||
// semantic element to represent it.
|
// semantic element to represent it.
|
||||||
SectionSemantics = 2
|
SectionSemantics = 2
|
||||||
|
|
||||||
// AsideSemantics - value of the view Semantic property: view represents a portion
|
// AsideSemantics - value of the view Semantic property: view represents a portion
|
||||||
// of a document whose content is only indirectly related to the document's main content.
|
// of a document whose content is only indirectly related to the document's main content.
|
||||||
// Asides are frequently presented as sidebars or call-out boxes.
|
// Asides are frequently presented as sidebars or call-out boxes.
|
||||||
AsideSemantics = 3
|
AsideSemantics = 3
|
||||||
|
|
||||||
// HeaderSemantics - value of the view Semantic property: view represents introductory
|
// HeaderSemantics - value of the view Semantic property: view represents introductory
|
||||||
// content, typically a group of introductory or navigational aids. It may contain
|
// content, typically a group of introductory or navigational aids. It may contain
|
||||||
// some heading elements but also a logo, a search form, an author name, and other elements.
|
// some heading elements but also a logo, a search form, an author name, and other elements.
|
||||||
HeaderSemantics = 4
|
HeaderSemantics = 4
|
||||||
|
|
||||||
// MainSemantics - value of the view Semantic property: view represents the dominant content
|
// MainSemantics - value of the view Semantic property: view represents the dominant content
|
||||||
// of the application. The main content area consists of content that is directly related
|
// of the application. The main content area consists of content that is directly related
|
||||||
// to or expands upon the central topic of a document, or the central functionality of an application.
|
// to or expands upon the central topic of a document, or the central functionality of an application.
|
||||||
MainSemantics = 5
|
MainSemantics = 5
|
||||||
|
|
||||||
// FooterSemantics - value of the view Semantic property: view represents a footer for its
|
// FooterSemantics - value of the view Semantic property: view represents a footer for its
|
||||||
// nearest sectioning content or sectioning root element. A footer view typically contains
|
// nearest sectioning content or sectioning root element. A footer view typically contains
|
||||||
// information about the author of the section, copyright data or links to related documents.
|
// information about the author of the section, copyright data or links to related documents.
|
||||||
FooterSemantics = 6
|
FooterSemantics = 6
|
||||||
|
|
||||||
// NavigationSemantics - value of the view Semantic property: view represents a section of
|
// NavigationSemantics - value of the view Semantic property: view represents a section of
|
||||||
// a page whose purpose is to provide navigation links, either within the current document
|
// a page whose purpose is to provide navigation links, either within the current document
|
||||||
// or to other documents. Common examples of navigation sections are menus, tables of contents,
|
// or to other documents. Common examples of navigation sections are menus, tables of contents,
|
||||||
// and indexes.
|
// and indexes.
|
||||||
NavigationSemantics = 7
|
NavigationSemantics = 7
|
||||||
|
|
||||||
// FigureSemantics - value of the view Semantic property: view represents self-contained content,
|
// FigureSemantics - value of the view Semantic property: view represents self-contained content,
|
||||||
// potentially with an optional caption, which is specified using the FigureCaptionSemantics view.
|
// potentially with an optional caption, which is specified using the FigureCaptionSemantics view.
|
||||||
FigureSemantics = 8
|
FigureSemantics = 8
|
||||||
|
|
||||||
// FigureCaptionSemantics - value of the view Semantic property: view represents a caption or
|
// FigureCaptionSemantics - value of the view Semantic property: view represents a caption or
|
||||||
// legend describing the rest of the contents of its parent FigureSemantics view.
|
// legend describing the rest of the contents of its parent FigureSemantics view.
|
||||||
FigureCaptionSemantics = 9
|
FigureCaptionSemantics = 9
|
||||||
|
|
||||||
// ButtonSemantics - value of the view Semantic property: view a clickable button
|
// ButtonSemantics - value of the view Semantic property: view a clickable button
|
||||||
ButtonSemantics = 10
|
ButtonSemantics = 10
|
||||||
|
|
||||||
// ParagraphSemantics - value of the view Semantic property: view represents a paragraph.
|
// ParagraphSemantics - value of the view Semantic property: view represents a paragraph.
|
||||||
// Paragraphs are usually represented in visual media as blocks of text separated
|
// Paragraphs are usually represented in visual media as blocks of text separated
|
||||||
// from adjacent blocks by blank lines and/or first-line indentation
|
// from adjacent blocks by blank lines and/or first-line indentation
|
||||||
ParagraphSemantics = 11
|
ParagraphSemantics = 11
|
||||||
|
|
||||||
// H1Semantics - value of the view Semantic property: view represent of first level section headings.
|
// H1Semantics - value of the view Semantic property: view represent of first level section headings.
|
||||||
// H1Semantics is the highest section level and H6Semantics is the lowest.
|
// H1Semantics is the highest section level and H6Semantics is the lowest.
|
||||||
H1Semantics = 12
|
H1Semantics = 12
|
||||||
|
|
||||||
// H2Semantics - value of the view Semantic property: view represent of second level section headings.
|
// H2Semantics - value of the view Semantic property: view represent of second level section headings.
|
||||||
// H1Semantics is the highest section level and H6Semantics is the lowest.
|
// H1Semantics is the highest section level and H6Semantics is the lowest.
|
||||||
H2Semantics = 13
|
H2Semantics = 13
|
||||||
|
|
||||||
// H3Semantics - value of the view Semantic property: view represent of third level section headings.
|
// H3Semantics - value of the view Semantic property: view represent of third level section headings.
|
||||||
// H1Semantics is the highest section level and H6Semantics is the lowest.
|
// H1Semantics is the highest section level and H6Semantics is the lowest.
|
||||||
H3Semantics = 14
|
H3Semantics = 14
|
||||||
|
|
||||||
// H4Semantics - value of the view Semantic property: view represent of fourth level section headings.
|
// H4Semantics - value of the view Semantic property: view represent of fourth level section headings.
|
||||||
// H1Semantics is the highest section level and H6Semantics is the lowest.
|
// H1Semantics is the highest section level and H6Semantics is the lowest.
|
||||||
H4Semantics = 15
|
H4Semantics = 15
|
||||||
|
|
||||||
// H5Semantics - value of the view Semantic property: view represent of fifth level section headings.
|
// H5Semantics - value of the view Semantic property: view represent of fifth level section headings.
|
||||||
// H1Semantics is the highest section level and H6Semantics is the lowest.
|
// H1Semantics is the highest section level and H6Semantics is the lowest.
|
||||||
H5Semantics = 16
|
H5Semantics = 16
|
||||||
|
|
||||||
// H6Semantics - value of the view Semantic property: view represent of sixth level section headings.
|
// H6Semantics - value of the view Semantic property: view represent of sixth level section headings.
|
||||||
// H1Semantics is the highest section level and H6Semantics is the lowest.
|
// H1Semantics is the highest section level and H6Semantics is the lowest.
|
||||||
H6Semantics = 17
|
H6Semantics = 17
|
||||||
|
|
||||||
// BlockquoteSemantics - value of the view Semantic property: view indicates that
|
// BlockquoteSemantics - value of the view Semantic property: view indicates that
|
||||||
// the enclosed text is an extended quotation.
|
// the enclosed text is an extended quotation.
|
||||||
BlockquoteSemantics = 18
|
BlockquoteSemantics = 18
|
||||||
|
|
||||||
// CodeSemantics - value of the view Semantic property: view displays its contents styled
|
// CodeSemantics - value of the view Semantic property: view displays its contents styled
|
||||||
// in a fashion intended to indicate that the text is a short fragment of computer code
|
// in a fashion intended to indicate that the text is a short fragment of computer code
|
||||||
CodeSemantics = 19
|
CodeSemantics = 19
|
||||||
|
|
||||||
// NoneFloat - value of the view "float" property: the View must not float.
|
// NoneFloat - value of the view "float" property: the View must not float.
|
||||||
NoneFloat = 0
|
NoneFloat = 0
|
||||||
|
|
||||||
// LeftFloat - value of the view "float" property: the View must float on the left side of its containing block.
|
// LeftFloat - value of the view "float" property: the View must float on the left side of its containing block.
|
||||||
LeftFloat = 1
|
LeftFloat = 1
|
||||||
|
|
||||||
// RightFloat - value of the view "float" property: the View must float on the right side of its containing block.
|
// RightFloat - value of the view "float" property: the View must float on the right side of its containing block.
|
||||||
RightFloat = 2
|
RightFloat = 2
|
||||||
|
|
||||||
// NoneResize - value of the view "resize" property: the View The offers no user-controllable method for resizing it.
|
// NoneResize - value of the view "resize" property: the View The offers no user-controllable method for resizing it.
|
||||||
NoneResize = 0
|
NoneResize = 0
|
||||||
|
|
||||||
// BothResize - value of the view "resize" property: the View displays a mechanism for allowing
|
// BothResize - value of the view "resize" property: the View displays a mechanism for allowing
|
||||||
// the user to resize it, which may be resized both horizontally and vertically.
|
// the user to resize it, which may be resized both horizontally and vertically.
|
||||||
BothResize = 1
|
BothResize = 1
|
||||||
|
|
||||||
// HorizontalResize - value of the view "resize" property: the View displays a mechanism for allowing
|
// HorizontalResize - value of the view "resize" property: the View displays a mechanism for allowing
|
||||||
// the user to resize it in the horizontal direction.
|
// the user to resize it in the horizontal direction.
|
||||||
HorizontalResize = 2
|
HorizontalResize = 2
|
||||||
|
|
||||||
// VerticalResize - value of the view "resize" property: the View displays a mechanism for allowing
|
// VerticalResize - value of the view "resize" property: the View displays a mechanism for allowing
|
||||||
// the user to resize it in the vertical direction.
|
// the user to resize it in the vertical direction.
|
||||||
VerticalResize = 3
|
VerticalResize = 3
|
||||||
|
@ -212,14 +291,17 @@ const (
|
||||||
// RowAutoFlow - value of the "grid-auto-flow" property of the GridLayout:
|
// RowAutoFlow - value of the "grid-auto-flow" property of the GridLayout:
|
||||||
// Views are placed by filling each row in turn, adding new rows as necessary.
|
// Views are placed by filling each row in turn, adding new rows as necessary.
|
||||||
RowAutoFlow = 0
|
RowAutoFlow = 0
|
||||||
|
|
||||||
// ColumnAutoFlow - value of the "grid-auto-flow" property of the GridLayout:
|
// ColumnAutoFlow - value of the "grid-auto-flow" property of the GridLayout:
|
||||||
// Views are placed by filling each column in turn, adding new columns as necessary.
|
// Views are placed by filling each column in turn, adding new columns as necessary.
|
||||||
ColumnAutoFlow = 1
|
ColumnAutoFlow = 1
|
||||||
|
|
||||||
// RowDenseAutoFlow - value of the "grid-auto-flow" property of the GridLayout:
|
// RowDenseAutoFlow - value of the "grid-auto-flow" property of the GridLayout:
|
||||||
// Views are placed by filling each row, adding new rows as necessary.
|
// Views are placed by filling each row, adding new rows as necessary.
|
||||||
// "dense" packing algorithm attempts to fill in holes earlier in the grid, if smaller items come up later.
|
// "dense" packing algorithm attempts to fill in holes earlier in the grid, if smaller items come up later.
|
||||||
// This may cause views to appear out-of-order, when doing so would fill in holes left by larger views.
|
// This may cause views to appear out-of-order, when doing so would fill in holes left by larger views.
|
||||||
RowDenseAutoFlow = 2
|
RowDenseAutoFlow = 2
|
||||||
|
|
||||||
// ColumnDenseAutoFlow - value of the "grid-auto-flow" property of the GridLayout:
|
// ColumnDenseAutoFlow - value of the "grid-auto-flow" property of the GridLayout:
|
||||||
// Views are placed by filling each column, adding new columns as necessary.
|
// Views are placed by filling each column, adding new columns as necessary.
|
||||||
// "dense" packing algorithm attempts to fill in holes earlier in the grid, if smaller items come up later.
|
// "dense" packing algorithm attempts to fill in holes earlier in the grid, if smaller items come up later.
|
||||||
|
|
47
radius.go
47
radius.go
|
@ -109,7 +109,7 @@ type radiusPropertyData struct {
|
||||||
// NewRadiusProperty creates the new RadiusProperty
|
// NewRadiusProperty creates the new RadiusProperty
|
||||||
func NewRadiusProperty(params Params) RadiusProperty {
|
func NewRadiusProperty(params Params) RadiusProperty {
|
||||||
result := new(radiusPropertyData)
|
result := new(radiusPropertyData)
|
||||||
result.properties = map[string]interface{}{}
|
result.properties = map[string]any{}
|
||||||
if params != nil {
|
if params != nil {
|
||||||
for _, tag := range []string{X, Y, TopLeft, TopRight, BottomLeft, BottomRight, TopLeftX, TopLeftY,
|
for _, tag := range []string{X, Y, TopLeft, TopRight, BottomLeft, BottomRight, TopLeftX, TopLeftY,
|
||||||
TopRightX, TopRightY, BottomLeftX, BottomLeftY, BottomRightX, BottomRightY} {
|
TopRightX, TopRightY, BottomLeftX, BottomLeftY, BottomRightX, BottomRightY} {
|
||||||
|
@ -172,7 +172,7 @@ func (radius *radiusPropertyData) deleteUnusedTags() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
equalValue := func(value1, value2 interface{}) bool {
|
equalValue := func(value1, value2 any) bool {
|
||||||
switch value1 := value1.(type) {
|
switch value1 := value1.(type) {
|
||||||
case string:
|
case string:
|
||||||
switch value2 := value2.(type) {
|
switch value2 := value2.(type) {
|
||||||
|
@ -243,7 +243,7 @@ func (radius *radiusPropertyData) Remove(tag string) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (radius *radiusPropertyData) Set(tag string, value interface{}) bool {
|
func (radius *radiusPropertyData) Set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
radius.Remove(tag)
|
radius.Remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -318,7 +318,7 @@ func (radius *radiusPropertyData) Set(tag string, value interface{}) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (radius *radiusPropertyData) Get(tag string) interface{} {
|
func (radius *radiusPropertyData) Get(tag string) any {
|
||||||
tag = radius.normalizeTag(tag)
|
tag = radius.normalizeTag(tag)
|
||||||
if value, ok := radius.properties[tag]; ok {
|
if value, ok := radius.properties[tag]; ok {
|
||||||
return value
|
return value
|
||||||
|
@ -455,7 +455,7 @@ func (radius BoxRadius) String() string {
|
||||||
return buffer.String()
|
return buffer.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (radius BoxRadius) cssValue(builder cssBuilder) {
|
func (radius BoxRadius) cssValue(builder cssBuilder, session Session) {
|
||||||
|
|
||||||
if (radius.TopLeftX.Type == Auto || radius.TopLeftX.Value == 0) &&
|
if (radius.TopLeftX.Type == Auto || radius.TopLeftX.Value == 0) &&
|
||||||
(radius.TopLeftY.Type == Auto || radius.TopLeftY.Value == 0) &&
|
(radius.TopLeftY.Type == Auto || radius.TopLeftY.Value == 0) &&
|
||||||
|
@ -471,23 +471,23 @@ func (radius BoxRadius) cssValue(builder cssBuilder) {
|
||||||
buffer := allocStringBuilder()
|
buffer := allocStringBuilder()
|
||||||
defer freeStringBuilder(buffer)
|
defer freeStringBuilder(buffer)
|
||||||
|
|
||||||
buffer.WriteString(radius.TopLeftX.cssString("0"))
|
buffer.WriteString(radius.TopLeftX.cssString("0", session))
|
||||||
|
|
||||||
if radius.AllAnglesIsEqual() {
|
if radius.AllAnglesIsEqual() {
|
||||||
|
|
||||||
if !radius.TopLeftX.Equal(radius.TopLeftY) {
|
if !radius.TopLeftX.Equal(radius.TopLeftY) {
|
||||||
buffer.WriteString(" / ")
|
buffer.WriteString(" / ")
|
||||||
buffer.WriteString(radius.TopLeftY.cssString("0"))
|
buffer.WriteString(radius.TopLeftY.cssString("0", session))
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
buffer.WriteRune(' ')
|
buffer.WriteRune(' ')
|
||||||
buffer.WriteString(radius.TopRightX.cssString("0"))
|
buffer.WriteString(radius.TopRightX.cssString("0", session))
|
||||||
buffer.WriteRune(' ')
|
buffer.WriteRune(' ')
|
||||||
buffer.WriteString(radius.BottomRightX.cssString("0"))
|
buffer.WriteString(radius.BottomRightX.cssString("0", session))
|
||||||
buffer.WriteRune(' ')
|
buffer.WriteRune(' ')
|
||||||
buffer.WriteString(radius.BottomLeftX.cssString("0"))
|
buffer.WriteString(radius.BottomLeftX.cssString("0", session))
|
||||||
|
|
||||||
if !radius.TopLeftX.Equal(radius.TopLeftY) ||
|
if !radius.TopLeftX.Equal(radius.TopLeftY) ||
|
||||||
!radius.TopRightX.Equal(radius.TopRightY) ||
|
!radius.TopRightX.Equal(radius.TopRightY) ||
|
||||||
|
@ -495,22 +495,22 @@ func (radius BoxRadius) cssValue(builder cssBuilder) {
|
||||||
!radius.BottomRightX.Equal(radius.BottomRightY) {
|
!radius.BottomRightX.Equal(radius.BottomRightY) {
|
||||||
|
|
||||||
buffer.WriteString(" / ")
|
buffer.WriteString(" / ")
|
||||||
buffer.WriteString(radius.TopLeftY.cssString("0"))
|
buffer.WriteString(radius.TopLeftY.cssString("0", session))
|
||||||
buffer.WriteRune(' ')
|
buffer.WriteRune(' ')
|
||||||
buffer.WriteString(radius.TopRightY.cssString("0"))
|
buffer.WriteString(radius.TopRightY.cssString("0", session))
|
||||||
buffer.WriteRune(' ')
|
buffer.WriteRune(' ')
|
||||||
buffer.WriteString(radius.BottomRightY.cssString("0"))
|
buffer.WriteString(radius.BottomRightY.cssString("0", session))
|
||||||
buffer.WriteRune(' ')
|
buffer.WriteRune(' ')
|
||||||
buffer.WriteString(radius.BottomLeftY.cssString("0"))
|
buffer.WriteString(radius.BottomLeftY.cssString("0", session))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.add("border-radius", buffer.String())
|
builder.add("border-radius", buffer.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (radius BoxRadius) cssString() string {
|
func (radius BoxRadius) cssString(session Session) string {
|
||||||
var builder cssValueBuilder
|
var builder cssValueBuilder
|
||||||
radius.cssValue(&builder)
|
radius.cssValue(&builder, session)
|
||||||
return builder.finish()
|
return builder.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,7 +570,7 @@ func getRadiusProperty(style Properties) RadiusProperty {
|
||||||
return NewRadiusProperty(nil)
|
return NewRadiusProperty(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (properties *propertyList) setRadius(value interface{}) bool {
|
func (properties *propertyList) setRadius(value any) bool {
|
||||||
|
|
||||||
if value == nil {
|
if value == nil {
|
||||||
delete(properties.properties, Radius)
|
delete(properties.properties, Radius)
|
||||||
|
@ -645,7 +645,16 @@ func (properties *propertyList) setRadius(value interface{}) bool {
|
||||||
properties.properties[Radius] = radius
|
properties.properties[Radius] = radius
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
case float32:
|
||||||
|
return properties.setRadius(Px(float64(value)))
|
||||||
|
|
||||||
|
case float64:
|
||||||
|
return properties.setRadius(Px(value))
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
if n, ok := isInt(value); ok {
|
||||||
|
return properties.setRadius(Px(float64(n)))
|
||||||
|
}
|
||||||
notCompatibleType(Radius, value)
|
notCompatibleType(Radius, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -664,7 +673,7 @@ func (properties *propertyList) removeRadiusElement(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (properties *propertyList) setRadiusElement(tag string, value interface{}) bool {
|
func (properties *propertyList) setRadiusElement(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
properties.removeRadiusElement(tag)
|
properties.removeRadiusElement(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -679,7 +688,7 @@ func (properties *propertyList) setRadiusElement(tag string, value interface{})
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRadiusElement(style Properties, tag string) interface{} {
|
func getRadiusElement(style Properties, tag string) any {
|
||||||
value := style.Get(Radius)
|
value := style.Get(Radius)
|
||||||
if value != nil {
|
if value != nil {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
|
|
18
resizable.go
18
resizable.go
|
@ -45,7 +45,7 @@ type resizableData struct {
|
||||||
// NewResizable create new Resizable object and return it
|
// NewResizable create new Resizable object and return it
|
||||||
func NewResizable(session Session, params Params) Resizable {
|
func NewResizable(session Session, params Params) Resizable {
|
||||||
view := new(resizableData)
|
view := new(resizableData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -54,8 +54,8 @@ func newResizable(session Session) View {
|
||||||
return NewResizable(session, nil)
|
return NewResizable(session, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (resizable *resizableData) Init(session Session) {
|
func (resizable *resizableData) init(session Session) {
|
||||||
resizable.viewData.Init(session)
|
resizable.viewData.init(session)
|
||||||
resizable.tag = "Resizable"
|
resizable.tag = "Resizable"
|
||||||
resizable.systemClass = "ruiGridLayout"
|
resizable.systemClass = "ruiGridLayout"
|
||||||
resizable.content = []View{}
|
resizable.content = []View{}
|
||||||
|
@ -108,11 +108,11 @@ func (resizable *resizableData) remove(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (resizable *resizableData) Set(tag string, value interface{}) bool {
|
func (resizable *resizableData) Set(tag string, value any) bool {
|
||||||
return resizable.set(strings.ToLower(tag), value)
|
return resizable.set(strings.ToLower(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (resizable *resizableData) set(tag string, value interface{}) bool {
|
func (resizable *resizableData) set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
resizable.remove(tag)
|
resizable.remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -183,7 +183,7 @@ func (resizable *resizableData) set(tag string, value interface{}) bool {
|
||||||
return resizable.viewData.set(tag, value)
|
return resizable.viewData.set(tag, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (resizable *resizableData) Get(tag string) interface{} {
|
func (resizable *resizableData) Get(tag string) any {
|
||||||
return resizable.get(strings.ToLower(tag))
|
return resizable.get(strings.ToLower(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,7 +235,7 @@ func (resizable *resizableData) getSide() int {
|
||||||
return AllSides
|
return AllSides
|
||||||
}
|
}
|
||||||
|
|
||||||
func (resizable *resizableData) setSide(value interface{}) bool {
|
func (resizable *resizableData) setSide(value any) bool {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case string:
|
case string:
|
||||||
if n, err := strconv.Atoi(value); err == nil {
|
if n, err := strconv.Atoi(value); err == nil {
|
||||||
|
@ -340,7 +340,7 @@ func (resizable *resizableData) updateResizeBorderWidth() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (resizable *resizableData) cellSizeCSS() (string, string) {
|
func (resizable *resizableData) cellSizeCSS() (string, string) {
|
||||||
w := resizable.resizeBorderWidth().cssString("4px")
|
w := resizable.resizeBorderWidth().cssString("4px", resizable.Session())
|
||||||
side := resizable.getSide()
|
side := resizable.getSide()
|
||||||
column := "1fr"
|
column := "1fr"
|
||||||
row := "1fr"
|
row := "1fr"
|
||||||
|
@ -384,7 +384,7 @@ func (resizable *resizableData) htmlSubviews(self View, buffer *strings.Builder)
|
||||||
top := 1
|
top := 1
|
||||||
leftSide := (side & LeftSide) != 0
|
leftSide := (side & LeftSide) != 0
|
||||||
rightSide := (side & RightSide) != 0
|
rightSide := (side & RightSide) != 0
|
||||||
w := resizable.resizeBorderWidth().cssString("4px")
|
w := resizable.resizeBorderWidth().cssString("4px", resizable.Session())
|
||||||
|
|
||||||
if leftSide {
|
if leftSide {
|
||||||
left = 2
|
left = 2
|
||||||
|
|
179
resizeEvent.go
179
resizeEvent.go
|
@ -3,9 +3,12 @@ package rui
|
||||||
// ResizeEvent is the constant for "resize-event" property tag.
|
// ResizeEvent is the constant for "resize-event" property tag.
|
||||||
// The "resize-event" is fired when the view changes its size.
|
// The "resize-event" is fired when the view changes its size.
|
||||||
// The main listener format:
|
// The main listener format:
|
||||||
// func(View, Frame).
|
//
|
||||||
|
// func(View, Frame).
|
||||||
|
//
|
||||||
// The additional listener formats:
|
// The additional listener formats:
|
||||||
// func(Frame), func(View), and func().
|
//
|
||||||
|
// func(Frame), func(View), and func().
|
||||||
const ResizeEvent = "resize-event"
|
const ResizeEvent = "resize-event"
|
||||||
|
|
||||||
func (view *viewData) onResize(self View, x, y, width, height float64) {
|
func (view *viewData) onResize(self View, x, y, width, height float64) {
|
||||||
|
@ -13,7 +16,7 @@ func (view *viewData) onResize(self View, x, y, width, height float64) {
|
||||||
view.frame.Top = y
|
view.frame.Top = y
|
||||||
view.frame.Width = width
|
view.frame.Width = width
|
||||||
view.frame.Height = height
|
view.frame.Height = height
|
||||||
for _, listener := range GetResizeListeners(view, "") {
|
for _, listener := range GetResizeListeners(view) {
|
||||||
listener(self, view.frame)
|
listener(self, view.frame)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,147 +24,19 @@ func (view *viewData) onResize(self View, x, y, width, height float64) {
|
||||||
func (view *viewData) onItemResize(self View, index string, x, y, width, height float64) {
|
func (view *viewData) onItemResize(self View, index string, x, y, width, height float64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *viewData) setFrameListener(tag string, value interface{}) bool {
|
func (view *viewData) setFrameListener(tag string, value any) bool {
|
||||||
if value == nil {
|
listeners, ok := valueToEventListeners[View, Frame](value)
|
||||||
delete(view.properties, tag)
|
if !ok {
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
switch value := value.(type) {
|
|
||||||
case func(View, Frame):
|
|
||||||
view.properties[tag] = []func(View, Frame){value}
|
|
||||||
|
|
||||||
case []func(View, Frame):
|
|
||||||
if len(value) > 0 {
|
|
||||||
view.properties[tag] = value
|
|
||||||
} else {
|
|
||||||
delete(view.properties, tag)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
case func(Frame):
|
|
||||||
fn := func(_ View, frame Frame) {
|
|
||||||
value(frame)
|
|
||||||
}
|
|
||||||
view.properties[tag] = []func(View, Frame){fn}
|
|
||||||
|
|
||||||
case []func(Frame):
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
delete(view.properties, tag)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
listeners := make([]func(View, Frame), count)
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
notCompatibleType(tag, val)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
listeners[i] = func(_ View, frame Frame) {
|
|
||||||
val(frame)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
view.properties[tag] = listeners
|
|
||||||
|
|
||||||
case func(View):
|
|
||||||
fn := func(view View, _ Frame) {
|
|
||||||
value(view)
|
|
||||||
}
|
|
||||||
view.properties[tag] = []func(View, Frame){fn}
|
|
||||||
|
|
||||||
case []func(View):
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
delete(view.properties, tag)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
listeners := make([]func(View, Frame), count)
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
notCompatibleType(tag, val)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
listeners[i] = func(view View, _ Frame) {
|
|
||||||
val(view)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
view.properties[tag] = listeners
|
|
||||||
|
|
||||||
case func():
|
|
||||||
fn := func(View, Frame) {
|
|
||||||
value()
|
|
||||||
}
|
|
||||||
view.properties[tag] = []func(View, Frame){fn}
|
|
||||||
|
|
||||||
case []func():
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
delete(view.properties, tag)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
listeners := make([]func(View, Frame), count)
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
notCompatibleType(tag, val)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
listeners[i] = func(View, Frame) {
|
|
||||||
val()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
view.properties[tag] = listeners
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
delete(view.properties, tag)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
listeners := make([]func(View, Frame), count)
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
notCompatibleType(tag, val)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
switch val := val.(type) {
|
|
||||||
case func(View, Frame):
|
|
||||||
listeners[i] = val
|
|
||||||
|
|
||||||
case func(Frame):
|
|
||||||
listeners[i] = func(_ View, frame Frame) {
|
|
||||||
val(frame)
|
|
||||||
}
|
|
||||||
|
|
||||||
case func(View):
|
|
||||||
listeners[i] = func(view View, _ Frame) {
|
|
||||||
val(view)
|
|
||||||
}
|
|
||||||
|
|
||||||
case func():
|
|
||||||
listeners[i] = func(View, Frame) {
|
|
||||||
val()
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
notCompatibleType(tag, val)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
view.properties[tag] = listeners
|
|
||||||
|
|
||||||
default:
|
|
||||||
notCompatibleType(tag, value)
|
notCompatibleType(tag, value)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if listeners == nil {
|
||||||
|
delete(view.properties, tag)
|
||||||
|
} else {
|
||||||
|
view.properties[tag] = listeners
|
||||||
|
}
|
||||||
|
view.propertyChangedEvent(tag)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,10 +65,10 @@ func (view *viewData) Frame() Frame {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetViewFrame returns the size and location of view's viewport.
|
// GetViewFrame returns the size and location of view's viewport.
|
||||||
// If the second argument (subviewID) is "" then the value of the first argument (view) is returned
|
// If the second argument (subviewID) is not specified or it is "" then the value of the first argument (view) is returned
|
||||||
func GetViewFrame(view View, subviewID string) Frame {
|
func GetViewFrame(view View, subviewID ...string) Frame {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view == nil {
|
if view == nil {
|
||||||
return Frame{}
|
return Frame{}
|
||||||
|
@ -202,17 +77,7 @@ func GetViewFrame(view View, subviewID string) Frame {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetResizeListeners returns the list of "resize-event" listeners. If there are no listeners then the empty list is returned
|
// GetResizeListeners returns the list of "resize-event" listeners. If there are no listeners then the empty list is returned
|
||||||
// If the second argument (subviewID) is "" then the listeners list of the first argument (view) is returned
|
// If the second argument (subviewID) is not specified or it is "" then the listeners list of the first argument (view) is returned
|
||||||
func GetResizeListeners(view View, subviewID string) []func(View, Frame) {
|
func GetResizeListeners(view View, subviewID ...string) []func(View, Frame) {
|
||||||
if subviewID != "" {
|
return getEventListeners[View, Frame](view, subviewID, ResizeEvent)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if value := view.Get(ResizeEvent); value != nil {
|
|
||||||
if result, ok := value.([]func(View, Frame)); ok {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []func(View, Frame){}
|
|
||||||
}
|
}
|
||||||
|
|
11
resources.go
11
resources.go
|
@ -3,7 +3,6 @@ package rui
|
||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -171,7 +170,7 @@ func registerImage(fs *embed.FS, path, filename string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func scanImagesDirectory(path, filePrefix string) {
|
func scanImagesDirectory(path, filePrefix string) {
|
||||||
if files, err := ioutil.ReadDir(path); err == nil {
|
if files, err := os.ReadDir(path); err == nil {
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
filename := file.Name()
|
filename := file.Name()
|
||||||
if filename[0] != '.' {
|
if filename[0] != '.' {
|
||||||
|
@ -189,7 +188,7 @@ func scanImagesDirectory(path, filePrefix string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func scanThemesDir(path string) {
|
func scanThemesDir(path string) {
|
||||||
if files, err := ioutil.ReadDir(path); err == nil {
|
if files, err := os.ReadDir(path); err == nil {
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
filename := file.Name()
|
filename := file.Name()
|
||||||
if filename[0] != '.' {
|
if filename[0] != '.' {
|
||||||
|
@ -197,7 +196,7 @@ func scanThemesDir(path string) {
|
||||||
if file.IsDir() {
|
if file.IsDir() {
|
||||||
scanThemesDir(newPath)
|
scanThemesDir(newPath)
|
||||||
} else if strings.ToLower(filepath.Ext(newPath)) == ".rui" {
|
} else if strings.ToLower(filepath.Ext(newPath)) == ".rui" {
|
||||||
if data, err := ioutil.ReadFile(newPath); err == nil {
|
if data, err := os.ReadFile(newPath); err == nil {
|
||||||
registerThemeText(string(data))
|
registerThemeText(string(data))
|
||||||
} else {
|
} else {
|
||||||
ErrorLog(err.Error())
|
ErrorLog(err.Error())
|
||||||
|
@ -380,7 +379,7 @@ func AllRawResources() []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
if resources.path != "" {
|
if resources.path != "" {
|
||||||
if files, err := ioutil.ReadDir(resources.path + rawDir); err == nil {
|
if files, err := os.ReadDir(resources.path + rawDir); err == nil {
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
result = append(result, file.Name())
|
result = append(result, file.Name())
|
||||||
}
|
}
|
||||||
|
@ -388,7 +387,7 @@ func AllRawResources() []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
if exe, err := os.Executable(); err == nil {
|
if exe, err := os.Executable(); err == nil {
|
||||||
if files, err := ioutil.ReadDir(filepath.Dir(exe) + "/resources/" + rawDir); err == nil {
|
if files, err := os.ReadDir(filepath.Dir(exe) + "/resources/" + rawDir); err == nil {
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
result = append(result, file.Name())
|
result = append(result, file.Name())
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ type ruiWriter interface {
|
||||||
endObject()
|
endObject()
|
||||||
startArrayProperty(tag string)
|
startArrayProperty(tag string)
|
||||||
endObArray()
|
endObArray()
|
||||||
writeProperty(tag string, value interface{})
|
writeProperty(tag string, value any)
|
||||||
finish() string
|
finish() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ func (writer *ruiWriterData) endObArray() {
|
||||||
writer.buffer.WriteString("],\n")
|
writer.buffer.WriteString("],\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (writer *ruiWriterData) writeValue(value interface{}) {
|
func (writer *ruiWriterData) writeValue(value any) {
|
||||||
|
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case string:
|
case string:
|
||||||
|
@ -175,7 +175,7 @@ func (writer *ruiWriterData) writeValue(value interface{}) {
|
||||||
writer.buffer.WriteRune(']')
|
writer.buffer.WriteRune(']')
|
||||||
}
|
}
|
||||||
|
|
||||||
case []interface{}:
|
case []any:
|
||||||
switch len(value) {
|
switch len(value) {
|
||||||
case 0:
|
case 0:
|
||||||
writer.buffer.WriteString("[]\n")
|
writer.buffer.WriteString("[]\n")
|
||||||
|
@ -205,7 +205,7 @@ func (writer *ruiWriterData) writeValue(value interface{}) {
|
||||||
writer.buffer.WriteString(",\n")
|
writer.buffer.WriteString(",\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (writer *ruiWriterData) writeProperty(tag string, value interface{}) {
|
func (writer *ruiWriterData) writeProperty(tag string, value any) {
|
||||||
writer.writeIndent()
|
writer.writeIndent()
|
||||||
writer.writeString(tag)
|
writer.writeString(tag)
|
||||||
writer.buffer.WriteString(" = ")
|
writer.buffer.WriteString(" = ")
|
||||||
|
|
|
@ -3,11 +3,14 @@ package rui
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
// ScrollEvent is the constant for "scroll-event" property tag.
|
// ScrollEvent is the constant for "scroll-event" property tag.
|
||||||
// The "resize-event" is fired when the content of the view is scrolled.
|
// The "scroll-event" is fired when the content of the view is scrolled.
|
||||||
// The main listener format:
|
// The main listener format:
|
||||||
// func(View, Frame).
|
//
|
||||||
|
// func(View, Frame).
|
||||||
|
//
|
||||||
// The additional listener formats:
|
// The additional listener formats:
|
||||||
// func(Frame), func(View), and func().
|
//
|
||||||
|
// func(Frame), func(View), and func().
|
||||||
const ScrollEvent = "scroll-event"
|
const ScrollEvent = "scroll-event"
|
||||||
|
|
||||||
func (view *viewData) onScroll(self View, x, y, width, height float64) {
|
func (view *viewData) onScroll(self View, x, y, width, height float64) {
|
||||||
|
@ -15,7 +18,7 @@ func (view *viewData) onScroll(self View, x, y, width, height float64) {
|
||||||
view.scroll.Top = y
|
view.scroll.Top = y
|
||||||
view.scroll.Width = width
|
view.scroll.Width = width
|
||||||
view.scroll.Height = height
|
view.scroll.Height = height
|
||||||
for _, listener := range GetScrollListeners(view, "") {
|
for _, listener := range GetScrollListeners(view) {
|
||||||
listener(self, view.scroll)
|
listener(self, view.scroll)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,10 +35,10 @@ func (view *viewData) setScroll(x, y, width, height float64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetViewScroll returns ...
|
// GetViewScroll returns ...
|
||||||
// If the second argument (subviewID) is "" then a value of the first argument (view) is returned
|
// If the second argument (subviewID) is not specified or it is "" then a value of the first argument (view) is returned
|
||||||
func GetViewScroll(view View, subviewID string) Frame {
|
func GetViewScroll(view View, subviewID ...string) Frame {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view == nil {
|
if view == nil {
|
||||||
return Frame{}
|
return Frame{}
|
||||||
|
@ -44,19 +47,9 @@ func GetViewScroll(view View, subviewID string) Frame {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetScrollListeners returns the list of "scroll-event" listeners. If there are no listeners then the empty list is returned
|
// GetScrollListeners returns the list of "scroll-event" listeners. If there are no listeners then the empty list is returned
|
||||||
// If the second argument (subviewID) is "" then the listeners list of the first argument (view) is returned
|
// If the second argument (subviewID) is not specified or it is "" then the listeners list of the first argument (view) is returned
|
||||||
func GetScrollListeners(view View, subviewID string) []func(View, Frame) {
|
func GetScrollListeners(view View, subviewID ...string) []func(View, Frame) {
|
||||||
if subviewID != "" {
|
return getEventListeners[View, Frame](view, subviewID, ResizeEvent)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if value := view.Get(ScrollEvent); value != nil {
|
|
||||||
if result, ok := value.([]func(View, Frame)); ok {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []func(View, Frame){}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScrollTo scrolls the view's content to the given position.
|
// ScrollTo scrolls the view's content to the given position.
|
||||||
|
@ -71,10 +64,10 @@ func ScrollViewTo(view View, subviewID string, x, y float64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScrollViewToEnd scrolls the view's content to the start of view.
|
// ScrollViewToEnd scrolls the view's content to the start of view.
|
||||||
// If the second argument (subviewID) is "" then the first argument (view) is used
|
// If the second argument (subviewID) is not specified or it is "" then the first argument (view) is used
|
||||||
func ScrollViewToStart(view View, subviewID string) {
|
func ScrollViewToStart(view View, subviewID ...string) {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view != nil {
|
if view != nil {
|
||||||
view.Session().runScript(`scrollToStart("` + view.htmlID() + `")`)
|
view.Session().runScript(`scrollToStart("` + view.htmlID() + `")`)
|
||||||
|
@ -82,10 +75,10 @@ func ScrollViewToStart(view View, subviewID string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScrollViewToEnd scrolls the view's content to the end of view.
|
// ScrollViewToEnd scrolls the view's content to the end of view.
|
||||||
// If the second argument (subviewID) is "" then the first argument (view) is used
|
// If the second argument (subviewID) is not specified or it is "" then the first argument (view) is used
|
||||||
func ScrollViewToEnd(view View, subviewID string) {
|
func ScrollViewToEnd(view View, subviewID ...string) {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view != nil {
|
if view != nil {
|
||||||
view.Session().runScript(`scrollToEnd("` + view.htmlID() + `")`)
|
view.Session().runScript(`scrollToEnd("` + view.htmlID() + `")`)
|
||||||
|
|
14
session.go
14
session.go
|
@ -60,11 +60,11 @@ type Session interface {
|
||||||
RootView() View
|
RootView() View
|
||||||
// Get returns a value of the view (with id defined by the first argument) property with name defined by the second argument.
|
// Get returns a value of the view (with id defined by the first argument) property with name defined by the second argument.
|
||||||
// The type of return value depends on the property. If the property is not set then nil is returned.
|
// The type of return value depends on the property. If the property is not set then nil is returned.
|
||||||
Get(viewID, tag string) interface{}
|
Get(viewID, tag string) any
|
||||||
// Set sets the value (third argument) of the property (second argument) of the view with id defined by the first argument.
|
// Set sets the value (third argument) of the property (second argument) of the view with id defined by the first argument.
|
||||||
// Return "true" if the value has been set, in the opposite case "false" are returned and
|
// Return "true" if the value has been set, in the opposite case "false" are returned and
|
||||||
// a description of the error is written to the log
|
// a description of the error is written to the log
|
||||||
Set(viewID, tag string, value interface{}) bool
|
Set(viewID, tag string, value any) bool
|
||||||
|
|
||||||
// DownloadFile downloads (saves) on the client side the file located at the specified path on the server.
|
// DownloadFile downloads (saves) on the client side the file located at the specified path on the server.
|
||||||
DownloadFile(path string)
|
DownloadFile(path string)
|
||||||
|
@ -83,7 +83,7 @@ type Session interface {
|
||||||
|
|
||||||
viewByHTMLID(id string) View
|
viewByHTMLID(id string) View
|
||||||
nextViewID() string
|
nextViewID() string
|
||||||
styleProperty(styleTag, property string) interface{}
|
styleProperty(styleTag, property string) any
|
||||||
|
|
||||||
setBrige(events chan DataObject, brige WebBrige)
|
setBrige(events chan DataObject, brige WebBrige)
|
||||||
writeInitScript(writer *strings.Builder)
|
writeInitScript(writer *strings.Builder)
|
||||||
|
@ -222,7 +222,7 @@ func (session *sessionData) close() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *sessionData) styleProperty(styleTag, propertyTag string) interface{} {
|
func (session *sessionData) styleProperty(styleTag, propertyTag string) any {
|
||||||
if style := session.getCurrentTheme().style(styleTag); style != nil {
|
if style := session.getCurrentTheme().style(styleTag); style != nil {
|
||||||
return style.getRaw(propertyTag)
|
return style.getRaw(propertyTag)
|
||||||
}
|
}
|
||||||
|
@ -312,14 +312,14 @@ func (session *sessionData) setIgnoreViewUpdates(ignore bool) {
|
||||||
session.ignoreUpdates = ignore
|
session.ignoreUpdates = ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *sessionData) Get(viewID, tag string) interface{} {
|
func (session *sessionData) Get(viewID, tag string) any {
|
||||||
if view := ViewByID(session.RootView(), viewID); view != nil {
|
if view := ViewByID(session.RootView(), viewID); view != nil {
|
||||||
return view.Get(tag)
|
return view.Get(tag)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *sessionData) Set(viewID, tag string, value interface{}) bool {
|
func (session *sessionData) Set(viewID, tag string, value any) bool {
|
||||||
if view := ViewByID(session.RootView(), viewID); view != nil {
|
if view := ViewByID(session.RootView(), viewID); view != nil {
|
||||||
return view.Set(tag, value)
|
return view.Set(tag, value)
|
||||||
}
|
}
|
||||||
|
@ -434,7 +434,7 @@ func (session *sessionData) handleViewEvent(command string, data DataObject) {
|
||||||
if view := session.viewByHTMLID(viewID); view != nil {
|
if view := session.viewByHTMLID(viewID); view != nil {
|
||||||
view.handleCommand(view, command, data)
|
view.handleCommand(view, command, data)
|
||||||
}
|
}
|
||||||
} else {
|
} else if command != "clickOutsidePopup" {
|
||||||
ErrorLog(`"id" property not found. Event: ` + command)
|
ErrorLog(`"id" property not found. Event: ` + command)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var stopTestLogFlag = false
|
// var stopTestLogFlag = false
|
||||||
var testLogDone chan int
|
// var testLogDone chan int
|
||||||
var ignoreTestLog = false
|
var ignoreTestLog = false
|
||||||
|
|
||||||
func createTestLog(t *testing.T, ignore bool) {
|
func createTestLog(t *testing.T, ignore bool) {
|
||||||
|
|
20
shadow.go
20
shadow.go
|
@ -111,7 +111,7 @@ func (shadow *viewShadowData) Remove(tag string) {
|
||||||
delete(shadow.properties, strings.ToLower(tag))
|
delete(shadow.properties, strings.ToLower(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (shadow *viewShadowData) Set(tag string, value interface{}) bool {
|
func (shadow *viewShadowData) Set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
shadow.Remove(tag)
|
shadow.Remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -127,7 +127,7 @@ func (shadow *viewShadowData) Set(tag string, value interface{}) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (shadow *viewShadowData) Get(tag string) interface{} {
|
func (shadow *viewShadowData) Get(tag string) any {
|
||||||
return shadow.propertyList.Get(strings.ToLower(tag))
|
return shadow.propertyList.Get(strings.ToLower(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,13 +151,13 @@ func (shadow *viewShadowData) cssStyle(buffer *strings.Builder, session Session,
|
||||||
buffer.WriteString("inset ")
|
buffer.WriteString("inset ")
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.WriteString(offsetX.cssString("0"))
|
buffer.WriteString(offsetX.cssString("0", session))
|
||||||
buffer.WriteByte(' ')
|
buffer.WriteByte(' ')
|
||||||
buffer.WriteString(offsetY.cssString("0"))
|
buffer.WriteString(offsetY.cssString("0", session))
|
||||||
buffer.WriteByte(' ')
|
buffer.WriteByte(' ')
|
||||||
buffer.WriteString(blurRadius.cssString("0"))
|
buffer.WriteString(blurRadius.cssString("0", session))
|
||||||
buffer.WriteByte(' ')
|
buffer.WriteByte(' ')
|
||||||
buffer.WriteString(spreadRadius.cssString("0"))
|
buffer.WriteString(spreadRadius.cssString("0", session))
|
||||||
buffer.WriteByte(' ')
|
buffer.WriteByte(' ')
|
||||||
buffer.WriteString(color.cssString())
|
buffer.WriteString(color.cssString())
|
||||||
return true
|
return true
|
||||||
|
@ -177,11 +177,11 @@ func (shadow *viewShadowData) cssTextStyle(buffer *strings.Builder, session Sess
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.WriteString(lead)
|
buffer.WriteString(lead)
|
||||||
buffer.WriteString(offsetX.cssString("0"))
|
buffer.WriteString(offsetX.cssString("0", session))
|
||||||
buffer.WriteByte(' ')
|
buffer.WriteByte(' ')
|
||||||
buffer.WriteString(offsetY.cssString("0"))
|
buffer.WriteString(offsetY.cssString("0", session))
|
||||||
buffer.WriteByte(' ')
|
buffer.WriteByte(' ')
|
||||||
buffer.WriteString(blurRadius.cssString("0"))
|
buffer.WriteString(blurRadius.cssString("0", session))
|
||||||
buffer.WriteByte(' ')
|
buffer.WriteByte(' ')
|
||||||
buffer.WriteString(color.cssString())
|
buffer.WriteString(color.cssString())
|
||||||
return true
|
return true
|
||||||
|
@ -225,7 +225,7 @@ func (shadow *viewShadowData) writeString(buffer *strings.Builder, indent string
|
||||||
buffer.WriteString(" }")
|
buffer.WriteString(" }")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (properties *propertyList) setShadow(tag string, value interface{}) bool {
|
func (properties *propertyList) setShadow(tag string, value any) bool {
|
||||||
|
|
||||||
if value == nil {
|
if value == nil {
|
||||||
delete(properties.properties, tag)
|
delete(properties.properties, tag)
|
||||||
|
|
|
@ -0,0 +1,373 @@
|
||||||
|
package rui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SizeFunc describes a function that calculates the SizeUnit size.
|
||||||
|
// Used as the value of the SizeUnit properties.
|
||||||
|
// "min", "max", "clamp", "sum", "sub", "mul", and "div" functions are available.
|
||||||
|
type SizeFunc interface {
|
||||||
|
fmt.Stringer
|
||||||
|
// Name() returns the function name: "min", "max", "clamp", "sum", "sub", "mul", or "div"
|
||||||
|
Name() string
|
||||||
|
// Args() returns a list of function arguments
|
||||||
|
Args() []any
|
||||||
|
cssString(session Session) string
|
||||||
|
writeCSS(topFunc string, buffer *strings.Builder, session Session)
|
||||||
|
writeString(topFunc string, buffer *strings.Builder)
|
||||||
|
}
|
||||||
|
|
||||||
|
type sizeFuncData struct {
|
||||||
|
tag string
|
||||||
|
args []any
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseSizeFunc(text string) SizeFunc {
|
||||||
|
text = strings.Trim(text, " ")
|
||||||
|
|
||||||
|
for _, tag := range []string{"min", "max", "sum", "sub", "mul", "div", "clamp"} {
|
||||||
|
if strings.HasPrefix(text, tag) {
|
||||||
|
text = strings.Trim(strings.TrimPrefix(text, tag), " ")
|
||||||
|
last := len(text) - 1
|
||||||
|
if text[0] == '(' && text[last] == ')' {
|
||||||
|
text = text[1:last]
|
||||||
|
bracket := 0
|
||||||
|
start := 0
|
||||||
|
args := []any{}
|
||||||
|
for i, ch := range text {
|
||||||
|
switch ch {
|
||||||
|
case ',':
|
||||||
|
if bracket == 0 {
|
||||||
|
args = append(args, text[start:i])
|
||||||
|
start = i + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
case '(':
|
||||||
|
bracket++
|
||||||
|
|
||||||
|
case ')':
|
||||||
|
bracket--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if bracket != 0 {
|
||||||
|
ErrorLogF(`Invalid "%s" function`, tag)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
args = append(args, text[start:])
|
||||||
|
switch tag {
|
||||||
|
case "sub", "mul", "div":
|
||||||
|
if len(args) != 2 {
|
||||||
|
ErrorLogF(`"%s" function needs 2 arguments`, tag)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
case "clamp":
|
||||||
|
if len(args) != 3 {
|
||||||
|
ErrorLog(`"clamp" function needs 3 arguments`)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data := new(sizeFuncData)
|
||||||
|
data.tag = tag
|
||||||
|
if data.parseArgs(args, tag == "mul" || tag == "div") {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorLogF(`Invalid "%s" function`, tag)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data *sizeFuncData) parseArgs(args []any, allowNumber bool) bool {
|
||||||
|
data.args = []any{}
|
||||||
|
|
||||||
|
numberArg := func(index int, value float64) bool {
|
||||||
|
if allowNumber {
|
||||||
|
if index == 1 {
|
||||||
|
if value == 0 && data.tag == "div" {
|
||||||
|
ErrorLog(`Division by 0 in div function`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
data.args = append(data.args, value)
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
ErrorLogF(`Only the second %s function argument can be a number`, data.tag)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorLogF(`The %s function argument cann't be a number`, data.tag)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, arg := range args {
|
||||||
|
switch arg := arg.(type) {
|
||||||
|
case string:
|
||||||
|
if arg = strings.Trim(arg, " \t\n"); arg == "" {
|
||||||
|
ErrorLogF(`Unsupported %s function argument #%d: ""`, data.tag, i)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if arg[0] == '@' {
|
||||||
|
data.args = append(data.args, arg)
|
||||||
|
} else if val, err := strconv.ParseFloat(arg, 64); err == nil {
|
||||||
|
return numberArg(i, val)
|
||||||
|
} else if fn := parseSizeFunc(arg); fn != nil {
|
||||||
|
data.args = append(data.args, fn)
|
||||||
|
} else if size, err := stringToSizeUnit(arg); err == nil {
|
||||||
|
data.args = append(data.args, size)
|
||||||
|
} else {
|
||||||
|
ErrorLogF(`Unsupported %s function argument #%d: "%s"`, data.tag, i, arg)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
case SizeFunc:
|
||||||
|
data.args = append(data.args, arg)
|
||||||
|
|
||||||
|
case SizeUnit:
|
||||||
|
if arg.Type == Auto {
|
||||||
|
ErrorLogF(`Unsupported %s function argument #%d: "auto"`, data.tag, i)
|
||||||
|
}
|
||||||
|
data.args = append(data.args, arg)
|
||||||
|
|
||||||
|
case float64:
|
||||||
|
return numberArg(i, arg)
|
||||||
|
|
||||||
|
case float32:
|
||||||
|
return numberArg(i, float64(arg))
|
||||||
|
|
||||||
|
default:
|
||||||
|
if n, ok := isInt(arg); ok {
|
||||||
|
return numberArg(i, float64(n))
|
||||||
|
}
|
||||||
|
ErrorLogF(`Unsupported %s function argument #%d: %v`, data.tag, i, arg)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data *sizeFuncData) String() string {
|
||||||
|
buffer := allocStringBuilder()
|
||||||
|
defer freeStringBuilder(buffer)
|
||||||
|
|
||||||
|
data.writeString("", buffer)
|
||||||
|
return buffer.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data *sizeFuncData) Name() string {
|
||||||
|
return data.tag
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data *sizeFuncData) Args() []any {
|
||||||
|
args := make([]any, len(data.args))
|
||||||
|
copy(args, data.args)
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data *sizeFuncData) writeString(topFunc string, buffer *strings.Builder) {
|
||||||
|
buffer.WriteString(data.tag)
|
||||||
|
buffer.WriteRune('(')
|
||||||
|
for i, arg := range data.args {
|
||||||
|
if i > 0 {
|
||||||
|
buffer.WriteString(", ")
|
||||||
|
}
|
||||||
|
switch arg := arg.(type) {
|
||||||
|
case string:
|
||||||
|
buffer.WriteString(arg)
|
||||||
|
|
||||||
|
case SizeFunc:
|
||||||
|
arg.writeString(data.tag, buffer)
|
||||||
|
|
||||||
|
case SizeUnit:
|
||||||
|
buffer.WriteString(arg.String())
|
||||||
|
|
||||||
|
case fmt.Stringer:
|
||||||
|
buffer.WriteString(arg.String())
|
||||||
|
|
||||||
|
case float64:
|
||||||
|
buffer.WriteString(fmt.Sprintf("%g", arg))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
buffer.WriteRune(')')
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data *sizeFuncData) cssString(session Session) string {
|
||||||
|
buffer := allocStringBuilder()
|
||||||
|
defer freeStringBuilder(buffer)
|
||||||
|
|
||||||
|
data.writeCSS("", buffer, session)
|
||||||
|
return buffer.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data *sizeFuncData) writeCSS(topFunc string, buffer *strings.Builder, session Session) {
|
||||||
|
bracket := true
|
||||||
|
sep := ", "
|
||||||
|
|
||||||
|
mathFunc := func(s string) {
|
||||||
|
sep = s
|
||||||
|
switch topFunc {
|
||||||
|
case "":
|
||||||
|
buffer.WriteString("calc(")
|
||||||
|
|
||||||
|
case "min", "max", "clamp":
|
||||||
|
bracket = false
|
||||||
|
|
||||||
|
default:
|
||||||
|
buffer.WriteRune('(')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch data.tag {
|
||||||
|
case "min", "max", "clamp":
|
||||||
|
buffer.WriteString(data.tag)
|
||||||
|
buffer.WriteRune('(')
|
||||||
|
|
||||||
|
case "sum":
|
||||||
|
mathFunc(" + ")
|
||||||
|
|
||||||
|
case "sub":
|
||||||
|
mathFunc(" - ")
|
||||||
|
|
||||||
|
case "mul":
|
||||||
|
mathFunc(" * ")
|
||||||
|
|
||||||
|
case "div":
|
||||||
|
mathFunc(" / ")
|
||||||
|
|
||||||
|
default:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, arg := range data.args {
|
||||||
|
if i > 0 {
|
||||||
|
buffer.WriteString(sep)
|
||||||
|
}
|
||||||
|
switch arg := arg.(type) {
|
||||||
|
case string:
|
||||||
|
if arg, ok := session.resolveConstants(arg); ok {
|
||||||
|
if fn := parseSizeFunc(arg); fn != nil {
|
||||||
|
fn.writeCSS(data.tag, buffer, session)
|
||||||
|
} else if size, err := stringToSizeUnit(arg); err == nil {
|
||||||
|
buffer.WriteString(size.cssString("0", session))
|
||||||
|
} else {
|
||||||
|
buffer.WriteString("0")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buffer.WriteString("0")
|
||||||
|
}
|
||||||
|
|
||||||
|
case SizeFunc:
|
||||||
|
arg.writeCSS(data.tag, buffer, session)
|
||||||
|
|
||||||
|
case SizeUnit:
|
||||||
|
buffer.WriteString(arg.cssString("0", session))
|
||||||
|
|
||||||
|
case fmt.Stringer:
|
||||||
|
buffer.WriteString(arg.String())
|
||||||
|
|
||||||
|
case float64:
|
||||||
|
buffer.WriteString(fmt.Sprintf("%g", arg))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if bracket {
|
||||||
|
buffer.WriteRune(')')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MaxSize creates a SizeUnit function that calculates the maximum argument.
|
||||||
|
// Valid argument types are SizeUnit, SizeFunc and a string which is a text description of SizeUnit or SizeFunc
|
||||||
|
func MaxSize(arg0, arg1 any, args ...any) SizeFunc {
|
||||||
|
data := new(sizeFuncData)
|
||||||
|
data.tag = "max"
|
||||||
|
if !data.parseArgs(append([]any{arg0, arg1}, args...), false) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
// MinSize creates a SizeUnit function that calculates the minimum argument.
|
||||||
|
// Valid argument types are SizeUnit, SizeFunc and a string which is a text description of SizeUnit or SizeFunc.
|
||||||
|
func MinSize(arg0, arg1 any, args ...any) SizeFunc {
|
||||||
|
data := new(sizeFuncData)
|
||||||
|
data.tag = "min"
|
||||||
|
if !data.parseArgs(append([]any{arg0, arg1}, args...), false) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
// SumSize creates a SizeUnit function that calculates the sum of arguments.
|
||||||
|
// Valid argument types are SizeUnit, SizeFunc and a string which is a text description of SizeUnit or SizeFunc.
|
||||||
|
func SumSize(arg0, arg1 any, args ...any) SizeFunc {
|
||||||
|
data := new(sizeFuncData)
|
||||||
|
data.tag = "sum"
|
||||||
|
if !data.parseArgs(append([]any{arg0, arg1}, args...), false) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
// SumSize creates a SizeUnit function that calculates the result of subtracting the arguments (arg1 - arg2).
|
||||||
|
// Valid argument types are SizeUnit, SizeFunc and a string which is a text description of SizeUnit or SizeFunc.
|
||||||
|
func SubSize(arg0, arg1 any) SizeFunc {
|
||||||
|
data := new(sizeFuncData)
|
||||||
|
data.tag = "sub"
|
||||||
|
if !data.parseArgs([]any{arg0, arg1}, false) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
// MulSize creates a SizeUnit function that calculates the result of multiplying the arguments (arg1 * arg2).
|
||||||
|
// Valid argument types are SizeUnit, SizeFunc and a string which is a text description of SizeUnit or SizeFunc.
|
||||||
|
// The second argument can also be a number (float32, float32, int, int8...int64, uint, uint8...unit64)
|
||||||
|
// or a string which is a text representation of a number.
|
||||||
|
func MulSize(arg0, arg1 any) SizeFunc {
|
||||||
|
data := new(sizeFuncData)
|
||||||
|
data.tag = "mul"
|
||||||
|
if !data.parseArgs([]any{arg0, arg1}, true) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
// DivSize creates a SizeUnit function that calculates the result of dividing the arguments (arg1 / arg2).
|
||||||
|
// Valid argument types are SizeUnit, SizeFunc and a string which is a text description of SizeUnit or SizeFunc.
|
||||||
|
// The second argument can also be a number (float32, float32, int, int8...int64, uint, uint8...unit64)
|
||||||
|
// or a string which is a text representation of a number.
|
||||||
|
func DivSize(arg0, arg1 any) SizeFunc {
|
||||||
|
data := new(sizeFuncData)
|
||||||
|
data.tag = "div"
|
||||||
|
if !data.parseArgs([]any{arg0, arg1}, true) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClampSize creates a SizeUnit function whose the result is calculated as follows:
|
||||||
|
//
|
||||||
|
// min ≤ value ≤ max -> value;
|
||||||
|
// value < min -> min;
|
||||||
|
// max < value -> max;
|
||||||
|
//
|
||||||
|
// Valid argument types are SizeUnit, SizeFunc and a string which is a text description of SizeUnit or SizeFunc.
|
||||||
|
func ClampSize(min, value, max any) SizeFunc {
|
||||||
|
data := new(sizeFuncData)
|
||||||
|
data.tag = "clamp"
|
||||||
|
if !data.parseArgs([]any{min, value, max}, false) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package rui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSizeFunc(t *testing.T) {
|
||||||
|
session := new(sessionData)
|
||||||
|
session.getCurrentTheme().SetConstant("a1", "120px", "120px")
|
||||||
|
|
||||||
|
SetErrorLog(func(text string) {
|
||||||
|
t.Error(text)
|
||||||
|
})
|
||||||
|
SetDebugLog(func(text string) {
|
||||||
|
t.Log(text)
|
||||||
|
})
|
||||||
|
|
||||||
|
testFunc := func(fn SizeFunc, str, css string) {
|
||||||
|
if fn != nil {
|
||||||
|
if text := fn.String(); str != text {
|
||||||
|
t.Error("String() error.\nResult: \"" + text + "\"\nExpected: \"" + str + `"`)
|
||||||
|
}
|
||||||
|
if text := fn.cssString(session); css != text {
|
||||||
|
t.Error("cssString() error.\nResult: \"" + text + "\"\nExpected: \"" + css + `"`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
testFunc(MinSize("100%", Px(10)), `min(100%, 10px)`, `min(100%, 10px)`)
|
||||||
|
testFunc(MaxSize(Percent(100), "@a1"), `max(100%, @a1)`, `max(100%, 120px)`)
|
||||||
|
testFunc(SumSize(Percent(100), "@a1"), `sum(100%, @a1)`, `calc(100% + 120px)`)
|
||||||
|
testFunc(SubSize(Percent(100), "@a1"), `sub(100%, @a1)`, `calc(100% - 120px)`)
|
||||||
|
testFunc(MulSize(Percent(100), "@a1"), `mul(100%, @a1)`, `calc(100% * 120px)`)
|
||||||
|
testFunc(DivSize(Percent(100), "@a1"), `div(100%, @a1)`, `calc(100% / 120px)`)
|
||||||
|
testFunc(ClampSize(Percent(20), "@a1", Percent(40)), `clamp(20%, @a1, 40%)`, `clamp(20%, 120px, 40%)`)
|
||||||
|
|
||||||
|
testFunc(MaxSize(SubSize(Percent(100), "@a1"), "@a1"), `max(sub(100%, @a1), @a1)`, `max(100% - 120px, 120px)`)
|
||||||
|
|
||||||
|
testParse := func(str, css string) {
|
||||||
|
if fn := parseSizeFunc(str); fn != nil {
|
||||||
|
testFunc(fn, str, css)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
testParse(`min(100%, 10px)`, `min(100%, 10px)`)
|
||||||
|
testParse(`max(100%, @a1)`, `max(100%, 120px)`)
|
||||||
|
testParse(`max(sub(100%, @a1), @a1)`, `max(100% - 120px, 120px)`)
|
||||||
|
testParse(`mul(sub(100%, @a1), @a1)`, `calc((100% - 120px) * 120px)`)
|
||||||
|
testParse(`mul(sub(100%, @a1), div(mul(@a1, 3), 2))`, `calc((100% - 120px) * ((120px * 3) / 2))`)
|
||||||
|
}
|
74
sizeUnit.go
74
sizeUnit.go
|
@ -14,89 +14,94 @@ import (
|
||||||
type SizeUnitType uint8
|
type SizeUnitType uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Auto - default value.
|
// Auto is the SizeUnit type: default value.
|
||||||
Auto SizeUnitType = 0
|
Auto SizeUnitType = 0
|
||||||
// SizeInPixel - size in pixels.
|
// SizeInPixel is the SizeUnit type: the Value field specifies the size in pixels.
|
||||||
SizeInPixel SizeUnitType = 1
|
SizeInPixel SizeUnitType = 1
|
||||||
// SizeInEM - size in em.
|
// SizeInEM is the SizeUnit type: the Value field specifies the size in em.
|
||||||
SizeInEM SizeUnitType = 2
|
SizeInEM SizeUnitType = 2
|
||||||
// SizeInEX - size in em.
|
// SizeInEX is the SizeUnit type: the Value field specifies the size in em.
|
||||||
SizeInEX SizeUnitType = 3
|
SizeInEX SizeUnitType = 3
|
||||||
// SizeInPercent - size in percents of a parant size.
|
// SizeInPercent is the SizeUnit type: the Value field specifies the size in percents of the parent size.
|
||||||
SizeInPercent SizeUnitType = 4
|
SizeInPercent SizeUnitType = 4
|
||||||
// SizeInPt - size in pt (1/72 inch).
|
// SizeInPt is the SizeUnit type: the Value field specifies the size in pt (1/72 inch).
|
||||||
SizeInPt SizeUnitType = 5
|
SizeInPt SizeUnitType = 5
|
||||||
// SizeInPc - size in pc (1pc = 12pt).
|
// SizeInPc is the SizeUnit type: the Value field specifies the size in pc (1pc = 12pt).
|
||||||
SizeInPc SizeUnitType = 6
|
SizeInPc SizeUnitType = 6
|
||||||
// SizeInInch - size in inches.
|
// SizeInInch is the SizeUnit type: the Value field specifies the size in inches.
|
||||||
SizeInInch SizeUnitType = 7
|
SizeInInch SizeUnitType = 7
|
||||||
// SizeInMM - size in millimeters.
|
// SizeInMM is the SizeUnit type: the Value field specifies the size in millimeters.
|
||||||
SizeInMM SizeUnitType = 8
|
SizeInMM SizeUnitType = 8
|
||||||
// SizeInCM - size in centimeters.
|
// SizeInCM is the SizeUnit type: the Value field specifies the size in centimeters.
|
||||||
SizeInCM SizeUnitType = 9
|
SizeInCM SizeUnitType = 9
|
||||||
// SizeInFraction - size in fraction. Used only for "cell-width" and "cell-height" property
|
// 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
|
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).
|
// SizeUnit describe a size (Value field) and size unit (Type field).
|
||||||
type SizeUnit struct {
|
type SizeUnit struct {
|
||||||
Type SizeUnitType
|
Type SizeUnitType
|
||||||
Value float64
|
Value float64
|
||||||
|
Function SizeFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
// AutoSize creates SizeUnit with Auto type
|
// AutoSize creates SizeUnit with Auto type
|
||||||
func AutoSize() SizeUnit {
|
func AutoSize() SizeUnit {
|
||||||
return SizeUnit{Auto, 0}
|
return SizeUnit{Auto, 0, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Px creates SizeUnit with SizeInPixel type
|
// Px creates SizeUnit with SizeInPixel type
|
||||||
func Px(value float64) SizeUnit {
|
func Px(value float64) SizeUnit {
|
||||||
return SizeUnit{SizeInPixel, value}
|
return SizeUnit{SizeInPixel, value, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Em creates SizeUnit with SizeInEM type
|
// Em creates SizeUnit with SizeInEM type
|
||||||
func Em(value float64) SizeUnit {
|
func Em(value float64) SizeUnit {
|
||||||
return SizeUnit{SizeInEM, value}
|
return SizeUnit{SizeInEM, value, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ex creates SizeUnit with SizeInEX type
|
// Ex creates SizeUnit with SizeInEX type
|
||||||
func Ex(value float64) SizeUnit {
|
func Ex(value float64) SizeUnit {
|
||||||
return SizeUnit{SizeInEX, value}
|
return SizeUnit{SizeInEX, value, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Percent creates SizeUnit with SizeInDIP type
|
// Percent creates SizeUnit with SizeInDIP type
|
||||||
func Percent(value float64) SizeUnit {
|
func Percent(value float64) SizeUnit {
|
||||||
return SizeUnit{SizeInPercent, value}
|
return SizeUnit{SizeInPercent, value, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pt creates SizeUnit with SizeInPt type
|
// Pt creates SizeUnit with SizeInPt type
|
||||||
func Pt(value float64) SizeUnit {
|
func Pt(value float64) SizeUnit {
|
||||||
return SizeUnit{SizeInPt, value}
|
return SizeUnit{SizeInPt, value, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pc creates SizeUnit with SizeInPc type
|
// Pc creates SizeUnit with SizeInPc type
|
||||||
func Pc(value float64) SizeUnit {
|
func Pc(value float64) SizeUnit {
|
||||||
return SizeUnit{SizeInPc, value}
|
return SizeUnit{SizeInPc, value, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mm creates SizeUnit with SizeInMM type
|
// Mm creates SizeUnit with SizeInMM type
|
||||||
func Mm(value float64) SizeUnit {
|
func Mm(value float64) SizeUnit {
|
||||||
return SizeUnit{SizeInMM, value}
|
return SizeUnit{SizeInMM, value, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cm creates SizeUnit with SizeInCM type
|
// Cm creates SizeUnit with SizeInCM type
|
||||||
func Cm(value float64) SizeUnit {
|
func Cm(value float64) SizeUnit {
|
||||||
return SizeUnit{SizeInCM, value}
|
return SizeUnit{SizeInCM, value, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inch creates SizeUnit with SizeInInch type
|
// Inch creates SizeUnit with SizeInInch type
|
||||||
func Inch(value float64) SizeUnit {
|
func Inch(value float64) SizeUnit {
|
||||||
return SizeUnit{SizeInInch, value}
|
return SizeUnit{SizeInInch, value, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fr creates SizeUnit with SizeInFraction type
|
// Fr creates SizeUnit with SizeInFraction type
|
||||||
func Fr(value float64) SizeUnit {
|
func Fr(value float64) SizeUnit {
|
||||||
return SizeUnit{SizeInFraction, value}
|
return SizeUnit{SizeInFraction, value, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal compare two SizeUnit. Return true if SizeUnit are equal
|
// Equal compare two SizeUnit. Return true if SizeUnit are equal
|
||||||
|
@ -152,13 +157,24 @@ func stringToSizeUnit(value string) (SizeUnit, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 + `"`)
|
return SizeUnit{Type: Auto, Value: 0}, errors.New(`Invalid SizeUnit value: "` + value + `"`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// String - convert SizeUnit to string
|
// String - convert SizeUnit to string
|
||||||
func (size SizeUnit) String() string {
|
func (size SizeUnit) String() string {
|
||||||
if size.Type == Auto {
|
switch size.Type {
|
||||||
|
case Auto:
|
||||||
return "auto"
|
return "auto"
|
||||||
|
|
||||||
|
case SizeFunction:
|
||||||
|
if size.Function == nil {
|
||||||
|
return "auto"
|
||||||
|
}
|
||||||
|
return size.Function.String()
|
||||||
}
|
}
|
||||||
if suffix, ok := sizeUnitSuffixes()[size.Type]; ok {
|
if suffix, ok := sizeUnitSuffixes()[size.Type]; ok {
|
||||||
return fmt.Sprintf("%g%s", size.Value, suffix)
|
return fmt.Sprintf("%g%s", size.Value, suffix)
|
||||||
|
@ -167,13 +183,19 @@ func (size SizeUnit) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// cssString - convert SizeUnit to string
|
// cssString - convert SizeUnit to string
|
||||||
func (size SizeUnit) cssString(textForAuto string) string {
|
func (size SizeUnit) cssString(textForAuto string, session Session) string {
|
||||||
switch size.Type {
|
switch size.Type {
|
||||||
case Auto:
|
case Auto:
|
||||||
return textForAuto
|
return textForAuto
|
||||||
|
|
||||||
case SizeInEM:
|
case SizeInEM:
|
||||||
return fmt.Sprintf("%grem", size.Value)
|
return fmt.Sprintf("%grem", size.Value)
|
||||||
|
|
||||||
|
case SizeFunction:
|
||||||
|
if size.Function == nil {
|
||||||
|
return textForAuto
|
||||||
|
}
|
||||||
|
return size.Function.cssString(session)
|
||||||
}
|
}
|
||||||
|
|
||||||
if size.Value == 0 {
|
if size.Value == 0 {
|
||||||
|
|
|
@ -41,7 +41,7 @@ type stackLayoutData struct {
|
||||||
// NewStackLayout create new StackLayout object and return it
|
// NewStackLayout create new StackLayout object and return it
|
||||||
func NewStackLayout(session Session, params Params) StackLayout {
|
func NewStackLayout(session Session, params Params) StackLayout {
|
||||||
view := new(stackLayoutData)
|
view := new(stackLayoutData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -51,8 +51,8 @@ func newStackLayout(session Session) View {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initialize fields of ViewsContainer by default values
|
// Init initialize fields of ViewsContainer by default values
|
||||||
func (layout *stackLayoutData) Init(session Session) {
|
func (layout *stackLayoutData) init(session Session) {
|
||||||
layout.viewsContainerData.Init(session)
|
layout.viewsContainerData.init(session)
|
||||||
layout.tag = "StackLayout"
|
layout.tag = "StackLayout"
|
||||||
layout.systemClass = "ruiStackLayout"
|
layout.systemClass = "ruiStackLayout"
|
||||||
layout.properties[TransitionEndEvent] = []func(View, string){layout.pushFinished, layout.popFinished}
|
layout.properties[TransitionEndEvent] = []func(View, string){layout.pushFinished, layout.popFinished}
|
||||||
|
@ -97,11 +97,11 @@ func (layout *stackLayoutData) popFinished(view View, tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (layout *stackLayoutData) Set(tag string, value interface{}) bool {
|
func (layout *stackLayoutData) Set(tag string, value any) bool {
|
||||||
return layout.set(strings.ToLower(tag), value)
|
return layout.set(strings.ToLower(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (layout *stackLayoutData) set(tag string, value interface{}) bool {
|
func (layout *stackLayoutData) set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
layout.remove(tag)
|
layout.remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -109,8 +109,8 @@ func (layout *stackLayoutData) set(tag string, value interface{}) bool {
|
||||||
|
|
||||||
switch tag {
|
switch tag {
|
||||||
case TransitionEndEvent:
|
case TransitionEndEvent:
|
||||||
listeners, ok := valueToAnimationListeners(value)
|
listeners, ok := valueToEventListeners[View, string](value)
|
||||||
if ok {
|
if ok && listeners != nil {
|
||||||
listeners = append(listeners, layout.pushFinished)
|
listeners = append(listeners, layout.pushFinished)
|
||||||
listeners = append(listeners, layout.popFinished)
|
listeners = append(listeners, layout.popFinished)
|
||||||
layout.properties[TransitionEndEvent] = listeners
|
layout.properties[TransitionEndEvent] = listeners
|
||||||
|
@ -179,11 +179,11 @@ func (layout *stackLayoutData) remove(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (layout *stackLayoutData) Get(tag string) interface{} {
|
func (layout *stackLayoutData) Get(tag string) any {
|
||||||
return layout.get(strings.ToLower(tag))
|
return layout.get(strings.ToLower(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (layout *stackLayoutData) get(tag string) interface{} {
|
func (layout *stackLayoutData) get(tag string) any {
|
||||||
if tag == Current {
|
if tag == Current {
|
||||||
return layout.peek
|
return layout.peek
|
||||||
}
|
}
|
||||||
|
@ -351,6 +351,8 @@ func (layout *stackLayoutData) Pop(animation int, onPopFinished func(View)) bool
|
||||||
buffer.WriteString(htmlID)
|
buffer.WriteString(htmlID)
|
||||||
buffer.WriteString(`pop" class="ruiStackPageLayout" ontransitionend="stackTransitionEndEvent(\'`)
|
buffer.WriteString(`pop" class="ruiStackPageLayout" ontransitionend="stackTransitionEndEvent(\'`)
|
||||||
buffer.WriteString(htmlID)
|
buffer.WriteString(htmlID)
|
||||||
|
buffer.WriteString(`\', \'ruiPop\', event)" ontransitioncancel="stackTransitionEndEvent(\'`)
|
||||||
|
buffer.WriteString(htmlID)
|
||||||
buffer.WriteString(`\', \'ruiPop\', event)" style="transition: transform 1s ease;">`)
|
buffer.WriteString(`\', \'ruiPop\', event)" style="transition: transform 1s ease;">`)
|
||||||
viewHTML(layout.popView, buffer)
|
viewHTML(layout.popView, buffer)
|
||||||
buffer.WriteString(`</div>`)
|
buffer.WriteString(`</div>`)
|
||||||
|
|
|
@ -2,7 +2,7 @@ package rui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
"io/ioutil"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -28,7 +28,7 @@ func scanEmbedStringsDir(fs *embed.FS, dir string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func scanStringsDir(path string) {
|
func scanStringsDir(path string) {
|
||||||
if files, err := ioutil.ReadDir(path); err == nil {
|
if files, err := os.ReadDir(path); err == nil {
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
filename := file.Name()
|
filename := file.Name()
|
||||||
if filename[0] != '.' {
|
if filename[0] != '.' {
|
||||||
|
@ -36,7 +36,7 @@ func scanStringsDir(path string) {
|
||||||
if file.IsDir() {
|
if file.IsDir() {
|
||||||
scanStringsDir(newPath)
|
scanStringsDir(newPath)
|
||||||
} else if strings.ToLower(filepath.Ext(newPath)) == ".rui" {
|
} else if strings.ToLower(filepath.Ext(newPath)) == ".rui" {
|
||||||
if data, err := ioutil.ReadFile(newPath); err == nil {
|
if data, err := os.ReadFile(newPath); err == nil {
|
||||||
loadStringResources(string(data))
|
loadStringResources(string(data))
|
||||||
} else {
|
} else {
|
||||||
ErrorLog(err.Error())
|
ErrorLog(err.Error())
|
||||||
|
|
|
@ -18,7 +18,7 @@ type TableAdapter interface {
|
||||||
// * rui.View
|
// * rui.View
|
||||||
// * fmt.Stringer
|
// * fmt.Stringer
|
||||||
// * rui.VerticalTableJoin, rui.HorizontalTableJoin
|
// * rui.VerticalTableJoin, rui.HorizontalTableJoin
|
||||||
Cell(row, column int) interface{}
|
Cell(row, column int) any
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableColumnStyle describes the style of TableView columns.
|
// TableColumnStyle describes the style of TableView columns.
|
||||||
|
@ -59,15 +59,15 @@ type TableAllowRowSelection interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SimpleTableAdapter is implementation of TableAdapter where the content
|
// SimpleTableAdapter is implementation of TableAdapter where the content
|
||||||
// defines as [][]interface{}.
|
// defines as [][]any.
|
||||||
// When you assign [][]interface{} value to the "content" property, it is converted to SimpleTableAdapter
|
// When you assign [][]any value to the "content" property, it is converted to SimpleTableAdapter
|
||||||
type SimpleTableAdapter interface {
|
type SimpleTableAdapter interface {
|
||||||
TableAdapter
|
TableAdapter
|
||||||
TableCellStyle
|
TableCellStyle
|
||||||
}
|
}
|
||||||
|
|
||||||
type simpleTableAdapter struct {
|
type simpleTableAdapter struct {
|
||||||
content [][]interface{}
|
content [][]any
|
||||||
columnCount int
|
columnCount int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ type HorizontalTableJoin struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSimpleTableAdapter creates the new SimpleTableAdapter
|
// NewSimpleTableAdapter creates the new SimpleTableAdapter
|
||||||
func NewSimpleTableAdapter(content [][]interface{}) SimpleTableAdapter {
|
func NewSimpleTableAdapter(content [][]any) SimpleTableAdapter {
|
||||||
if content == nil {
|
if content == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -125,7 +125,7 @@ func (adapter *simpleTableAdapter) ColumnCount() int {
|
||||||
return adapter.columnCount
|
return adapter.columnCount
|
||||||
}
|
}
|
||||||
|
|
||||||
func (adapter *simpleTableAdapter) Cell(row, column int) interface{} {
|
func (adapter *simpleTableAdapter) Cell(row, column int) any {
|
||||||
if adapter.content != nil && row >= 0 && row < len(adapter.content) &&
|
if adapter.content != nil && row >= 0 && row < len(adapter.content) &&
|
||||||
adapter.content[row] != nil && column >= 0 && column < len(adapter.content[row]) {
|
adapter.content[row] != nil && column >= 0 && column < len(adapter.content[row]) {
|
||||||
return adapter.content[row][column]
|
return adapter.content[row][column]
|
||||||
|
@ -220,7 +220,7 @@ func (adapter *textTableAdapter) ColumnCount() int {
|
||||||
return adapter.columnCount
|
return adapter.columnCount
|
||||||
}
|
}
|
||||||
|
|
||||||
func (adapter *textTableAdapter) Cell(row, column int) interface{} {
|
func (adapter *textTableAdapter) Cell(row, column int) any {
|
||||||
if adapter.content != nil && row >= 0 && row < len(adapter.content) &&
|
if adapter.content != nil && row >= 0 && row < len(adapter.content) &&
|
||||||
adapter.content[row] != nil && column >= 0 && column < len(adapter.content[row]) {
|
adapter.content[row] != nil && column >= 0 && column < len(adapter.content[row]) {
|
||||||
return adapter.content[row][column]
|
return adapter.content[row][column]
|
||||||
|
@ -242,7 +242,7 @@ func (style *simpleTableRowStyle) RowStyle(row int) Params {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (table *tableViewData) setRowStyle(value interface{}) bool {
|
func (table *tableViewData) setRowStyle(value any) bool {
|
||||||
newSimpleTableRowStyle := func(params []Params) TableRowStyle {
|
newSimpleTableRowStyle := func(params []Params) TableRowStyle {
|
||||||
if len(params) == 0 {
|
if len(params) == 0 {
|
||||||
return nil
|
return nil
|
||||||
|
@ -319,7 +319,7 @@ func (style *simpleTableColumnStyle) ColumnStyle(row int) Params {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (table *tableViewData) setColumnStyle(value interface{}) bool {
|
func (table *tableViewData) setColumnStyle(value any) bool {
|
||||||
newSimpleTableColumnStyle := func(params []Params) TableColumnStyle {
|
newSimpleTableColumnStyle := func(params []Params) TableColumnStyle {
|
||||||
if len(params) == 0 {
|
if len(params) == 0 {
|
||||||
return nil
|
return nil
|
||||||
|
|
145
tableView.go
145
tableView.go
|
@ -245,7 +245,7 @@ type tableCellView struct {
|
||||||
// NewTableView create new TableView object and return it
|
// NewTableView create new TableView object and return it
|
||||||
func NewTableView(session Session, params Params) TableView {
|
func NewTableView(session Session, params Params) TableView {
|
||||||
view := new(tableViewData)
|
view := new(tableViewData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -255,8 +255,8 @@ func newTableView(session Session) View {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initialize fields of TableView by default values
|
// Init initialize fields of TableView by default values
|
||||||
func (table *tableViewData) Init(session Session) {
|
func (table *tableViewData) init(session Session) {
|
||||||
table.viewData.Init(session)
|
table.viewData.init(session)
|
||||||
table.tag = "TableView"
|
table.tag = "TableView"
|
||||||
table.cellViews = []View{}
|
table.cellViews = []View{}
|
||||||
table.cellFrame = []Frame{}
|
table.cellFrame = []Frame{}
|
||||||
|
@ -290,10 +290,10 @@ func (table *tableViewData) normalizeTag(tag string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (table *tableViewData) Focusable() bool {
|
func (table *tableViewData) Focusable() bool {
|
||||||
return GetTableSelectionMode(table, "") != NoneSelection
|
return GetTableSelectionMode(table) != NoneSelection
|
||||||
}
|
}
|
||||||
|
|
||||||
func (table *tableViewData) Get(tag string) interface{} {
|
func (table *tableViewData) Get(tag string) any {
|
||||||
return table.get(table.normalizeTag(tag))
|
return table.get(table.normalizeTag(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,11 +340,11 @@ func (table *tableViewData) remove(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (table *tableViewData) Set(tag string, value interface{}) bool {
|
func (table *tableViewData) Set(tag string, value any) bool {
|
||||||
return table.set(table.normalizeTag(tag), value)
|
return table.set(table.normalizeTag(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (table *tableViewData) set(tag string, value interface{}) bool {
|
func (table *tableViewData) set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
table.remove(tag)
|
table.remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -356,7 +356,7 @@ func (table *tableViewData) set(tag string, value interface{}) bool {
|
||||||
case TableAdapter:
|
case TableAdapter:
|
||||||
table.properties[Content] = value
|
table.properties[Content] = value
|
||||||
|
|
||||||
case [][]interface{}:
|
case [][]any:
|
||||||
table.properties[Content] = NewSimpleTableAdapter(val)
|
table.properties[Content] = NewSimpleTableAdapter(val)
|
||||||
|
|
||||||
case [][]string:
|
case [][]string:
|
||||||
|
@ -384,20 +384,24 @@ func (table *tableViewData) set(tag string, value interface{}) bool {
|
||||||
table.cellSelectedListener = listeners
|
table.cellSelectedListener = listeners
|
||||||
|
|
||||||
case TableRowClickedEvent:
|
case TableRowClickedEvent:
|
||||||
listeners := table.valueToRowListeners(value)
|
listeners, ok := valueToEventListeners[TableView, int](value)
|
||||||
if listeners == nil {
|
if !ok {
|
||||||
notCompatibleType(tag, value)
|
notCompatibleType(tag, value)
|
||||||
return false
|
return false
|
||||||
|
} else if listeners == nil {
|
||||||
|
listeners = []func(TableView, int){}
|
||||||
}
|
}
|
||||||
table.rowClickedListener = listeners
|
table.rowClickedListener = listeners
|
||||||
|
|
||||||
case TableRowSelectedEvent:
|
case TableRowSelectedEvent:
|
||||||
listeners := table.valueToRowListeners(value)
|
listeners, ok := valueToEventListeners[TableView, int](value)
|
||||||
if listeners == nil {
|
if !ok {
|
||||||
notCompatibleType(tag, value)
|
notCompatibleType(tag, value)
|
||||||
return false
|
return false
|
||||||
|
} else if listeners == nil {
|
||||||
|
listeners = []func(TableView, int){}
|
||||||
}
|
}
|
||||||
table.rowSelectedListener = []func(TableView, int){}
|
table.rowSelectedListener = listeners
|
||||||
|
|
||||||
case CellStyle:
|
case CellStyle:
|
||||||
if style, ok := value.(TableCellStyle); ok {
|
if style, ok := value.(TableCellStyle); ok {
|
||||||
|
@ -450,21 +454,23 @@ func (table *tableViewData) set(tag string, value interface{}) bool {
|
||||||
delete(table.properties, tag)
|
delete(table.properties, tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case DataObject:
|
||||||
|
params := Params{}
|
||||||
|
for k := 0; k < value.PropertyCount(); k++ {
|
||||||
|
if prop := value.Property(k); prop != nil && prop.Type() == TextNode {
|
||||||
|
params[prop.Tag()] = prop.Text()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(params) > 0 {
|
||||||
|
table.properties[tag] = params
|
||||||
|
} else {
|
||||||
|
delete(table.properties, tag)
|
||||||
|
}
|
||||||
|
|
||||||
case DataNode:
|
case DataNode:
|
||||||
switch value.Type() {
|
switch value.Type() {
|
||||||
case ObjectNode:
|
case ObjectNode:
|
||||||
obj := value.Object()
|
return table.set(tag, value.Object())
|
||||||
params := Params{}
|
|
||||||
for k := 0; k < obj.PropertyCount(); k++ {
|
|
||||||
if prop := obj.Property(k); prop != nil && prop.Type() == TextNode {
|
|
||||||
params[prop.Tag()] = prop.Text()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(params) > 0 {
|
|
||||||
table.properties[tag] = params
|
|
||||||
} else {
|
|
||||||
delete(table.properties, tag)
|
|
||||||
}
|
|
||||||
|
|
||||||
case TextNode:
|
case TextNode:
|
||||||
table.properties[tag] = value.Text()
|
table.properties[tag] = value.Text()
|
||||||
|
@ -590,7 +596,7 @@ func (table *tableViewData) propertyChanged(tag string) {
|
||||||
updateCSSProperty(htmlID, "border-spacing", "0", session)
|
updateCSSProperty(htmlID, "border-spacing", "0", session)
|
||||||
updateCSSProperty(htmlID, "border-collapse", "collapse", session)
|
updateCSSProperty(htmlID, "border-collapse", "collapse", session)
|
||||||
} else {
|
} else {
|
||||||
updateCSSProperty(htmlID, "border-spacing", gap.cssString("0"), session)
|
updateCSSProperty(htmlID, "border-spacing", gap.cssString("0", session), session)
|
||||||
updateCSSProperty(htmlID, "border-collapse", "separate", session)
|
updateCSSProperty(htmlID, "border-collapse", "separate", session)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -598,7 +604,7 @@ func (table *tableViewData) propertyChanged(tag string) {
|
||||||
htmlID := table.htmlID()
|
htmlID := table.htmlID()
|
||||||
session := table.Session()
|
session := table.Session()
|
||||||
|
|
||||||
switch GetTableSelectionMode(table, "") {
|
switch GetTableSelectionMode(table) {
|
||||||
case CellSelection:
|
case CellSelection:
|
||||||
updateProperty(htmlID, "tabindex", "0", session)
|
updateProperty(htmlID, "tabindex", "0", session)
|
||||||
updateProperty(htmlID, "onfocus", "tableViewFocusEvent(this, event)", session)
|
updateProperty(htmlID, "onfocus", "tableViewFocusEvent(this, event)", session)
|
||||||
|
@ -676,7 +682,7 @@ func (table *tableViewData) currentInactiveStyle() string {
|
||||||
return "ruiCurrentTableCell"
|
return "ruiCurrentTableCell"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (table *tableViewData) valueToCellListeners(value interface{}) []func(TableView, int, int) {
|
func (table *tableViewData) valueToCellListeners(value any) []func(TableView, int, int) {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return []func(TableView, int, int){}
|
return []func(TableView, int, int){}
|
||||||
}
|
}
|
||||||
|
@ -706,7 +712,7 @@ func (table *tableViewData) valueToCellListeners(value interface{}) []func(Table
|
||||||
}
|
}
|
||||||
return listeners
|
return listeners
|
||||||
|
|
||||||
case []interface{}:
|
case []any:
|
||||||
listeners := make([]func(TableView, int, int), len(value))
|
listeners := make([]func(TableView, int, int), len(value))
|
||||||
for i, val := range value {
|
for i, val := range value {
|
||||||
if val == nil {
|
if val == nil {
|
||||||
|
@ -731,61 +737,6 @@ func (table *tableViewData) valueToCellListeners(value interface{}) []func(Table
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (table *tableViewData) valueToRowListeners(value interface{}) []func(TableView, int) {
|
|
||||||
if value == nil {
|
|
||||||
return []func(TableView, int){}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch value := value.(type) {
|
|
||||||
case func(TableView, int):
|
|
||||||
return []func(TableView, int){value}
|
|
||||||
|
|
||||||
case func(int):
|
|
||||||
fn := func(_ TableView, index int) {
|
|
||||||
value(index)
|
|
||||||
}
|
|
||||||
return []func(TableView, int){fn}
|
|
||||||
|
|
||||||
case []func(TableView, int):
|
|
||||||
return value
|
|
||||||
|
|
||||||
case []func(int):
|
|
||||||
listeners := make([]func(TableView, int), len(value))
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
listeners[i] = func(_ TableView, index int) {
|
|
||||||
val(index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
listeners := make([]func(TableView, int), len(value))
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
switch val := val.(type) {
|
|
||||||
case func(TableView, int):
|
|
||||||
listeners[i] = val
|
|
||||||
|
|
||||||
case func(int):
|
|
||||||
listeners[i] = func(_ TableView, index int) {
|
|
||||||
val(index)
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (table *tableViewData) htmlTag() string {
|
func (table *tableViewData) htmlTag() string {
|
||||||
return "table"
|
return "table"
|
||||||
}
|
}
|
||||||
|
@ -808,7 +759,7 @@ func (table *tableViewData) htmlProperties(self View, buffer *strings.Builder) {
|
||||||
buffer.WriteRune('"')
|
buffer.WriteRune('"')
|
||||||
}
|
}
|
||||||
|
|
||||||
if selectionMode := GetTableSelectionMode(table, ""); selectionMode != NoneSelection {
|
if selectionMode := GetTableSelectionMode(table); selectionMode != NoneSelection {
|
||||||
buffer.WriteString(` onfocus="tableViewFocusEvent(this, event)" onblur="tableViewBlurEvent(this, event)" data-focusitemstyle="`)
|
buffer.WriteString(` onfocus="tableViewFocusEvent(this, event)" onblur="tableViewBlurEvent(this, event)" data-focusitemstyle="`)
|
||||||
buffer.WriteString(table.currentStyle())
|
buffer.WriteString(table.currentStyle())
|
||||||
buffer.WriteString(`" data-bluritemstyle="`)
|
buffer.WriteString(`" data-bluritemstyle="`)
|
||||||
|
@ -879,10 +830,10 @@ func (table *tableViewData) htmlSubviews(self View, buffer *strings.Builder) {
|
||||||
defer freeStringBuilder(cssBuilder.buffer)
|
defer freeStringBuilder(cssBuilder.buffer)
|
||||||
|
|
||||||
var view tableCellView
|
var view tableCellView
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
|
|
||||||
ignorCells := []struct{ row, column int }{}
|
ignorCells := []struct{ row, column int }{}
|
||||||
selectionMode := GetTableSelectionMode(table, "")
|
selectionMode := GetTableSelectionMode(table)
|
||||||
|
|
||||||
var allowCellSelection TableAllowCellSelection = nil
|
var allowCellSelection TableAllowCellSelection = nil
|
||||||
if allow, ok := adapter.(TableAllowCellSelection); ok {
|
if allow, ok := adapter.(TableAllowCellSelection); ok {
|
||||||
|
@ -905,7 +856,7 @@ func (table *tableViewData) htmlSubviews(self View, buffer *strings.Builder) {
|
||||||
}
|
}
|
||||||
|
|
||||||
vAlignCss := enumProperties[TableVerticalAlign].cssValues
|
vAlignCss := enumProperties[TableVerticalAlign].cssValues
|
||||||
vAlignValue := GetTableVerticalAlign(table, "")
|
vAlignValue := GetTableVerticalAlign(table)
|
||||||
if vAlignValue < 0 || vAlignValue >= len(vAlignCss) {
|
if vAlignValue < 0 || vAlignValue >= len(vAlignCss) {
|
||||||
vAlignValue = 0
|
vAlignValue = 0
|
||||||
}
|
}
|
||||||
|
@ -1160,8 +1111,8 @@ func (table *tableViewData) htmlSubviews(self View, buffer *strings.Builder) {
|
||||||
buffer.WriteString("</colgroup>")
|
buffer.WriteString("</colgroup>")
|
||||||
}
|
}
|
||||||
|
|
||||||
headHeight := GetTableHeadHeight(table, "")
|
headHeight := GetTableHeadHeight(table)
|
||||||
footHeight := GetTableFootHeight(table, "")
|
footHeight := GetTableFootHeight(table)
|
||||||
cellBorder := table.getCellBorder()
|
cellBorder := table.getCellBorder()
|
||||||
cellPadding := table.boundsProperty(CellPadding)
|
cellPadding := table.boundsProperty(CellPadding)
|
||||||
if cellPadding == nil {
|
if cellPadding == nil {
|
||||||
|
@ -1370,24 +1321,26 @@ func (table *tableViewData) getCurrent() CellIndex {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (table *tableViewData) cssStyle(self View, builder cssBuilder) {
|
func (table *tableViewData) cssStyle(self View, builder cssBuilder) {
|
||||||
table.viewData.cssViewStyle(builder, table.Session())
|
session := table.Session()
|
||||||
|
table.viewData.cssViewStyle(builder, session)
|
||||||
|
|
||||||
gap, ok := sizeProperty(table, Gap, table.Session())
|
gap, ok := sizeProperty(table, Gap, session)
|
||||||
if !ok || gap.Type == Auto || gap.Value <= 0 {
|
if !ok || gap.Type == Auto || gap.Value <= 0 {
|
||||||
builder.add("border-spacing", "0")
|
builder.add("border-spacing", "0")
|
||||||
builder.add("border-collapse", "collapse")
|
builder.add("border-collapse", "collapse")
|
||||||
} else {
|
} else {
|
||||||
builder.add("border-spacing", gap.cssString("0"))
|
builder.add("border-spacing", gap.cssString("0", session))
|
||||||
builder.add("border-collapse", "separate")
|
builder.add("border-collapse", "separate")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (table *tableViewData) ReloadTableData() {
|
func (table *tableViewData) ReloadTableData() {
|
||||||
|
session := table.Session()
|
||||||
if content := table.content(); content != nil {
|
if content := table.content(); content != nil {
|
||||||
updateProperty(table.htmlID(), "data-rows", strconv.Itoa(content.RowCount()), table.Session())
|
updateProperty(table.htmlID(), "data-rows", strconv.Itoa(content.RowCount()), session)
|
||||||
updateProperty(table.htmlID(), "data-columns", strconv.Itoa(content.ColumnCount()), table.Session())
|
updateProperty(table.htmlID(), "data-columns", strconv.Itoa(content.ColumnCount()), session)
|
||||||
}
|
}
|
||||||
updateInnerHTML(table.htmlID(), table.Session())
|
updateInnerHTML(table.htmlID(), session)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (table *tableViewData) onItemResize(self View, index string, x, y, width, height float64) {
|
func (table *tableViewData) onItemResize(self View, index string, x, y, width, height float64) {
|
||||||
|
|
|
@ -2,11 +2,11 @@ package rui
|
||||||
|
|
||||||
import "strings"
|
import "strings"
|
||||||
|
|
||||||
func (cell *tableCellView) Set(tag string, value interface{}) bool {
|
func (cell *tableCellView) Set(tag string, value any) bool {
|
||||||
return cell.set(strings.ToLower(tag), value)
|
return cell.set(strings.ToLower(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cell *tableCellView) set(tag string, value interface{}) bool {
|
func (cell *tableCellView) set(tag string, value any) bool {
|
||||||
switch tag {
|
switch tag {
|
||||||
case VerticalAlign:
|
case VerticalAlign:
|
||||||
tag = TableVerticalAlign
|
tag = TableVerticalAlign
|
||||||
|
@ -24,10 +24,10 @@ func (cell *tableCellView) cssStyle(self View, builder cssBuilder) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTableContent returns a TableAdapter which defines the TableView content.
|
// GetTableContent returns a TableAdapter which defines the TableView content.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTableContent(view View, subviewID string) TableAdapter {
|
func GetTableContent(view View, subviewID ...string) TableAdapter {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
if view != nil {
|
if view != nil {
|
||||||
|
@ -40,10 +40,10 @@ func GetTableContent(view View, subviewID string) TableAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTableRowStyle returns a TableRowStyle which defines styles of TableView rows.
|
// GetTableRowStyle returns a TableRowStyle which defines styles of TableView rows.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTableRowStyle(view View, subviewID string) TableRowStyle {
|
func GetTableRowStyle(view View, subviewID ...string) TableRowStyle {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
if view != nil {
|
if view != nil {
|
||||||
|
@ -56,10 +56,10 @@ func GetTableRowStyle(view View, subviewID string) TableRowStyle {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTableColumnStyle returns a TableColumnStyle which defines styles of TableView columns.
|
// GetTableColumnStyle returns a TableColumnStyle which defines styles of TableView columns.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTableColumnStyle(view View, subviewID string) TableColumnStyle {
|
func GetTableColumnStyle(view View, subviewID ...string) TableColumnStyle {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
if view != nil {
|
if view != nil {
|
||||||
|
@ -72,10 +72,10 @@ func GetTableColumnStyle(view View, subviewID string) TableColumnStyle {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTableCellStyle returns a TableCellStyle which defines styles of TableView cells.
|
// GetTableCellStyle returns a TableCellStyle which defines styles of TableView cells.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTableCellStyle(view View, subviewID string) TableCellStyle {
|
func GetTableCellStyle(view View, subviewID ...string) TableCellStyle {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
if view != nil {
|
if view != nil {
|
||||||
|
@ -89,72 +89,42 @@ func GetTableCellStyle(view View, subviewID string) TableCellStyle {
|
||||||
|
|
||||||
// GetTableSelectionMode returns the mode of the TableView elements selection.
|
// GetTableSelectionMode returns the mode of the TableView elements selection.
|
||||||
// Valid values are NoneSelection (0), CellSelection (1), and RowSelection (2).
|
// Valid values are NoneSelection (0), CellSelection (1), and RowSelection (2).
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTableSelectionMode(view View, subviewID string) int {
|
func GetTableSelectionMode(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return enumStyledProperty(view, subviewID, SelectionMode, NoneSelection, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if result, ok := enumStyledProperty(view, SelectionMode, NoneSelection); ok {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NoneSelection
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTableVerticalAlign returns a vertical align in a TavleView cell. Returns one of next values:
|
// GetTableVerticalAlign returns a vertical align in a TavleView cell. Returns one of next values:
|
||||||
// TopAlign (0), BottomAlign (1), CenterAlign (2), and BaselineAlign (3)
|
// TopAlign (0), BottomAlign (1), CenterAlign (2), and BaselineAlign (3)
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTableVerticalAlign(view View, subviewID string) int {
|
func GetTableVerticalAlign(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return enumStyledProperty(view, subviewID, TableVerticalAlign, TopAlign, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if result, ok := enumStyledProperty(view, TableVerticalAlign, TopAlign); ok {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TopAlign
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTableHeadHeight returns the number of rows in the table header.
|
// GetTableHeadHeight returns the number of rows in the table header.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTableHeadHeight(view View, subviewID string) int {
|
func GetTableHeadHeight(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return intStyledProperty(view, subviewID, HeadHeight, 0)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
headHeight, _ := intStyledProperty(view, HeadHeight, 0)
|
|
||||||
return headHeight
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTableFootHeight returns the number of rows in the table footer.
|
// GetTableFootHeight returns the number of rows in the table footer.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTableFootHeight(view View, subviewID string) int {
|
func GetTableFootHeight(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return intStyledProperty(view, subviewID, FootHeight, 0)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
headHeight, _ := intStyledProperty(view, FootHeight, 0)
|
|
||||||
return headHeight
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTableCurrent returns the row and column index of the TableView selected cell/row.
|
// GetTableCurrent returns the row and column index of the TableView selected cell/row.
|
||||||
// If there is no selected cell/row or the selection mode is NoneSelection (0),
|
// If there is no selected cell/row or the selection mode is NoneSelection (0),
|
||||||
// then a value of the row and column index less than 0 is returned.
|
// then a value of the row and column index less than 0 is returned.
|
||||||
// If the selection mode is RowSelection (2) then the returned column index is less than 0.
|
// If the selection mode is RowSelection (2) then the returned column index is less than 0.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTableCurrent(view View, subviewID string) CellIndex {
|
func GetTableCurrent(view View, subviewID ...string) CellIndex {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
if view != nil {
|
if view != nil {
|
||||||
if selectionMode := GetTableSelectionMode(view, ""); selectionMode != NoneSelection {
|
if selectionMode := GetTableSelectionMode(view); selectionMode != NoneSelection {
|
||||||
if tableView, ok := view.(TableView); ok {
|
if tableView, ok := view.(TableView); ok {
|
||||||
return tableView.getCurrent()
|
return tableView.getCurrent()
|
||||||
}
|
}
|
||||||
|
@ -165,10 +135,10 @@ func GetTableCurrent(view View, subviewID string) CellIndex {
|
||||||
|
|
||||||
// GetTableCellClickedListeners returns listeners of event which occurs when the user clicks on a table cell.
|
// GetTableCellClickedListeners returns listeners of event which occurs when the user clicks on a table cell.
|
||||||
// If there are no listeners then the empty list is returned.
|
// If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTableCellClickedListeners(view View, subviewID string) []func(TableView, int, int) {
|
func GetTableCellClickedListeners(view View, subviewID ...string) []func(TableView, int, int) {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view != nil {
|
if view != nil {
|
||||||
if value := view.Get(TableCellClickedEvent); value != nil {
|
if value := view.Get(TableCellClickedEvent); value != nil {
|
||||||
|
@ -182,10 +152,10 @@ func GetTableCellClickedListeners(view View, subviewID string) []func(TableView,
|
||||||
|
|
||||||
// GetTableCellSelectedListeners returns listeners of event which occurs when a table cell becomes selected.
|
// GetTableCellSelectedListeners returns listeners of event which occurs when a table cell becomes selected.
|
||||||
// If there are no listeners then the empty list is returned.
|
// If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTableCellSelectedListeners(view View, subviewID string) []func(TableView, int, int) {
|
func GetTableCellSelectedListeners(view View, subviewID ...string) []func(TableView, int, int) {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view != nil {
|
if view != nil {
|
||||||
if value := view.Get(TableCellSelectedEvent); value != nil {
|
if value := view.Get(TableCellSelectedEvent); value != nil {
|
||||||
|
@ -199,43 +169,23 @@ func GetTableCellSelectedListeners(view View, subviewID string) []func(TableView
|
||||||
|
|
||||||
// GetTableRowClickedListeners returns listeners of event which occurs when the user clicks on a table row.
|
// GetTableRowClickedListeners returns listeners of event which occurs when the user clicks on a table row.
|
||||||
// If there are no listeners then the empty list is returned.
|
// If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTableRowClickedListeners(view View, subviewID string) []func(TableView, int) {
|
func GetTableRowClickedListeners(view View, subviewID ...string) []func(TableView, int) {
|
||||||
if subviewID != "" {
|
return getEventListeners[TableView, int](view, subviewID, TableRowClickedEvent)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if value := view.Get(TableRowClickedEvent); value != nil {
|
|
||||||
if result, ok := value.([]func(TableView, int)); ok {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []func(TableView, int){}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTableRowSelectedListeners returns listeners of event which occurs when a table row becomes selected.
|
// GetTableRowSelectedListeners returns listeners of event which occurs when a table row becomes selected.
|
||||||
// If there are no listeners then the empty list is returned.
|
// If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTableRowSelectedListeners(view View, subviewID string) []func(TableView, int) {
|
func GetTableRowSelectedListeners(view View, subviewID ...string) []func(TableView, int) {
|
||||||
if subviewID != "" {
|
return getEventListeners[TableView, int](view, subviewID, TableRowSelectedEvent)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if value := view.Get(TableRowSelectedEvent); value != nil {
|
|
||||||
if result, ok := value.([]func(TableView, int)); ok {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []func(TableView, int){}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReloadTableViewData updates TableView
|
// ReloadTableViewData updates TableView
|
||||||
func ReloadTableViewData(view View, subviewID string) bool {
|
func ReloadTableViewData(view View, subviewID ...string) bool {
|
||||||
var tableView TableView
|
var tableView TableView
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
if tableView = TableViewByID(view, subviewID); tableView == nil {
|
if tableView = TableViewByID(view, subviewID[0]); tableView == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -81,7 +81,7 @@ type tabsLayoutData struct {
|
||||||
// NewTabsLayout create new TabsLayout object and return it
|
// NewTabsLayout create new TabsLayout object and return it
|
||||||
func NewTabsLayout(session Session, params Params) TabsLayout {
|
func NewTabsLayout(session Session, params Params) TabsLayout {
|
||||||
view := new(tabsLayoutData)
|
view := new(tabsLayoutData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -91,8 +91,8 @@ func newTabsLayout(session Session) View {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initialize fields of ViewsContainer by default values
|
// Init initialize fields of ViewsContainer by default values
|
||||||
func (tabsLayout *tabsLayoutData) Init(session Session) {
|
func (tabsLayout *tabsLayoutData) init(session Session) {
|
||||||
tabsLayout.viewsContainerData.Init(session)
|
tabsLayout.viewsContainerData.init(session)
|
||||||
tabsLayout.tag = "TabsLayout"
|
tabsLayout.tag = "TabsLayout"
|
||||||
tabsLayout.systemClass = "ruiTabsLayout"
|
tabsLayout.systemClass = "ruiTabsLayout"
|
||||||
tabsLayout.tabListener = []func(TabsLayout, int, int){}
|
tabsLayout.tabListener = []func(TabsLayout, int, int){}
|
||||||
|
@ -108,11 +108,11 @@ func (tabsLayout *tabsLayoutData) currentItem(defaultValue int) int {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tabsLayout *tabsLayoutData) Get(tag string) interface{} {
|
func (tabsLayout *tabsLayoutData) Get(tag string) any {
|
||||||
return tabsLayout.get(strings.ToLower(tag))
|
return tabsLayout.get(strings.ToLower(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tabsLayout *tabsLayoutData) get(tag string) interface{} {
|
func (tabsLayout *tabsLayoutData) get(tag string) any {
|
||||||
switch tag {
|
switch tag {
|
||||||
case CurrentTabChangedEvent:
|
case CurrentTabChangedEvent:
|
||||||
return tabsLayout.tabListener
|
return tabsLayout.tabListener
|
||||||
|
@ -190,11 +190,11 @@ func (tabsLayout *tabsLayoutData) remove(tag string) {
|
||||||
tabsLayout.propertyChangedEvent(tag)
|
tabsLayout.propertyChangedEvent(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tabsLayout *tabsLayoutData) Set(tag string, value interface{}) bool {
|
func (tabsLayout *tabsLayoutData) Set(tag string, value any) bool {
|
||||||
return tabsLayout.set(strings.ToLower(tag), value)
|
return tabsLayout.set(strings.ToLower(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tabsLayout *tabsLayoutData) set(tag string, value interface{}) bool {
|
func (tabsLayout *tabsLayoutData) set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
tabsLayout.remove(tag)
|
tabsLayout.remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -210,10 +210,12 @@ func (tabsLayout *tabsLayoutData) set(tag string, value interface{}) bool {
|
||||||
tabsLayout.tabListener = listeners
|
tabsLayout.tabListener = listeners
|
||||||
|
|
||||||
case TabCloseEvent:
|
case TabCloseEvent:
|
||||||
listeners := tabsLayout.valueToCloseListeners(value)
|
listeners, ok := valueToEventListeners[TabsLayout, int](value)
|
||||||
if listeners == nil {
|
if !ok {
|
||||||
notCompatibleType(tag, value)
|
notCompatibleType(tag, value)
|
||||||
return false
|
return false
|
||||||
|
} else if listeners == nil {
|
||||||
|
listeners = []func(TabsLayout, int){}
|
||||||
}
|
}
|
||||||
tabsLayout.tabCloseListener = listeners
|
tabsLayout.tabCloseListener = listeners
|
||||||
|
|
||||||
|
@ -286,7 +288,7 @@ func (tabsLayout *tabsLayoutData) set(tag string, value interface{}) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tabsLayout *tabsLayoutData) valueToTabListeners(value interface{}) []func(TabsLayout, int, int) {
|
func (tabsLayout *tabsLayoutData) valueToTabListeners(value any) []func(TabsLayout, int, int) {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return []func(TabsLayout, int, int){}
|
return []func(TabsLayout, int, int){}
|
||||||
}
|
}
|
||||||
|
@ -388,7 +390,7 @@ func (tabsLayout *tabsLayoutData) valueToTabListeners(value interface{}) []func(
|
||||||
}
|
}
|
||||||
return listeners
|
return listeners
|
||||||
|
|
||||||
case []interface{}:
|
case []any:
|
||||||
listeners := make([]func(TabsLayout, int, int), len(value))
|
listeners := make([]func(TabsLayout, int, int), len(value))
|
||||||
for i, val := range value {
|
for i, val := range value {
|
||||||
if val == nil {
|
if val == nil {
|
||||||
|
@ -433,61 +435,6 @@ func (tabsLayout *tabsLayoutData) valueToTabListeners(value interface{}) []func(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tabsLayout *tabsLayoutData) valueToCloseListeners(value interface{}) []func(TabsLayout, int) {
|
|
||||||
if value == nil {
|
|
||||||
return []func(TabsLayout, int){}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch value := value.(type) {
|
|
||||||
case func(TabsLayout, int):
|
|
||||||
return []func(TabsLayout, int){value}
|
|
||||||
|
|
||||||
case func(int):
|
|
||||||
fn := func(_ TabsLayout, index int) {
|
|
||||||
value(index)
|
|
||||||
}
|
|
||||||
return []func(TabsLayout, int){fn}
|
|
||||||
|
|
||||||
case []func(TabsLayout, int):
|
|
||||||
return value
|
|
||||||
|
|
||||||
case []func(int):
|
|
||||||
listeners := make([]func(TabsLayout, int), len(value))
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
listeners[i] = func(_ TabsLayout, index int) {
|
|
||||||
val(index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
listeners := make([]func(TabsLayout, int), len(value))
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
switch val := val.(type) {
|
|
||||||
case func(TabsLayout, int):
|
|
||||||
listeners[i] = val
|
|
||||||
|
|
||||||
case func(int):
|
|
||||||
listeners[i] = func(_ TabsLayout, index int) {
|
|
||||||
val(index)
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tabsLayout *tabsLayoutData) tabsLocation() int {
|
func (tabsLayout *tabsLayoutData) tabsLocation() int {
|
||||||
tabs, _ := enumProperty(tabsLayout, Tabs, tabsLayout.session, 0)
|
tabs, _ := enumProperty(tabsLayout, Tabs, tabsLayout.session, 0)
|
||||||
return tabs
|
return tabs
|
||||||
|
@ -576,7 +523,7 @@ func (tabsLayout *tabsLayoutData) ListItem(index int, session Session) View {
|
||||||
if !ok || title == "" {
|
if !ok || title == "" {
|
||||||
title = "No title"
|
title = "No title"
|
||||||
}
|
}
|
||||||
if !GetNotTranslate(tabsLayout, "") {
|
if !GetNotTranslate(tabsLayout) {
|
||||||
title, _ = tabsLayout.Session().GetString(title)
|
title, _ = tabsLayout.Session().GetString(title)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -776,7 +723,7 @@ func (tabsLayout *tabsLayoutData) htmlSubviews(self View, buffer *strings.Builde
|
||||||
inactiveStyle := tabsLayout.inactiveTabStyle()
|
inactiveStyle := tabsLayout.inactiveTabStyle()
|
||||||
activeStyle := tabsLayout.activeTabStyle()
|
activeStyle := tabsLayout.activeTabStyle()
|
||||||
|
|
||||||
notTranslate := GetNotTranslate(tabsLayout, "")
|
notTranslate := GetNotTranslate(tabsLayout)
|
||||||
closeButton, _ := boolProperty(tabsLayout, TabCloseButton, tabsLayout.session)
|
closeButton, _ := boolProperty(tabsLayout, TabCloseButton, tabsLayout.session)
|
||||||
|
|
||||||
var tabStyle, titleDiv string
|
var tabStyle, titleDiv string
|
||||||
|
|
27
textView.go
27
textView.go
|
@ -17,7 +17,7 @@ type textViewData struct {
|
||||||
// NewTextView create new TextView object and return it
|
// NewTextView create new TextView object and return it
|
||||||
func NewTextView(session Session, params Params) TextView {
|
func NewTextView(session Session, params Params) TextView {
|
||||||
view := new(textViewData)
|
view := new(textViewData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -27,8 +27,8 @@ func newTextView(session Session) View {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initialize fields of TextView by default values
|
// Init initialize fields of TextView by default values
|
||||||
func (textView *textViewData) Init(session Session) {
|
func (textView *textViewData) init(session Session) {
|
||||||
textView.viewData.Init(session)
|
textView.viewData.init(session)
|
||||||
textView.tag = "TextView"
|
textView.tag = "TextView"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ func (textView *textViewData) String() string {
|
||||||
return getViewString(textView)
|
return getViewString(textView)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (textView *textViewData) Get(tag string) interface{} {
|
func (textView *textViewData) Get(tag string) any {
|
||||||
return textView.get(strings.ToLower(tag))
|
return textView.get(strings.ToLower(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,11 +57,11 @@ func (textView *textViewData) remove(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (textView *textViewData) Set(tag string, value interface{}) bool {
|
func (textView *textViewData) Set(tag string, value any) bool {
|
||||||
return textView.set(strings.ToLower(tag), value)
|
return textView.set(strings.ToLower(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (textView *textViewData) set(tag string, value interface{}) bool {
|
func (textView *textViewData) set(tag string, value any) bool {
|
||||||
switch tag {
|
switch tag {
|
||||||
case Text:
|
case Text:
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
|
@ -155,7 +155,7 @@ func textToJS(text string) string {
|
||||||
func (textView *textViewData) htmlSubviews(self View, buffer *strings.Builder) {
|
func (textView *textViewData) htmlSubviews(self View, buffer *strings.Builder) {
|
||||||
if value := textView.getRaw(Text); value != nil {
|
if value := textView.getRaw(Text); value != nil {
|
||||||
if text, ok := value.(string); ok {
|
if text, ok := value.(string); ok {
|
||||||
if !GetNotTranslate(textView, "") {
|
if !GetNotTranslate(textView) {
|
||||||
text, _ = textView.session.GetString(text)
|
text, _ = textView.session.GetString(text)
|
||||||
}
|
}
|
||||||
buffer.WriteString(textToJS(text))
|
buffer.WriteString(textToJS(text))
|
||||||
|
@ -165,14 +165,7 @@ func (textView *textViewData) htmlSubviews(self View, buffer *strings.Builder) {
|
||||||
|
|
||||||
// GetTextOverflow returns a value of the "text-overflow" property:
|
// GetTextOverflow returns a value of the "text-overflow" property:
|
||||||
// TextOverflowClip (0) or TextOverflowEllipsis (1).
|
// TextOverflowClip (0) or TextOverflowEllipsis (1).
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTextOverflow(view View, subviewID string) int {
|
func GetTextOverflow(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return enumStyledProperty(view, subviewID, TextOverflow, SingleLineText, false)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view == nil {
|
|
||||||
return SingleLineText
|
|
||||||
}
|
|
||||||
t, _ := enumStyledProperty(view, TextOverflow, SingleLineText)
|
|
||||||
return t
|
|
||||||
}
|
}
|
||||||
|
|
148
timePicker.go
148
timePicker.go
|
@ -29,7 +29,7 @@ type timePickerData struct {
|
||||||
// NewTimePicker create new TimePicker object and return it
|
// NewTimePicker create new TimePicker object and return it
|
||||||
func NewTimePicker(session Session, params Params) TimePicker {
|
func NewTimePicker(session Session, params Params) TimePicker {
|
||||||
view := new(timePickerData)
|
view := new(timePickerData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -38,8 +38,8 @@ func newTimePicker(session Session) View {
|
||||||
return NewTimePicker(session, nil)
|
return NewTimePicker(session, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *timePickerData) Init(session Session) {
|
func (picker *timePickerData) init(session Session) {
|
||||||
picker.viewData.Init(session)
|
picker.viewData.init(session)
|
||||||
picker.tag = "TimePicker"
|
picker.tag = "TimePicker"
|
||||||
picker.timeChangedListeners = []func(TimePicker, time.Time){}
|
picker.timeChangedListeners = []func(TimePicker, time.Time){}
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ func (picker *timePickerData) remove(tag string) {
|
||||||
case TimePickerValue:
|
case TimePickerValue:
|
||||||
if _, ok := picker.properties[TimePickerValue]; ok {
|
if _, ok := picker.properties[TimePickerValue]; ok {
|
||||||
delete(picker.properties, TimePickerValue)
|
delete(picker.properties, TimePickerValue)
|
||||||
time := GetTimePickerValue(picker, "")
|
time := GetTimePickerValue(picker)
|
||||||
if picker.created {
|
if picker.created {
|
||||||
picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), time.Format(timeFormat)))
|
picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), time.Format(timeFormat)))
|
||||||
}
|
}
|
||||||
|
@ -114,11 +114,11 @@ func (picker *timePickerData) remove(tag string) {
|
||||||
picker.propertyChangedEvent(tag)
|
picker.propertyChangedEvent(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *timePickerData) Set(tag string, value interface{}) bool {
|
func (picker *timePickerData) Set(tag string, value any) bool {
|
||||||
return picker.set(picker.normalizeTag(tag), value)
|
return picker.set(picker.normalizeTag(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *timePickerData) set(tag string, value interface{}) bool {
|
func (picker *timePickerData) set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
picker.remove(tag)
|
picker.remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -192,9 +192,9 @@ func (picker *timePickerData) set(tag string, value interface{}) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
case TimePickerStep:
|
case TimePickerStep:
|
||||||
oldStep := GetTimePickerStep(picker, "")
|
oldStep := GetTimePickerStep(picker)
|
||||||
if picker.setIntProperty(TimePickerStep, value) {
|
if picker.setIntProperty(TimePickerStep, value) {
|
||||||
if step := GetTimePickerStep(picker, ""); oldStep != step {
|
if step := GetTimePickerStep(picker); oldStep != step {
|
||||||
if picker.created {
|
if picker.created {
|
||||||
if step > 0 {
|
if step > 0 {
|
||||||
updateProperty(picker.htmlID(), Step, strconv.Itoa(step), picker.session)
|
updateProperty(picker.htmlID(), Step, strconv.Itoa(step), picker.session)
|
||||||
|
@ -208,7 +208,7 @@ func (picker *timePickerData) set(tag string, value interface{}) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
case TimePickerValue:
|
case TimePickerValue:
|
||||||
oldTime := GetTimePickerValue(picker, "")
|
oldTime := GetTimePickerValue(picker)
|
||||||
if time, ok := setTimeValue(TimePickerValue); ok {
|
if time, ok := setTimeValue(TimePickerValue); ok {
|
||||||
if time != oldTime {
|
if time != oldTime {
|
||||||
if picker.created {
|
if picker.created {
|
||||||
|
@ -223,57 +223,14 @@ func (picker *timePickerData) set(tag string, value interface{}) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
case TimeChangedEvent:
|
case TimeChangedEvent:
|
||||||
switch value := value.(type) {
|
listeners, ok := valueToEventListeners[TimePicker, time.Time](value)
|
||||||
case func(TimePicker, time.Time):
|
if !ok {
|
||||||
picker.timeChangedListeners = []func(TimePicker, time.Time){value}
|
notCompatibleType(tag, value)
|
||||||
|
return false
|
||||||
case func(time.Time):
|
} else if listeners == nil {
|
||||||
fn := func(_ TimePicker, time time.Time) {
|
listeners = []func(TimePicker, time.Time){}
|
||||||
value(time)
|
|
||||||
}
|
|
||||||
picker.timeChangedListeners = []func(TimePicker, time.Time){fn}
|
|
||||||
|
|
||||||
case []func(TimePicker, time.Time):
|
|
||||||
picker.timeChangedListeners = value
|
|
||||||
|
|
||||||
case []func(time.Time):
|
|
||||||
listeners := make([]func(TimePicker, time.Time), len(value))
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
notCompatibleType(tag, val)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
listeners[i] = func(_ TimePicker, time time.Time) {
|
|
||||||
val(time)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
picker.timeChangedListeners = listeners
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
listeners := make([]func(TimePicker, time.Time), len(value))
|
|
||||||
for i, val := range value {
|
|
||||||
if val == nil {
|
|
||||||
notCompatibleType(tag, val)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
switch val := val.(type) {
|
|
||||||
case func(TimePicker, time.Time):
|
|
||||||
listeners[i] = val
|
|
||||||
|
|
||||||
case func(time.Time):
|
|
||||||
listeners[i] = func(_ TimePicker, time time.Time) {
|
|
||||||
val(time)
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
notCompatibleType(tag, val)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
picker.timeChangedListeners = listeners
|
|
||||||
}
|
}
|
||||||
|
picker.timeChangedListeners = listeners
|
||||||
picker.propertyChangedEvent(tag)
|
picker.propertyChangedEvent(tag)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
@ -283,11 +240,11 @@ func (picker *timePickerData) set(tag string, value interface{}) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *timePickerData) Get(tag string) interface{} {
|
func (picker *timePickerData) Get(tag string) any {
|
||||||
return picker.get(picker.normalizeTag(tag))
|
return picker.get(picker.normalizeTag(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *timePickerData) get(tag string) interface{} {
|
func (picker *timePickerData) get(tag string) any {
|
||||||
switch tag {
|
switch tag {
|
||||||
case TimeChangedEvent:
|
case TimeChangedEvent:
|
||||||
return picker.timeChangedListeners
|
return picker.timeChangedListeners
|
||||||
|
@ -325,7 +282,7 @@ func (picker *timePickerData) htmlProperties(self View, buffer *strings.Builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.WriteString(` value="`)
|
buffer.WriteString(` value="`)
|
||||||
buffer.WriteString(GetTimePickerValue(picker, "").Format(timeFormat))
|
buffer.WriteString(GetTimePickerValue(picker).Format(timeFormat))
|
||||||
buffer.WriteByte('"')
|
buffer.WriteByte('"')
|
||||||
|
|
||||||
buffer.WriteString(` oninput="editViewInputEvent(this)"`)
|
buffer.WriteString(` oninput="editViewInputEvent(this)"`)
|
||||||
|
@ -335,7 +292,7 @@ func (picker *timePickerData) htmlProperties(self View, buffer *strings.Builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (picker *timePickerData) htmlDisabledProperties(self View, buffer *strings.Builder) {
|
func (picker *timePickerData) htmlDisabledProperties(self View, buffer *strings.Builder) {
|
||||||
if IsDisabled(self, "") {
|
if IsDisabled(self) {
|
||||||
buffer.WriteString(` disabled`)
|
buffer.WriteString(` disabled`)
|
||||||
}
|
}
|
||||||
picker.viewData.htmlDisabledProperties(self, buffer)
|
picker.viewData.htmlDisabledProperties(self, buffer)
|
||||||
|
@ -346,7 +303,7 @@ func (picker *timePickerData) handleCommand(self View, command string, data Data
|
||||||
case "textChanged":
|
case "textChanged":
|
||||||
if text, ok := data.PropertyValue("text"); ok {
|
if text, ok := data.PropertyValue("text"); ok {
|
||||||
if value, err := time.Parse(timeFormat, text); err == nil {
|
if value, err := time.Parse(timeFormat, text); err == nil {
|
||||||
oldValue := GetTimePickerValue(picker, "")
|
oldValue := GetTimePickerValue(picker)
|
||||||
picker.properties[TimePickerValue] = value
|
picker.properties[TimePickerValue] = value
|
||||||
if value != oldValue {
|
if value != oldValue {
|
||||||
for _, listener := range picker.timeChangedListeners {
|
for _, listener := range picker.timeChangedListeners {
|
||||||
|
@ -362,7 +319,7 @@ func (picker *timePickerData) handleCommand(self View, command string, data Data
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTimeProperty(view View, mainTag, shortTag string) (time.Time, bool) {
|
func getTimeProperty(view View, mainTag, shortTag string) (time.Time, bool) {
|
||||||
valueToTime := func(value interface{}) (time.Time, bool) {
|
valueToTime := func(value any) (time.Time, bool) {
|
||||||
if value != nil {
|
if value != nil {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case time.Time:
|
case time.Time:
|
||||||
|
@ -396,10 +353,10 @@ func getTimeProperty(view View, mainTag, shortTag string) (time.Time, bool) {
|
||||||
|
|
||||||
// GetTimePickerMin returns the min time of TimePicker subview and "true" as the second value if the min time is set,
|
// GetTimePickerMin returns the min time of TimePicker subview and "true" as the second value if the min time is set,
|
||||||
// "false" as the second value otherwise.
|
// "false" as the second value otherwise.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTimePickerMin(view View, subviewID string) (time.Time, bool) {
|
func GetTimePickerMin(view View, subviewID ...string) (time.Time, bool) {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view != nil {
|
if view != nil {
|
||||||
return getTimeProperty(view, TimePickerMin, Min)
|
return getTimeProperty(view, TimePickerMin, Min)
|
||||||
|
@ -409,10 +366,10 @@ func GetTimePickerMin(view View, subviewID string) (time.Time, bool) {
|
||||||
|
|
||||||
// GetTimePickerMax returns the max time of TimePicker subview and "true" as the second value if the min time is set,
|
// GetTimePickerMax returns the max time of TimePicker subview and "true" as the second value if the min time is set,
|
||||||
// "false" as the second value otherwise.
|
// "false" as the second value otherwise.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTimePickerMax(view View, subviewID string) (time.Time, bool) {
|
func GetTimePickerMax(view View, subviewID ...string) (time.Time, bool) {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view != nil {
|
if view != nil {
|
||||||
return getTimeProperty(view, TimePickerMax, Max)
|
return getTimeProperty(view, TimePickerMax, Max)
|
||||||
|
@ -421,31 +378,16 @@ func GetTimePickerMax(view View, subviewID string) (time.Time, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTimePickerStep returns the time changing step in seconds of TimePicker subview.
|
// GetTimePickerStep returns the time changing step in seconds of TimePicker subview.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTimePickerStep(view View, subviewID string) int {
|
func GetTimePickerStep(view View, subviewID ...string) int {
|
||||||
if subviewID != "" {
|
return intStyledProperty(view, subviewID, TimePickerStep, 60)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view == nil {
|
|
||||||
return 60
|
|
||||||
}
|
|
||||||
|
|
||||||
result, ok := intStyledProperty(view, TimePickerStep, 60)
|
|
||||||
if !ok {
|
|
||||||
result, _ = intStyledProperty(view, Step, 60)
|
|
||||||
}
|
|
||||||
|
|
||||||
if result < 0 {
|
|
||||||
return 60
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTimePickerValue returns the time of TimePicker subview.
|
// GetTimePickerValue returns the time of TimePicker subview.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTimePickerValue(view View, subviewID string) time.Time {
|
func GetTimePickerValue(view View, subviewID ...string) time.Time {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view == nil {
|
if view == nil {
|
||||||
return time.Now()
|
return time.Now()
|
||||||
|
@ -456,17 +398,7 @@ func GetTimePickerValue(view View, subviewID string) time.Time {
|
||||||
|
|
||||||
// GetTimeChangedListeners returns the TimeChangedListener list of an TimePicker subview.
|
// GetTimeChangedListeners returns the TimeChangedListener list of an TimePicker subview.
|
||||||
// If there are no listeners then the empty list is returned
|
// If there are no listeners then the empty list is returned
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTimeChangedListeners(view View, subviewID string) []func(TimePicker, time.Time) {
|
func GetTimeChangedListeners(view View, subviewID ...string) []func(TimePicker, time.Time) {
|
||||||
if subviewID != "" {
|
return getEventListeners[TimePicker, time.Time](view, subviewID, TimeChangedEvent)
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if value := view.Get(TimeChangedEvent); value != nil {
|
|
||||||
if listeners, ok := value.([]func(TimePicker, time.Time)); ok {
|
|
||||||
return listeners
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []func(TimePicker, time.Time){}
|
|
||||||
}
|
}
|
||||||
|
|
169
touchEvents.go
169
touchEvents.go
|
@ -90,131 +90,6 @@ type TouchEvent struct {
|
||||||
MetaKey bool
|
MetaKey bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func valueToTouchListeners(value interface{}) ([]func(View, TouchEvent), bool) {
|
|
||||||
if value == nil {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
|
|
||||||
switch value := value.(type) {
|
|
||||||
case func(View, TouchEvent):
|
|
||||||
return []func(View, TouchEvent){value}, true
|
|
||||||
|
|
||||||
case func(TouchEvent):
|
|
||||||
fn := func(_ View, event TouchEvent) {
|
|
||||||
value(event)
|
|
||||||
}
|
|
||||||
return []func(View, TouchEvent){fn}, true
|
|
||||||
|
|
||||||
case func(View):
|
|
||||||
fn := func(view View, _ TouchEvent) {
|
|
||||||
value(view)
|
|
||||||
}
|
|
||||||
return []func(View, TouchEvent){fn}, true
|
|
||||||
|
|
||||||
case func():
|
|
||||||
fn := func(View, TouchEvent) {
|
|
||||||
value()
|
|
||||||
}
|
|
||||||
return []func(View, TouchEvent){fn}, true
|
|
||||||
|
|
||||||
case []func(View, TouchEvent):
|
|
||||||
if len(value) == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
for _, fn := range value {
|
|
||||||
if fn == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value, true
|
|
||||||
|
|
||||||
case []func(TouchEvent):
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(View, TouchEvent), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
listeners[i] = func(_ View, event TouchEvent) {
|
|
||||||
v(event)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
|
|
||||||
case []func(View):
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(View, TouchEvent), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
listeners[i] = func(view View, _ TouchEvent) {
|
|
||||||
v(view)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
|
|
||||||
case []func():
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(View, TouchEvent), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
listeners[i] = func(View, TouchEvent) {
|
|
||||||
v()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
count := len(value)
|
|
||||||
if count == 0 {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
listeners := make([]func(View, TouchEvent), count)
|
|
||||||
for i, v := range value {
|
|
||||||
if v == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
switch v := v.(type) {
|
|
||||||
case func(View, TouchEvent):
|
|
||||||
listeners[i] = v
|
|
||||||
|
|
||||||
case func(TouchEvent):
|
|
||||||
listeners[i] = func(_ View, event TouchEvent) {
|
|
||||||
v(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
case func(View):
|
|
||||||
listeners[i] = func(view View, _ TouchEvent) {
|
|
||||||
v(view)
|
|
||||||
}
|
|
||||||
|
|
||||||
case func():
|
|
||||||
listeners[i] = func(View, TouchEvent) {
|
|
||||||
v()
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listeners, true
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
var touchEvents = map[string]struct{ jsEvent, jsFunc string }{
|
var touchEvents = map[string]struct{ jsEvent, jsFunc string }{
|
||||||
TouchStart: {jsEvent: "ontouchstart", jsFunc: "touchStartEvent"},
|
TouchStart: {jsEvent: "ontouchstart", jsFunc: "touchStartEvent"},
|
||||||
TouchEnd: {jsEvent: "ontouchend", jsFunc: "touchEndEvent"},
|
TouchEnd: {jsEvent: "ontouchend", jsFunc: "touchEndEvent"},
|
||||||
|
@ -222,8 +97,8 @@ var touchEvents = map[string]struct{ jsEvent, jsFunc string }{
|
||||||
TouchCancel: {jsEvent: "ontouchcancel", jsFunc: "touchCancelEvent"},
|
TouchCancel: {jsEvent: "ontouchcancel", jsFunc: "touchCancelEvent"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *viewData) setTouchListener(tag string, value interface{}) bool {
|
func (view *viewData) setTouchListener(tag string, value any) bool {
|
||||||
listeners, ok := valueToTouchListeners(value)
|
listeners, ok := valueToEventListeners[View, TouchEvent](value)
|
||||||
if !ok {
|
if !ok {
|
||||||
notCompatibleType(tag, value)
|
notCompatibleType(tag, value)
|
||||||
return false
|
return false
|
||||||
|
@ -251,20 +126,6 @@ func (view *viewData) removeTouchListener(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTouchListeners(view View, subviewID string, tag string) []func(View, TouchEvent) {
|
|
||||||
if subviewID != "" {
|
|
||||||
view = ViewByID(view, subviewID)
|
|
||||||
}
|
|
||||||
if view != nil {
|
|
||||||
if value := view.Get(tag); value != nil {
|
|
||||||
if result, ok := value.([]func(View, TouchEvent)); ok {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []func(View, TouchEvent){}
|
|
||||||
}
|
|
||||||
|
|
||||||
func touchEventsHtml(view View, buffer *strings.Builder) {
|
func touchEventsHtml(view View, buffer *strings.Builder) {
|
||||||
for tag, js := range touchEvents {
|
for tag, js := range touchEvents {
|
||||||
if value := view.getRaw(tag); value != nil {
|
if value := view.getRaw(tag); value != nil {
|
||||||
|
@ -309,7 +170,7 @@ func (event *TouchEvent) init(data DataObject) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleTouchEvents(view View, tag string, data DataObject) {
|
func handleTouchEvents(view View, tag string, data DataObject) {
|
||||||
listeners := getTouchListeners(view, "", tag)
|
listeners := getEventListeners[View, TouchEvent](view, nil, tag)
|
||||||
if len(listeners) == 0 {
|
if len(listeners) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -323,25 +184,25 @@ func handleTouchEvents(view View, tag string, data DataObject) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTouchStartListeners returns the "touch-start" listener list. If there are no listeners then the empty list is returned.
|
// GetTouchStartListeners returns the "touch-start" listener list. If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTouchStartListeners(view View, subviewID string) []func(View, TouchEvent) {
|
func GetTouchStartListeners(view View, subviewID ...string) []func(View, TouchEvent) {
|
||||||
return getTouchListeners(view, subviewID, TouchStart)
|
return getEventListeners[View, TouchEvent](view, subviewID, TouchStart)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTouchEndListeners returns the "touch-end" listener list. If there are no listeners then the empty list is returned.
|
// GetTouchEndListeners returns the "touch-end" listener list. If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTouchEndListeners(view View, subviewID string) []func(View, TouchEvent) {
|
func GetTouchEndListeners(view View, subviewID ...string) []func(View, TouchEvent) {
|
||||||
return getTouchListeners(view, subviewID, TouchEnd)
|
return getEventListeners[View, TouchEvent](view, subviewID, TouchEnd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTouchMoveListeners returns the "touch-move" listener list. If there are no listeners then the empty list is returned.
|
// GetTouchMoveListeners returns the "touch-move" listener list. If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTouchMoveListeners(view View, subviewID string) []func(View, TouchEvent) {
|
func GetTouchMoveListeners(view View, subviewID ...string) []func(View, TouchEvent) {
|
||||||
return getTouchListeners(view, subviewID, TouchMove)
|
return getEventListeners[View, TouchEvent](view, subviewID, TouchMove)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTouchCancelListeners returns the "touch-cancel" listener list. If there are no listeners then the empty list is returned.
|
// GetTouchCancelListeners returns the "touch-cancel" listener list. If there are no listeners then the empty list is returned.
|
||||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||||
func GetTouchCancelListeners(view View, subviewID string) []func(View, TouchEvent) {
|
func GetTouchCancelListeners(view View, subviewID ...string) []func(View, TouchEvent) {
|
||||||
return getTouchListeners(view, subviewID, TouchCancel)
|
return getEventListeners[View, TouchEvent](view, subviewID, TouchCancel)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package rui
|
package rui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -30,7 +29,7 @@ type videoPlayerData struct {
|
||||||
// NewVideoPlayer create new MediaPlayer object and return it
|
// NewVideoPlayer create new MediaPlayer object and return it
|
||||||
func NewVideoPlayer(session Session, params Params) VideoPlayer {
|
func NewVideoPlayer(session Session, params Params) VideoPlayer {
|
||||||
view := new(videoPlayerData)
|
view := new(videoPlayerData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
view.tag = "VideoPlayer"
|
view.tag = "VideoPlayer"
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
|
@ -40,8 +39,8 @@ func newVideoPlayer(session Session) View {
|
||||||
return NewVideoPlayer(session, nil)
|
return NewVideoPlayer(session, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (player *videoPlayerData) Init(session Session) {
|
func (player *videoPlayerData) init(session Session) {
|
||||||
player.mediaPlayerData.Init(session)
|
player.mediaPlayerData.init(session)
|
||||||
player.tag = "VideoPlayer"
|
player.tag = "VideoPlayer"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,11 +76,11 @@ func (player *videoPlayerData) remove(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (player *videoPlayerData) Set(tag string, value interface{}) bool {
|
func (player *videoPlayerData) Set(tag string, value any) bool {
|
||||||
return player.set(strings.ToLower(tag), value)
|
return player.set(strings.ToLower(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (player *videoPlayerData) set(tag string, value interface{}) bool {
|
func (player *videoPlayerData) set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
player.remove(tag)
|
player.remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -90,9 +89,9 @@ func (player *videoPlayerData) set(tag string, value interface{}) bool {
|
||||||
if player.mediaPlayerData.set(tag, value) {
|
if player.mediaPlayerData.set(tag, value) {
|
||||||
session := player.Session()
|
session := player.Session()
|
||||||
updateSize := func(cssTag string) {
|
updateSize := func(cssTag string) {
|
||||||
if size, ok := floatProperty(player, tag, session, 0); ok {
|
if size, ok := floatTextProperty(player, tag, session, 0); ok {
|
||||||
if size > 0 {
|
if size != "0" {
|
||||||
updateProperty(player.htmlID(), cssTag, fmt.Sprintf("%g", size), session)
|
updateProperty(player.htmlID(), cssTag, size, session)
|
||||||
} else {
|
} else {
|
||||||
removeProperty(player.htmlID(), cssTag, session)
|
removeProperty(player.htmlID(), cssTag, session)
|
||||||
}
|
}
|
||||||
|
@ -122,12 +121,16 @@ func (player *videoPlayerData) htmlProperties(self View, buffer *strings.Builder
|
||||||
|
|
||||||
session := player.Session()
|
session := player.Session()
|
||||||
|
|
||||||
if size, ok := floatProperty(player, VideoWidth, session, 0); ok && size > 0 {
|
if size, ok := floatTextProperty(player, VideoWidth, session, 0); ok && size != "0" {
|
||||||
buffer.WriteString(fmt.Sprintf(` width="%g"`, size))
|
buffer.WriteString(` width="`)
|
||||||
|
buffer.WriteString(size)
|
||||||
|
buffer.WriteString(`"`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if size, ok := floatProperty(player, VideoHeight, session, 0); ok && size > 0 {
|
if size, ok := floatTextProperty(player, VideoHeight, session, 0); ok && size != "0" {
|
||||||
buffer.WriteString(fmt.Sprintf(` height="%g"`, size))
|
buffer.WriteString(` height="`)
|
||||||
|
buffer.WriteString(size)
|
||||||
|
buffer.WriteString(`"`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if url, ok := stringProperty(player, Poster, session); ok && url != "" {
|
if url, ok := stringProperty(player, Poster, session); ok && url != "" {
|
||||||
|
|
71
view.go
71
view.go
|
@ -33,14 +33,10 @@ type View interface {
|
||||||
ViewStyle
|
ViewStyle
|
||||||
fmt.Stringer
|
fmt.Stringer
|
||||||
|
|
||||||
// Init initializes fields of View by default values
|
|
||||||
Init(session Session)
|
|
||||||
// Session returns the current Session interface
|
// Session returns the current Session interface
|
||||||
Session() Session
|
Session() Session
|
||||||
// Parent returns the parent view
|
// Parent returns the parent view
|
||||||
Parent() View
|
Parent() View
|
||||||
parentHTMLID() string
|
|
||||||
setParentID(parentID string)
|
|
||||||
// Tag returns the tag of View interface
|
// Tag returns the tag of View interface
|
||||||
Tag() string
|
Tag() string
|
||||||
// ID returns the id of the view
|
// ID returns the id of the view
|
||||||
|
@ -54,7 +50,7 @@ type View interface {
|
||||||
// SetAnimated sets the value (second argument) of the property with name defined by the first argument.
|
// SetAnimated sets the value (second argument) of the property with name defined by the first argument.
|
||||||
// Return "true" if the value has been set, in the opposite case "false" are returned and
|
// Return "true" if the value has been set, in the opposite case "false" are returned and
|
||||||
// a description of the error is written to the log
|
// a description of the error is written to the log
|
||||||
SetAnimated(tag string, value interface{}, animation Animation) bool
|
SetAnimated(tag string, value any, animation Animation) bool
|
||||||
// SetChangeListener set the function to track the change of the View property
|
// SetChangeListener set the function to track the change of the View property
|
||||||
SetChangeListener(tag string, listener func(View, string))
|
SetChangeListener(tag string, listener func(View, string))
|
||||||
// HasFocus returns 'true' if the view has focus
|
// HasFocus returns 'true' if the view has focus
|
||||||
|
@ -65,14 +61,14 @@ type View interface {
|
||||||
htmlTag() string
|
htmlTag() string
|
||||||
closeHTMLTag() bool
|
closeHTMLTag() bool
|
||||||
htmlID() string
|
htmlID() string
|
||||||
|
parentHTMLID() string
|
||||||
|
setParentID(parentID string)
|
||||||
htmlSubviews(self View, buffer *strings.Builder)
|
htmlSubviews(self View, buffer *strings.Builder)
|
||||||
htmlProperties(self View, buffer *strings.Builder)
|
htmlProperties(self View, buffer *strings.Builder)
|
||||||
htmlDisabledProperties(self View, buffer *strings.Builder)
|
htmlDisabledProperties(self View, buffer *strings.Builder)
|
||||||
cssStyle(self View, builder cssBuilder)
|
cssStyle(self View, builder cssBuilder)
|
||||||
addToCSSStyle(addCSS map[string]string)
|
addToCSSStyle(addCSS map[string]string)
|
||||||
|
|
||||||
getTransitions() Params
|
|
||||||
|
|
||||||
onResize(self View, x, y, width, height float64)
|
onResize(self View, x, y, width, height float64)
|
||||||
onItemResize(self View, index string, x, y, width, height float64)
|
onItemResize(self View, index string, x, y, width, height float64)
|
||||||
setNoResizeEvent()
|
setNoResizeEvent()
|
||||||
|
@ -102,7 +98,7 @@ type viewData struct {
|
||||||
|
|
||||||
func newView(session Session) View {
|
func newView(session Session) View {
|
||||||
view := new(viewData)
|
view := new(viewData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,12 +120,12 @@ func setInitParams(view View, params Params) {
|
||||||
// NewView create new View object and return it
|
// NewView create new View object and return it
|
||||||
func NewView(session Session, params Params) View {
|
func NewView(session Session, params Params) View {
|
||||||
view := new(viewData)
|
view := new(viewData)
|
||||||
view.Init(session)
|
view.init(session)
|
||||||
setInitParams(view, params)
|
setInitParams(view, params)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *viewData) Init(session Session) {
|
func (view *viewData) init(session Session) {
|
||||||
view.viewStyle.init()
|
view.viewStyle.init()
|
||||||
view.tag = "View"
|
view.tag = "View"
|
||||||
view.session = session
|
view.session = session
|
||||||
|
@ -197,7 +193,7 @@ func (view *viewData) remove(tag string) {
|
||||||
case Style, StyleDisabled:
|
case Style, StyleDisabled:
|
||||||
if _, ok := view.properties[tag]; ok {
|
if _, ok := view.properties[tag]; ok {
|
||||||
delete(view.properties, tag)
|
delete(view.properties, tag)
|
||||||
updateProperty(view.htmlID(), "class", view.htmlClass(IsDisabled(view, "")), view.session)
|
updateProperty(view.htmlID(), "class", view.htmlClass(IsDisabled(view)), view.session)
|
||||||
}
|
}
|
||||||
|
|
||||||
case FocusEvent, LostFocusEvent:
|
case FocusEvent, LostFocusEvent:
|
||||||
|
@ -290,11 +286,11 @@ func (view *viewData) propertyChangedEvent(tag string) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *viewData) Set(tag string, value interface{}) bool {
|
func (view *viewData) Set(tag string, value any) bool {
|
||||||
return view.set(strings.ToLower(tag), value)
|
return view.set(strings.ToLower(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *viewData) set(tag string, value interface{}) bool {
|
func (view *viewData) set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
view.remove(tag)
|
view.remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -327,7 +323,7 @@ func (view *viewData) set(tag string, value interface{}) bool {
|
||||||
}
|
}
|
||||||
view.properties[tag] = text
|
view.properties[tag] = text
|
||||||
if view.created {
|
if view.created {
|
||||||
updateProperty(view.htmlID(), "class", view.htmlClass(IsDisabled(view, "")), view.session)
|
updateProperty(view.htmlID(), "class", view.htmlClass(IsDisabled(view)), view.session)
|
||||||
}
|
}
|
||||||
|
|
||||||
case FocusEvent, LostFocusEvent:
|
case FocusEvent, LostFocusEvent:
|
||||||
|
@ -381,7 +377,7 @@ func viewPropertyChanged(view *viewData, tag string) {
|
||||||
return
|
return
|
||||||
|
|
||||||
case Visibility:
|
case Visibility:
|
||||||
switch GetVisibility(view, "") {
|
switch GetVisibility(view) {
|
||||||
case Invisible:
|
case Invisible:
|
||||||
updateCSSProperty(htmlID, Visibility, "hidden", session)
|
updateCSSProperty(htmlID, Visibility, "hidden", session)
|
||||||
updateCSSProperty(htmlID, "display", "", session)
|
updateCSSProperty(htmlID, "display", "", session)
|
||||||
|
@ -450,7 +446,7 @@ func viewPropertyChanged(view *viewData, tag string) {
|
||||||
return
|
return
|
||||||
|
|
||||||
case Outline, OutlineColor, OutlineStyle, OutlineWidth:
|
case Outline, OutlineColor, OutlineStyle, OutlineWidth:
|
||||||
updateCSSProperty(htmlID, Outline, GetOutline(view, "").cssString(), session)
|
updateCSSProperty(htmlID, Outline, GetOutline(view).cssString(session), session)
|
||||||
return
|
return
|
||||||
|
|
||||||
case Shadow:
|
case Shadow:
|
||||||
|
@ -465,20 +461,20 @@ func viewPropertyChanged(view *viewData, tag string) {
|
||||||
RadiusTopRight, RadiusTopRightX, RadiusTopRightY,
|
RadiusTopRight, RadiusTopRightX, RadiusTopRightY,
|
||||||
RadiusBottomLeft, RadiusBottomLeftX, RadiusBottomLeftY,
|
RadiusBottomLeft, RadiusBottomLeftX, RadiusBottomLeftY,
|
||||||
RadiusBottomRight, RadiusBottomRightX, RadiusBottomRightY:
|
RadiusBottomRight, RadiusBottomRightX, RadiusBottomRightY:
|
||||||
radius := GetRadius(view, "")
|
radius := GetRadius(view)
|
||||||
updateCSSProperty(htmlID, "border-radius", radius.cssString(), session)
|
updateCSSProperty(htmlID, "border-radius", radius.cssString(session), session)
|
||||||
return
|
return
|
||||||
|
|
||||||
case Margin, MarginTop, MarginRight, MarginBottom, MarginLeft,
|
case Margin, MarginTop, MarginRight, MarginBottom, MarginLeft,
|
||||||
"top-margin", "right-margin", "bottom-margin", "left-margin":
|
"top-margin", "right-margin", "bottom-margin", "left-margin":
|
||||||
margin := GetMargin(view, "")
|
margin := GetMargin(view)
|
||||||
updateCSSProperty(htmlID, Margin, margin.cssString(), session)
|
updateCSSProperty(htmlID, Margin, margin.cssString(session), session)
|
||||||
return
|
return
|
||||||
|
|
||||||
case Padding, PaddingTop, PaddingRight, PaddingBottom, PaddingLeft,
|
case Padding, PaddingTop, PaddingRight, PaddingBottom, PaddingLeft,
|
||||||
"top-padding", "right-padding", "bottom-padding", "left-padding":
|
"top-padding", "right-padding", "bottom-padding", "left-padding":
|
||||||
padding := GetPadding(view, "")
|
padding := GetPadding(view)
|
||||||
updateCSSProperty(htmlID, Padding, padding.cssString(), session)
|
updateCSSProperty(htmlID, Padding, padding.cssString(session), session)
|
||||||
return
|
return
|
||||||
|
|
||||||
case AvoidBreak:
|
case AvoidBreak:
|
||||||
|
@ -593,9 +589,9 @@ func viewPropertyChanged(view *viewData, tag string) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
||||||
case ZIndex:
|
case ZIndex, TabSize:
|
||||||
if i, ok := intProperty(view, ZIndex, session, 0); ok {
|
if i, ok := intProperty(view, tag, session, 0); ok {
|
||||||
updateCSSProperty(htmlID, ZIndex, strconv.Itoa(i), session)
|
updateCSSProperty(htmlID, tag, strconv.Itoa(i), session)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -630,7 +626,7 @@ func viewPropertyChanged(view *viewData, tag string) {
|
||||||
|
|
||||||
if cssTag, ok := sizeProperties[tag]; ok {
|
if cssTag, ok := sizeProperties[tag]; ok {
|
||||||
size, _ := sizeProperty(view, tag, session)
|
size, _ := sizeProperty(view, tag, session)
|
||||||
updateCSSProperty(htmlID, cssTag, size.cssString(""), session)
|
updateCSSProperty(htmlID, cssTag, size.cssString("", session), session)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,6 +635,7 @@ func viewPropertyChanged(view *viewData, tag string) {
|
||||||
TextColor: "color",
|
TextColor: "color",
|
||||||
TextLineColor: "text-decoration-color",
|
TextLineColor: "text-decoration-color",
|
||||||
CaretColor: CaretColor,
|
CaretColor: CaretColor,
|
||||||
|
AccentColor: AccentColor,
|
||||||
}
|
}
|
||||||
if cssTag, ok := colorTags[tag]; ok {
|
if cssTag, ok := colorTags[tag]; ok {
|
||||||
if color, ok := colorProperty(view, tag, session); ok {
|
if color, ok := colorProperty(view, tag, session); ok {
|
||||||
|
@ -657,19 +654,19 @@ func viewPropertyChanged(view *viewData, tag string) {
|
||||||
|
|
||||||
for _, floatTag := range []string{Opacity, ScaleX, ScaleY, ScaleZ, RotateX, RotateY, RotateZ} {
|
for _, floatTag := range []string{Opacity, ScaleX, ScaleY, ScaleZ, RotateX, RotateY, RotateZ} {
|
||||||
if tag == floatTag {
|
if tag == floatTag {
|
||||||
if f, ok := floatProperty(view, floatTag, session, 0); ok {
|
if f, ok := floatTextProperty(view, floatTag, session, 0); ok {
|
||||||
updateCSSProperty(htmlID, floatTag, strconv.FormatFloat(f, 'g', -1, 64), session)
|
updateCSSProperty(htmlID, floatTag, f, session)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *viewData) Get(tag string) interface{} {
|
func (view *viewData) Get(tag string) any {
|
||||||
return view.get(strings.ToLower(tag))
|
return view.get(strings.ToLower(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *viewData) get(tag string) interface{} {
|
func (view *viewData) get(tag string) any {
|
||||||
if tag == ID {
|
if tag == ID {
|
||||||
if view.viewID != "" {
|
if view.viewID != "" {
|
||||||
return view.viewID
|
return view.viewID
|
||||||
|
@ -681,7 +678,7 @@ func (view *viewData) get(tag string) interface{} {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *viewData) htmlTag() string {
|
func (view *viewData) htmlTag() string {
|
||||||
if semantics := GetSemantics(view, ""); semantics > DefaultSemantics {
|
if semantics := GetSemantics(view); semantics > DefaultSemantics {
|
||||||
values := enumProperties[Semantics].cssValues
|
values := enumProperties[Semantics].cssValues
|
||||||
if semantics < len(values) {
|
if semantics < len(values) {
|
||||||
return values[semantics]
|
return values[semantics]
|
||||||
|
@ -710,7 +707,7 @@ func (view *viewData) addToCSSStyle(addCSS map[string]string) {
|
||||||
|
|
||||||
func (view *viewData) cssStyle(self View, builder cssBuilder) {
|
func (view *viewData) cssStyle(self View, builder cssBuilder) {
|
||||||
view.viewStyle.cssViewStyle(builder, view.session)
|
view.viewStyle.cssViewStyle(builder, view.session)
|
||||||
switch GetVisibility(view, "") {
|
switch GetVisibility(view) {
|
||||||
case Invisible:
|
case Invisible:
|
||||||
builder.add(`visibility`, `hidden`)
|
builder.add(`visibility`, `hidden`)
|
||||||
|
|
||||||
|
@ -734,7 +731,7 @@ func (view *viewData) htmlProperties(self View, buffer *strings.Builder) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *viewData) htmlDisabledProperties(self View, buffer *strings.Builder) {
|
func (view *viewData) htmlDisabledProperties(self View, buffer *strings.Builder) {
|
||||||
if IsDisabled(self, "") {
|
if IsDisabled(self) {
|
||||||
buffer.WriteString(` data-disabled="1"`)
|
buffer.WriteString(` data-disabled="1"`)
|
||||||
} else {
|
} else {
|
||||||
buffer.WriteString(` data-disabled="0"`)
|
buffer.WriteString(` data-disabled="0"`)
|
||||||
|
@ -749,7 +746,7 @@ func viewHTML(view View, buffer *strings.Builder) {
|
||||||
buffer.WriteString(view.htmlID())
|
buffer.WriteString(view.htmlID())
|
||||||
buffer.WriteRune('"')
|
buffer.WriteRune('"')
|
||||||
|
|
||||||
disabled := IsDisabled(view, "")
|
disabled := IsDisabled(view)
|
||||||
|
|
||||||
if cls := view.htmlClass(disabled); cls != "" {
|
if cls := view.htmlClass(disabled); cls != "" {
|
||||||
buffer.WriteString(` class="`)
|
buffer.WriteString(` class="`)
|
||||||
|
@ -826,7 +823,7 @@ func (view *viewData) handleCommand(self View, command string, data DataObject)
|
||||||
switch command {
|
switch command {
|
||||||
|
|
||||||
case KeyDownEvent, KeyUpEvent:
|
case KeyDownEvent, KeyUpEvent:
|
||||||
if !IsDisabled(self, "") {
|
if !IsDisabled(self) {
|
||||||
handleKeyEvents(self, command, data)
|
handleKeyEvents(self, command, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -841,13 +838,13 @@ func (view *viewData) handleCommand(self View, command string, data DataObject)
|
||||||
|
|
||||||
case FocusEvent:
|
case FocusEvent:
|
||||||
view.hasFocus = true
|
view.hasFocus = true
|
||||||
for _, listener := range getFocusListeners(view, "", command) {
|
for _, listener := range getFocusListeners(view, nil, command) {
|
||||||
listener(self)
|
listener(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
case LostFocusEvent:
|
case LostFocusEvent:
|
||||||
view.hasFocus = false
|
view.hasFocus = false
|
||||||
for _, listener := range getFocusListeners(view, "", command) {
|
for _, listener := range getFocusListeners(view, nil, command) {
|
||||||
listener(self)
|
listener(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
76
viewClip.go
76
viewClip.go
|
@ -27,7 +27,7 @@ type circleClip struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type polygonClip struct {
|
type polygonClip struct {
|
||||||
points []interface{}
|
points []any
|
||||||
}
|
}
|
||||||
|
|
||||||
// InsetClip creates a rectangle View clipping area.
|
// InsetClip creates a rectangle View clipping area.
|
||||||
|
@ -73,9 +73,9 @@ func EllipseClip(x, y, rx, ry SizeUnit) ClipShape {
|
||||||
// PolygonClip creates a polygon View clipping area.
|
// PolygonClip creates a polygon View clipping area.
|
||||||
// The elements of the function argument can be or text constants,
|
// The elements of the function argument can be or text constants,
|
||||||
// or the text representation of SizeUnit, or elements of SizeUnit type.
|
// or the text representation of SizeUnit, or elements of SizeUnit type.
|
||||||
func PolygonClip(points []interface{}) ClipShape {
|
func PolygonClip(points []any) ClipShape {
|
||||||
clip := new(polygonClip)
|
clip := new(polygonClip)
|
||||||
clip.points = []interface{}{}
|
clip.points = []any{}
|
||||||
if clip.Set(Points, points) {
|
if clip.Set(Points, points) {
|
||||||
return clip
|
return clip
|
||||||
}
|
}
|
||||||
|
@ -85,14 +85,14 @@ func PolygonClip(points []interface{}) ClipShape {
|
||||||
// PolygonPointsClip creates a polygon View clipping area.
|
// PolygonPointsClip creates a polygon View clipping area.
|
||||||
func PolygonPointsClip(points []SizeUnit) ClipShape {
|
func PolygonPointsClip(points []SizeUnit) ClipShape {
|
||||||
clip := new(polygonClip)
|
clip := new(polygonClip)
|
||||||
clip.points = []interface{}{}
|
clip.points = []any{}
|
||||||
if clip.Set(Points, points) {
|
if clip.Set(Points, points) {
|
||||||
return clip
|
return clip
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (clip *insetClip) Set(tag string, value interface{}) bool {
|
func (clip *insetClip) Set(tag string, value any) bool {
|
||||||
switch strings.ToLower(tag) {
|
switch strings.ToLower(tag) {
|
||||||
case Top, Right, Bottom, Left:
|
case Top, Right, Bottom, Left:
|
||||||
if value == nil {
|
if value == nil {
|
||||||
|
@ -146,13 +146,13 @@ func (clip *insetClip) cssStyle(session Session) string {
|
||||||
for _, tag := range []string{Top, Right, Bottom, Left} {
|
for _, tag := range []string{Top, Right, Bottom, Left} {
|
||||||
value, _ := sizeProperty(clip, tag, session)
|
value, _ := sizeProperty(clip, tag, session)
|
||||||
buffer.WriteString(leadText)
|
buffer.WriteString(leadText)
|
||||||
buffer.WriteString(value.cssString("0px"))
|
buffer.WriteString(value.cssString("0px", session))
|
||||||
leadText = " "
|
leadText = " "
|
||||||
}
|
}
|
||||||
|
|
||||||
if radius := getRadiusProperty(clip); radius != nil {
|
if radius := getRadiusProperty(clip); radius != nil {
|
||||||
buffer.WriteString(" round ")
|
buffer.WriteString(" round ")
|
||||||
buffer.WriteString(radius.BoxRadius(session).cssString())
|
buffer.WriteString(radius.BoxRadius(session).cssString(session))
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.WriteRune(')')
|
buffer.WriteRune(')')
|
||||||
|
@ -168,7 +168,7 @@ func (clip *insetClip) valid(session Session) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (clip *circleClip) Set(tag string, value interface{}) bool {
|
func (clip *circleClip) Set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
clip.Remove(tag)
|
clip.Remove(tag)
|
||||||
}
|
}
|
||||||
|
@ -211,15 +211,15 @@ func (clip *circleClip) cssStyle(session Session) string {
|
||||||
|
|
||||||
buffer.WriteString("circle(")
|
buffer.WriteString("circle(")
|
||||||
r, _ := sizeProperty(clip, Radius, session)
|
r, _ := sizeProperty(clip, Radius, session)
|
||||||
buffer.WriteString(r.cssString("50%"))
|
buffer.WriteString(r.cssString("50%", session))
|
||||||
|
|
||||||
buffer.WriteString(" at ")
|
buffer.WriteString(" at ")
|
||||||
x, _ := sizeProperty(clip, X, session)
|
x, _ := sizeProperty(clip, X, session)
|
||||||
buffer.WriteString(x.cssString("50%"))
|
buffer.WriteString(x.cssString("50%", session))
|
||||||
buffer.WriteRune(' ')
|
buffer.WriteRune(' ')
|
||||||
|
|
||||||
y, _ := sizeProperty(clip, Y, session)
|
y, _ := sizeProperty(clip, Y, session)
|
||||||
buffer.WriteString(y.cssString("50%"))
|
buffer.WriteString(y.cssString("50%", session))
|
||||||
buffer.WriteRune(')')
|
buffer.WriteRune(')')
|
||||||
|
|
||||||
return buffer.String()
|
return buffer.String()
|
||||||
|
@ -232,7 +232,7 @@ func (clip *circleClip) valid(session Session) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (clip *ellipseClip) Set(tag string, value interface{}) bool {
|
func (clip *ellipseClip) Set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
clip.Remove(tag)
|
clip.Remove(tag)
|
||||||
}
|
}
|
||||||
|
@ -280,17 +280,17 @@ func (clip *ellipseClip) cssStyle(session Session) string {
|
||||||
rx, _ := sizeProperty(clip, RadiusX, session)
|
rx, _ := sizeProperty(clip, RadiusX, session)
|
||||||
ry, _ := sizeProperty(clip, RadiusX, session)
|
ry, _ := sizeProperty(clip, RadiusX, session)
|
||||||
buffer.WriteString("ellipse(")
|
buffer.WriteString("ellipse(")
|
||||||
buffer.WriteString(rx.cssString("50%"))
|
buffer.WriteString(rx.cssString("50%", session))
|
||||||
buffer.WriteRune(' ')
|
buffer.WriteRune(' ')
|
||||||
buffer.WriteString(ry.cssString("50%"))
|
buffer.WriteString(ry.cssString("50%", session))
|
||||||
|
|
||||||
buffer.WriteString(" at ")
|
buffer.WriteString(" at ")
|
||||||
x, _ := sizeProperty(clip, X, session)
|
x, _ := sizeProperty(clip, X, session)
|
||||||
buffer.WriteString(x.cssString("50%"))
|
buffer.WriteString(x.cssString("50%", session))
|
||||||
buffer.WriteRune(' ')
|
buffer.WriteRune(' ')
|
||||||
|
|
||||||
y, _ := sizeProperty(clip, Y, session)
|
y, _ := sizeProperty(clip, Y, session)
|
||||||
buffer.WriteString(y.cssString("50%"))
|
buffer.WriteString(y.cssString("50%", session))
|
||||||
buffer.WriteRune(')')
|
buffer.WriteRune(')')
|
||||||
|
|
||||||
return buffer.String()
|
return buffer.String()
|
||||||
|
@ -302,23 +302,23 @@ func (clip *ellipseClip) valid(session Session) bool {
|
||||||
return rx.Value != 0 && ry.Value != 0
|
return rx.Value != 0 && ry.Value != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (clip *polygonClip) Get(tag string) interface{} {
|
func (clip *polygonClip) Get(tag string) any {
|
||||||
if Points == strings.ToLower(tag) {
|
if Points == strings.ToLower(tag) {
|
||||||
return clip.points
|
return clip.points
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (clip *polygonClip) getRaw(tag string) interface{} {
|
func (clip *polygonClip) getRaw(tag string) any {
|
||||||
return clip.Get(tag)
|
return clip.Get(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (clip *polygonClip) Set(tag string, value interface{}) bool {
|
func (clip *polygonClip) Set(tag string, value any) bool {
|
||||||
if Points == strings.ToLower(tag) {
|
if Points == strings.ToLower(tag) {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case []interface{}:
|
case []any:
|
||||||
result := true
|
result := true
|
||||||
clip.points = make([]interface{}, len(value))
|
clip.points = make([]any, len(value))
|
||||||
for i, val := range value {
|
for i, val := range value {
|
||||||
switch val := val.(type) {
|
switch val := val.(type) {
|
||||||
case string:
|
case string:
|
||||||
|
@ -343,7 +343,7 @@ func (clip *polygonClip) Set(tag string, value interface{}) bool {
|
||||||
return result
|
return result
|
||||||
|
|
||||||
case []SizeUnit:
|
case []SizeUnit:
|
||||||
clip.points = make([]interface{}, len(value))
|
clip.points = make([]any, len(value))
|
||||||
for i, point := range value {
|
for i, point := range value {
|
||||||
clip.points[i] = point
|
clip.points[i] = point
|
||||||
}
|
}
|
||||||
|
@ -352,7 +352,7 @@ func (clip *polygonClip) Set(tag string, value interface{}) bool {
|
||||||
case string:
|
case string:
|
||||||
result := true
|
result := true
|
||||||
values := strings.Split(value, ",")
|
values := strings.Split(value, ",")
|
||||||
clip.points = make([]interface{}, len(values))
|
clip.points = make([]any, len(values))
|
||||||
for i, val := range values {
|
for i, val := range values {
|
||||||
val = strings.Trim(val, " \t\n\r")
|
val = strings.Trim(val, " \t\n\r")
|
||||||
if isConstantName(val) {
|
if isConstantName(val) {
|
||||||
|
@ -370,18 +370,18 @@ func (clip *polygonClip) Set(tag string, value interface{}) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (clip *polygonClip) setRaw(tag string, value interface{}) {
|
func (clip *polygonClip) setRaw(tag string, value any) {
|
||||||
clip.Set(tag, value)
|
clip.Set(tag, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (clip *polygonClip) Remove(tag string) {
|
func (clip *polygonClip) Remove(tag string) {
|
||||||
if Points == strings.ToLower(tag) {
|
if Points == strings.ToLower(tag) {
|
||||||
clip.points = []interface{}{}
|
clip.points = []any{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (clip *polygonClip) Clear() {
|
func (clip *polygonClip) Clear() {
|
||||||
clip.points = []interface{}{}
|
clip.points = []any{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (clip *polygonClip) AllTags() []string {
|
func (clip *polygonClip) AllTags() []string {
|
||||||
|
@ -422,18 +422,18 @@ func (clip *polygonClip) cssStyle(session Session) string {
|
||||||
buffer := allocStringBuilder()
|
buffer := allocStringBuilder()
|
||||||
defer freeStringBuilder(buffer)
|
defer freeStringBuilder(buffer)
|
||||||
|
|
||||||
writePoint := func(value interface{}) {
|
writePoint := func(value any) {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case string:
|
case string:
|
||||||
if val, ok := session.resolveConstants(value); ok {
|
if val, ok := session.resolveConstants(value); ok {
|
||||||
if size, ok := StringToSizeUnit(val); ok {
|
if size, ok := StringToSizeUnit(val); ok {
|
||||||
buffer.WriteString(size.cssString("0px"))
|
buffer.WriteString(size.cssString("0px", session))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case SizeUnit:
|
case SizeUnit:
|
||||||
buffer.WriteString(value.cssString("0px"))
|
buffer.WriteString(value.cssString("0px", session))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -501,7 +501,7 @@ func parseClipShape(obj DataObject) ClipShape {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (style *viewStyle) setClipShape(tag string, value interface{}) bool {
|
func (style *viewStyle) setClipShape(tag string, value any) bool {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case ClipShape:
|
case ClipShape:
|
||||||
style.properties[tag] = value
|
style.properties[tag] = value
|
||||||
|
@ -558,10 +558,10 @@ func getClipShape(prop Properties, tag string, session Session) ClipShape {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetClip returns a View clipping area.
|
// GetClip returns a View clipping area.
|
||||||
// If the second argument (subviewID) is "" then a top position of the first argument (view) is returned
|
// If the second argument (subviewID) is not specified or it is "" then a top position of the first argument (view) is returned
|
||||||
func GetClip(view View, subviewID string) ClipShape {
|
func GetClip(view View, subviewID ...string) ClipShape {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view != nil {
|
if view != nil {
|
||||||
return getClipShape(view, Clip, view.Session())
|
return getClipShape(view, Clip, view.Session())
|
||||||
|
@ -571,10 +571,10 @@ func GetClip(view View, subviewID string) ClipShape {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetShapeOutside returns a shape around which adjacent inline content.
|
// GetShapeOutside returns a shape around which adjacent inline content.
|
||||||
// If the second argument (subviewID) is "" then a top position of the first argument (view) is returned
|
// If the second argument (subviewID) is not specified or it is "" then a top position of the first argument (view) is returned
|
||||||
func GetShapeOutside(view View, subviewID string) ClipShape {
|
func GetShapeOutside(view View, subviewID ...string) ClipShape {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
if view != nil {
|
if view != nil {
|
||||||
return getClipShape(view, ShapeOutside, view.Session())
|
return getClipShape(view, ShapeOutside, view.Session())
|
||||||
|
|
|
@ -130,7 +130,7 @@ func newViewFilter(obj DataObject) ViewFilter {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (filter *viewFilter) Set(tag string, value interface{}) bool {
|
func (filter *viewFilter) Set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
filter.Remove(tag)
|
filter.Remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -180,20 +180,22 @@ func (filter *viewFilter) cssStyle(session Session) string {
|
||||||
buffer := allocStringBuilder()
|
buffer := allocStringBuilder()
|
||||||
defer freeStringBuilder(buffer)
|
defer freeStringBuilder(buffer)
|
||||||
|
|
||||||
if value, ok := floatProperty(filter, Blur, session, 0); ok {
|
if value, ok := floatTextProperty(filter, Blur, session, 0); ok {
|
||||||
size := SizeUnit{Type: SizeInPixel, Value: value}
|
|
||||||
buffer.WriteString(Blur)
|
buffer.WriteString(Blur)
|
||||||
buffer.WriteRune('(')
|
buffer.WriteRune('(')
|
||||||
buffer.WriteString(size.cssString("0px"))
|
buffer.WriteString(value)
|
||||||
buffer.WriteRune(')')
|
buffer.WriteString("px)")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tag := range []string{Brightness, Contrast, Saturate, Grayscale, Invert, Opacity, Sepia} {
|
for _, tag := range []string{Brightness, Contrast, Saturate, Grayscale, Invert, Opacity, Sepia} {
|
||||||
if value, ok := floatProperty(filter, tag, session, 0); ok {
|
if value, ok := floatTextProperty(filter, tag, session, 0); ok {
|
||||||
if buffer.Len() > 0 {
|
if buffer.Len() > 0 {
|
||||||
buffer.WriteRune(' ')
|
buffer.WriteRune(' ')
|
||||||
}
|
}
|
||||||
buffer.WriteString(fmt.Sprintf("%s(%g%%)", tag, value))
|
buffer.WriteString(tag)
|
||||||
|
buffer.WriteRune('(')
|
||||||
|
buffer.WriteString(value)
|
||||||
|
buffer.WriteString("%)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,7 +226,7 @@ func (filter *viewFilter) cssStyle(session Session) string {
|
||||||
return buffer.String()
|
return buffer.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (style *viewStyle) setFilter(tag string, value interface{}) bool {
|
func (style *viewStyle) setFilter(tag string, value any) bool {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case ViewFilter:
|
case ViewFilter:
|
||||||
style.properties[tag] = value
|
style.properties[tag] = value
|
||||||
|
@ -257,34 +259,46 @@ func (style *viewStyle) setFilter(tag string, value interface{}) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFilter returns a View graphical effects like blur or color shift.
|
// GetFilter returns a View graphical effects like blur or color shift.
|
||||||
// If the second argument (subviewID) is "" then a top position of the first argument (view) is returned
|
// 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 {
|
func GetFilter(view View, subviewID ...string) ViewFilter {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
if view != nil {
|
if view != nil {
|
||||||
if value := view.getRaw(Filter); value != nil {
|
if value := view.getRaw(Filter); value != nil {
|
||||||
if filter, ok := value.(ViewFilter); ok {
|
if filter, ok := value.(ViewFilter); ok {
|
||||||
return filter
|
return filter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if value := valueFromStyle(view, Filter); value != nil {
|
||||||
|
if filter, ok := value.(ViewFilter); ok {
|
||||||
|
return filter
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBackdropFilter returns the area behind a View graphical effects like blur or color shift.
|
// GetBackdropFilter returns the area behind a View graphical effects like blur or color shift.
|
||||||
// If the second argument (subviewID) is "" then a top position of the first argument (view) is returned
|
// 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 {
|
func GetBackdropFilter(view View, subviewID ...string) ViewFilter {
|
||||||
if subviewID != "" {
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
if view != nil {
|
if view != nil {
|
||||||
if value := view.getRaw(BackdropFilter); value != nil {
|
if value := view.getRaw(BackdropFilter); value != nil {
|
||||||
if filter, ok := value.(ViewFilter); ok {
|
if filter, ok := value.(ViewFilter); ok {
|
||||||
return filter
|
return filter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if value := valueFromStyle(view, BackdropFilter); value != nil {
|
||||||
|
if filter, ok := value.(ViewFilter); ok {
|
||||||
|
return filter
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
60
viewStyle.go
60
viewStyle.go
|
@ -10,6 +10,16 @@ import (
|
||||||
// ViewStyle interface of the style of view
|
// ViewStyle interface of the style of view
|
||||||
type ViewStyle interface {
|
type ViewStyle interface {
|
||||||
Properties
|
Properties
|
||||||
|
|
||||||
|
// Transition returns the transition animation of the property. Returns nil is there is no transition animation.
|
||||||
|
Transition(tag string) Animation
|
||||||
|
// Transitions returns the map of transition animations. The result is always non-nil.
|
||||||
|
Transitions() map[string]Animation
|
||||||
|
// SetTransition sets the transition animation for the property if "animation" argument is not nil, and
|
||||||
|
// removes the transition animation of the property if "animation" argument is nil.
|
||||||
|
// The "tag" argument is the property name.
|
||||||
|
SetTransition(tag string, animation Animation)
|
||||||
|
|
||||||
cssViewStyle(buffer cssBuilder, session Session)
|
cssViewStyle(buffer cssBuilder, session Session)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,11 +173,11 @@ func (style *viewStyle) backgroundCSS(session Session) string {
|
||||||
func (style *viewStyle) cssViewStyle(builder cssBuilder, session Session) {
|
func (style *viewStyle) cssViewStyle(builder cssBuilder, session Session) {
|
||||||
|
|
||||||
if margin, ok := boundsProperty(style, Margin, session); ok {
|
if margin, ok := boundsProperty(style, Margin, session); ok {
|
||||||
margin.cssValue(Margin, builder)
|
margin.cssValue(Margin, builder, session)
|
||||||
}
|
}
|
||||||
|
|
||||||
if padding, ok := boundsProperty(style, Padding, session); ok {
|
if padding, ok := boundsProperty(style, Padding, session); ok {
|
||||||
padding.cssValue(Padding, builder)
|
padding.cssValue(Padding, builder, session)
|
||||||
}
|
}
|
||||||
|
|
||||||
if border := getBorder(style, Border); border != nil {
|
if border := getBorder(style, Border); border != nil {
|
||||||
|
@ -177,10 +187,10 @@ func (style *viewStyle) cssViewStyle(builder cssBuilder, session Session) {
|
||||||
}
|
}
|
||||||
|
|
||||||
radius := getRadius(style, session)
|
radius := getRadius(style, session)
|
||||||
radius.cssValue(builder)
|
radius.cssValue(builder, session)
|
||||||
|
|
||||||
if outline := getOutline(style); outline != nil {
|
if outline := getOutline(style); outline != nil {
|
||||||
outline.ViewOutline(session).cssValue(builder)
|
outline.ViewOutline(session).cssValue(builder, session)
|
||||||
}
|
}
|
||||||
|
|
||||||
if z, ok := intProperty(style, ZIndex, session, 0); ok {
|
if z, ok := intProperty(style, ZIndex, session, 0); ok {
|
||||||
|
@ -198,14 +208,14 @@ func (style *viewStyle) cssViewStyle(builder cssBuilder, session Session) {
|
||||||
for _, tag := range []string{
|
for _, tag := range []string{
|
||||||
Width, Height, MinWidth, MinHeight, MaxWidth, MaxHeight, Left, Right, Top, Bottom,
|
Width, Height, MinWidth, MinHeight, MaxWidth, MaxHeight, Left, Right, Top, Bottom,
|
||||||
TextSize, TextIndent, LetterSpacing, WordSpacing, LineHeight, TextLineThickness,
|
TextSize, TextIndent, LetterSpacing, WordSpacing, LineHeight, TextLineThickness,
|
||||||
GridRowGap, GridColumnGap, ColumnGap, ColumnWidth} {
|
ListRowGap, ListColumnGap, GridRowGap, GridColumnGap, ColumnGap, ColumnWidth} {
|
||||||
|
|
||||||
if size, ok := sizeProperty(style, tag, session); ok && size.Type != Auto {
|
if size, ok := sizeProperty(style, tag, session); ok && size.Type != Auto {
|
||||||
cssTag, ok := sizeProperties[tag]
|
cssTag, ok := sizeProperties[tag]
|
||||||
if !ok {
|
if !ok {
|
||||||
cssTag = tag
|
cssTag = tag
|
||||||
}
|
}
|
||||||
builder.add(cssTag, size.cssString(""))
|
builder.add(cssTag, size.cssString("", session))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,6 +224,7 @@ func (style *viewStyle) cssViewStyle(builder cssBuilder, session Session) {
|
||||||
{TextColor, "color"},
|
{TextColor, "color"},
|
||||||
{TextLineColor, "text-decoration-color"},
|
{TextLineColor, "text-decoration-color"},
|
||||||
{CaretColor, CaretColor},
|
{CaretColor, CaretColor},
|
||||||
|
{AccentColor, AccentColor},
|
||||||
}
|
}
|
||||||
for _, p := range colorProperties {
|
for _, p := range colorProperties {
|
||||||
if color, ok := colorProperty(style, p.property, session); ok && color != 0 {
|
if color, ok := colorProperty(style, p.property, session); ok && color != 0 {
|
||||||
|
@ -235,7 +246,7 @@ func (style *viewStyle) cssViewStyle(builder cssBuilder, session Session) {
|
||||||
|
|
||||||
writingMode := 0
|
writingMode := 0
|
||||||
for _, tag := range []string{
|
for _, tag := range []string{
|
||||||
TextAlign, TextTransform, TextWeight, TextLineStyle, WritingMode, TextDirection,
|
Overflow, TextAlign, TextTransform, TextWeight, TextLineStyle, WritingMode, TextDirection,
|
||||||
VerticalTextOrientation, CellVerticalAlign, CellHorizontalAlign, GridAutoFlow, Cursor,
|
VerticalTextOrientation, CellVerticalAlign, CellHorizontalAlign, GridAutoFlow, Cursor,
|
||||||
WhiteSpace, WordBreak, TextOverflow, Float, TableVerticalAlign, Resize} {
|
WhiteSpace, WordBreak, TextOverflow, Float, TableVerticalAlign, Resize} {
|
||||||
|
|
||||||
|
@ -268,6 +279,10 @@ func (style *viewStyle) cssViewStyle(builder cssBuilder, session Session) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if tabSize, ok := intProperty(style, TabSize, session, 8); ok && tabSize > 0 {
|
||||||
|
builder.add(TabSize, strconv.Itoa(tabSize))
|
||||||
|
}
|
||||||
|
|
||||||
if text := style.cssTextDecoration(session); text != "" {
|
if text := style.cssTextDecoration(session); text != "" {
|
||||||
builder.add("text-decoration", text)
|
builder.add("text-decoration", text)
|
||||||
}
|
}
|
||||||
|
@ -384,12 +399,10 @@ func (style *viewStyle) cssViewStyle(builder cssBuilder, session Session) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if r, ok := rangeProperty(style, Row, session); ok {
|
if r, ok := rangeProperty(style, Row, session); ok {
|
||||||
builder.add("grid-row-start", strconv.Itoa(r.First+1))
|
builder.add("grid-row", fmt.Sprintf("%d / %d", r.First+1, r.Last+2))
|
||||||
builder.add("grid-row-end", strconv.Itoa(r.Last+2))
|
|
||||||
}
|
}
|
||||||
if r, ok := rangeProperty(style, Column, session); ok {
|
if r, ok := rangeProperty(style, Column, session); ok {
|
||||||
builder.add("grid-column-start", strconv.Itoa(r.First+1))
|
builder.add("grid-column", fmt.Sprintf("%d / %d", r.First+1, r.Last+2))
|
||||||
builder.add("grid-column-end", strconv.Itoa(r.Last+2))
|
|
||||||
}
|
}
|
||||||
if text := style.gridCellSizesCSS(CellWidth, session); text != "" {
|
if text := style.gridCellSizesCSS(CellWidth, session); text != "" {
|
||||||
builder.add(`grid-template-columns`, text)
|
builder.add(`grid-template-columns`, text)
|
||||||
|
@ -442,7 +455,7 @@ func (style *viewStyle) cssViewStyle(builder cssBuilder, session Session) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func valueToOrientation(value interface{}, session Session) (int, bool) {
|
func valueToOrientation(value any, session Session) (int, bool) {
|
||||||
if value != nil {
|
if value != nil {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case int:
|
case int:
|
||||||
|
@ -471,11 +484,11 @@ func valueToOrientation(value interface{}, session Session) (int, bool) {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (style *viewStyle) Get(tag string) interface{} {
|
func (style *viewStyle) Get(tag string) any {
|
||||||
return style.get(strings.ToLower(tag))
|
return style.get(strings.ToLower(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (style *viewStyle) get(tag string) interface{} {
|
func (style *viewStyle) get(tag string) any {
|
||||||
switch tag {
|
switch tag {
|
||||||
case Border, CellBorder:
|
case Border, CellBorder:
|
||||||
return getBorder(&style.propertyList, tag)
|
return getBorder(&style.propertyList, tag)
|
||||||
|
@ -539,7 +552,7 @@ func (style *viewStyle) AllTags() []string {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func supportedPropertyValue(value interface{}) bool {
|
func supportedPropertyValue(value any) bool {
|
||||||
switch value.(type) {
|
switch value.(type) {
|
||||||
case string:
|
case string:
|
||||||
case []string:
|
case []string:
|
||||||
|
@ -551,7 +564,7 @@ func supportedPropertyValue(value interface{}) bool {
|
||||||
case fmt.Stringer:
|
case fmt.Stringer:
|
||||||
case []ViewShadow:
|
case []ViewShadow:
|
||||||
case []View:
|
case []View:
|
||||||
case []interface{}:
|
case []any:
|
||||||
case map[string]Animation:
|
case map[string]Animation:
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
|
@ -559,7 +572,7 @@ func supportedPropertyValue(value interface{}) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func writePropertyValue(buffer *strings.Builder, tag string, value interface{}, indent string) {
|
func writePropertyValue(buffer *strings.Builder, tag string, value any, indent string) {
|
||||||
|
|
||||||
writeString := func(text string) {
|
writeString := func(text string) {
|
||||||
simple := (tag != Text && tag != Title && tag != Summary)
|
simple := (tag != Text && tag != Title && tag != Summary)
|
||||||
|
@ -569,7 +582,8 @@ func writePropertyValue(buffer *strings.Builder, tag string, value interface{},
|
||||||
} else {
|
} else {
|
||||||
for _, ch := range text {
|
for _, ch := range text {
|
||||||
if (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') ||
|
if (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') ||
|
||||||
ch == '+' || ch == '-' || ch == '@' || ch == '/' || ch == '_' || ch == ':' {
|
ch == '+' || ch == '-' || ch == '@' || ch == '/' || ch == '_' || ch == ':' ||
|
||||||
|
ch == '#' || ch == '%' || ch == 'π' || ch == '°' {
|
||||||
} else {
|
} else {
|
||||||
simple = false
|
simple = false
|
||||||
break
|
break
|
||||||
|
@ -654,7 +668,7 @@ func writePropertyValue(buffer *strings.Builder, tag string, value interface{},
|
||||||
value.writeString(buffer, indent+"\t")
|
value.writeString(buffer, indent+"\t")
|
||||||
|
|
||||||
case fmt.Stringer:
|
case fmt.Stringer:
|
||||||
buffer.WriteString(value.String())
|
writeString(value.String())
|
||||||
|
|
||||||
case []ViewShadow:
|
case []ViewShadow:
|
||||||
switch len(value) {
|
switch len(value) {
|
||||||
|
@ -697,7 +711,7 @@ func writePropertyValue(buffer *strings.Builder, tag string, value interface{},
|
||||||
buffer.WriteRune(']')
|
buffer.WriteRune(']')
|
||||||
}
|
}
|
||||||
|
|
||||||
case []interface{}:
|
case []any:
|
||||||
switch count := len(value); count {
|
switch count := len(value); count {
|
||||||
case 0:
|
case 0:
|
||||||
buffer.WriteString("[]")
|
buffer.WriteString("[]")
|
||||||
|
@ -741,7 +755,7 @@ func writePropertyValue(buffer *strings.Builder, tag string, value interface{},
|
||||||
if animation := value[tag]; animation != nil {
|
if animation := value[tag]; animation != nil {
|
||||||
buffer.WriteString(indent2)
|
buffer.WriteString(indent2)
|
||||||
animation.writeTransitionString(tag, buffer)
|
animation.writeTransitionString(tag, buffer)
|
||||||
buffer.WriteString("\n")
|
buffer.WriteString(",\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buffer.WriteString(indent)
|
buffer.WriteString(indent)
|
||||||
|
@ -755,7 +769,7 @@ func writeViewStyle(name string, view ViewStyle, buffer *strings.Builder, indent
|
||||||
buffer.WriteString(" {\n")
|
buffer.WriteString(" {\n")
|
||||||
indent += "\t"
|
indent += "\t"
|
||||||
|
|
||||||
writeProperty := func(tag string, value interface{}) {
|
writeProperty := func(tag string, value any) {
|
||||||
if supportedPropertyValue(value) {
|
if supportedPropertyValue(value) {
|
||||||
buffer.WriteString(indent)
|
buffer.WriteString(indent)
|
||||||
buffer.WriteString(tag)
|
buffer.WriteString(tag)
|
||||||
|
@ -786,7 +800,7 @@ func writeViewStyle(name string, view ViewStyle, buffer *strings.Builder, indent
|
||||||
Opacity, ZIndex, Width, Height, MinWidth, MinHeight, MaxWidth, MaxHeight,
|
Opacity, ZIndex, Width, Height, MinWidth, MinHeight, MaxWidth, MaxHeight,
|
||||||
Margin, Padding, BackgroundClip, BackgroundColor, Background, Border, Radius, Outline, Shadow,
|
Margin, Padding, BackgroundClip, BackgroundColor, Background, Border, Radius, Outline, Shadow,
|
||||||
Orientation, ListWrap, VerticalAlign, HorizontalAlign, CellWidth, CellHeight,
|
Orientation, ListWrap, VerticalAlign, HorizontalAlign, CellWidth, CellHeight,
|
||||||
CellVerticalAlign, CellHorizontalAlign, GridRowGap, GridColumnGap,
|
CellVerticalAlign, CellHorizontalAlign, ListRowGap, ListColumnGap, GridRowGap, GridColumnGap,
|
||||||
ColumnCount, ColumnWidth, ColumnSeparator, ColumnGap, AvoidBreak,
|
ColumnCount, ColumnWidth, ColumnSeparator, ColumnGap, AvoidBreak,
|
||||||
Current, Expanded, Side, ResizeBorderWidth, EditViewType, MaxLength, Hint, Text, EditWrap,
|
Current, Expanded, Side, ResizeBorderWidth, EditViewType, MaxLength, Hint, Text, EditWrap,
|
||||||
TextOverflow, FontName, TextSize, TextColor, TextWeight, Italic, SmallCaps,
|
TextOverflow, FontName, TextSize, TextColor, TextWeight, Italic, SmallCaps,
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (style *viewStyle) setRange(tag string, value interface{}) bool {
|
func (style *viewStyle) setRange(tag string, value any) bool {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case string:
|
case string:
|
||||||
if strings.Contains(value, "@") {
|
if strings.Contains(value, "@") {
|
||||||
|
@ -31,7 +31,7 @@ func (style *viewStyle) setRange(tag string, value interface{}) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (style *viewStyle) setBackground(value interface{}) bool {
|
func (style *viewStyle) setBackground(value any) bool {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case BackgroundElement:
|
case BackgroundElement:
|
||||||
style.properties[Background] = []BackgroundElement{value}
|
style.properties[Background] = []BackgroundElement{value}
|
||||||
|
@ -122,11 +122,11 @@ func (style *viewStyle) remove(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (style *viewStyle) Set(tag string, value interface{}) bool {
|
func (style *viewStyle) Set(tag string, value any) bool {
|
||||||
return style.set(strings.ToLower(tag), value)
|
return style.set(strings.ToLower(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (style *viewStyle) set(tag string, value interface{}) bool {
|
func (style *viewStyle) set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
style.remove(tag)
|
style.remove(tag)
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
package rui
|
package rui
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Perspective is the name of the SizeUnit property that determines the distance between the z = 0 plane
|
// Perspective is the name of the SizeUnit property that determines the distance between the z = 0 plane
|
||||||
// and the user in order to give a 3D-positioned element some perspective. Each 3D element
|
// and the user in order to give a 3D-positioned element some perspective. Each 3D element
|
||||||
|
@ -104,20 +100,6 @@ func getTranslate(style Properties, session Session) (SizeUnit, SizeUnit, SizeUn
|
||||||
return x, y, z
|
return x, y, z
|
||||||
}
|
}
|
||||||
|
|
||||||
func getScale(style Properties, session Session) (float64, float64, float64, bool) {
|
|
||||||
scaleX, okX := floatProperty(style, ScaleX, session, 1)
|
|
||||||
scaleY, okY := floatProperty(style, ScaleY, session, 1)
|
|
||||||
scaleZ, okZ := floatProperty(style, ScaleZ, session, 1)
|
|
||||||
return scaleX, scaleY, scaleZ, okX || okY || okZ
|
|
||||||
}
|
|
||||||
|
|
||||||
func getRotateVector(style Properties, session Session) (float64, float64, float64) {
|
|
||||||
rotateX, _ := floatProperty(style, RotateX, session, 1)
|
|
||||||
rotateY, _ := floatProperty(style, RotateY, session, 1)
|
|
||||||
rotateZ, _ := floatProperty(style, RotateZ, session, 1)
|
|
||||||
return rotateX, rotateY, rotateZ
|
|
||||||
}
|
|
||||||
|
|
||||||
func (style *viewStyle) transform(session Session) string {
|
func (style *viewStyle) transform(session Session) string {
|
||||||
|
|
||||||
buffer := allocStringBuilder()
|
buffer := allocStringBuilder()
|
||||||
|
@ -133,45 +115,52 @@ func (style *viewStyle) transform(session Session) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
x, y, z := getTranslate(style, session)
|
x, y, z := getTranslate(style, session)
|
||||||
scaleX, scaleY, scaleZ, scaleOK := getScale(style, session)
|
|
||||||
|
scaleX, okScaleX := floatTextProperty(style, ScaleX, session, 1)
|
||||||
|
scaleY, okScaleY := floatTextProperty(style, ScaleY, session, 1)
|
||||||
|
|
||||||
if getTransform3D(style, session) {
|
if getTransform3D(style, session) {
|
||||||
if x.Type != Auto || y.Type != Auto || z.Type != Auto {
|
if x.Type != Auto || y.Type != Auto || z.Type != Auto {
|
||||||
if buffer.Len() > 0 {
|
if buffer.Len() > 0 {
|
||||||
buffer.WriteRune(' ')
|
buffer.WriteRune(' ')
|
||||||
}
|
}
|
||||||
buffer.WriteString(`translate3d(`)
|
buffer.WriteString(`translate3d(`)
|
||||||
buffer.WriteString(x.cssString("0"))
|
buffer.WriteString(x.cssString("0", session))
|
||||||
buffer.WriteRune(',')
|
buffer.WriteRune(',')
|
||||||
buffer.WriteString(y.cssString("0"))
|
buffer.WriteString(y.cssString("0", session))
|
||||||
buffer.WriteRune(',')
|
buffer.WriteRune(',')
|
||||||
buffer.WriteString(z.cssString("0"))
|
buffer.WriteString(z.cssString("0", session))
|
||||||
buffer.WriteRune(')')
|
buffer.WriteRune(')')
|
||||||
}
|
}
|
||||||
|
|
||||||
if scaleOK {
|
scaleZ, okScaleZ := floatTextProperty(style, ScaleZ, session, 1)
|
||||||
|
if okScaleX || okScaleY || okScaleZ {
|
||||||
if buffer.Len() > 0 {
|
if buffer.Len() > 0 {
|
||||||
buffer.WriteRune(' ')
|
buffer.WriteRune(' ')
|
||||||
}
|
}
|
||||||
buffer.WriteString(`scale3d(`)
|
buffer.WriteString(`scale3d(`)
|
||||||
buffer.WriteString(strconv.FormatFloat(scaleX, 'g', -1, 64))
|
buffer.WriteString(scaleX)
|
||||||
buffer.WriteRune(',')
|
buffer.WriteRune(',')
|
||||||
buffer.WriteString(strconv.FormatFloat(scaleY, 'g', -1, 64))
|
buffer.WriteString(scaleY)
|
||||||
buffer.WriteRune(',')
|
buffer.WriteRune(',')
|
||||||
buffer.WriteString(strconv.FormatFloat(scaleZ, 'g', -1, 64))
|
buffer.WriteString(scaleZ)
|
||||||
buffer.WriteRune(')')
|
buffer.WriteRune(')')
|
||||||
}
|
}
|
||||||
|
|
||||||
if angle, ok := angleProperty(style, Rotate, session); ok {
|
if angle, ok := angleProperty(style, Rotate, session); ok {
|
||||||
rotateX, rotateY, rotateZ := getRotateVector(style, session)
|
rotateX, _ := floatTextProperty(style, RotateX, session, 1)
|
||||||
|
rotateY, _ := floatTextProperty(style, RotateY, session, 1)
|
||||||
|
rotateZ, _ := floatTextProperty(style, RotateZ, session, 1)
|
||||||
|
|
||||||
if buffer.Len() > 0 {
|
if buffer.Len() > 0 {
|
||||||
buffer.WriteRune(' ')
|
buffer.WriteRune(' ')
|
||||||
}
|
}
|
||||||
buffer.WriteString(`rotate3d(`)
|
buffer.WriteString(`rotate3d(`)
|
||||||
buffer.WriteString(strconv.FormatFloat(rotateX, 'g', -1, 64))
|
buffer.WriteString(rotateX)
|
||||||
buffer.WriteRune(',')
|
buffer.WriteRune(',')
|
||||||
buffer.WriteString(strconv.FormatFloat(rotateY, 'g', -1, 64))
|
buffer.WriteString(rotateY)
|
||||||
buffer.WriteRune(',')
|
buffer.WriteRune(',')
|
||||||
buffer.WriteString(strconv.FormatFloat(rotateZ, 'g', -1, 64))
|
buffer.WriteString(rotateZ)
|
||||||
buffer.WriteRune(',')
|
buffer.WriteRune(',')
|
||||||
buffer.WriteString(angle.cssString())
|
buffer.WriteString(angle.cssString())
|
||||||
buffer.WriteRune(')')
|
buffer.WriteRune(')')
|
||||||
|
@ -183,20 +172,20 @@ func (style *viewStyle) transform(session Session) string {
|
||||||
buffer.WriteRune(' ')
|
buffer.WriteRune(' ')
|
||||||
}
|
}
|
||||||
buffer.WriteString(`translate(`)
|
buffer.WriteString(`translate(`)
|
||||||
buffer.WriteString(x.cssString("0"))
|
buffer.WriteString(x.cssString("0", session))
|
||||||
buffer.WriteRune(',')
|
buffer.WriteRune(',')
|
||||||
buffer.WriteString(y.cssString("0"))
|
buffer.WriteString(y.cssString("0", session))
|
||||||
buffer.WriteRune(')')
|
buffer.WriteRune(')')
|
||||||
}
|
}
|
||||||
|
|
||||||
if scaleOK {
|
if okScaleX || okScaleY {
|
||||||
if buffer.Len() > 0 {
|
if buffer.Len() > 0 {
|
||||||
buffer.WriteRune(' ')
|
buffer.WriteRune(' ')
|
||||||
}
|
}
|
||||||
buffer.WriteString(`scale(`)
|
buffer.WriteString(`scale(`)
|
||||||
buffer.WriteString(strconv.FormatFloat(scaleX, 'g', -1, 64))
|
buffer.WriteString(scaleX)
|
||||||
buffer.WriteRune(',')
|
buffer.WriteRune(',')
|
||||||
buffer.WriteString(strconv.FormatFloat(scaleY, 'g', -1, 64))
|
buffer.WriteString(scaleY)
|
||||||
buffer.WriteRune(')')
|
buffer.WriteRune(')')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,12 +205,12 @@ func (style *viewStyle) transform(session Session) string {
|
||||||
func (style *viewStyle) writeViewTransformCSS(builder cssBuilder, session Session) {
|
func (style *viewStyle) writeViewTransformCSS(builder cssBuilder, session Session) {
|
||||||
if getTransform3D(style, session) {
|
if getTransform3D(style, session) {
|
||||||
if perspective, ok := sizeProperty(style, Perspective, session); ok && perspective.Type != Auto && perspective.Value != 0 {
|
if perspective, ok := sizeProperty(style, Perspective, session); ok && perspective.Type != Auto && perspective.Value != 0 {
|
||||||
builder.add(`perspective`, perspective.cssString("0"))
|
builder.add(`perspective`, perspective.cssString("0", session))
|
||||||
}
|
}
|
||||||
|
|
||||||
x, y := getPerspectiveOrigin(style, session)
|
x, y := getPerspectiveOrigin(style, session)
|
||||||
if x.Type != Auto || y.Type != Auto {
|
if x.Type != Auto || y.Type != Auto {
|
||||||
builder.addValues(`perspective-origin`, ` `, x.cssString("50%"), y.cssString("50%"))
|
builder.addValues(`perspective-origin`, ` `, x.cssString("50%", session), y.cssString("50%", session))
|
||||||
}
|
}
|
||||||
|
|
||||||
if backfaceVisible, ok := boolProperty(style, BackfaceVisible, session); ok {
|
if backfaceVisible, ok := boolProperty(style, BackfaceVisible, session); ok {
|
||||||
|
@ -234,12 +223,12 @@ func (style *viewStyle) writeViewTransformCSS(builder cssBuilder, session Sessio
|
||||||
|
|
||||||
x, y, z := getOrigin(style, session)
|
x, y, z := getOrigin(style, session)
|
||||||
if x.Type != Auto || y.Type != Auto || z.Type != Auto {
|
if x.Type != Auto || y.Type != Auto || z.Type != Auto {
|
||||||
builder.addValues(`transform-origin`, ` `, x.cssString("50%"), y.cssString("50%"), z.cssString("0"))
|
builder.addValues(`transform-origin`, ` `, x.cssString("50%", session), y.cssString("50%", session), z.cssString("0", session))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
x, y, _ := getOrigin(style, session)
|
x, y, _ := getOrigin(style, session)
|
||||||
if x.Type != Auto || y.Type != Auto {
|
if x.Type != Auto || y.Type != Auto {
|
||||||
builder.addValues(`transform-origin`, ` `, x.cssString("50%"), y.cssString("50%"))
|
builder.addValues(`transform-origin`, ` `, x.cssString("50%", session), y.cssString("50%", session))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,17 +245,17 @@ func (view *viewData) updateTransformProperty(tag string) bool {
|
||||||
|
|
||||||
case PerspectiveOriginX, PerspectiveOriginY:
|
case PerspectiveOriginX, PerspectiveOriginY:
|
||||||
if getTransform3D(view, session) {
|
if getTransform3D(view, session) {
|
||||||
x, y := GetPerspectiveOrigin(view, "")
|
x, y := GetPerspectiveOrigin(view)
|
||||||
value := ""
|
value := ""
|
||||||
if x.Type != Auto || y.Type != Auto {
|
if x.Type != Auto || y.Type != Auto {
|
||||||
value = x.cssString("50%") + " " + y.cssString("50%")
|
value = x.cssString("50%", session) + " " + y.cssString("50%", session)
|
||||||
}
|
}
|
||||||
updateCSSProperty(htmlID, "perspective-origin", value, session)
|
updateCSSProperty(htmlID, "perspective-origin", value, session)
|
||||||
}
|
}
|
||||||
|
|
||||||
case BackfaceVisible:
|
case BackfaceVisible:
|
||||||
if getTransform3D(view, session) {
|
if getTransform3D(view, session) {
|
||||||
if GetBackfaceVisible(view, "") {
|
if GetBackfaceVisible(view) {
|
||||||
updateCSSProperty(htmlID, BackfaceVisible, "visible", session)
|
updateCSSProperty(htmlID, BackfaceVisible, "visible", session)
|
||||||
} else {
|
} else {
|
||||||
updateCSSProperty(htmlID, BackfaceVisible, "hidden", session)
|
updateCSSProperty(htmlID, BackfaceVisible, "hidden", session)
|
||||||
|
@ -278,11 +267,11 @@ func (view *viewData) updateTransformProperty(tag string) bool {
|
||||||
value := ""
|
value := ""
|
||||||
if getTransform3D(view, session) {
|
if getTransform3D(view, session) {
|
||||||
if x.Type != Auto || y.Type != Auto || z.Type != Auto {
|
if x.Type != Auto || y.Type != Auto || z.Type != Auto {
|
||||||
value = x.cssString("50%") + " " + y.cssString("50%") + " " + z.cssString("50%")
|
value = x.cssString("50%", session) + " " + y.cssString("50%", session) + " " + z.cssString("50%", session)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if x.Type != Auto || y.Type != Auto {
|
if x.Type != Auto || y.Type != Auto {
|
||||||
value = x.cssString("50%") + " " + y.cssString("50%")
|
value = x.cssString("50%", session) + " " + y.cssString("50%", session)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateCSSProperty(htmlID, "transform-origin", value, session)
|
updateCSSProperty(htmlID, "transform-origin", value, session)
|
||||||
|
|
1014
viewUtils.go
1014
viewUtils.go
File diff suppressed because it is too large
Load Diff
|
@ -25,8 +25,8 @@ type viewsContainerData struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initialize fields of ViewsContainer by default values
|
// Init initialize fields of ViewsContainer by default values
|
||||||
func (container *viewsContainerData) Init(session Session) {
|
func (container *viewsContainerData) init(session Session) {
|
||||||
container.viewData.Init(session)
|
container.viewData.init(session)
|
||||||
container.tag = "ViewsContainer"
|
container.tag = "ViewsContainer"
|
||||||
container.views = []View{}
|
container.views = []View{}
|
||||||
}
|
}
|
||||||
|
@ -47,8 +47,7 @@ func (container *viewsContainerData) setParentID(parentID string) {
|
||||||
func (container *viewsContainerData) Views() []View {
|
func (container *viewsContainerData) Views() []View {
|
||||||
if container.views == nil {
|
if container.views == nil {
|
||||||
container.views = []View{}
|
container.views = []View{}
|
||||||
}
|
} else if count := len(container.views); count > 0 {
|
||||||
if count := len(container.views); count > 0 {
|
|
||||||
views := make([]View, count)
|
views := make([]View, count)
|
||||||
copy(views, container.views)
|
copy(views, container.views)
|
||||||
return views
|
return views
|
||||||
|
@ -172,11 +171,11 @@ func (container *viewsContainerData) remove(tag string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (container *viewsContainerData) Set(tag string, value interface{}) bool {
|
func (container *viewsContainerData) Set(tag string, value any) bool {
|
||||||
return container.set(strings.ToLower(tag), value)
|
return container.set(strings.ToLower(tag), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (container *viewsContainerData) set(tag string, value interface{}) bool {
|
func (container *viewsContainerData) set(tag string, value any) bool {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
container.remove(tag)
|
container.remove(tag)
|
||||||
return true
|
return true
|
||||||
|
@ -187,9 +186,9 @@ func (container *viewsContainerData) set(tag string, value interface{}) bool {
|
||||||
// do nothing
|
// do nothing
|
||||||
|
|
||||||
case Disabled:
|
case Disabled:
|
||||||
oldDisabled := IsDisabled(container, "")
|
oldDisabled := IsDisabled(container)
|
||||||
if container.viewData.Set(Disabled, value) {
|
if container.viewData.Set(Disabled, value) {
|
||||||
disabled := IsDisabled(container, "")
|
disabled := IsDisabled(container)
|
||||||
if oldDisabled != disabled {
|
if oldDisabled != disabled {
|
||||||
if container.views != nil {
|
if container.views != nil {
|
||||||
for _, view := range container.views {
|
for _, view := range container.views {
|
||||||
|
@ -224,7 +223,7 @@ func (container *viewsContainerData) set(tag string, value interface{}) bool {
|
||||||
}
|
}
|
||||||
container.views = views
|
container.views = views
|
||||||
|
|
||||||
case []interface{}:
|
case []any:
|
||||||
views := []View{}
|
views := []View{}
|
||||||
for _, v := range value {
|
for _, v := range value {
|
||||||
switch v := v.(type) {
|
switch v := v.(type) {
|
||||||
|
@ -279,11 +278,11 @@ func (container *viewsContainerData) set(tag string, value interface{}) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (container *viewsContainerData) Get(tag string) interface{} {
|
func (container *viewsContainerData) Get(tag string) any {
|
||||||
return container.get(strings.ToLower(tag))
|
return container.get(strings.ToLower(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (container *viewsContainerData) get(tag string) interface{} {
|
func (container *viewsContainerData) get(tag string) any {
|
||||||
switch tag {
|
switch tag {
|
||||||
case Content:
|
case Content:
|
||||||
return container.views
|
return container.views
|
||||||
|
|
Loading…
Reference in New Issue