mirror of https://github.com/anoshenko/rui.git
Added change listener binding
This commit is contained in:
parent
d633c80155
commit
0433f460e4
|
@ -160,7 +160,7 @@ func (picker *colorPickerData) handleCommand(self View, command PropertyName, da
|
|||
listener.Run(picker, color, oldColor)
|
||||
}
|
||||
if listener, ok := picker.changeListener[ColorPickerValue]; ok {
|
||||
listener(picker, ColorPickerValue)
|
||||
listener.Run(picker, ColorPickerValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,8 +98,8 @@ func (customView *CustomViewData) SetParams(params Params) bool {
|
|||
}
|
||||
|
||||
// SetChangeListener set the function to track the change of the View property
|
||||
func (customView *CustomViewData) SetChangeListener(tag PropertyName, listener func(View, PropertyName)) {
|
||||
customView.superView.SetChangeListener(tag, listener)
|
||||
func (customView *CustomViewData) SetChangeListener(tag PropertyName, listener any) bool {
|
||||
return customView.superView.SetChangeListener(tag, listener)
|
||||
}
|
||||
|
||||
// Remove removes the property with name defined by the argument
|
||||
|
|
13
data.go
13
data.go
|
@ -49,14 +49,17 @@ type DataObject interface {
|
|||
ToParams() Params
|
||||
}
|
||||
|
||||
// DataNodeType defines the type of DataNode
|
||||
type DataNodeType int
|
||||
|
||||
// Constants which are used to describe a node type, see [DataNode]
|
||||
const (
|
||||
// TextNode - node is the pair "tag - text value". Syntax: <tag> = <text>
|
||||
TextNode = 0
|
||||
TextNode DataNodeType = 0
|
||||
// ObjectNode - node is the pair "tag - object". Syntax: <tag> = <object name>{...}
|
||||
ObjectNode = 1
|
||||
ObjectNode DataNodeType = 1
|
||||
// ArrayNode - node is the pair "tag - object". Syntax: <tag> = [...]
|
||||
ArrayNode = 2
|
||||
ArrayNode DataNodeType = 2
|
||||
)
|
||||
|
||||
// DataNode interface of a data node
|
||||
|
@ -65,7 +68,7 @@ type DataNode interface {
|
|||
Tag() string
|
||||
|
||||
// Type returns a node type. Possible values are TextNode, ObjectNode and ArrayNode
|
||||
Type() int
|
||||
Type() DataNodeType
|
||||
|
||||
// Text returns node text
|
||||
Text() string
|
||||
|
@ -253,7 +256,7 @@ func (node *dataNode) Tag() string {
|
|||
return node.tag
|
||||
}
|
||||
|
||||
func (node *dataNode) Type() int {
|
||||
func (node *dataNode) Type() DataNodeType {
|
||||
if node.array != nil {
|
||||
return ArrayNode
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ func TestParseDataText(t *testing.T) {
|
|||
t.Errorf(`obj.PropertyValue("key5") result: ("%s",%v)`, val, ok)
|
||||
}
|
||||
|
||||
testKey := func(obj DataObject, index int, tag string, nodeType int) DataNode {
|
||||
testKey := func(obj DataObject, index int, tag string, nodeType DataNodeType) DataNode {
|
||||
key := obj.Property(index)
|
||||
if key == nil {
|
||||
t.Errorf(`%s.Property(%d) == nil`, obj.Tag(), index)
|
||||
|
@ -118,7 +118,7 @@ func TestParseDataText(t *testing.T) {
|
|||
|
||||
type testKeyData struct {
|
||||
tag string
|
||||
nodeType int
|
||||
nodeType DataNodeType
|
||||
}
|
||||
|
||||
data := []testKeyData{
|
||||
|
|
|
@ -352,7 +352,7 @@ func (picker *datePickerData) handleCommand(self View, command PropertyName, dat
|
|||
listener.Run(picker, value, oldValue)
|
||||
}
|
||||
if listener, ok := picker.changeListener[DatePickerValue]; ok {
|
||||
listener(picker, DatePickerValue)
|
||||
listener.Run(picker, DatePickerValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -193,7 +193,7 @@ func (detailsView *detailsViewData) handleCommand(self View, command PropertyNam
|
|||
if n, ok := dataIntProperty(data, "open"); ok {
|
||||
detailsView.properties[Expanded] = (n != 0)
|
||||
if listener, ok := detailsView.changeListener[Expanded]; ok {
|
||||
listener(detailsView, Expanded)
|
||||
listener.Run(detailsView, Expanded)
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
|
|
@ -249,7 +249,7 @@ func (list *dropDownListData) handleCommand(self View, command PropertyName, dat
|
|||
listener.Run(list, number, old)
|
||||
}
|
||||
if listener, ok := list.changeListener[Current]; ok {
|
||||
listener(list, Current)
|
||||
listener.Run(list, Current)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -272,7 +272,7 @@ func (edit *editViewData) textChanged(newText, oldText string) {
|
|||
listener.Run(edit, newText, oldText)
|
||||
}
|
||||
if listener, ok := edit.changeListener[Text]; ok {
|
||||
listener(edit, Text)
|
||||
listener.Run(edit, Text)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -139,8 +139,7 @@ func (data *noArgListenerBinding[V]) Run(view V) {
|
|||
args = []reflect.Value{}
|
||||
|
||||
case 1:
|
||||
inType := methodType.In(0)
|
||||
if inType == reflect.TypeOf(view) {
|
||||
if equalType(methodType.In(0), reflect.TypeOf(view)) {
|
||||
args = []reflect.Value{reflect.ValueOf(view)}
|
||||
}
|
||||
}
|
||||
|
@ -152,6 +151,10 @@ func (data *noArgListenerBinding[V]) Run(view V) {
|
|||
}
|
||||
}
|
||||
|
||||
func equalType(inType reflect.Type, argType reflect.Type) bool {
|
||||
return inType == argType || (inType.Kind() == reflect.Interface && argType.Implements(inType))
|
||||
}
|
||||
|
||||
func (data *noArgListenerBinding[V]) rawListener() any {
|
||||
return data.name
|
||||
}
|
||||
|
|
|
@ -106,6 +106,7 @@ func (data *oneArgListenerBinding[V, E]) Run(view V, event E) {
|
|||
}
|
||||
|
||||
methodType := method.Type()
|
||||
|
||||
var args []reflect.Value = nil
|
||||
switch methodType.NumIn() {
|
||||
case 0:
|
||||
|
@ -113,14 +114,15 @@ func (data *oneArgListenerBinding[V, E]) Run(view V, event E) {
|
|||
|
||||
case 1:
|
||||
inType := methodType.In(0)
|
||||
if inType == reflect.TypeOf(view) {
|
||||
args = []reflect.Value{reflect.ValueOf(view)}
|
||||
} else if inType == reflect.TypeOf(event) {
|
||||
if equalType(inType, reflect.TypeOf(event)) {
|
||||
args = []reflect.Value{reflect.ValueOf(event)}
|
||||
} else if equalType(inType, reflect.TypeOf(view)) {
|
||||
args = []reflect.Value{reflect.ValueOf(view)}
|
||||
}
|
||||
|
||||
case 2:
|
||||
if methodType.In(0) == reflect.TypeOf(view) && methodType.In(1) == reflect.TypeOf(event) {
|
||||
if equalType(methodType.In(0), reflect.TypeOf(view)) &&
|
||||
equalType(methodType.In(1), reflect.TypeOf(event)) {
|
||||
args = []reflect.Value{reflect.ValueOf(view), reflect.ValueOf(event)}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,6 +140,7 @@ func (data *twoArgListenerBinding[V, E]) Run(view V, arg1 E, arg2 E) {
|
|||
}
|
||||
|
||||
methodType := method.Type()
|
||||
|
||||
var args []reflect.Value = nil
|
||||
switch methodType.NumIn() {
|
||||
case 0:
|
||||
|
@ -147,23 +148,25 @@ func (data *twoArgListenerBinding[V, E]) Run(view V, arg1 E, arg2 E) {
|
|||
|
||||
case 1:
|
||||
inType := methodType.In(0)
|
||||
if inType == reflect.TypeOf(view) {
|
||||
args = []reflect.Value{reflect.ValueOf(view)}
|
||||
} else if inType == reflect.TypeOf(arg1) {
|
||||
if equalType(inType, reflect.TypeOf(arg1)) {
|
||||
args = []reflect.Value{reflect.ValueOf(arg1)}
|
||||
} else if equalType(inType, reflect.TypeOf(view)) {
|
||||
args = []reflect.Value{reflect.ValueOf(view)}
|
||||
}
|
||||
|
||||
case 2:
|
||||
valType := reflect.TypeOf(arg1)
|
||||
if methodType.In(0) == reflect.TypeOf(view) && methodType.In(1) == valType {
|
||||
inType0 := methodType.In(0)
|
||||
inType1 := methodType.In(1)
|
||||
if equalType(inType0, reflect.TypeOf(view)) && equalType(inType1, reflect.TypeOf(arg1)) {
|
||||
args = []reflect.Value{reflect.ValueOf(view), reflect.ValueOf(arg1)}
|
||||
} else if methodType.In(0) == valType && methodType.In(1) == valType {
|
||||
} else if equalType(inType0, reflect.TypeOf(arg1)) && equalType(inType1, reflect.TypeOf(arg2)) {
|
||||
args = []reflect.Value{reflect.ValueOf(arg1), reflect.ValueOf(arg2)}
|
||||
}
|
||||
|
||||
case 3:
|
||||
valType := reflect.TypeOf(arg1)
|
||||
if methodType.In(0) == reflect.TypeOf(view) && methodType.In(1) == valType && methodType.In(2) == valType {
|
||||
if equalType(methodType.In(0), reflect.TypeOf(view)) &&
|
||||
equalType(methodType.In(1), reflect.TypeOf(arg1)) &&
|
||||
equalType(methodType.In(2), reflect.TypeOf(arg2)) {
|
||||
args = []reflect.Value{reflect.ValueOf(view), reflect.ValueOf(arg1), reflect.ValueOf(arg2)}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -458,10 +458,7 @@ func (gridLayout *gridLayoutData) UpdateGridContent() {
|
|||
if gridLayout.created {
|
||||
updateInnerHTML(gridLayout.htmlID(), gridLayout.session)
|
||||
}
|
||||
|
||||
if listener, ok := gridLayout.changeListener[Content]; ok {
|
||||
listener(gridLayout, Content)
|
||||
}
|
||||
gridLayout.contentChanged()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -196,10 +196,7 @@ func (listLayout *listLayoutData) UpdateContent() {
|
|||
if listLayout.created {
|
||||
updateInnerHTML(listLayout.htmlID(), listLayout.session)
|
||||
}
|
||||
|
||||
if listener, ok := listLayout.changeListener[Content]; ok {
|
||||
listener(listLayout, Content)
|
||||
}
|
||||
listLayout.contentChanged()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -963,7 +963,7 @@ func (listView *listViewData) handleCurrent(number int) {
|
|||
listener.Run(listView, number)
|
||||
}
|
||||
if listener, ok := listView.changeListener[Current]; ok {
|
||||
listener(listView, Current)
|
||||
listener.Run(listView, Current)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1022,7 +1022,7 @@ func (listView *listViewData) onItemClick(number int) {
|
|||
|
||||
setArrayPropertyValue(listView, Checked, checkedItem)
|
||||
if listener, ok := listView.changeListener[Checked]; ok {
|
||||
listener(listView, Checked)
|
||||
listener.Run(listView, Checked)
|
||||
}
|
||||
|
||||
for _, listener := range getOneArgEventListeners[ListView, []int](listView, nil, ListItemCheckedEvent) {
|
||||
|
|
|
@ -1430,32 +1430,32 @@ func (data *mediaPlayerErrorListenerBinding) Run(player MediaPlayer, code int, m
|
|||
args = []reflect.Value{}
|
||||
|
||||
case 1:
|
||||
switch methodType.In(0) {
|
||||
case reflect.TypeOf(player):
|
||||
inType := methodType.In(0)
|
||||
if equalType(inType, reflect.TypeOf(player)) {
|
||||
args = []reflect.Value{reflect.ValueOf(player)}
|
||||
case reflect.TypeOf(code):
|
||||
} else if equalType(inType, reflect.TypeOf(code)) {
|
||||
args = []reflect.Value{reflect.ValueOf(code)}
|
||||
case reflect.TypeOf(message):
|
||||
} else if equalType(inType, reflect.TypeOf(message)) {
|
||||
args = []reflect.Value{reflect.ValueOf(message)}
|
||||
}
|
||||
|
||||
case 2:
|
||||
in0 := methodType.In(0)
|
||||
in1 := methodType.In(1)
|
||||
if in0 == reflect.TypeOf(player) {
|
||||
if in1 == reflect.TypeOf(code) {
|
||||
if equalType(in0, reflect.TypeOf(player)) {
|
||||
if equalType(in1, reflect.TypeOf(code)) {
|
||||
args = []reflect.Value{reflect.ValueOf(player), reflect.ValueOf(code)}
|
||||
} else if in1 == reflect.TypeOf(message) {
|
||||
} else if equalType(in1, reflect.TypeOf(message)) {
|
||||
args = []reflect.Value{reflect.ValueOf(player), reflect.ValueOf(message)}
|
||||
}
|
||||
} else if in0 == reflect.TypeOf(code) && in1 == reflect.TypeOf(message) {
|
||||
} else if equalType(in0, reflect.TypeOf(code)) && equalType(in1, reflect.TypeOf(message)) {
|
||||
args = []reflect.Value{reflect.ValueOf(code), reflect.ValueOf(message)}
|
||||
}
|
||||
|
||||
case 3:
|
||||
if methodType.In(0) == reflect.TypeOf(player) &&
|
||||
methodType.In(1) == reflect.TypeOf(code) &&
|
||||
methodType.In(2) == reflect.TypeOf(message) {
|
||||
if equalType(methodType.In(0), reflect.TypeOf(player)) &&
|
||||
equalType(methodType.In(1), reflect.TypeOf(code)) &&
|
||||
equalType(methodType.In(2), reflect.TypeOf(message)) {
|
||||
args = []reflect.Value{
|
||||
reflect.ValueOf(player),
|
||||
reflect.ValueOf(code),
|
||||
|
|
|
@ -284,7 +284,7 @@ func (picker *numberPickerData) handleCommand(self View, command PropertyName, d
|
|||
listener.Run(picker, value, oldValue)
|
||||
}
|
||||
if listener, ok := picker.changeListener[NumberPickerValue]; ok {
|
||||
listener(picker, NumberPickerValue)
|
||||
listener.Run(picker, NumberPickerValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -610,12 +610,6 @@ func (layout *stackLayoutData) moveToFrontByIndex(index int, onShow []func(View)
|
|||
session.updateCSSProperty(peekPageID, "transform", transformCSS)
|
||||
}
|
||||
|
||||
func (layout *stackLayoutData) contentChanged() {
|
||||
if listener, ok := layout.changeListener[Content]; ok {
|
||||
listener(layout, Content)
|
||||
}
|
||||
}
|
||||
|
||||
func (layout *stackLayoutData) RemovePeek() View {
|
||||
return layout.RemoveView(len(layout.views) - 1)
|
||||
}
|
||||
|
@ -683,9 +677,7 @@ func (layout *stackLayoutData) Append(view View) {
|
|||
}
|
||||
session.appendToInnerHTML(stackID, buffer.String())
|
||||
|
||||
if listener, ok := layout.changeListener[Content]; ok {
|
||||
listener(layout, Content)
|
||||
}
|
||||
layout.contentChanged()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -721,9 +713,7 @@ func (layout *stackLayoutData) Insert(view View, index int) {
|
|||
session := layout.Session()
|
||||
session.appendToInnerHTML(stackID, buffer.String())
|
||||
|
||||
if listener, ok := layout.changeListener[Content]; ok {
|
||||
listener(layout, Content)
|
||||
}
|
||||
layout.contentChanged()
|
||||
}
|
||||
|
||||
// Remove removes view from list and return it
|
||||
|
@ -754,10 +744,7 @@ func (layout *stackLayoutData) RemoveView(index int) View {
|
|||
}
|
||||
|
||||
layout.Session().callFunc("removeView", view.htmlID()+"page")
|
||||
|
||||
if listener, ok := layout.changeListener[Content]; ok {
|
||||
listener(layout, Content)
|
||||
}
|
||||
layout.contentChanged()
|
||||
return view
|
||||
}
|
||||
|
||||
|
|
|
@ -1676,7 +1676,7 @@ func (table *tableViewData) handleCommand(self View, command PropertyName, data
|
|||
current.Row = row
|
||||
table.setRaw(Current, current.Row)
|
||||
if listener, ok := table.changeListener[Current]; ok {
|
||||
listener(table, Current)
|
||||
listener.Run(table, Current)
|
||||
}
|
||||
|
||||
for _, listener := range getOneArgEventListeners[TableView, int](table, nil, TableRowSelectedEvent) {
|
||||
|
@ -1693,7 +1693,7 @@ func (table *tableViewData) handleCommand(self View, command PropertyName, data
|
|||
current.Column = column
|
||||
table.setRaw(Current, current.Row)
|
||||
if listener, ok := table.changeListener[Current]; ok {
|
||||
listener(table, Current)
|
||||
listener.Run(table, Current)
|
||||
}
|
||||
|
||||
for _, listener := range getTwoArgEventListeners[TableView, int](table, nil, TableCellSelectedEvent) {
|
||||
|
|
|
@ -403,9 +403,7 @@ func (tabsLayout *tabsLayoutData) Append(view View) {
|
|||
view.SetChangeListener(TabCloseButton, tabsLayout.updateTabCloseButton)
|
||||
if tabsLayout.created {
|
||||
updateInnerHTML(tabsLayout.htmlID(), tabsLayout.Session())
|
||||
if listener, ok := tabsLayout.changeListener[Content]; ok {
|
||||
listener(tabsLayout, Content)
|
||||
}
|
||||
tabsLayout.contentChanged()
|
||||
tabsLayout.Set(Current, len(tabsLayout.views)-1)
|
||||
}
|
||||
}
|
||||
|
@ -429,9 +427,7 @@ func (tabsLayout *tabsLayoutData) currentChanged(newCurrent, oldCurrent int) {
|
|||
for _, listener := range getTwoArgEventListeners[TabsLayout, int](tabsLayout, nil, CurrentTabChangedEvent) {
|
||||
listener.Run(tabsLayout, newCurrent, oldCurrent)
|
||||
}
|
||||
if listener, ok := tabsLayout.changeListener[Current]; ok {
|
||||
listener(tabsLayout, Current)
|
||||
}
|
||||
tabsLayout.contentChanged()
|
||||
}
|
||||
|
||||
// Remove removes view from list and return it
|
||||
|
@ -457,9 +453,7 @@ func (tabsLayout *tabsLayoutData) RemoveView(index int) View {
|
|||
tabsLayout.Set(Current, newCurrent)
|
||||
}
|
||||
updateInnerHTML(tabsLayout.htmlID(), tabsLayout.Session())
|
||||
if listener, ok := tabsLayout.changeListener[Content]; ok {
|
||||
listener(tabsLayout, Content)
|
||||
}
|
||||
tabsLayout.contentChanged()
|
||||
} else if newCurrent != oldCurrent {
|
||||
tabsLayout.setRaw(Current, newCurrent)
|
||||
}
|
||||
|
|
|
@ -324,7 +324,7 @@ func (picker *timePickerData) handleCommand(self View, command PropertyName, dat
|
|||
listener.Run(picker, value, oldValue)
|
||||
}
|
||||
if listener, ok := picker.changeListener[TimePickerValue]; ok {
|
||||
listener(picker, TimePickerValue)
|
||||
listener.Run(picker, TimePickerValue)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
81
view.go
81
view.go
|
@ -30,6 +30,8 @@ func (frame Frame) Bottom() float64 {
|
|||
return frame.Top + frame.Height
|
||||
}
|
||||
|
||||
const changeListeners PropertyName = "change-listeners"
|
||||
|
||||
// View represents a base view interface
|
||||
type View interface {
|
||||
ViewStyle
|
||||
|
@ -66,8 +68,18 @@ type View interface {
|
|||
// a description of the error is written to the log
|
||||
SetAnimated(tag PropertyName, value any, animation AnimationProperty) bool
|
||||
|
||||
// SetChangeListener set the function to track the change of the View property
|
||||
SetChangeListener(tag PropertyName, listener func(View, PropertyName))
|
||||
// SetChangeListener set the function (the second argument) to track the change of the View property (the first argument).
|
||||
//
|
||||
// Allowed listener function formats:
|
||||
//
|
||||
// func(view rui.View, property rui.PropertyName)
|
||||
// func(view rui.View)
|
||||
// func(property rui.PropertyName)
|
||||
// func()
|
||||
// string
|
||||
//
|
||||
// If the second argument is given as a string, it specifies the name of the binding function.
|
||||
SetChangeListener(tag PropertyName, listener any) bool
|
||||
|
||||
// HasFocus returns 'true' if the view has focus
|
||||
HasFocus() bool
|
||||
|
@ -110,7 +122,7 @@ type viewData struct {
|
|||
_htmlID string
|
||||
parentID string
|
||||
systemClass string
|
||||
changeListener map[PropertyName]func(View, PropertyName)
|
||||
changeListener map[PropertyName]oneArgListener[View, PropertyName]
|
||||
singleTransition map[PropertyName]AnimationProperty
|
||||
addCSS map[string]string
|
||||
frame Frame
|
||||
|
@ -162,7 +174,7 @@ func (view *viewData) init(session Session) {
|
|||
view.changed = view.propertyChanged
|
||||
view.tag = "View"
|
||||
view.session = session
|
||||
view.changeListener = map[PropertyName]func(View, PropertyName){}
|
||||
view.changeListener = map[PropertyName]oneArgListener[View, PropertyName]{}
|
||||
view.addCSS = map[string]string{}
|
||||
//view.animation = map[string]AnimationEndListener{}
|
||||
view.singleTransition = map[PropertyName]AnimationProperty{}
|
||||
|
@ -242,11 +254,8 @@ func (view *viewData) Remove(tag PropertyName) {
|
|||
if view.created && len(changedTags) > 0 {
|
||||
for _, tag := range changedTags {
|
||||
view.changed(tag)
|
||||
}
|
||||
|
||||
for _, tag := range changedTags {
|
||||
if listener, ok := view.changeListener[tag]; ok {
|
||||
listener(view, tag)
|
||||
listener.Run(view, tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -273,11 +282,8 @@ func (view *viewData) Set(tag PropertyName, value any) bool {
|
|||
if view.created && len(changedTags) > 0 {
|
||||
for _, tag := range changedTags {
|
||||
view.changed(tag)
|
||||
}
|
||||
|
||||
for _, tag := range changedTags {
|
||||
if listener, ok := view.changeListener[tag]; ok {
|
||||
listener(view, tag)
|
||||
listener.Run(view, tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -295,7 +301,8 @@ func normalizeViewTag(tag PropertyName) PropertyName {
|
|||
}
|
||||
|
||||
func (view *viewData) getFunc(tag PropertyName) any {
|
||||
if tag == ID {
|
||||
switch tag {
|
||||
case ID:
|
||||
if id := view.ID(); id != "" {
|
||||
return id
|
||||
} else {
|
||||
|
@ -361,6 +368,29 @@ func (view *viewData) setFunc(tag PropertyName, value any) []PropertyName {
|
|||
view.setRaw(Binding, value)
|
||||
return []PropertyName{Binding}
|
||||
|
||||
case changeListeners:
|
||||
switch value := value.(type) {
|
||||
case DataObject:
|
||||
for i := range value.PropertyCount() {
|
||||
node := value.Property(i)
|
||||
if node.Type() == TextNode {
|
||||
if text := node.Text(); text != "" {
|
||||
view.changeListener[PropertyName(node.Tag())] = newOneArgListenerBinding[View, PropertyName](text)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(view.changeListener) > 0 {
|
||||
view.setRaw(changeListeners, view.changeListener)
|
||||
}
|
||||
return []PropertyName{tag}
|
||||
|
||||
case DataNode:
|
||||
if value.Type() == ObjectNode {
|
||||
return view.setFunc(tag, value.Object())
|
||||
}
|
||||
}
|
||||
return []PropertyName{}
|
||||
|
||||
case Animation:
|
||||
oldAnimations := []AnimationProperty{}
|
||||
if val := view.getRaw(Animation); val != nil {
|
||||
|
@ -1251,12 +1281,33 @@ func (view *viewData) handleCommand(self View, command PropertyName, data DataOb
|
|||
|
||||
}
|
||||
|
||||
func (view *viewData) SetChangeListener(tag PropertyName, listener func(View, PropertyName)) {
|
||||
func (view *viewData) SetChangeListener(tag PropertyName, listener any) bool {
|
||||
if listener == nil {
|
||||
delete(view.changeListener, tag)
|
||||
} else {
|
||||
view.changeListener[tag] = listener
|
||||
switch listener := listener.(type) {
|
||||
case func():
|
||||
view.changeListener[tag] = newOneArgListener0[View, PropertyName](listener)
|
||||
|
||||
case func(View):
|
||||
view.changeListener[tag] = newOneArgListenerV[View, PropertyName](listener)
|
||||
|
||||
case func(PropertyName):
|
||||
view.changeListener[tag] = newOneArgListenerE[View](listener)
|
||||
|
||||
case func(View, PropertyName):
|
||||
view.changeListener[tag] = newOneArgListenerVE(listener)
|
||||
|
||||
case string:
|
||||
view.changeListener[tag] = newOneArgListenerBinding[View, PropertyName](listener)
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
view.setRaw(changeListeners, view.changeListener)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (view *viewData) HasFocus() bool {
|
||||
|
|
25
viewStyle.go
25
viewStyle.go
|
@ -661,6 +661,14 @@ func supportedPropertyValue(value any) bool {
|
|||
case []mediaPlayerErrorListener:
|
||||
return getMediaPlayerErrorListenerBinding(value) != ""
|
||||
|
||||
case map[PropertyName]oneArgListener[View, PropertyName]:
|
||||
for _, listener := range value {
|
||||
if text, ok := listener.rawListener().(string); ok && text != "" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
@ -978,6 +986,23 @@ func writePropertyValue(buffer *strings.Builder, tag PropertyName, value any, in
|
|||
|
||||
case []mediaPlayerErrorListener:
|
||||
buffer.WriteString(getMediaPlayerErrorListenerBinding(value))
|
||||
|
||||
case map[PropertyName]oneArgListener[View, PropertyName]:
|
||||
buffer.WriteString("_{")
|
||||
for key, listener := range value {
|
||||
if text, ok := listener.rawListener().(string); ok && text != "" {
|
||||
buffer.WriteRune('\n')
|
||||
buffer.WriteString(indent)
|
||||
buffer.WriteRune('\t')
|
||||
writeString(string(key))
|
||||
buffer.WriteString(" = ")
|
||||
writeString(text)
|
||||
buffer.WriteRune(',')
|
||||
}
|
||||
buffer.WriteRune('\n')
|
||||
buffer.WriteString(indent)
|
||||
buffer.WriteRune('}')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -85,11 +85,14 @@ func (container *viewsContainerData) Append(view View) {
|
|||
|
||||
viewHTML(view, buffer, "")
|
||||
container.Session().appendToInnerHTML(container.htmlID(), buffer.String())
|
||||
|
||||
if listener, ok := container.changeListener[Content]; ok {
|
||||
listener(container, Content)
|
||||
container.contentChanged()
|
||||
}
|
||||
}
|
||||
|
||||
func (container *viewsContainerData) contentChanged() {
|
||||
if listener, ok := container.changeListener[Content]; ok {
|
||||
listener.Run(container, Content)
|
||||
}
|
||||
}
|
||||
|
||||
func (container *viewsContainerData) insert(view View, index int) bool {
|
||||
|
@ -113,9 +116,7 @@ func (container *viewsContainerData) insert(view View, index int) bool {
|
|||
func (container *viewsContainerData) Insert(view View, index int) {
|
||||
if container.insert(view, index) && container.created {
|
||||
updateInnerHTML(container.htmlID(), container.Session())
|
||||
if listener, ok := container.changeListener[Content]; ok {
|
||||
listener(container, Content)
|
||||
}
|
||||
container.contentChanged()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,9 +150,7 @@ func (container *viewsContainerData) RemoveView(index int) View {
|
|||
view := container.removeView(index)
|
||||
if view != nil && container.created {
|
||||
container.Session().callFunc("removeView", view.htmlID())
|
||||
if listener, ok := container.changeListener[Content]; ok {
|
||||
listener(container, Content)
|
||||
}
|
||||
container.contentChanged()
|
||||
}
|
||||
return view
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue