mirror of https://github.com/anoshenko/rui.git
346 lines
8.1 KiB
Go
346 lines
8.1 KiB
Go
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 equalType(inType, reflect.TypeOf(arg1)) {
|
|
args = []reflect.Value{reflect.ValueOf(arg1)}
|
|
} else if equalType(inType, reflect.TypeOf(view)) {
|
|
args = []reflect.Value{reflect.ValueOf(view)}
|
|
}
|
|
|
|
case 2:
|
|
inType0 := methodType.In(0)
|
|
inType1 := methodType.In(1)
|
|
if equalType(inType0, reflect.TypeOf(view)) && equalType(inType1, reflect.TypeOf(arg1)) {
|
|
args = []reflect.Value{reflect.ValueOf(view), reflect.ValueOf(arg1)}
|
|
} else if equalType(inType0, reflect.TypeOf(arg1)) && equalType(inType1, reflect.TypeOf(arg2)) {
|
|
args = []reflect.Value{reflect.ValueOf(arg1), reflect.ValueOf(arg2)}
|
|
}
|
|
|
|
case 3:
|
|
if equalType(methodType.In(0), reflect.TypeOf(view)) &&
|
|
equalType(methodType.In(1), reflect.TypeOf(arg1)) &&
|
|
equalType(methodType.In(2), reflect.TypeOf(arg2)) {
|
|
args = []reflect.Value{reflect.ValueOf(view), reflect.ValueOf(arg1), reflect.ValueOf(arg2)}
|
|
}
|
|
}
|
|
|
|
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 {
|
|
return setArrayPropertyValue(view, tag, listeners)
|
|
}
|
|
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
|
|
}
|
|
|
|
func getTwoArgBinding[V View, E any](listeners []twoArgListener[V, E]) string {
|
|
for _, listener := range listeners {
|
|
raw := listener.rawListener()
|
|
if text, ok := raw.(string); ok && text != "" {
|
|
return text
|
|
}
|
|
}
|
|
return ""
|
|
}
|