mirror of https://github.com/anoshenko/rui.git
				
				
				
			Improved binding for 2 args listeners
This commit is contained in:
		
							parent
							
								
									3c3c09b043
								
							
						
					
					
						commit
						4b00299878
					
				| 
						 | 
				
			
			@ -106,13 +106,13 @@ func (picker *colorPickerData) propertyChanged(tag PropertyName) {
 | 
			
		|||
		color := GetColorPickerValue(picker)
 | 
			
		||||
		picker.Session().callFunc("setInputValue", picker.htmlID(), color.rgbString())
 | 
			
		||||
 | 
			
		||||
		if listeners := GetColorChangedListeners(picker); len(listeners) > 0 {
 | 
			
		||||
		if listeners := getTwoArgEventListeners[ColorPicker, Color](picker, nil, ColorChangedEvent); len(listeners) > 0 {
 | 
			
		||||
			oldColor := Color(0)
 | 
			
		||||
			if value := picker.getRaw("old-color"); value != nil {
 | 
			
		||||
				oldColor = value.(Color)
 | 
			
		||||
			}
 | 
			
		||||
			for _, listener := range listeners {
 | 
			
		||||
				listener(picker, color, oldColor)
 | 
			
		||||
				listener.Run(picker, color, oldColor)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -156,8 +156,8 @@ func (picker *colorPickerData) handleCommand(self View, command PropertyName, da
 | 
			
		|||
				oldColor := GetColorPickerValue(picker)
 | 
			
		||||
				picker.properties[ColorPickerValue] = color
 | 
			
		||||
				if color != oldColor {
 | 
			
		||||
					for _, listener := range GetColorChangedListeners(picker) {
 | 
			
		||||
						listener(picker, color, oldColor)
 | 
			
		||||
					for _, listener := range getTwoArgEventListeners[ColorPicker, Color](picker, nil, ColorChangedEvent) {
 | 
			
		||||
						listener.Run(picker, color, oldColor)
 | 
			
		||||
					}
 | 
			
		||||
					if listener, ok := picker.changeListener[ColorPickerValue]; ok {
 | 
			
		||||
						listener(picker, ColorPickerValue)
 | 
			
		||||
| 
						 | 
				
			
			@ -194,8 +194,17 @@ func GetColorPickerValue(view View, subviewID ...string) Color {
 | 
			
		|||
// GetColorChangedListeners returns the ColorChangedListener list of an ColorPicker subview.
 | 
			
		||||
// If there are no listeners then the empty list is returned
 | 
			
		||||
//
 | 
			
		||||
// Result elements can be of the following types:
 | 
			
		||||
//   - func(rui.ColorPicker, rui.Color, rui.Color),
 | 
			
		||||
//   - func(rui.ColorPicker, rui.Color),
 | 
			
		||||
//   - func(rui.ColorPicker),
 | 
			
		||||
//   - func(rui.Color, rui.Color),
 | 
			
		||||
//   - func(rui.Color),
 | 
			
		||||
//   - func(),
 | 
			
		||||
//   - string.
 | 
			
		||||
//
 | 
			
		||||
// The second argument (subviewID) specifies the path to the child element whose value needs to be returned.
 | 
			
		||||
// If it is not specified then a value from the first argument (view) is returned.
 | 
			
		||||
func GetColorChangedListeners(view View, subviewID ...string) []func(ColorPicker, Color, Color) {
 | 
			
		||||
	return getTwoArgEventListeners[ColorPicker, Color](view, subviewID, ColorChangedEvent)
 | 
			
		||||
func GetColorChangedListeners(view View, subviewID ...string) []any {
 | 
			
		||||
	return getTwoArgEventRawListeners[ColorPicker, Color](view, subviewID, ColorChangedEvent)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -274,7 +274,7 @@ func (picker *datePickerData) propertyChanged(tag PropertyName) {
 | 
			
		|||
		date := GetDatePickerValue(picker)
 | 
			
		||||
		session.callFunc("setInputValue", picker.htmlID(), date.Format(dateFormat))
 | 
			
		||||
 | 
			
		||||
		if listeners := GetDateChangedListeners(picker); len(listeners) > 0 {
 | 
			
		||||
		if listeners := getTwoArgEventListeners[DatePicker, time.Time](picker, nil, DateChangedEvent); len(listeners) > 0 {
 | 
			
		||||
			oldDate := time.Now()
 | 
			
		||||
			if value := picker.getRaw("old-date"); value != nil {
 | 
			
		||||
				if date, ok := value.(time.Time); ok {
 | 
			
		||||
| 
						 | 
				
			
			@ -282,7 +282,7 @@ func (picker *datePickerData) propertyChanged(tag PropertyName) {
 | 
			
		|||
				}
 | 
			
		||||
			}
 | 
			
		||||
			for _, listener := range listeners {
 | 
			
		||||
				listener(picker, date, oldDate)
 | 
			
		||||
				listener.Run(picker, date, oldDate)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -348,8 +348,8 @@ func (picker *datePickerData) handleCommand(self View, command PropertyName, dat
 | 
			
		|||
				oldValue := GetDatePickerValue(picker)
 | 
			
		||||
				picker.properties[DatePickerValue] = value
 | 
			
		||||
				if value != oldValue {
 | 
			
		||||
					for _, listener := range GetDateChangedListeners(picker) {
 | 
			
		||||
						listener(picker, value, oldValue)
 | 
			
		||||
					for _, listener := range getTwoArgEventListeners[DatePicker, time.Time](picker, nil, DateChangedEvent) {
 | 
			
		||||
						listener.Run(picker, value, oldValue)
 | 
			
		||||
					}
 | 
			
		||||
					if listener, ok := picker.changeListener[DatePickerValue]; ok {
 | 
			
		||||
						listener(picker, DatePickerValue)
 | 
			
		||||
| 
						 | 
				
			
			@ -445,8 +445,17 @@ func GetDatePickerValue(view View, subviewID ...string) time.Time {
 | 
			
		|||
// GetDateChangedListeners returns the DateChangedListener list of an DatePicker subview.
 | 
			
		||||
// If there are no listeners then the empty list is returned
 | 
			
		||||
//
 | 
			
		||||
// Result elements can be of the following types:
 | 
			
		||||
//   - func(rui.DatePicker, time.Time, time.Time),
 | 
			
		||||
//   - func(rui.DatePicker, time.Time),
 | 
			
		||||
//   - func(rui.DatePicker),
 | 
			
		||||
//   - func(time.Time, time.Time),
 | 
			
		||||
//   - func(time.Time),
 | 
			
		||||
//   - func(),
 | 
			
		||||
//   - string.
 | 
			
		||||
//
 | 
			
		||||
// The second argument (subviewID) specifies the path to the child element whose value needs to be returned.
 | 
			
		||||
// If it is not specified then a value from the first argument (view) is returned.
 | 
			
		||||
func GetDateChangedListeners(view View, subviewID ...string) []func(DatePicker, time.Time, time.Time) {
 | 
			
		||||
	return getTwoArgEventListeners[DatePicker, time.Time](view, subviewID, DateChangedEvent)
 | 
			
		||||
func GetDateChangedListeners(view View, subviewID ...string) []any {
 | 
			
		||||
	return getTwoArgEventRawListeners[DatePicker, time.Time](view, subviewID, DateChangedEvent)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -104,8 +104,8 @@ func (list *dropDownListData) propertyChanged(tag PropertyName) {
 | 
			
		|||
		list.Session().callFunc("selectDropDownListItem", list.htmlID(), current)
 | 
			
		||||
 | 
			
		||||
		oldCurrent, _ := intProperty(list, "old-current", list.Session(), -1)
 | 
			
		||||
		for _, listener := range GetDropDownListeners(list) {
 | 
			
		||||
			listener(list, current, oldCurrent)
 | 
			
		||||
		for _, listener := range getTwoArgEventListeners[DropDownList, int](list, nil, DropDownEvent) {
 | 
			
		||||
			listener.Run(list, current, oldCurrent)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
| 
						 | 
				
			
			@ -245,8 +245,8 @@ func (list *dropDownListData) handleCommand(self View, command PropertyName, dat
 | 
			
		|||
				if GetCurrent(list) != number && number >= 0 && number < len(items) {
 | 
			
		||||
					old := GetCurrent(list)
 | 
			
		||||
					list.properties[Current] = number
 | 
			
		||||
					for _, listener := range GetDropDownListeners(list) {
 | 
			
		||||
						listener(list, number, old)
 | 
			
		||||
					for _, listener := range getTwoArgEventListeners[DropDownList, int](list, nil, DropDownEvent) {
 | 
			
		||||
						listener.Run(list, number, old)
 | 
			
		||||
					}
 | 
			
		||||
					if listener, ok := list.changeListener[Current]; ok {
 | 
			
		||||
						listener(list, Current)
 | 
			
		||||
| 
						 | 
				
			
			@ -265,10 +265,19 @@ func (list *dropDownListData) handleCommand(self View, command PropertyName, dat
 | 
			
		|||
 | 
			
		||||
// GetDropDownListeners returns the "drop-down-event" listener list. If there are no listeners then the empty list is returned.
 | 
			
		||||
//
 | 
			
		||||
// Result elements can be of the following types:
 | 
			
		||||
//   - func(rui.DropDownList, int, int),
 | 
			
		||||
//   - func(rui.DropDownList, int),
 | 
			
		||||
//   - func(rui.DropDownList),
 | 
			
		||||
//   - func(int, int),
 | 
			
		||||
//   - func(int),
 | 
			
		||||
//   - func(),
 | 
			
		||||
//   - string.
 | 
			
		||||
//
 | 
			
		||||
// The second argument (subviewID) specifies the path to the child element whose value needs to be returned.
 | 
			
		||||
// If it is not specified then a value from the first argument (view) is returned.
 | 
			
		||||
func GetDropDownListeners(view View, subviewID ...string) []func(DropDownList, int, int) {
 | 
			
		||||
	return getTwoArgEventListeners[DropDownList, int](view, subviewID, DropDownEvent)
 | 
			
		||||
func GetDropDownListeners(view View, subviewID ...string) []any {
 | 
			
		||||
	return getTwoArgEventRawListeners[DropDownList, int](view, subviewID, DropDownEvent)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetDropDownItems return the DropDownList items list.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										17
									
								
								editView.go
								
								
								
								
							
							
						
						
									
										17
									
								
								editView.go
								
								
								
								
							| 
						 | 
				
			
			@ -268,8 +268,8 @@ func (edit *editViewData) AppendText(text string) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (edit *editViewData) textChanged(newText, oldText string) {
 | 
			
		||||
	for _, listener := range GetTextChangedListeners(edit) {
 | 
			
		||||
		listener(edit, newText, oldText)
 | 
			
		||||
	for _, listener := range getTwoArgEventListeners[EditView, string](edit, nil, EditTextChangedEvent) {
 | 
			
		||||
		listener.Run(edit, newText, oldText)
 | 
			
		||||
	}
 | 
			
		||||
	if listener, ok := edit.changeListener[Text]; ok {
 | 
			
		||||
		listener(edit, Text)
 | 
			
		||||
| 
						 | 
				
			
			@ -461,10 +461,19 @@ func IsSpellcheck(view View, subviewID ...string) bool {
 | 
			
		|||
// GetTextChangedListeners returns the TextChangedListener list of an EditView or MultiLineEditView subview.
 | 
			
		||||
// If there are no listeners then the empty list is returned
 | 
			
		||||
//
 | 
			
		||||
// Result elements can be of the following types:
 | 
			
		||||
//   - func(rui.EditView, string, string),
 | 
			
		||||
//   - func(rui.EditView, string),
 | 
			
		||||
//   - func(rui.EditView),
 | 
			
		||||
//   - func(string, string),
 | 
			
		||||
//   - func(string),
 | 
			
		||||
//   - func(),
 | 
			
		||||
//   - string.
 | 
			
		||||
//
 | 
			
		||||
// The second argument (subviewID) specifies the path to the child element whose value needs to be returned.
 | 
			
		||||
// If it is not specified then a value from the first argument (view) is returned.
 | 
			
		||||
func GetTextChangedListeners(view View, subviewID ...string) []func(EditView, string, string) {
 | 
			
		||||
	return getTwoArgEventListeners[EditView, string](view, subviewID, EditTextChangedEvent)
 | 
			
		||||
func GetTextChangedListeners(view View, subviewID ...string) []any {
 | 
			
		||||
	return getTwoArgEventRawListeners[EditView, string](view, subviewID, EditTextChangedEvent)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetEditViewType returns a value of the Type property of EditView.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										589
									
								
								events.go
								
								
								
								
							
							
						
						
									
										589
									
								
								events.go
								
								
								
								
							| 
						 | 
				
			
			@ -41,161 +41,32 @@ var eventJsFunc = map[PropertyName]struct{ jsEvent, jsFunc string }{
 | 
			
		|||
	DragLeaveEvent:          {jsEvent: "ondragleave", jsFunc: "dragLeaveEvent"},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
type oneArgListener[V View, E any] interface {
 | 
			
		||||
	call(V, E)
 | 
			
		||||
	listener() func(V, E)
 | 
			
		||||
	rawListener() any
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type oneArgListener0[V View, E any] struct {
 | 
			
		||||
	fn func()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type oneArgListenerV[V View, E any] struct {
 | 
			
		||||
	fn func(V)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type oneArgListenerE[V View, E any] struct {
 | 
			
		||||
	fn func(E)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type oneArgListenerVE[V View, E any] struct {
 | 
			
		||||
	fn func(V, E)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type oneArgListenerBinding[V View, E any] struct {
 | 
			
		||||
	name string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newOneArgListener0[V View, E any](fn func()) oneArgListener[V, E] {
 | 
			
		||||
	obj := new(oneArgListener0[V, E])
 | 
			
		||||
	obj.fn = fn
 | 
			
		||||
	return obj
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *oneArgListener0[V, E]) call(_ V, _ E) {
 | 
			
		||||
	data.fn()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *oneArgListener0[V, E]) listener() func(V, E) {
 | 
			
		||||
	return data.call
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *oneArgListener0[V, E]) rawListener() any {
 | 
			
		||||
	return data.fn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newOneArgListenerV[V View, E any](fn func(V)) oneArgListener[V, E] {
 | 
			
		||||
	obj := new(oneArgListenerV[V, E])
 | 
			
		||||
	obj.fn = fn
 | 
			
		||||
	return obj
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *oneArgListenerV[V, E]) call(view V, _ E) {
 | 
			
		||||
	data.fn(view)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *oneArgListenerV[V, E]) listener() func(V, E) {
 | 
			
		||||
	return data.call
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *oneArgListenerV[V, E]) rawListener() any {
 | 
			
		||||
	return data.fn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newOneArgListenerE[V View, E any](fn func(E)) oneArgListener[V, E] {
 | 
			
		||||
	obj := new(oneArgListenerE[V, E])
 | 
			
		||||
	obj.fn = fn
 | 
			
		||||
	return obj
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *oneArgListenerE[V, E]) call(_ V, event E) {
 | 
			
		||||
	data.fn(event)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *oneArgListenerE[V, E]) listener() func(V, E) {
 | 
			
		||||
	return data.call
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *oneArgListenerE[V, E]) rawListener() any {
 | 
			
		||||
	return data.fn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newOneArgListenerVE[V View, E any](fn func(V, E)) oneArgListener[V, E] {
 | 
			
		||||
	obj := new(oneArgListenerVE[V, E])
 | 
			
		||||
	obj.fn = fn
 | 
			
		||||
	return obj
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *oneArgListenerVE[V, E]) call(view V, arg E) {
 | 
			
		||||
	data.fn(view, arg)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *oneArgListenerVE[V, E]) listener() func(V, E) {
 | 
			
		||||
	return data.fn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *oneArgListenerVE[V, E]) rawListener() any {
 | 
			
		||||
	return data.fn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newOneArgListenerBinding[V View, E any](name string) oneArgListener[V, E] {
 | 
			
		||||
	obj := new(oneArgListenerBinding[V, E])
 | 
			
		||||
	obj.name = name
 | 
			
		||||
	return obj
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *oneArgListenerBinding[V, E]) call(view V, event E) {
 | 
			
		||||
	bind := view.binding()
 | 
			
		||||
	if bind == nil {
 | 
			
		||||
		ErrorLogF(`There is no a binding object for call "%s"`, data.name)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	val := reflect.ValueOf(bind)
 | 
			
		||||
	method := val.MethodByName(data.name)
 | 
			
		||||
	if !method.IsValid() {
 | 
			
		||||
		ErrorLogF(`The "%s" method is not valid`, data.name)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	methodType := method.Type()
 | 
			
		||||
	var args []reflect.Value = nil
 | 
			
		||||
	switch methodType.NumIn() {
 | 
			
		||||
	case 0:
 | 
			
		||||
		args = []reflect.Value{}
 | 
			
		||||
 | 
			
		||||
	case 1:
 | 
			
		||||
		inType := methodType.In(0)
 | 
			
		||||
		if inType == reflect.TypeOf(view) {
 | 
			
		||||
			args = []reflect.Value{reflect.ValueOf(view)}
 | 
			
		||||
		} else if inType == reflect.TypeOf(event) {
 | 
			
		||||
			args = []reflect.Value{reflect.ValueOf(event)}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	case 2:
 | 
			
		||||
		if methodType.In(0) == reflect.TypeOf(view) && methodType.In(1) == reflect.TypeOf(event) {
 | 
			
		||||
			args = []reflect.Value{reflect.ValueOf(view), reflect.ValueOf(event)}
 | 
			
		||||
func viewEventsHtml[T any](view View, events []PropertyName, buffer *strings.Builder) {
 | 
			
		||||
	for _, tag := range events {
 | 
			
		||||
		if js, ok := eventJsFunc[tag]; ok {
 | 
			
		||||
			if value := getOneArgEventListeners[View, T](view, nil, tag); len(value) > 0 {
 | 
			
		||||
				buffer.WriteString(js.jsEvent)
 | 
			
		||||
				buffer.WriteString(`="`)
 | 
			
		||||
				buffer.WriteString(js.jsFunc)
 | 
			
		||||
				buffer.WriteString(`(this, event)" `)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	if args != nil {
 | 
			
		||||
		method.Call(args)
 | 
			
		||||
func updateEventListenerHtml(view View, tag PropertyName) {
 | 
			
		||||
	if js, ok := eventJsFunc[tag]; ok {
 | 
			
		||||
		value := view.getRaw(tag)
 | 
			
		||||
		session := view.Session()
 | 
			
		||||
		htmlID := view.htmlID()
 | 
			
		||||
		if value == nil {
 | 
			
		||||
			session.removeProperty(view.htmlID(), js.jsEvent)
 | 
			
		||||
		} else {
 | 
			
		||||
		ErrorLogF(`Unsupported prototype of "%s" method`, data.name)
 | 
			
		||||
			session.updateProperty(htmlID, js.jsEvent, js.jsFunc+"(this, event)")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *oneArgListenerBinding[V, E]) listener() func(V, E) {
 | 
			
		||||
	return data.call
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *oneArgListenerBinding[V, E]) rawListener() any {
 | 
			
		||||
	return data.name
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
func valueToNoArgEventListeners[V any](view View, value any) ([]func(V), bool) {
 | 
			
		||||
	if value == nil {
 | 
			
		||||
		return nil, true
 | 
			
		||||
| 
						 | 
				
			
			@ -303,326 +174,6 @@ func valueToNoArgEventListeners[V any](view View, value any) ([]func(V), bool) {
 | 
			
		|||
	return nil, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
	func valueToOneArgEventListeners[V View, E any](view View, value any) ([]oneArgListener[V, E], bool) {
 | 
			
		||||
		if value == nil {
 | 
			
		||||
			return nil, true
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch value := value.(type) {
 | 
			
		||||
		case string:
 | 
			
		||||
			return []oneArgListener[V, E]{newOneArgListenerBinding[V, E](value)}, true
 | 
			
		||||
 | 
			
		||||
		case func(V, E):
 | 
			
		||||
			return []oneArgListener[V, E]{newOneArgListenerVE[V, E](value)}, true
 | 
			
		||||
 | 
			
		||||
		case func(V):
 | 
			
		||||
			return []oneArgListener[V, E]{newOneArgListenerV[V, E](value)}, true
 | 
			
		||||
 | 
			
		||||
		case func(E):
 | 
			
		||||
			return []oneArgListener[V, E]{newOneArgListenerE[V, E](value)}, true
 | 
			
		||||
 | 
			
		||||
		case func():
 | 
			
		||||
			return []oneArgListener[V, E]{newOneArgListener0[V, E](value)}, true
 | 
			
		||||
 | 
			
		||||
		case []func(V, E):
 | 
			
		||||
			result := make([]oneArgListener[V, E], 0, len(value))
 | 
			
		||||
			for _, fn := range value {
 | 
			
		||||
				if fn != nil {
 | 
			
		||||
					result = append(result, newOneArgListenerVE[V, E](fn))
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			return result, len(result) > 0
 | 
			
		||||
 | 
			
		||||
		case []func(E):
 | 
			
		||||
			result := make([]oneArgListener[V, E], 0, len(value))
 | 
			
		||||
			for _, fn := range value {
 | 
			
		||||
				if fn != nil {
 | 
			
		||||
					result = append(result, newOneArgListenerE[V, E](fn))
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			return result, len(result) > 0
 | 
			
		||||
 | 
			
		||||
		case []func(V):
 | 
			
		||||
			result := make([]oneArgListener[V, E], 0, len(value))
 | 
			
		||||
			for _, fn := range value {
 | 
			
		||||
				if fn != nil {
 | 
			
		||||
					result = append(result, newOneArgListenerV[V, E](fn))
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			return result, len(result) > 0
 | 
			
		||||
 | 
			
		||||
		case []func():
 | 
			
		||||
			result := make([]oneArgListener[V, E], 0, len(value))
 | 
			
		||||
			for _, fn := range value {
 | 
			
		||||
				if fn != nil {
 | 
			
		||||
					result = append(result, newOneArgListener0[V, E](fn))
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			return result, len(result) > 0
 | 
			
		||||
 | 
			
		||||
		case []any:
 | 
			
		||||
			result := make([]oneArgListener[V, E], 0, len(value))
 | 
			
		||||
			for _, v := range value {
 | 
			
		||||
				if v != nil {
 | 
			
		||||
					switch v := v.(type) {
 | 
			
		||||
					case func(V, E):
 | 
			
		||||
						result = append(result, newOneArgListenerVE[V, E](v))
 | 
			
		||||
 | 
			
		||||
					case func(E):
 | 
			
		||||
						result = append(result, newOneArgListenerE[V, E](v))
 | 
			
		||||
 | 
			
		||||
					case func(V):
 | 
			
		||||
						result = append(result, newOneArgListenerV[V, E](v))
 | 
			
		||||
 | 
			
		||||
					case func():
 | 
			
		||||
						result = append(result, newOneArgListener0[V, E](v))
 | 
			
		||||
 | 
			
		||||
					case string:
 | 
			
		||||
						result = append(result, newOneArgListenerBinding[V, E](v))
 | 
			
		||||
 | 
			
		||||
					default:
 | 
			
		||||
						return nil, false
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			return result, len(result) > 0
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return nil, false
 | 
			
		||||
	}
 | 
			
		||||
*/
 | 
			
		||||
func valueToTwoArgEventListeners[V View, E any](view View, value any) ([]func(V, E, E), bool) {
 | 
			
		||||
	if value == nil {
 | 
			
		||||
		return nil, true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch value := value.(type) {
 | 
			
		||||
	case string:
 | 
			
		||||
		fn := func(view V, val1 E, val2 E) {
 | 
			
		||||
			bind := view.binding()
 | 
			
		||||
			if bind == nil {
 | 
			
		||||
				ErrorLogF(`There is no a binding object for call "%s"`, value)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			val := reflect.ValueOf(bind)
 | 
			
		||||
			method := val.MethodByName(value)
 | 
			
		||||
			if !method.IsValid() {
 | 
			
		||||
				ErrorLogF(`The "%s" method is not valid`, value)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			methodType := method.Type()
 | 
			
		||||
			var args []reflect.Value = nil
 | 
			
		||||
			switch methodType.NumIn() {
 | 
			
		||||
			case 0:
 | 
			
		||||
				args = []reflect.Value{}
 | 
			
		||||
 | 
			
		||||
			case 1:
 | 
			
		||||
				inType := methodType.In(0)
 | 
			
		||||
				if inType == reflect.TypeOf(view) {
 | 
			
		||||
					args = []reflect.Value{reflect.ValueOf(view)}
 | 
			
		||||
				} else if inType == reflect.TypeOf(val1) {
 | 
			
		||||
					args = []reflect.Value{reflect.ValueOf(val1)}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			case 2:
 | 
			
		||||
				valType := reflect.TypeOf(val1)
 | 
			
		||||
				if methodType.In(0) == reflect.TypeOf(view) && methodType.In(1) == valType {
 | 
			
		||||
					args = []reflect.Value{reflect.ValueOf(view), reflect.ValueOf(val1)}
 | 
			
		||||
				} else if methodType.In(0) == valType && methodType.In(1) == valType {
 | 
			
		||||
					args = []reflect.Value{reflect.ValueOf(val1), reflect.ValueOf(val2)}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			case 3:
 | 
			
		||||
				valType := reflect.TypeOf(val1)
 | 
			
		||||
				if methodType.In(0) == reflect.TypeOf(view) && methodType.In(1) == valType && methodType.In(2) == valType {
 | 
			
		||||
					args = []reflect.Value{reflect.ValueOf(view), reflect.ValueOf(val1), reflect.ValueOf(val2)}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if args != nil {
 | 
			
		||||
				method.Call(args)
 | 
			
		||||
			} else {
 | 
			
		||||
				ErrorLogF(`Unsupported prototype of "%s" method`, value)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return []func(V, E, E){fn}, true
 | 
			
		||||
 | 
			
		||||
	case func(V, E, E):
 | 
			
		||||
		return []func(V, E, E){value}, true
 | 
			
		||||
 | 
			
		||||
	case func(V, E):
 | 
			
		||||
		fn := func(v V, val, _ E) {
 | 
			
		||||
			value(v, val)
 | 
			
		||||
		}
 | 
			
		||||
		return []func(V, E, E){fn}, true
 | 
			
		||||
 | 
			
		||||
	case func(E, E):
 | 
			
		||||
		fn := func(_ V, val, old E) {
 | 
			
		||||
			value(val, old)
 | 
			
		||||
		}
 | 
			
		||||
		return []func(V, E, E){fn}, true
 | 
			
		||||
 | 
			
		||||
	case func(E):
 | 
			
		||||
		fn := func(_ V, val, _ E) {
 | 
			
		||||
			value(val)
 | 
			
		||||
		}
 | 
			
		||||
		return []func(V, E, E){fn}, true
 | 
			
		||||
 | 
			
		||||
	case func(V):
 | 
			
		||||
		fn := func(v V, _, _ E) {
 | 
			
		||||
			value(v)
 | 
			
		||||
		}
 | 
			
		||||
		return []func(V, E, E){fn}, true
 | 
			
		||||
 | 
			
		||||
	case func():
 | 
			
		||||
		fn := func(V, E, E) {
 | 
			
		||||
			value()
 | 
			
		||||
		}
 | 
			
		||||
		return []func(V, E, E){fn}, true
 | 
			
		||||
 | 
			
		||||
	case []func(V, E, E):
 | 
			
		||||
		if len(value) == 0 {
 | 
			
		||||
			return nil, true
 | 
			
		||||
		}
 | 
			
		||||
		for _, fn := range value {
 | 
			
		||||
			if fn == nil {
 | 
			
		||||
				return nil, false
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return value, true
 | 
			
		||||
 | 
			
		||||
	case []func(V, E):
 | 
			
		||||
		count := len(value)
 | 
			
		||||
		if count == 0 {
 | 
			
		||||
			return nil, true
 | 
			
		||||
		}
 | 
			
		||||
		listeners := make([]func(V, E, E), count)
 | 
			
		||||
		for i, fn := range value {
 | 
			
		||||
			if fn == nil {
 | 
			
		||||
				return nil, false
 | 
			
		||||
			}
 | 
			
		||||
			listeners[i] = func(view V, val, _ E) {
 | 
			
		||||
				fn(view, val)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return listeners, true
 | 
			
		||||
 | 
			
		||||
	case []func(E):
 | 
			
		||||
		count := len(value)
 | 
			
		||||
		if count == 0 {
 | 
			
		||||
			return nil, true
 | 
			
		||||
		}
 | 
			
		||||
		listeners := make([]func(V, E, E), count)
 | 
			
		||||
		for i, fn := range value {
 | 
			
		||||
			if fn == nil {
 | 
			
		||||
				return nil, false
 | 
			
		||||
			}
 | 
			
		||||
			listeners[i] = func(_ V, val, _ E) {
 | 
			
		||||
				fn(val)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return listeners, true
 | 
			
		||||
 | 
			
		||||
	case []func(E, E):
 | 
			
		||||
		count := len(value)
 | 
			
		||||
		if count == 0 {
 | 
			
		||||
			return nil, true
 | 
			
		||||
		}
 | 
			
		||||
		listeners := make([]func(V, E, E), count)
 | 
			
		||||
		for i, fn := range value {
 | 
			
		||||
			if fn == nil {
 | 
			
		||||
				return nil, false
 | 
			
		||||
			}
 | 
			
		||||
			listeners[i] = func(_ V, val, old E) {
 | 
			
		||||
				fn(val, old)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return listeners, true
 | 
			
		||||
 | 
			
		||||
	case []func(V):
 | 
			
		||||
		count := len(value)
 | 
			
		||||
		if count == 0 {
 | 
			
		||||
			return nil, true
 | 
			
		||||
		}
 | 
			
		||||
		listeners := make([]func(V, E, E), count)
 | 
			
		||||
		for i, fn := range value {
 | 
			
		||||
			if fn == nil {
 | 
			
		||||
				return nil, false
 | 
			
		||||
			}
 | 
			
		||||
			listeners[i] = func(view V, _, _ E) {
 | 
			
		||||
				fn(view)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return listeners, true
 | 
			
		||||
 | 
			
		||||
	case []func():
 | 
			
		||||
		count := len(value)
 | 
			
		||||
		if count == 0 {
 | 
			
		||||
			return nil, true
 | 
			
		||||
		}
 | 
			
		||||
		listeners := make([]func(V, E, E), count)
 | 
			
		||||
		for i, fn := range value {
 | 
			
		||||
			if fn == nil {
 | 
			
		||||
				return nil, false
 | 
			
		||||
			}
 | 
			
		||||
			listeners[i] = func(V, E, E) {
 | 
			
		||||
				fn()
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return listeners, true
 | 
			
		||||
 | 
			
		||||
	case []any:
 | 
			
		||||
		count := len(value)
 | 
			
		||||
		if count == 0 {
 | 
			
		||||
			return nil, true
 | 
			
		||||
		}
 | 
			
		||||
		listeners := make([]func(V, E, E), count)
 | 
			
		||||
		for i, v := range value {
 | 
			
		||||
			if v == nil {
 | 
			
		||||
				return nil, false
 | 
			
		||||
			}
 | 
			
		||||
			switch fn := v.(type) {
 | 
			
		||||
			case func(V, E, E):
 | 
			
		||||
				listeners[i] = fn
 | 
			
		||||
 | 
			
		||||
			case func(V, E):
 | 
			
		||||
				listeners[i] = func(view V, val, _ E) {
 | 
			
		||||
					fn(view, val)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			case func(E, E):
 | 
			
		||||
				listeners[i] = func(_ V, val, old E) {
 | 
			
		||||
					fn(val, old)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			case func(E):
 | 
			
		||||
				listeners[i] = func(_ V, val, _ E) {
 | 
			
		||||
					fn(val)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			case func(V):
 | 
			
		||||
				listeners[i] = func(view V, _, _ E) {
 | 
			
		||||
					fn(view)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			case func():
 | 
			
		||||
				listeners[i] = func(V, E, E) {
 | 
			
		||||
					fn()
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			default:
 | 
			
		||||
				return nil, false
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return listeners, true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getNoArgEventListeners[V View](view View, subviewID []string, tag PropertyName) []func(V) {
 | 
			
		||||
	if view = getSubview(view, subviewID); view != nil {
 | 
			
		||||
		if value := view.Get(tag); value != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -634,38 +185,6 @@ func getNoArgEventListeners[V View](view View, subviewID []string, tag PropertyN
 | 
			
		|||
	return []func(V){}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
	func getOneArgEventListeners[V View, E any](view View, subviewID []string, tag PropertyName) []oneArgListener[V, E] {
 | 
			
		||||
		if view = getSubview(view, subviewID); view != nil {
 | 
			
		||||
			if value := view.Get(tag); value != nil {
 | 
			
		||||
				if result, ok := value.([]oneArgListener[V, E]); ok {
 | 
			
		||||
					return result
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return []oneArgListener[V, E]{}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	func getOneArgEventRawListeners[V View, E any](view View, subviewID []string, tag PropertyName) []any {
 | 
			
		||||
		listeners := getOneArgEventListeners[V, E](view, subviewID, tag)
 | 
			
		||||
		result := make([]any, len(listeners))
 | 
			
		||||
		for i, l := range listeners {
 | 
			
		||||
			result[i] = l.rawListener()
 | 
			
		||||
		}
 | 
			
		||||
		return result
 | 
			
		||||
	}
 | 
			
		||||
*/
 | 
			
		||||
func getTwoArgEventListeners[V View, E any](view View, subviewID []string, tag PropertyName) []func(V, E, E) {
 | 
			
		||||
	if view = getSubview(view, subviewID); view != nil {
 | 
			
		||||
		if value := view.Get(tag); value != nil {
 | 
			
		||||
			if result, ok := value.([]func(V, E, E)); ok {
 | 
			
		||||
				return result
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return []func(V, E, E){}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func setNoArgEventListener[V View](view View, tag PropertyName, value any) []PropertyName {
 | 
			
		||||
	if listeners, ok := valueToNoArgEventListeners[V](view, value); ok {
 | 
			
		||||
		if len(listeners) > 0 {
 | 
			
		||||
| 
						 | 
				
			
			@ -680,73 +199,3 @@ func setNoArgEventListener[V View](view View, tag PropertyName, value any) []Pro
 | 
			
		|||
	notCompatibleType(tag, value)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
func setOneArgEventListener[V View, T any](view View, tag PropertyName, value any) []PropertyName {
 | 
			
		||||
	if listeners, ok := valueToOneArgEventListeners[V, T](view, value); ok {
 | 
			
		||||
		if len(listeners) > 0 {
 | 
			
		||||
			view.setRaw(tag, listeners)
 | 
			
		||||
		} else if view.getRaw(tag) != nil {
 | 
			
		||||
			view.setRaw(tag, nil)
 | 
			
		||||
		} else {
 | 
			
		||||
			return []PropertyName{}
 | 
			
		||||
		}
 | 
			
		||||
		return []PropertyName{tag}
 | 
			
		||||
	}
 | 
			
		||||
	notCompatibleType(tag, value)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
func setTwoArgEventListener[V View, T any](view View, tag PropertyName, value any) []PropertyName {
 | 
			
		||||
	listeners, ok := valueToTwoArgEventListeners[V, T](view, value)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		notCompatibleType(tag, value)
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	if len(listeners) > 0 {
 | 
			
		||||
		view.setRaw(tag, listeners)
 | 
			
		||||
	} else if view.getRaw(tag) != nil {
 | 
			
		||||
		view.setRaw(tag, nil)
 | 
			
		||||
	} else {
 | 
			
		||||
		return []PropertyName{}
 | 
			
		||||
	}
 | 
			
		||||
	return []PropertyName{tag}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func viewEventsHtml[T any](view View, events []PropertyName, buffer *strings.Builder) {
 | 
			
		||||
	for _, tag := range events {
 | 
			
		||||
		if js, ok := eventJsFunc[tag]; ok {
 | 
			
		||||
			if value := getOneArgEventListeners[View, T](view, nil, tag); len(value) > 0 {
 | 
			
		||||
				buffer.WriteString(js.jsEvent)
 | 
			
		||||
				buffer.WriteString(`="`)
 | 
			
		||||
				buffer.WriteString(js.jsFunc)
 | 
			
		||||
				buffer.WriteString(`(this, event)" `)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		/*if value := view.getRaw(tag); value != nil {
 | 
			
		||||
			if js, ok := eventJsFunc[tag]; ok {
 | 
			
		||||
				if listeners, ok := value.([] func(View, T)); ok && len(listeners) > 0 {
 | 
			
		||||
					buffer.WriteString(js.jsEvent)
 | 
			
		||||
					buffer.WriteString(`="`)
 | 
			
		||||
					buffer.WriteString(js.jsFunc)
 | 
			
		||||
					buffer.WriteString(`(this, event)" `)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		*/
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func updateEventListenerHtml(view View, tag PropertyName) {
 | 
			
		||||
	if js, ok := eventJsFunc[tag]; ok {
 | 
			
		||||
		value := view.getRaw(tag)
 | 
			
		||||
		session := view.Session()
 | 
			
		||||
		htmlID := view.htmlID()
 | 
			
		||||
		if value == nil {
 | 
			
		||||
			session.removeProperty(view.htmlID(), js.jsEvent)
 | 
			
		||||
		} else {
 | 
			
		||||
			session.updateProperty(htmlID, js.jsEvent, js.jsFunc+"(this, event)")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,339 @@
 | 
			
		|||
package rui
 | 
			
		||||
 | 
			
		||||
import "reflect"
 | 
			
		||||
 | 
			
		||||
type twoArgListener[V View, E any] interface {
 | 
			
		||||
	Run(V, E, E)
 | 
			
		||||
	rawListener() any
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type twoArgListener0[V View, E any] struct {
 | 
			
		||||
	fn func()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type twoArgListenerV[V View, E any] struct {
 | 
			
		||||
	fn func(V)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type twoArgListenerE[V View, E any] struct {
 | 
			
		||||
	fn func(E)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type twoArgListenerVE[V View, E any] struct {
 | 
			
		||||
	fn func(V, E)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type twoArgListenerEE[V View, E any] struct {
 | 
			
		||||
	fn func(E, E)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type twoArgListenerVEE[V View, E any] struct {
 | 
			
		||||
	fn func(V, E, E)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type twoArgListenerBinding[V View, E any] struct {
 | 
			
		||||
	name string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newTwoArgListener0[V View, E any](fn func()) twoArgListener[V, E] {
 | 
			
		||||
	obj := new(twoArgListener0[V, E])
 | 
			
		||||
	obj.fn = fn
 | 
			
		||||
	return obj
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *twoArgListener0[V, E]) Run(_ V, _ E, _ E) {
 | 
			
		||||
	data.fn()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *twoArgListener0[V, E]) rawListener() any {
 | 
			
		||||
	return data.fn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newTwoArgListenerV[V View, E any](fn func(V)) twoArgListener[V, E] {
 | 
			
		||||
	obj := new(twoArgListenerV[V, E])
 | 
			
		||||
	obj.fn = fn
 | 
			
		||||
	return obj
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *twoArgListenerV[V, E]) Run(view V, _ E, _ E) {
 | 
			
		||||
	data.fn(view)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *twoArgListenerV[V, E]) rawListener() any {
 | 
			
		||||
	return data.fn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newTwoArgListenerE[V View, E any](fn func(E)) twoArgListener[V, E] {
 | 
			
		||||
	obj := new(twoArgListenerE[V, E])
 | 
			
		||||
	obj.fn = fn
 | 
			
		||||
	return obj
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *twoArgListenerE[V, E]) Run(_ V, arg E, _ E) {
 | 
			
		||||
	data.fn(arg)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *twoArgListenerE[V, E]) rawListener() any {
 | 
			
		||||
	return data.fn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newTwoArgListenerVE[V View, E any](fn func(V, E)) twoArgListener[V, E] {
 | 
			
		||||
	obj := new(twoArgListenerVE[V, E])
 | 
			
		||||
	obj.fn = fn
 | 
			
		||||
	return obj
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *twoArgListenerVE[V, E]) Run(view V, arg E, _ E) {
 | 
			
		||||
	data.fn(view, arg)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *twoArgListenerVE[V, E]) rawListener() any {
 | 
			
		||||
	return data.fn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newTwoArgListenerEE[V View, E any](fn func(E, E)) twoArgListener[V, E] {
 | 
			
		||||
	obj := new(twoArgListenerEE[V, E])
 | 
			
		||||
	obj.fn = fn
 | 
			
		||||
	return obj
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *twoArgListenerEE[V, E]) Run(_ V, arg1 E, arg2 E) {
 | 
			
		||||
	data.fn(arg1, arg2)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *twoArgListenerEE[V, E]) rawListener() any {
 | 
			
		||||
	return data.fn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newTwoArgListenerVEE[V View, E any](fn func(V, E, E)) twoArgListener[V, E] {
 | 
			
		||||
	obj := new(twoArgListenerVEE[V, E])
 | 
			
		||||
	obj.fn = fn
 | 
			
		||||
	return obj
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *twoArgListenerVEE[V, E]) Run(view V, arg1 E, arg2 E) {
 | 
			
		||||
	data.fn(view, arg1, arg2)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *twoArgListenerVEE[V, E]) rawListener() any {
 | 
			
		||||
	return data.fn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newTwoArgListenerBinding[V View, E any](name string) twoArgListener[V, E] {
 | 
			
		||||
	obj := new(twoArgListenerBinding[V, E])
 | 
			
		||||
	obj.name = name
 | 
			
		||||
	return obj
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *twoArgListenerBinding[V, E]) Run(view V, arg1 E, arg2 E) {
 | 
			
		||||
	bind := view.binding()
 | 
			
		||||
	if bind == nil {
 | 
			
		||||
		ErrorLogF(`There is no a binding object for call "%s"`, data.name)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	val := reflect.ValueOf(bind)
 | 
			
		||||
	method := val.MethodByName(data.name)
 | 
			
		||||
	if !method.IsValid() {
 | 
			
		||||
		ErrorLogF(`The "%s" method is not valid`, data.name)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	methodType := method.Type()
 | 
			
		||||
	var args []reflect.Value = nil
 | 
			
		||||
	switch methodType.NumIn() {
 | 
			
		||||
	case 0:
 | 
			
		||||
		args = []reflect.Value{}
 | 
			
		||||
 | 
			
		||||
	case 1:
 | 
			
		||||
		inType := methodType.In(0)
 | 
			
		||||
		if inType == reflect.TypeOf(view) {
 | 
			
		||||
			args = []reflect.Value{reflect.ValueOf(view)}
 | 
			
		||||
		} else if inType == reflect.TypeOf(arg1) {
 | 
			
		||||
			args = []reflect.Value{reflect.ValueOf(arg1)}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	case 2:
 | 
			
		||||
		valType := reflect.TypeOf(arg1)
 | 
			
		||||
		if methodType.In(0) == reflect.TypeOf(view) && methodType.In(1) == valType {
 | 
			
		||||
			args = []reflect.Value{reflect.ValueOf(view), reflect.ValueOf(arg1)}
 | 
			
		||||
		} else if methodType.In(0) == valType && methodType.In(1) == valType {
 | 
			
		||||
			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 {
 | 
			
		||||
			args = []reflect.Value{reflect.ValueOf(view), reflect.ValueOf(arg1), reflect.ValueOf(arg2)}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if args != nil {
 | 
			
		||||
		method.Call(args)
 | 
			
		||||
	} else {
 | 
			
		||||
		ErrorLogF(`Unsupported prototype of "%s" method`, data.name)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (data *twoArgListenerBinding[V, E]) rawListener() any {
 | 
			
		||||
	return data.name
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func valueToTwoArgEventListeners[V View, E any](value any) ([]twoArgListener[V, E], bool) {
 | 
			
		||||
	if value == nil {
 | 
			
		||||
		return nil, true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch value := value.(type) {
 | 
			
		||||
	case []twoArgListener[V, E]:
 | 
			
		||||
		return value, true
 | 
			
		||||
 | 
			
		||||
	case twoArgListener[V, E]:
 | 
			
		||||
		return []twoArgListener[V, E]{value}, true
 | 
			
		||||
 | 
			
		||||
	case string:
 | 
			
		||||
		return []twoArgListener[V, E]{newTwoArgListenerBinding[V, E](value)}, true
 | 
			
		||||
 | 
			
		||||
	case func(V, E):
 | 
			
		||||
		return []twoArgListener[V, E]{newTwoArgListenerVE(value)}, true
 | 
			
		||||
 | 
			
		||||
	case func(V):
 | 
			
		||||
		return []twoArgListener[V, E]{newTwoArgListenerV[V, E](value)}, true
 | 
			
		||||
 | 
			
		||||
	case func(E):
 | 
			
		||||
		return []twoArgListener[V, E]{newTwoArgListenerE[V](value)}, true
 | 
			
		||||
 | 
			
		||||
	case func():
 | 
			
		||||
		return []twoArgListener[V, E]{newTwoArgListener0[V, E](value)}, true
 | 
			
		||||
 | 
			
		||||
	case func(E, E):
 | 
			
		||||
		return []twoArgListener[V, E]{newTwoArgListenerEE[V](value)}, true
 | 
			
		||||
 | 
			
		||||
	case func(V, E, E):
 | 
			
		||||
		return []twoArgListener[V, E]{newTwoArgListenerVEE(value)}, true
 | 
			
		||||
 | 
			
		||||
	case []func(V, E):
 | 
			
		||||
		result := make([]twoArgListener[V, E], 0, len(value))
 | 
			
		||||
		for _, fn := range value {
 | 
			
		||||
			if fn != nil {
 | 
			
		||||
				result = append(result, newTwoArgListenerVE(fn))
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return result, len(result) > 0
 | 
			
		||||
 | 
			
		||||
	case []func(E):
 | 
			
		||||
		result := make([]twoArgListener[V, E], 0, len(value))
 | 
			
		||||
		for _, fn := range value {
 | 
			
		||||
			if fn != nil {
 | 
			
		||||
				result = append(result, newTwoArgListenerE[V](fn))
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return result, len(result) > 0
 | 
			
		||||
 | 
			
		||||
	case []func(V):
 | 
			
		||||
		result := make([]twoArgListener[V, E], 0, len(value))
 | 
			
		||||
		for _, fn := range value {
 | 
			
		||||
			if fn != nil {
 | 
			
		||||
				result = append(result, newTwoArgListenerV[V, E](fn))
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return result, len(result) > 0
 | 
			
		||||
 | 
			
		||||
	case []func():
 | 
			
		||||
		result := make([]twoArgListener[V, E], 0, len(value))
 | 
			
		||||
		for _, fn := range value {
 | 
			
		||||
			if fn != nil {
 | 
			
		||||
				result = append(result, newTwoArgListener0[V, E](fn))
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return result, len(result) > 0
 | 
			
		||||
 | 
			
		||||
	case []func(E, E):
 | 
			
		||||
		result := make([]twoArgListener[V, E], 0, len(value))
 | 
			
		||||
		for _, fn := range value {
 | 
			
		||||
			if fn != nil {
 | 
			
		||||
				result = append(result, newTwoArgListenerEE[V](fn))
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return result, len(result) > 0
 | 
			
		||||
 | 
			
		||||
	case []func(V, E, E):
 | 
			
		||||
		result := make([]twoArgListener[V, E], 0, len(value))
 | 
			
		||||
		for _, fn := range value {
 | 
			
		||||
			if fn != nil {
 | 
			
		||||
				result = append(result, newTwoArgListenerVEE(fn))
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return result, len(result) > 0
 | 
			
		||||
 | 
			
		||||
	case []any:
 | 
			
		||||
		result := make([]twoArgListener[V, E], 0, len(value))
 | 
			
		||||
		for _, v := range value {
 | 
			
		||||
			if v != nil {
 | 
			
		||||
				switch v := v.(type) {
 | 
			
		||||
				case func(V, E):
 | 
			
		||||
					result = append(result, newTwoArgListenerVE(v))
 | 
			
		||||
 | 
			
		||||
				case func(E):
 | 
			
		||||
					result = append(result, newTwoArgListenerE[V](v))
 | 
			
		||||
 | 
			
		||||
				case func(V):
 | 
			
		||||
					result = append(result, newTwoArgListenerV[V, E](v))
 | 
			
		||||
 | 
			
		||||
				case func():
 | 
			
		||||
					result = append(result, newTwoArgListener0[V, E](v))
 | 
			
		||||
 | 
			
		||||
				case func(E, E):
 | 
			
		||||
					result = append(result, newTwoArgListenerEE[V](v))
 | 
			
		||||
 | 
			
		||||
				case func(V, E, E):
 | 
			
		||||
					result = append(result, newTwoArgListenerVEE(v))
 | 
			
		||||
 | 
			
		||||
				case string:
 | 
			
		||||
					result = append(result, newTwoArgListenerBinding[V, E](v))
 | 
			
		||||
 | 
			
		||||
				default:
 | 
			
		||||
					return nil, false
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return result, len(result) > 0
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func setTwoArgEventListener[V View, T any](view View, tag PropertyName, value any) []PropertyName {
 | 
			
		||||
	if listeners, ok := valueToTwoArgEventListeners[V, T](value); ok {
 | 
			
		||||
		if len(listeners) > 0 {
 | 
			
		||||
			view.setRaw(tag, listeners)
 | 
			
		||||
		} else if view.getRaw(tag) != nil {
 | 
			
		||||
			view.setRaw(tag, nil)
 | 
			
		||||
		} else {
 | 
			
		||||
			return []PropertyName{}
 | 
			
		||||
		}
 | 
			
		||||
		return []PropertyName{tag}
 | 
			
		||||
	}
 | 
			
		||||
	notCompatibleType(tag, value)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getTwoArgEventListeners[V View, E any](view View, subviewID []string, tag PropertyName) []twoArgListener[V, E] {
 | 
			
		||||
	if view = getSubview(view, subviewID); view != nil {
 | 
			
		||||
		if value := view.Get(tag); value != nil {
 | 
			
		||||
			if result, ok := value.([]twoArgListener[V, E]); ok {
 | 
			
		||||
				return result
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return []twoArgListener[V, E]{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getTwoArgEventRawListeners[V View, E any](view View, subviewID []string, tag PropertyName) []any {
 | 
			
		||||
	listeners := getTwoArgEventListeners[V, E](view, subviewID, tag)
 | 
			
		||||
	result := make([]any, len(listeners))
 | 
			
		||||
	for i, l := range listeners {
 | 
			
		||||
		result[i] = l.rawListener()
 | 
			
		||||
	}
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -201,7 +201,7 @@ func (picker *numberPickerData) propertyChanged(tag PropertyName) {
 | 
			
		|||
		format := picker.numberFormat()
 | 
			
		||||
		picker.Session().callFunc("setInputValue", picker.htmlID(), fmt.Sprintf(format, value))
 | 
			
		||||
 | 
			
		||||
		if listeners := GetNumberChangedListeners(picker); len(listeners) > 0 {
 | 
			
		||||
		if listeners := getTwoArgEventListeners[NumberPicker, float64](picker, nil, NumberChangedEvent); len(listeners) > 0 {
 | 
			
		||||
			old := 0.0
 | 
			
		||||
			if val := picker.getRaw("old-number"); val != nil {
 | 
			
		||||
				if n, ok := val.(float64); ok {
 | 
			
		||||
| 
						 | 
				
			
			@ -210,7 +210,7 @@ func (picker *numberPickerData) propertyChanged(tag PropertyName) {
 | 
			
		|||
			}
 | 
			
		||||
			if old != value {
 | 
			
		||||
				for _, listener := range listeners {
 | 
			
		||||
					listener(picker, value, old)
 | 
			
		||||
					listener.Run(picker, value, old)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -280,8 +280,8 @@ func (picker *numberPickerData) handleCommand(self View, command PropertyName, d
 | 
			
		|||
				oldValue := GetNumberPickerValue(picker)
 | 
			
		||||
				picker.properties[NumberPickerValue] = text
 | 
			
		||||
				if value != oldValue {
 | 
			
		||||
					for _, listener := range GetNumberChangedListeners(picker) {
 | 
			
		||||
						listener(picker, value, oldValue)
 | 
			
		||||
					for _, listener := range getTwoArgEventListeners[NumberPicker, float64](picker, nil, NumberChangedEvent) {
 | 
			
		||||
						listener.Run(picker, value, oldValue)
 | 
			
		||||
					}
 | 
			
		||||
					if listener, ok := picker.changeListener[NumberPickerValue]; ok {
 | 
			
		||||
						listener(picker, NumberPickerValue)
 | 
			
		||||
| 
						 | 
				
			
			@ -359,10 +359,19 @@ func GetNumberPickerValue(view View, subviewID ...string) float64 {
 | 
			
		|||
// GetNumberChangedListeners returns the NumberChangedListener list of an NumberPicker subview.
 | 
			
		||||
// If there are no listeners then the empty list is returned
 | 
			
		||||
//
 | 
			
		||||
// Result elements can be of the following types:
 | 
			
		||||
//   - func(rui.NumberPicker, float64, float64),
 | 
			
		||||
//   - func(rui.NumberPicker, float64),
 | 
			
		||||
//   - func(rui.NumberPicker),
 | 
			
		||||
//   - func(float64, float64),
 | 
			
		||||
//   - func(float64),
 | 
			
		||||
//   - func(),
 | 
			
		||||
//   - string.
 | 
			
		||||
//
 | 
			
		||||
// The second argument (subviewID) specifies the path to the child element whose value needs to be returned.
 | 
			
		||||
// If it is not specified then a value from the first argument (view) is returned.
 | 
			
		||||
func GetNumberChangedListeners(view View, subviewID ...string) []func(NumberPicker, float64, float64) {
 | 
			
		||||
	return getTwoArgEventListeners[NumberPicker, float64](view, subviewID, NumberChangedEvent)
 | 
			
		||||
func GetNumberChangedListeners(view View, subviewID ...string) []any {
 | 
			
		||||
	return getTwoArgEventRawListeners[NumberPicker, float64](view, subviewID, NumberChangedEvent)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetNumberPickerPrecision returns the precision of displaying fractional part in editor of NumberPicker subview.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										19
									
								
								tableView.go
								
								
								
								
							
							
						
						
									
										19
									
								
								tableView.go
								
								
								
								
							| 
						 | 
				
			
			@ -845,8 +845,17 @@ func (table *tableViewData) propertyChanged(tag PropertyName) {
 | 
			
		|||
			current := tableViewCurrent(table)
 | 
			
		||||
			session.callFunc("setTableCellCursorByID", htmlID, current.Row, current.Column)
 | 
			
		||||
 | 
			
		||||
			for _, listener := range getTwoArgEventListeners[TableView, int](table, nil, TableCellSelectedEvent) {
 | 
			
		||||
				listener.Run(table, current.Row, current.Column)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		case RowSelection:
 | 
			
		||||
			session.callFunc("setTableRowCursorByID", htmlID, tableViewCurrent(table).Row)
 | 
			
		||||
			current := tableViewCurrent(table)
 | 
			
		||||
			session.callFunc("setTableRowCursorByID", htmlID, current.Row)
 | 
			
		||||
 | 
			
		||||
			for _, listener := range getOneArgEventListeners[TableView, int](table, nil, TableRowSelectedEvent) {
 | 
			
		||||
				listener.Run(table, current.Row)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	case Gap:
 | 
			
		||||
| 
						 | 
				
			
			@ -1687,8 +1696,8 @@ func (table *tableViewData) handleCommand(self View, command PropertyName, data
 | 
			
		|||
						listener(table, Current)
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					for _, listener := range GetTableCellSelectedListeners(table) {
 | 
			
		||||
						listener(table, row, column)
 | 
			
		||||
					for _, listener := range getTwoArgEventListeners[TableView, int](table, nil, TableCellSelectedEvent) {
 | 
			
		||||
						listener.Run(table, row, column)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -1704,8 +1713,8 @@ func (table *tableViewData) handleCommand(self View, command PropertyName, data
 | 
			
		|||
	case "cellClick":
 | 
			
		||||
		if row, ok := dataIntProperty(data, "row"); ok {
 | 
			
		||||
			if column, ok := dataIntProperty(data, "column"); ok {
 | 
			
		||||
				for _, listener := range GetTableCellClickedListeners(table) {
 | 
			
		||||
					listener(table, row, column)
 | 
			
		||||
				for _, listener := range getTwoArgEventListeners[TableView, int](table, nil, TableCellClickedEvent) {
 | 
			
		||||
					listener.Run(table, row, column)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -149,19 +149,37 @@ func GetTableCurrent(view View, subviewID ...string) CellIndex {
 | 
			
		|||
// 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.
 | 
			
		||||
//
 | 
			
		||||
// Result elements can be of the following types:
 | 
			
		||||
//   - func(rui.TableView, int, int),
 | 
			
		||||
//   - func(rui.TableView, int),
 | 
			
		||||
//   - func(rui.TableView),
 | 
			
		||||
//   - func(int, int),
 | 
			
		||||
//   - func(int),
 | 
			
		||||
//   - func(),
 | 
			
		||||
//   - string.
 | 
			
		||||
//
 | 
			
		||||
// The second argument (subviewID) specifies the path to the child element whose value needs to be returned.
 | 
			
		||||
// If it is not specified then a value from the first argument (view) is returned.
 | 
			
		||||
func GetTableCellClickedListeners(view View, subviewID ...string) []func(TableView, int, int) {
 | 
			
		||||
	return getTwoArgEventListeners[TableView, int](view, subviewID, TableCellClickedEvent)
 | 
			
		||||
func GetTableCellClickedListeners(view View, subviewID ...string) []any {
 | 
			
		||||
	return getTwoArgEventRawListeners[TableView, int](view, subviewID, TableCellClickedEvent)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetTableCellSelectedListeners returns listeners of event which occurs when a table cell becomes selected.
 | 
			
		||||
// If there are no listeners then the empty list is returned.
 | 
			
		||||
//
 | 
			
		||||
// Result elements can be of the following types:
 | 
			
		||||
//   - func(rui.TableView, int, int),
 | 
			
		||||
//   - func(rui.TableView, int),
 | 
			
		||||
//   - func(rui.TableView),
 | 
			
		||||
//   - func(int, int),
 | 
			
		||||
//   - func(int),
 | 
			
		||||
//   - func(),
 | 
			
		||||
//   - string.
 | 
			
		||||
//
 | 
			
		||||
// The second argument (subviewID) specifies the path to the child element whose value needs to be returned.
 | 
			
		||||
// If it is not specified then a value from the first argument (view) is returned.
 | 
			
		||||
func GetTableCellSelectedListeners(view View, subviewID ...string) []func(TableView, int, int) {
 | 
			
		||||
	return getTwoArgEventListeners[TableView, int](view, subviewID, TableCellSelectedEvent)
 | 
			
		||||
func GetTableCellSelectedListeners(view View, subviewID ...string) []any {
 | 
			
		||||
	return getTwoArgEventRawListeners[TableView, int](view, subviewID, TableCellSelectedEvent)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetTableRowClickedListeners returns listeners of event which occurs when the user clicks on a table row.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -211,7 +211,7 @@ func (tabsLayout *tabsLayoutData) propertyChanged(tag PropertyName) {
 | 
			
		|||
		if listeners := getTwoArgEventListeners[TabsLayout, int](tabsLayout, nil, CurrentTabChangedEvent); len(listeners) > 0 {
 | 
			
		||||
			oldCurrent, _ := intProperty(tabsLayout, "old-current", session, -1)
 | 
			
		||||
			for _, listener := range listeners {
 | 
			
		||||
				listener(tabsLayout, current, oldCurrent)
 | 
			
		||||
				listener.Run(tabsLayout, current, oldCurrent)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -427,7 +427,7 @@ func (tabsLayout *tabsLayoutData) Insert(view View, index int) {
 | 
			
		|||
 | 
			
		||||
func (tabsLayout *tabsLayoutData) currentChanged(newCurrent, oldCurrent int) {
 | 
			
		||||
	for _, listener := range getTwoArgEventListeners[TabsLayout, int](tabsLayout, nil, CurrentTabChangedEvent) {
 | 
			
		||||
		listener(tabsLayout, newCurrent, oldCurrent)
 | 
			
		||||
		listener.Run(tabsLayout, newCurrent, oldCurrent)
 | 
			
		||||
	}
 | 
			
		||||
	if listener, ok := tabsLayout.changeListener[Current]; ok {
 | 
			
		||||
		listener(tabsLayout, Current)
 | 
			
		||||
| 
						 | 
				
			
			@ -766,3 +766,20 @@ func (tabsLayout *tabsLayoutData) handleCommand(self View, command PropertyName,
 | 
			
		|||
func GetTabCloseEventListeners(view View, subviewID ...string) []any {
 | 
			
		||||
	return getOneArgEventRawListeners[TabsLayout, int](view, subviewID, TabCloseEvent)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetCurrentTabChangedEventListeners returns the "current-tab-changed" listener list. If there are no listeners then the empty list is returned.
 | 
			
		||||
//
 | 
			
		||||
// Result elements can be of the following types:
 | 
			
		||||
//   - func(rui.TabsLayout, int, int),
 | 
			
		||||
//   - func(rui.TabsLayout, int),
 | 
			
		||||
//   - func(rui.TabsLayout),
 | 
			
		||||
//   - func(int, int),
 | 
			
		||||
//   - func(int),
 | 
			
		||||
//   - func(),
 | 
			
		||||
//   - string.
 | 
			
		||||
//
 | 
			
		||||
// The second argument (subviewID) specifies the path to the child element whose value needs to be returned.
 | 
			
		||||
// If it is not specified then a value from the first argument (view) is returned.
 | 
			
		||||
func GetCurrentTabChangedEventListeners(view View, subviewID ...string) []any {
 | 
			
		||||
	return getTwoArgEventRawListeners[TabsLayout, int](view, subviewID, CurrentTabChangedEvent)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -246,7 +246,7 @@ func (picker *timePickerData) propertyChanged(tag PropertyName) {
 | 
			
		|||
		value := GetTimePickerValue(picker)
 | 
			
		||||
		session.callFunc("setInputValue", picker.htmlID(), value.Format(timeFormat))
 | 
			
		||||
 | 
			
		||||
		if listeners := GetTimeChangedListeners(picker); len(listeners) > 0 {
 | 
			
		||||
		if listeners := getTwoArgEventListeners[TimePicker, time.Time](picker, nil, TimeChangedEvent); len(listeners) > 0 {
 | 
			
		||||
			oldTime := time.Now()
 | 
			
		||||
			if val := picker.getRaw("old-time"); val != nil {
 | 
			
		||||
				if time, ok := val.(time.Time); ok {
 | 
			
		||||
| 
						 | 
				
			
			@ -254,7 +254,7 @@ func (picker *timePickerData) propertyChanged(tag PropertyName) {
 | 
			
		|||
				}
 | 
			
		||||
			}
 | 
			
		||||
			for _, listener := range listeners {
 | 
			
		||||
				listener(picker, value, oldTime)
 | 
			
		||||
				listener.Run(picker, value, oldTime)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -320,8 +320,8 @@ func (picker *timePickerData) handleCommand(self View, command PropertyName, dat
 | 
			
		|||
				oldValue := GetTimePickerValue(picker)
 | 
			
		||||
				picker.properties[TimePickerValue] = value
 | 
			
		||||
				if value != oldValue {
 | 
			
		||||
					for _, listener := range GetTimeChangedListeners(picker) {
 | 
			
		||||
						listener(picker, value, oldValue)
 | 
			
		||||
					for _, listener := range getTwoArgEventListeners[TimePicker, time.Time](picker, nil, TimeChangedEvent) {
 | 
			
		||||
						listener.Run(picker, value, oldValue)
 | 
			
		||||
					}
 | 
			
		||||
					if listener, ok := picker.changeListener[TimePickerValue]; ok {
 | 
			
		||||
						listener(picker, TimePickerValue)
 | 
			
		||||
| 
						 | 
				
			
			@ -418,8 +418,17 @@ func GetTimePickerValue(view View, subviewID ...string) time.Time {
 | 
			
		|||
// GetTimeChangedListeners returns the TimeChangedListener list of an TimePicker subview.
 | 
			
		||||
// If there are no listeners then the empty list is returned
 | 
			
		||||
//
 | 
			
		||||
// Result elements can be of the following types:
 | 
			
		||||
//   - func(rui.TimePicker, time.Time, time.Time),
 | 
			
		||||
//   - func(rui.TimePicker, time.Time),
 | 
			
		||||
//   - func(rui.TimePicker),
 | 
			
		||||
//   - func(time.Time, time.Time),
 | 
			
		||||
//   - func(time.Time),
 | 
			
		||||
//   - func(),
 | 
			
		||||
//   - string.
 | 
			
		||||
//
 | 
			
		||||
// The second argument (subviewID) specifies the path to the child element whose value needs to be returned.
 | 
			
		||||
// If it is not specified then a value from the first argument (view) is returned.
 | 
			
		||||
func GetTimeChangedListeners(view View, subviewID ...string) []func(TimePicker, time.Time, time.Time) {
 | 
			
		||||
	return getTwoArgEventListeners[TimePicker, time.Time](view, subviewID, TimeChangedEvent)
 | 
			
		||||
func GetTimeChangedListeners(view View, subviewID ...string) []any {
 | 
			
		||||
	return getTwoArgEventRawListeners[TimePicker, time.Time](view, subviewID, TimeChangedEvent)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue