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.
|
||||
|
|
591
events.go
591
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)
|
||||
} else {
|
||||
ErrorLogF(`Unsupported prototype of "%s" method`, data.name)
|
||||
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)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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