forked from mbk-lab/rui_orig
2
0
Fork 0

Refactoring and optimisation

This commit is contained in:
Alexei Anoshenko 2022-07-27 20:31:57 +03:00
parent ece1d04e4e
commit e23ad83b6c
23 changed files with 228 additions and 1765 deletions

View File

@ -51,131 +51,6 @@ const (
AnimationIterationEvent = "animation-iteration-event"
)
func valueToAnimationListeners(value any) ([]func(View, string), bool) {
if value == nil {
return nil, true
}
switch value := value.(type) {
case func(View, string):
return []func(View, string){value}, true
case func(string):
fn := func(_ View, event string) {
value(event)
}
return []func(View, string){fn}, true
case func(View):
fn := func(view View, _ string) {
value(view)
}
return []func(View, string){fn}, true
case func():
fn := func(View, string) {
value()
}
return []func(View, string){fn}, true
case []func(View, string):
if len(value) == 0 {
return nil, true
}
for _, fn := range value {
if fn == nil {
return nil, false
}
}
return value, true
case []func(string):
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(View, string), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(_ View, event string) {
v(event)
}
}
return listeners, true
case []func(View):
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(View, string), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(view View, _ string) {
v(view)
}
}
return listeners, true
case []func():
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(View, string), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(View, string) {
v()
}
}
return listeners, true
case []any:
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(View, string), count)
for i, v := range value {
if v == nil {
return nil, false
}
switch v := v.(type) {
case func(View, string):
listeners[i] = v
case func(string):
listeners[i] = func(_ View, event string) {
v(event)
}
case func(View):
listeners[i] = func(view View, _ string) {
v(view)
}
case func():
listeners[i] = func(View, string) {
v()
}
default:
return nil, false
}
}
return listeners, true
}
return nil, false
}
var transitionEvents = map[string]struct{ jsEvent, jsFunc string }{
TransitionRunEvent: {jsEvent: "ontransitionrun", jsFunc: "transitionRunEvent"},
TransitionStartEvent: {jsEvent: "ontransitionstart", jsFunc: "transitionStartEvent"},
@ -184,7 +59,7 @@ var transitionEvents = map[string]struct{ jsEvent, jsFunc string }{
}
func (view *viewData) setTransitionListener(tag string, value any) bool {
listeners, ok := valueToAnimationListeners(value)
listeners, ok := valueToEventListeners[View, string](value)
if !ok {
notCompatibleType(tag, value)
return false
@ -212,20 +87,6 @@ func (view *viewData) removeTransitionListener(tag string) {
}
}
func getAnimationListeners(view View, subviewID string, tag string) []func(View, string) {
if subviewID != "" {
view = ViewByID(view, subviewID)
}
if view != nil {
if value := view.Get(tag); value != nil {
if result, ok := value.([]func(View, string)); ok {
return result
}
}
}
return []func(View, string){}
}
func transitionEventsHtml(view View, buffer *strings.Builder) {
for tag, js := range transitionEvents {
if value := view.getRaw(tag); value != nil {
@ -250,7 +111,7 @@ func (view *viewData) handleTransitionEvents(tag string, data DataObject) {
}
}
for _, listener := range getAnimationListeners(view, "", tag) {
for _, listener := range getEventListeners[View, string](view, "", tag) {
listener(view, property)
}
}
@ -264,7 +125,7 @@ var animationEvents = map[string]struct{ jsEvent, jsFunc string }{
}
func (view *viewData) setAnimationListener(tag string, value any) bool {
listeners, ok := valueToAnimationListeners(value)
listeners, ok := valueToEventListeners[View, string](value)
if !ok {
notCompatibleType(tag, value)
return false
@ -303,7 +164,7 @@ func animationEventsHtml(view View, buffer *strings.Builder) {
}
func (view *viewData) handleAnimationEvents(tag string, data DataObject) {
if listeners := getAnimationListeners(view, "", tag); len(listeners) > 0 {
if listeners := getEventListeners[View, string](view, "", tag); len(listeners) > 0 {
id := ""
if name, ok := data.PropertyValue("name"); ok {
for _, animation := range GetAnimation(view, "") {
@ -322,54 +183,54 @@ func (view *viewData) handleAnimationEvents(tag string, data DataObject) {
// If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetTransitionRunListeners(view View, subviewID string) []func(View, string) {
return getAnimationListeners(view, subviewID, TransitionRunEvent)
return getEventListeners[View, string](view, subviewID, TransitionRunEvent)
}
// GetTransitionStartListeners returns the "transition-start-event" listener list.
// If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetTransitionStartListeners(view View, subviewID string) []func(View, string) {
return getAnimationListeners(view, subviewID, TransitionStartEvent)
return getEventListeners[View, string](view, subviewID, TransitionStartEvent)
}
// GetTransitionEndListeners returns the "transition-end-event" listener list.
// If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetTransitionEndListeners(view View, subviewID string) []func(View, string) {
return getAnimationListeners(view, subviewID, TransitionEndEvent)
return getEventListeners[View, string](view, subviewID, TransitionEndEvent)
}
// GetTransitionCancelListeners returns the "transition-cancel-event" listener list.
// If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetTransitionCancelListeners(view View, subviewID string) []func(View, string) {
return getAnimationListeners(view, subviewID, TransitionCancelEvent)
return getEventListeners[View, string](view, subviewID, TransitionCancelEvent)
}
// GetAnimationStartListeners returns the "animation-start-event" listener list.
// If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetAnimationStartListeners(view View, subviewID string) []func(View, string) {
return getAnimationListeners(view, subviewID, AnimationStartEvent)
return getEventListeners[View, string](view, subviewID, AnimationStartEvent)
}
// GetAnimationEndListeners returns the "animation-end-event" listener list.
// If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetAnimationEndListeners(view View, subviewID string) []func(View, string) {
return getAnimationListeners(view, subviewID, AnimationEndEvent)
return getEventListeners[View, string](view, subviewID, AnimationEndEvent)
}
// GetAnimationCancelListeners returns the "animation-cancel-event" listener list.
// If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetAnimationCancelListeners(view View, subviewID string) []func(View, string) {
return getAnimationListeners(view, subviewID, AnimationCancelEvent)
return getEventListeners[View, string](view, subviewID, AnimationCancelEvent)
}
// GetAnimationIterationListeners returns the "animation-iteration-event" listener list.
// If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetAnimationIterationListeners(view View, subviewID string) []func(View, string) {
return getAnimationListeners(view, subviewID, AnimationIterationEvent)
return getEventListeners[View, string](view, subviewID, AnimationIterationEvent)
}

View File

@ -87,57 +87,14 @@ func (picker *colorPickerData) set(tag string, value any) bool {
switch tag {
case ColorChangedEvent:
switch value := value.(type) {
case func(ColorPicker, Color):
picker.colorChangedListeners = []func(ColorPicker, Color){value}
case func(Color):
fn := func(_ ColorPicker, date Color) {
value(date)
}
picker.colorChangedListeners = []func(ColorPicker, Color){fn}
case []func(ColorPicker, Color):
picker.colorChangedListeners = value
case []func(Color):
listeners := make([]func(ColorPicker, Color), len(value))
for i, val := range value {
if val == nil {
notCompatibleType(tag, val)
return false
}
listeners[i] = func(_ ColorPicker, date Color) {
val(date)
}
}
picker.colorChangedListeners = listeners
case []any:
listeners := make([]func(ColorPicker, Color), len(value))
for i, val := range value {
if val == nil {
notCompatibleType(tag, val)
return false
}
switch val := val.(type) {
case func(ColorPicker, Color):
listeners[i] = val
case func(Color):
listeners[i] = func(_ ColorPicker, date Color) {
val(date)
}
default:
notCompatibleType(tag, val)
return false
}
}
picker.colorChangedListeners = listeners
listeners, ok := valueToEventListeners[ColorPicker, Color](value)
if !ok {
notCompatibleType(tag, value)
return false
} else if listeners == nil {
listeners = []func(ColorPicker, Color){}
}
picker.colorChangedListeners = listeners
picker.propertyChangedEvent(tag)
return true
@ -249,15 +206,5 @@ func GetColorPickerValue(view View, subviewID string) Color {
// If there are no listeners then the empty list is returned
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetColorChangedListeners(view View, subviewID string) []func(ColorPicker, Color) {
if subviewID != "" {
view = ViewByID(view, subviewID)
}
if view != nil {
if value := view.Get(ColorChangedEvent); value != nil {
if listeners, ok := value.([]func(ColorPicker, Color)); ok {
return listeners
}
}
}
return []func(ColorPicker, Color){}
return getEventListeners[ColorPicker, Color](view, subviewID, ColorChangedEvent)
}

View File

@ -235,57 +235,14 @@ func (picker *datePickerData) set(tag string, value any) bool {
}
case DateChangedEvent:
switch value := value.(type) {
case func(DatePicker, time.Time):
picker.dateChangedListeners = []func(DatePicker, time.Time){value}
case func(time.Time):
fn := func(_ DatePicker, date time.Time) {
value(date)
}
picker.dateChangedListeners = []func(DatePicker, time.Time){fn}
case []func(DatePicker, time.Time):
picker.dateChangedListeners = value
case []func(time.Time):
listeners := make([]func(DatePicker, time.Time), len(value))
for i, val := range value {
if val == nil {
notCompatibleType(tag, val)
return false
}
listeners[i] = func(_ DatePicker, date time.Time) {
val(date)
}
}
picker.dateChangedListeners = listeners
case []any:
listeners := make([]func(DatePicker, time.Time), len(value))
for i, val := range value {
if val == nil {
notCompatibleType(tag, val)
return false
}
switch val := val.(type) {
case func(DatePicker, time.Time):
listeners[i] = val
case func(time.Time):
listeners[i] = func(_ DatePicker, date time.Time) {
val(date)
}
default:
notCompatibleType(tag, val)
return false
}
}
picker.dateChangedListeners = listeners
listeners, ok := valueToEventListeners[DatePicker, time.Time](value)
if !ok {
notCompatibleType(tag, value)
return false
} else if listeners == nil {
listeners = []func(DatePicker, time.Time){}
}
picker.dateChangedListeners = listeners
picker.propertyChangedEvent(tag)
return true
@ -463,15 +420,5 @@ func GetDatePickerValue(view View, subviewID string) time.Time {
// If there are no listeners then the empty list is returned
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetDateChangedListeners(view View, subviewID string) []func(DatePicker, time.Time) {
if subviewID != "" {
view = ViewByID(view, subviewID)
}
if view != nil {
if value := view.Get(DateChangedEvent); value != nil {
if listeners, ok := value.([]func(DatePicker, time.Time)); ok {
return listeners
}
}
}
return []func(DatePicker, time.Time){}
return getEventListeners[DatePicker, time.Time](view, subviewID, DateChangedEvent)
}

View File

@ -113,7 +113,16 @@ func (list *dropDownListData) set(tag string, value any) bool {
return list.setDisabledItems(value)
case DropDownEvent:
return list.setDropDownListener(value)
listeners, ok := valueToEventListeners[DropDownList, int](value)
if !ok {
notCompatibleType(tag, value)
return false
} else if listeners == nil {
listeners = []func(DropDownList, int){}
}
list.dropDownListener = listeners
list.propertyChangedEvent(tag)
return true
case Current:
oldCurrent := GetCurrent(list, "")
@ -291,64 +300,6 @@ func (list *dropDownListData) setDisabledItems(value any) bool {
}
func (list *dropDownListData) setDropDownListener(value any) bool {
switch value := value.(type) {
case func(DropDownList, int):
list.dropDownListener = []func(DropDownList, int){value}
case func(int):
list.dropDownListener = []func(DropDownList, int){func(_ DropDownList, index int) {
value(index)
}}
case []func(DropDownList, int):
list.dropDownListener = value
case []func(int):
listeners := make([]func(DropDownList, int), len(value))
for i, val := range value {
if val == nil {
notCompatibleType(DropDownEvent, value)
return false
}
listeners[i] = func(_ DropDownList, index int) {
val(index)
}
}
list.dropDownListener = listeners
case []any:
listeners := make([]func(DropDownList, int), len(value))
for i, val := range value {
if val == nil {
notCompatibleType(DropDownEvent, value)
return false
}
switch val := val.(type) {
case func(DropDownList, int):
listeners[i] = val
case func(int):
listeners[i] = func(_ DropDownList, index int) {
val(index)
}
default:
notCompatibleType(DropDownEvent, value)
return false
}
}
list.dropDownListener = listeners
default:
notCompatibleType(DropDownEvent, value)
return false
}
list.propertyChangedEvent(DropDownEvent)
return true
}
func (list *dropDownListData) Get(tag string) any {
return list.get(strings.ToLower(tag))
}

View File

@ -333,75 +333,29 @@ func (edit *editViewData) set(tag string, value any) bool {
return false
case EditTextChangedEvent:
ok := edit.setChangeListeners(value)
listeners, ok := valueToEventListeners[EditView, string](value)
if !ok {
notCompatibleType(tag, value)
return false
} else if listeners == nil {
listeners = []func(EditView, string){}
}
edit.textChangeListeners = listeners
edit.propertyChangedEvent(tag)
return ok
return true
}
return edit.viewData.set(tag, value)
}
func (edit *editViewData) setChangeListeners(value any) bool {
switch value := value.(type) {
case func(EditView, string):
edit.textChangeListeners = []func(EditView, string){value}
case func(string):
fn := func(_ EditView, text string) {
value(text)
}
edit.textChangeListeners = []func(EditView, string){fn}
case []func(EditView, string):
edit.textChangeListeners = value
case []func(string):
listeners := make([]func(EditView, string), len(value))
for i, v := range value {
if v == nil {
return false
}
listeners[i] = func(_ EditView, text string) {
v(text)
}
}
edit.textChangeListeners = listeners
case []any:
listeners := make([]func(EditView, string), len(value))
for i, v := range value {
if v == nil {
return false
}
switch v := v.(type) {
case func(EditView, string):
listeners[i] = v
case func(string):
listeners[i] = func(_ EditView, text string) {
v(text)
}
default:
return false
}
}
edit.textChangeListeners = listeners
default:
return false
}
return true
}
func (edit *editViewData) Get(tag string) any {
return edit.get(edit.normalizeTag(tag))
}
func (edit *editViewData) get(tag string) any {
if tag == EditTextChangedEvent {
return edit.textChangeListeners
}
return edit.viewData.get(tag)
}
@ -635,17 +589,7 @@ func IsSpellcheck(view View, subviewID string) bool {
// If there are no listeners then the empty list is returned
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetTextChangedListeners(view View, subviewID string) []func(EditView, string) {
if subviewID != "" {
view = ViewByID(view, subviewID)
}
if view != nil {
if value := view.Get(EditTextChangedEvent); value != nil {
if result, ok := value.([]func(EditView, string)); ok {
return result
}
}
}
return []func(EditView, string){}
return getEventListeners[EditView, string](view, subviewID, EditTextChangedEvent)
}
// GetEditViewType returns a value of the Type property of EditView.

View File

@ -151,57 +151,14 @@ func (picker *filePickerData) set(tag string, value any) bool {
switch tag {
case FileSelectedEvent:
switch value := value.(type) {
case func(FilePicker, []FileInfo):
picker.fileSelectedListeners = []func(FilePicker, []FileInfo){value}
case func([]FileInfo):
fn := func(_ FilePicker, files []FileInfo) {
value(files)
}
picker.fileSelectedListeners = []func(FilePicker, []FileInfo){fn}
case []func(FilePicker, []FileInfo):
picker.fileSelectedListeners = value
case []func([]FileInfo):
listeners := make([]func(FilePicker, []FileInfo), len(value))
for i, val := range value {
if val == nil {
notCompatibleType(tag, val)
return false
}
listeners[i] = func(_ FilePicker, files []FileInfo) {
val(files)
}
}
picker.fileSelectedListeners = listeners
case []any:
listeners := make([]func(FilePicker, []FileInfo), len(value))
for i, val := range value {
if val == nil {
notCompatibleType(tag, val)
return false
}
switch val := val.(type) {
case func(FilePicker, []FileInfo):
listeners[i] = val
case func([]FileInfo):
listeners[i] = func(_ FilePicker, files []FileInfo) {
val(files)
}
default:
notCompatibleType(tag, val)
return false
}
}
picker.fileSelectedListeners = listeners
listeners, ok := valueToEventListeners[FilePicker, []FileInfo](value)
if !ok {
notCompatibleType(tag, value)
return false
} else if listeners == nil {
listeners = []func(FilePicker, []FileInfo){}
}
picker.fileSelectedListeners = listeners
picker.propertyChangedEvent(tag)
return true
@ -436,15 +393,5 @@ func GetFilePickerAccept(view View, subviewID string) []string {
// If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetFileSelectedListeners(view View, subviewID string) []func(FilePicker, []FileInfo) {
if subviewID != "" {
view = ViewByID(view, subviewID)
}
if view != nil {
if value := view.Get(FileSelectedEvent); value != nil {
if result, ok := value.([]func(FilePicker, []FileInfo)); ok {
return result
}
}
}
return []func(FilePicker, []FileInfo){}
return getEventListeners[FilePicker, []FileInfo](view, subviewID, FileSelectedEvent)
}

View File

@ -20,22 +20,22 @@ const (
LostFocusEvent = "lost-focus-event"
)
func valueToFocusListeners(value any) ([]func(View), bool) {
func valueToNoParamListeners[V View](value any) ([]func(V), bool) {
if value == nil {
return nil, true
}
switch value := value.(type) {
case func(View):
return []func(View){value}, true
case func(V):
return []func(V){value}, true
case func():
fn := func(View) {
fn := func(V) {
value()
}
return []func(View){fn}, true
return []func(V){fn}, true
case []func(View):
case []func(V):
if len(value) == 0 {
return nil, true
}
@ -51,12 +51,12 @@ func valueToFocusListeners(value any) ([]func(View), bool) {
if count == 0 {
return nil, true
}
listeners := make([]func(View), count)
listeners := make([]func(V), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(View) {
listeners[i] = func(V) {
v()
}
}
@ -67,17 +67,17 @@ func valueToFocusListeners(value any) ([]func(View), bool) {
if count == 0 {
return nil, true
}
listeners := make([]func(View), count)
listeners := make([]func(V), count)
for i, v := range value {
if v == nil {
return nil, false
}
switch v := v.(type) {
case func(View):
case func(V):
listeners[i] = v
case func():
listeners[i] = func(View) {
listeners[i] = func(V) {
v()
}
@ -97,7 +97,7 @@ var focusEvents = map[string]struct{ jsEvent, jsFunc string }{
}
func (view *viewData) setFocusListener(tag string, value any) bool {
listeners, ok := valueToFocusListeners(value)
listeners, ok := valueToNoParamListeners[View](value)
if !ok {
notCompatibleType(tag, value)
return false

View File

@ -118,77 +118,6 @@ func (imageView *imageViewData) Set(tag string, value any) bool {
return imageView.set(imageView.normalizeTag(tag), value)
}
func valueToImageListeners(value any) ([]func(ImageView), bool) {
if value == nil {
return nil, true
}
switch value := value.(type) {
case func(ImageView):
return []func(ImageView){value}, true
case func():
fn := func(ImageView) {
value()
}
return []func(ImageView){fn}, true
case []func(ImageView):
if len(value) == 0 {
return nil, true
}
for _, fn := range value {
if fn == nil {
return nil, false
}
}
return value, true
case []func():
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(ImageView), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(ImageView) {
v()
}
}
return listeners, true
case []any:
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(ImageView), count)
for i, v := range value {
if v == nil {
return nil, false
}
switch v := v.(type) {
case func(ImageView):
listeners[i] = v
case func():
listeners[i] = func(ImageView) {
v()
}
default:
return nil, false
}
}
return listeners, true
}
return nil, false
}
func (imageView *imageViewData) set(tag string, value any) bool {
if value == nil {
imageView.remove(tag)
@ -228,8 +157,12 @@ func (imageView *imageViewData) set(tag string, value any) bool {
notCompatibleType(tag, value)
case LoadedEvent, ErrorEvent:
if listeners, ok := valueToImageListeners(value); ok {
imageView.properties[tag] = listeners
if listeners, ok := valueToNoParamListeners[ImageView](value); ok {
if listeners == nil {
delete(imageView.properties, tag)
} else {
imageView.properties[tag] = listeners
}
return true
}

View File

@ -50,34 +50,52 @@ type KeyEvent struct {
MetaKey bool
}
func valueToKeyListeners(value any) ([]func(View, KeyEvent), bool) {
func (event *KeyEvent) init(data DataObject) {
getBool := func(tag string) bool {
if value, ok := data.PropertyValue(tag); ok && value == "1" {
return true
}
return false
}
event.Key, _ = data.PropertyValue("key")
event.Code, _ = data.PropertyValue("code")
event.TimeStamp = getTimeStamp(data)
event.Repeat = getBool("repeat")
event.CtrlKey = getBool("ctrlKey")
event.ShiftKey = getBool("shiftKey")
event.AltKey = getBool("altKey")
event.MetaKey = getBool("metaKey")
}
func valueToEventListeners[V View, E any](value any) ([]func(V, E), bool) {
if value == nil {
return nil, true
}
switch value := value.(type) {
case func(View, KeyEvent):
return []func(View, KeyEvent){value}, true
case func(V, E):
return []func(V, E){value}, true
case func(KeyEvent):
fn := func(_ View, event KeyEvent) {
case func(E):
fn := func(_ V, event E) {
value(event)
}
return []func(View, KeyEvent){fn}, true
return []func(V, E){fn}, true
case func(View):
fn := func(view View, _ KeyEvent) {
case func(V):
fn := func(view V, _ E) {
value(view)
}
return []func(View, KeyEvent){fn}, true
return []func(V, E){fn}, true
case func():
fn := func(View, KeyEvent) {
fn := func(V, E) {
value()
}
return []func(View, KeyEvent){fn}, true
return []func(V, E){fn}, true
case []func(View, KeyEvent):
case []func(V, E):
if len(value) == 0 {
return nil, true
}
@ -88,33 +106,33 @@ func valueToKeyListeners(value any) ([]func(View, KeyEvent), bool) {
}
return value, true
case []func(KeyEvent):
case []func(E):
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(View, KeyEvent), count)
listeners := make([]func(V, E), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(_ View, event KeyEvent) {
listeners[i] = func(_ V, event E) {
v(event)
}
}
return listeners, true
case []func(View):
case []func(V):
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(View, KeyEvent), count)
listeners := make([]func(V, E), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(view View, _ KeyEvent) {
listeners[i] = func(view V, _ E) {
v(view)
}
}
@ -125,12 +143,12 @@ func valueToKeyListeners(value any) ([]func(View, KeyEvent), bool) {
if count == 0 {
return nil, true
}
listeners := make([]func(View, KeyEvent), count)
listeners := make([]func(V, E), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(View, KeyEvent) {
listeners[i] = func(V, E) {
v()
}
}
@ -141,27 +159,27 @@ func valueToKeyListeners(value any) ([]func(View, KeyEvent), bool) {
if count == 0 {
return nil, true
}
listeners := make([]func(View, KeyEvent), count)
listeners := make([]func(V, E), count)
for i, v := range value {
if v == nil {
return nil, false
}
switch v := v.(type) {
case func(View, KeyEvent):
case func(V, E):
listeners[i] = v
case func(KeyEvent):
listeners[i] = func(_ View, event KeyEvent) {
case func(E):
listeners[i] = func(_ V, event E) {
v(event)
}
case func(View):
listeners[i] = func(view View, _ KeyEvent) {
case func(V):
listeners[i] = func(view V, _ E) {
v(view)
}
case func():
listeners[i] = func(View, KeyEvent) {
listeners[i] = func(V, E) {
v()
}
@ -181,7 +199,7 @@ var keyEvents = map[string]struct{ jsEvent, jsFunc string }{
}
func (view *viewData) setKeyListener(tag string, value any) bool {
listeners, ok := valueToKeyListeners(value)
listeners, ok := valueToEventListeners[View, KeyEvent](value)
if !ok {
notCompatibleType(tag, value)
return false
@ -209,67 +227,48 @@ func (view *viewData) removeKeyListener(tag string) {
}
}
func getKeyListeners(view View, subviewID string, tag string) []func(View, KeyEvent) {
func getEventListeners[V View, E any](view View, subviewID string, tag string) []func(V, E) {
if subviewID != "" {
view = ViewByID(view, subviewID)
}
if view != nil {
if value := view.Get(tag); value != nil {
if result, ok := value.([]func(View, KeyEvent)); ok {
if result, ok := value.([]func(V, E)); ok {
return result
}
}
}
return []func(View, KeyEvent){}
return []func(V, E){}
}
func keyEventsHtml(view View, buffer *strings.Builder) {
for tag, js := range keyEvents {
if listeners := getKeyListeners(view, "", tag); len(listeners) > 0 {
if listeners := getEventListeners[View, KeyEvent](view, "", tag); len(listeners) > 0 {
buffer.WriteString(js.jsEvent + `="` + js.jsFunc + `(this, event)" `)
}
}
}
func handleKeyEvents(view View, tag string, data DataObject) {
listeners := getKeyListeners(view, "", tag)
if len(listeners) == 0 {
return
}
listeners := getEventListeners[View, KeyEvent](view, "", tag)
if len(listeners) > 0 {
var event KeyEvent
event.init(data)
getBool := func(tag string) bool {
if value, ok := data.PropertyValue(tag); ok && value == "1" {
return true
for _, listener := range listeners {
listener(view, event)
}
return false
}
key, _ := data.PropertyValue("key")
code, _ := data.PropertyValue("code")
event := KeyEvent{
TimeStamp: getTimeStamp(data),
Key: key,
Code: code,
Repeat: getBool("repeat"),
CtrlKey: getBool("ctrlKey"),
ShiftKey: getBool("shiftKey"),
AltKey: getBool("altKey"),
MetaKey: getBool("metaKey"),
}
for _, listener := range listeners {
listener(view, event)
}
}
// GetKeyDownListeners returns the "key-down-event" listener list. If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetKeyDownListeners(view View, subviewID string) []func(View, KeyEvent) {
return getKeyListeners(view, subviewID, KeyDownEvent)
return getEventListeners[View, KeyEvent](view, subviewID, KeyDownEvent)
}
// GetKeyUpListeners returns the "key-up-event" listener list. If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetKeyUpListeners(view View, subviewID string) []func(View, KeyEvent) {
return getKeyListeners(view, subviewID, KeyUpEvent)
return getEventListeners[View, KeyEvent](view, subviewID, KeyUpEvent)
}

View File

@ -205,29 +205,38 @@ func (listView *listViewData) set(tag string, value any) bool {
switch tag {
case ListItemClickedEvent:
listeners := listView.valueToItemListeners(value)
if listeners == nil {
listeners, ok := valueToEventListeners[ListView, int](value)
if !ok {
notCompatibleType(tag, value)
return false
} else if listeners == nil {
listeners = []func(ListView, int){}
}
listView.clickedListeners = listeners
listView.propertyChangedEvent(tag)
return true
case ListItemSelectedEvent:
listeners := listView.valueToItemListeners(value)
if listeners == nil {
listeners, ok := valueToEventListeners[ListView, int](value)
if !ok {
notCompatibleType(tag, value)
return false
} else if listeners == nil {
listeners = []func(ListView, int){}
}
listView.selectedListeners = listeners
listView.propertyChangedEvent(tag)
return true
case ListItemCheckedEvent:
if !listView.setItemCheckedEvent(value) {
listeners, ok := valueToEventListeners[ListView, []int](value)
if !ok {
notCompatibleType(tag, value)
return false
} else if listeners == nil {
listeners = []func(ListView, []int){}
}
listView.checkedListeners = listeners
listView.propertyChangedEvent(tag)
return true
@ -288,61 +297,6 @@ func (listView *listViewData) set(tag string, value any) bool {
return true
}
func (listView *listViewData) setItemCheckedEvent(value any) bool {
switch value := value.(type) {
case func(ListView, []int):
listView.checkedListeners = []func(ListView, []int){value}
case func([]int):
fn := func(_ ListView, date []int) {
value(date)
}
listView.checkedListeners = []func(ListView, []int){fn}
case []func(ListView, []int):
listView.checkedListeners = value
case []func([]int):
listeners := make([]func(ListView, []int), len(value))
for i, val := range value {
if val == nil {
notCompatibleType(ListItemCheckedEvent, val)
return false
}
listeners[i] = func(_ ListView, date []int) {
val(date)
}
}
listView.checkedListeners = listeners
case []any:
listeners := make([]func(ListView, []int), len(value))
for i, val := range value {
if val == nil {
notCompatibleType(ListItemCheckedEvent, val)
return false
}
switch val := val.(type) {
case func(ListView, []int):
listeners[i] = val
case func([]int):
listeners[i] = func(_ ListView, checked []int) {
val(checked)
}
default:
notCompatibleType(ListItemCheckedEvent, val)
return false
}
}
listView.checkedListeners = listeners
}
return true
}
func (listView *listViewData) Get(tag string) any {
return listView.get(listView.normalizeTag(tag))
}
@ -460,61 +414,6 @@ func (listView *listViewData) setItems(value any) bool {
return true
}
func (listView *listViewData) valueToItemListeners(value any) []func(ListView, int) {
if value == nil {
return []func(ListView, int){}
}
switch value := value.(type) {
case func(ListView, int):
return []func(ListView, int){value}
case func(int):
fn := func(_ ListView, index int) {
value(index)
}
return []func(ListView, int){fn}
case []func(ListView, int):
return value
case []func(int):
listeners := make([]func(ListView, int), len(value))
for i, val := range value {
if val == nil {
return nil
}
listeners[i] = func(_ ListView, index int) {
val(index)
}
}
return listeners
case []any:
listeners := make([]func(ListView, int), len(value))
for i, val := range value {
if val == nil {
return nil
}
switch val := val.(type) {
case func(ListView, int):
listeners[i] = val
case func(int):
listeners[i] = func(_ ListView, index int) {
val(index)
}
default:
return nil
}
}
return listeners
}
return nil
}
func (listView *listViewData) setChecked(value any) bool {
var checked []int
if value == nil {

View File

@ -205,7 +205,7 @@ func (player *mediaPlayerData) set(tag string, value any) bool {
case AbortEvent, CanPlayEvent, CanPlayThroughEvent, CompleteEvent, EmptiedEvent, LoadStartEvent,
EndedEvent, LoadedDataEvent, LoadedMetadataEvent, PauseEvent, PlayEvent, PlayingEvent,
ProgressEvent, SeekedEvent, SeekingEvent, StalledEvent, SuspendEvent, WaitingEvent:
if listeners, ok := valueToPlayerListeners(value); ok {
if listeners, ok := valueToNoParamListeners[MediaPlayer](value); ok {
if listeners == nil {
delete(player.properties, tag)
} else {
@ -218,7 +218,7 @@ func (player *mediaPlayerData) set(tag string, value any) bool {
notCompatibleType(tag, value)
case DurationChangedEvent, RateChangedEvent, TimeUpdateEvent, VolumeChangedEvent:
if listeners, ok := valueToPlayerTimeListeners(value); ok {
if listeners, ok := valueToEventListeners[MediaPlayer, float64](value); ok {
if listeners == nil {
delete(player.properties, tag)
} else {
@ -311,202 +311,6 @@ func (player *mediaPlayerData) setSource(value any) bool {
return true
}
func valueToPlayerListeners(value any) ([]func(MediaPlayer), bool) {
if value == nil {
return nil, true
}
switch value := value.(type) {
case func(MediaPlayer):
return []func(MediaPlayer){value}, true
case func():
fn := func(MediaPlayer) {
value()
}
return []func(MediaPlayer){fn}, true
case []func(MediaPlayer):
if len(value) == 0 {
return nil, true
}
for _, fn := range value {
if fn == nil {
return nil, false
}
}
return value, true
case []func():
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(MediaPlayer), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(MediaPlayer) {
v()
}
}
return listeners, true
case []any:
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(MediaPlayer), count)
for i, v := range value {
if v == nil {
return nil, false
}
switch v := v.(type) {
case func(MediaPlayer):
listeners[i] = v
case func():
listeners[i] = func(MediaPlayer) {
v()
}
default:
return nil, false
}
}
return listeners, true
}
return nil, false
}
func valueToPlayerTimeListeners(value any) ([]func(MediaPlayer, float64), bool) {
if value == nil {
return nil, true
}
switch value := value.(type) {
case func(MediaPlayer, float64):
return []func(MediaPlayer, float64){value}, true
case func(float64):
fn := func(_ MediaPlayer, time float64) {
value(time)
}
return []func(MediaPlayer, float64){fn}, true
case func(MediaPlayer):
fn := func(player MediaPlayer, _ float64) {
value(player)
}
return []func(MediaPlayer, float64){fn}, true
case func():
fn := func(MediaPlayer, float64) {
value()
}
return []func(MediaPlayer, float64){fn}, true
case []func(MediaPlayer, float64):
if len(value) == 0 {
return nil, true
}
for _, fn := range value {
if fn == nil {
return nil, false
}
}
return value, true
case []func(float64):
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(MediaPlayer, float64), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(_ MediaPlayer, time float64) {
v(time)
}
}
return listeners, true
case []func(MediaPlayer):
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(MediaPlayer, float64), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(player MediaPlayer, _ float64) {
v(player)
}
}
return listeners, true
case []func():
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(MediaPlayer, float64), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(MediaPlayer, float64) {
v()
}
}
return listeners, true
case []any:
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(MediaPlayer, float64), count)
for i, v := range value {
if v == nil {
return nil, false
}
switch v := v.(type) {
case func(MediaPlayer, float64):
listeners[i] = v
case func(float64):
listeners[i] = func(_ MediaPlayer, time float64) {
v(time)
}
case func(MediaPlayer):
listeners[i] = func(player MediaPlayer, _ float64) {
v(player)
}
case func():
listeners[i] = func(MediaPlayer, float64) {
v()
}
default:
return nil, false
}
}
return listeners, true
}
return nil, false
}
func valueToPlayerErrorListeners(value any) ([]func(MediaPlayer, int, string), bool) {
if value == nil {
return nil, true

View File

@ -144,131 +144,6 @@ type MouseEvent struct {
MetaKey bool
}
func valueToMouseListeners(value any) ([]func(View, MouseEvent), bool) {
if value == nil {
return nil, true
}
switch value := value.(type) {
case func(View, MouseEvent):
return []func(View, MouseEvent){value}, true
case func(MouseEvent):
fn := func(_ View, event MouseEvent) {
value(event)
}
return []func(View, MouseEvent){fn}, true
case func(View):
fn := func(view View, _ MouseEvent) {
value(view)
}
return []func(View, MouseEvent){fn}, true
case func():
fn := func(View, MouseEvent) {
value()
}
return []func(View, MouseEvent){fn}, true
case []func(View, MouseEvent):
if len(value) == 0 {
return nil, true
}
for _, fn := range value {
if fn == nil {
return nil, false
}
}
return value, true
case []func(MouseEvent):
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(View, MouseEvent), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(_ View, event MouseEvent) {
v(event)
}
}
return listeners, true
case []func(View):
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(View, MouseEvent), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(view View, _ MouseEvent) {
v(view)
}
}
return listeners, true
case []func():
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(View, MouseEvent), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(View, MouseEvent) {
v()
}
}
return listeners, true
case []any:
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(View, MouseEvent), count)
for i, v := range value {
if v == nil {
return nil, false
}
switch v := v.(type) {
case func(View, MouseEvent):
listeners[i] = v
case func(MouseEvent):
listeners[i] = func(_ View, event MouseEvent) {
v(event)
}
case func(View):
listeners[i] = func(view View, _ MouseEvent) {
v(view)
}
case func():
listeners[i] = func(View, MouseEvent) {
v()
}
default:
return nil, false
}
}
return listeners, true
}
return nil, false
}
var mouseEvents = map[string]struct{ jsEvent, jsFunc string }{
ClickEvent: {jsEvent: "onclick", jsFunc: "clickEvent"},
DoubleClickEvent: {jsEvent: "ondblclick", jsFunc: "doubleClickEvent"},
@ -281,7 +156,7 @@ var mouseEvents = map[string]struct{ jsEvent, jsFunc string }{
}
func (view *viewData) setMouseListener(tag string, value any) bool {
listeners, ok := valueToMouseListeners(value)
listeners, ok := valueToEventListeners[View, MouseEvent](value)
if !ok {
notCompatibleType(tag, value)
return false
@ -309,20 +184,6 @@ func (view *viewData) removeMouseListener(tag string) {
}
}
func getMouseListeners(view View, subviewID string, tag string) []func(View, MouseEvent) {
if subviewID != "" {
view = ViewByID(view, subviewID)
}
if view != nil {
if value := view.Get(tag); value != nil {
if result, ok := value.([]func(View, MouseEvent)); ok {
return result
}
}
}
return []func(View, MouseEvent){}
}
func mouseEventsHtml(view View, buffer *strings.Builder) {
for tag, js := range mouseEvents {
if value := view.getRaw(tag); value != nil {
@ -363,64 +224,62 @@ func (event *MouseEvent) init(data DataObject) {
}
func handleMouseEvents(view View, tag string, data DataObject) {
listeners := getMouseListeners(view, "", tag)
if len(listeners) == 0 {
return
}
listeners := getEventListeners[View, MouseEvent](view, "", tag)
if len(listeners) > 0 {
var event MouseEvent
event.init(data)
var event MouseEvent
event.init(data)
for _, listener := range listeners {
listener(view, event)
for _, listener := range listeners {
listener(view, event)
}
}
}
// GetClickListeners returns the "click-event" listener list. If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetClickListeners(view View, subviewID string) []func(View, MouseEvent) {
return getMouseListeners(view, subviewID, ClickEvent)
return getEventListeners[View, MouseEvent](view, subviewID, ClickEvent)
}
// GetDoubleClickListeners returns the "double-click-event" listener list. If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetDoubleClickListeners(view View, subviewID string) []func(View, MouseEvent) {
return getMouseListeners(view, subviewID, DoubleClickEvent)
return getEventListeners[View, MouseEvent](view, subviewID, DoubleClickEvent)
}
// GetContextMenuListeners returns the "context-menu" listener list.
// If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetContextMenuListeners(view View, subviewID string) []func(View, MouseEvent) {
return getMouseListeners(view, subviewID, ContextMenuEvent)
return getEventListeners[View, MouseEvent](view, subviewID, ContextMenuEvent)
}
// GetMouseDownListeners returns the "mouse-down" listener list. If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetMouseDownListeners(view View, subviewID string) []func(View, MouseEvent) {
return getMouseListeners(view, subviewID, MouseDown)
return getEventListeners[View, MouseEvent](view, subviewID, MouseDown)
}
// GetMouseUpListeners returns the "mouse-up" listener list. If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetMouseUpListeners(view View, subviewID string) []func(View, MouseEvent) {
return getMouseListeners(view, subviewID, MouseUp)
return getEventListeners[View, MouseEvent](view, subviewID, MouseUp)
}
// GetMouseMoveListeners returns the "mouse-move" listener list. If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetMouseMoveListeners(view View, subviewID string) []func(View, MouseEvent) {
return getMouseListeners(view, subviewID, MouseMove)
return getEventListeners[View, MouseEvent](view, subviewID, MouseMove)
}
// GetMouseOverListeners returns the "mouse-over" listener list. If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetMouseOverListeners(view View, subviewID string) []func(View, MouseEvent) {
return getMouseListeners(view, subviewID, MouseOver)
return getEventListeners[View, MouseEvent](view, subviewID, MouseOver)
}
// GetMouseOutListeners returns the "mouse-out" listener list. If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetMouseOutListeners(view View, subviewID string) []func(View, MouseEvent) {
return getMouseListeners(view, subviewID, MouseOut)
return getEventListeners[View, MouseEvent](view, subviewID, MouseOut)
}

View File

@ -99,52 +99,14 @@ func (picker *numberPickerData) set(tag string, value any) bool {
switch tag {
case NumberChangedEvent:
switch value := value.(type) {
case func(NumberPicker, float64):
picker.numberChangedListeners = []func(NumberPicker, float64){value}
case func(float64):
fn := func(_ NumberPicker, newValue float64) {
value(newValue)
}
picker.numberChangedListeners = []func(NumberPicker, float64){fn}
case []func(NumberPicker, float64):
picker.numberChangedListeners = value
case []func(float64):
listeners := make([]func(NumberPicker, float64), len(value))
for i, val := range value {
if val == nil {
notCompatibleType(tag, val)
return false
}
listeners[i] = func(_ NumberPicker, newValue float64) {
val(newValue)
}
}
picker.numberChangedListeners = listeners
case []any:
listeners := make([]func(NumberPicker, float64), len(value))
for i, val := range value {
if val == nil {
notCompatibleType(tag, val)
return false
}
switch val := val.(type) {
case func(NumberPicker, float64):
listeners[i] = val
default:
notCompatibleType(tag, val)
return false
}
}
picker.numberChangedListeners = listeners
listeners, ok := valueToEventListeners[NumberPicker, float64](value)
if !ok {
notCompatibleType(tag, value)
return false
} else if listeners == nil {
listeners = []func(NumberPicker, float64){}
}
picker.numberChangedListeners = listeners
picker.propertyChangedEvent(tag)
return true
@ -386,15 +348,5 @@ func GetNumberPickerValue(view View, subviewID string) float64 {
// If there are no listeners then the empty list is returned
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetNumberChangedListeners(view View, subviewID string) []func(NumberPicker, float64) {
if subviewID != "" {
view = ViewByID(view, subviewID)
}
if view != nil {
if value := view.Get(NumberChangedEvent); value != nil {
if listeners, ok := value.([]func(NumberPicker, float64)); ok {
return listeners
}
}
}
return []func(NumberPicker, float64){}
return getEventListeners[NumberPicker, float64](view, subviewID, NumberChangedEvent)
}

View File

@ -87,131 +87,6 @@ type PointerEvent struct {
IsPrimary bool
}
func valueToPointerListeners(value any) ([]func(View, PointerEvent), bool) {
if value == nil {
return nil, true
}
switch value := value.(type) {
case func(View, PointerEvent):
return []func(View, PointerEvent){value}, true
case func(PointerEvent):
fn := func(_ View, event PointerEvent) {
value(event)
}
return []func(View, PointerEvent){fn}, true
case func(View):
fn := func(view View, _ PointerEvent) {
value(view)
}
return []func(View, PointerEvent){fn}, true
case func():
fn := func(View, PointerEvent) {
value()
}
return []func(View, PointerEvent){fn}, true
case []func(View, PointerEvent):
if len(value) == 0 {
return nil, true
}
for _, fn := range value {
if fn == nil {
return nil, false
}
}
return value, true
case []func(PointerEvent):
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(View, PointerEvent), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(_ View, event PointerEvent) {
v(event)
}
}
return listeners, true
case []func(View):
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(View, PointerEvent), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(view View, _ PointerEvent) {
v(view)
}
}
return listeners, true
case []func():
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(View, PointerEvent), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(View, PointerEvent) {
v()
}
}
return listeners, true
case []any:
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(View, PointerEvent), count)
for i, v := range value {
if v == nil {
return nil, false
}
switch v := v.(type) {
case func(View, PointerEvent):
listeners[i] = v
case func(PointerEvent):
listeners[i] = func(_ View, event PointerEvent) {
v(event)
}
case func(View):
listeners[i] = func(view View, _ PointerEvent) {
v(view)
}
case func():
listeners[i] = func(View, PointerEvent) {
v()
}
default:
return nil, false
}
}
return listeners, true
}
return nil, false
}
var pointerEvents = map[string]struct{ jsEvent, jsFunc string }{
PointerDown: {jsEvent: "onpointerdown", jsFunc: "pointerDownEvent"},
PointerUp: {jsEvent: "onpointerup", jsFunc: "pointerUpEvent"},
@ -222,7 +97,7 @@ var pointerEvents = map[string]struct{ jsEvent, jsFunc string }{
}
func (view *viewData) setPointerListener(tag string, value any) bool {
listeners, ok := valueToPointerListeners(value)
listeners, ok := valueToEventListeners[View, PointerEvent](value)
if !ok {
notCompatibleType(tag, value)
return false
@ -250,20 +125,6 @@ func (view *viewData) removePointerListener(tag string) {
}
}
func getPointerListeners(view View, subviewID string, tag string) []func(View, PointerEvent) {
if subviewID != "" {
view = ViewByID(view, subviewID)
}
if view != nil {
if value := view.Get(tag); value != nil {
if result, ok := value.([]func(View, PointerEvent)); ok {
return result
}
}
}
return []func(View, PointerEvent){}
}
func pointerEventsHtml(view View, buffer *strings.Builder) {
for tag, js := range pointerEvents {
if value := view.getRaw(tag); value != nil {
@ -291,7 +152,7 @@ func (event *PointerEvent) init(data DataObject) {
}
func handlePointerEvents(view View, tag string, data DataObject) {
listeners := getPointerListeners(view, "", tag)
listeners := getEventListeners[View, PointerEvent](view, "", tag)
if len(listeners) == 0 {
return
}
@ -307,35 +168,35 @@ func handlePointerEvents(view View, tag string, data DataObject) {
// GetPointerDownListeners returns the "pointer-down" listener list. If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetPointerDownListeners(view View, subviewID string) []func(View, PointerEvent) {
return getPointerListeners(view, subviewID, PointerDown)
return getEventListeners[View, PointerEvent](view, subviewID, PointerDown)
}
// GetPointerUpListeners returns the "pointer-up" listener list. If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetPointerUpListeners(view View, subviewID string) []func(View, PointerEvent) {
return getPointerListeners(view, subviewID, PointerUp)
return getEventListeners[View, PointerEvent](view, subviewID, PointerUp)
}
// GetPointerMoveListeners returns the "pointer-move" listener list. If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetPointerMoveListeners(view View, subviewID string) []func(View, PointerEvent) {
return getPointerListeners(view, subviewID, PointerMove)
return getEventListeners[View, PointerEvent](view, subviewID, PointerMove)
}
// GetPointerCancelListeners returns the "pointer-cancel" listener list. If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetPointerCancelListeners(view View, subviewID string) []func(View, PointerEvent) {
return getPointerListeners(view, subviewID, PointerCancel)
return getEventListeners[View, PointerEvent](view, subviewID, PointerCancel)
}
// GetPointerOverListeners returns the "pointer-over" listener list. If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetPointerOverListeners(view View, subviewID string) []func(View, PointerEvent) {
return getPointerListeners(view, subviewID, PointerOver)
return getEventListeners[View, PointerEvent](view, subviewID, PointerOver)
}
// GetPointerOutListeners returns the "pointer-out" listener list. If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetPointerOutListeners(view View, subviewID string) []func(View, PointerEvent) {
return getPointerListeners(view, subviewID, PointerOut)
return getEventListeners[View, PointerEvent](view, subviewID, PointerOut)
}

View File

@ -36,6 +36,10 @@ const (
// It occurs after the Popup disappears from the screen.
// The main listener for this event has the following format: func(Popup)
DismissEvent = "dismiss-event"
// PopupArrow is the constant for the "popup-arrow" property tag.
// Using the "popup-arrow" property you can add ...
PopupArrow = "popup-arrow"
)
// PopupButton describes a button that will be placed at the bottom of the window.
@ -181,11 +185,10 @@ func (popup *popupData) init(view View, params Params) {
viewRow := 0
if title != nil || closeButton {
viewRow = 1
titleHeight, _ := sizeConstant(popup.Session(), "ruiPopupTitleHeight")
titleView := NewGridLayout(session, Params{
Row: 0,
Style: titleStyle,
CellWidth: []SizeUnit{Fr(1), titleHeight},
CellWidth: []any{Fr(1), "@ruiPopupTitleHeight"},
CellVerticalAlign: CenterAlign,
PaddingLeft: Px(12),
})
@ -195,8 +198,8 @@ func (popup *popupData) init(view View, params Params) {
if closeButton {
titleView.Append(NewGridLayout(session, Params{
Column: 1,
Height: titleHeight,
Width: titleHeight,
Height: "@ruiPopupTitleHeight",
Width: "@ruiPopupTitleHeight",
CellHorizontalAlign: CenterAlign,
CellVerticalAlign: CenterAlign,
TextSize: Px(20),

View File

@ -22,146 +22,18 @@ func (view *viewData) onItemResize(self View, index string, x, y, width, height
}
func (view *viewData) setFrameListener(tag string, value any) bool {
if value == nil {
delete(view.properties, tag)
return true
}
switch value := value.(type) {
case func(View, Frame):
view.properties[tag] = []func(View, Frame){value}
case []func(View, Frame):
if len(value) > 0 {
view.properties[tag] = value
} else {
delete(view.properties, tag)
return true
}
case func(Frame):
fn := func(_ View, frame Frame) {
value(frame)
}
view.properties[tag] = []func(View, Frame){fn}
case []func(Frame):
count := len(value)
if count == 0 {
delete(view.properties, tag)
return true
}
listeners := make([]func(View, Frame), count)
for i, val := range value {
if val == nil {
notCompatibleType(tag, val)
return false
}
listeners[i] = func(_ View, frame Frame) {
val(frame)
}
}
view.properties[tag] = listeners
case func(View):
fn := func(view View, _ Frame) {
value(view)
}
view.properties[tag] = []func(View, Frame){fn}
case []func(View):
count := len(value)
if count == 0 {
delete(view.properties, tag)
return true
}
listeners := make([]func(View, Frame), count)
for i, val := range value {
if val == nil {
notCompatibleType(tag, val)
return false
}
listeners[i] = func(view View, _ Frame) {
val(view)
}
}
view.properties[tag] = listeners
case func():
fn := func(View, Frame) {
value()
}
view.properties[tag] = []func(View, Frame){fn}
case []func():
count := len(value)
if count == 0 {
delete(view.properties, tag)
return true
}
listeners := make([]func(View, Frame), count)
for i, val := range value {
if val == nil {
notCompatibleType(tag, val)
return false
}
listeners[i] = func(View, Frame) {
val()
}
}
view.properties[tag] = listeners
case []any:
count := len(value)
if count == 0 {
delete(view.properties, tag)
return true
}
listeners := make([]func(View, Frame), count)
for i, val := range value {
if val == nil {
notCompatibleType(tag, val)
return false
}
switch val := val.(type) {
case func(View, Frame):
listeners[i] = val
case func(Frame):
listeners[i] = func(_ View, frame Frame) {
val(frame)
}
case func(View):
listeners[i] = func(view View, _ Frame) {
val(view)
}
case func():
listeners[i] = func(View, Frame) {
val()
}
default:
notCompatibleType(tag, val)
return false
}
}
view.properties[tag] = listeners
default:
listeners, ok := valueToEventListeners[FilePicker, []FileInfo](value)
if !ok {
notCompatibleType(tag, value)
return false
}
if listeners == nil {
delete(view.properties, tag)
} else {
view.properties[tag] = listeners
}
view.propertyChangedEvent(tag)
return true
}
@ -204,15 +76,5 @@ func GetViewFrame(view View, subviewID string) Frame {
// GetResizeListeners returns the list of "resize-event" listeners. If there are no listeners then the empty list is returned
// If the second argument (subviewID) is "" then the listeners list of the first argument (view) is returned
func GetResizeListeners(view View, subviewID string) []func(View, Frame) {
if subviewID != "" {
view = ViewByID(view, subviewID)
}
if view != nil {
if value := view.Get(ResizeEvent); value != nil {
if result, ok := value.([]func(View, Frame)); ok {
return result
}
}
}
return []func(View, Frame){}
return getEventListeners[View, Frame](view, subviewID, ResizeEvent)
}

View File

@ -3,7 +3,7 @@ package rui
import "fmt"
// ScrollEvent is the constant for "scroll-event" property tag.
// The "resize-event" is fired when the content of the view is scrolled.
// The "scroll-event" is fired when the content of the view is scrolled.
// The main listener format:
// func(View, Frame).
// The additional listener formats:
@ -46,17 +46,7 @@ func GetViewScroll(view View, subviewID string) Frame {
// GetScrollListeners returns the list of "scroll-event" listeners. If there are no listeners then the empty list is returned
// If the second argument (subviewID) is "" then the listeners list of the first argument (view) is returned
func GetScrollListeners(view View, subviewID string) []func(View, Frame) {
if subviewID != "" {
view = ViewByID(view, subviewID)
}
if view != nil {
if value := view.Get(ScrollEvent); value != nil {
if result, ok := value.([]func(View, Frame)); ok {
return result
}
}
}
return []func(View, Frame){}
return getEventListeners[View, Frame](view, subviewID, ResizeEvent)
}
// ScrollTo scrolls the view's content to the given position.

View File

@ -431,7 +431,7 @@ func (session *sessionData) handleViewEvent(command string, data DataObject) {
if view := session.viewByHTMLID(viewID); view != nil {
view.handleCommand(view, command, data)
}
} else {
} else if command != "clickOutsidePopup" {
ErrorLog(`"id" property not found. Event: ` + command)
}
}

View File

@ -109,8 +109,8 @@ func (layout *stackLayoutData) set(tag string, value any) bool {
switch tag {
case TransitionEndEvent:
listeners, ok := valueToAnimationListeners(value)
if ok {
listeners, ok := valueToEventListeners[View, string](value)
if ok && listeners != nil {
listeners = append(listeners, layout.pushFinished)
listeners = append(listeners, layout.popFinished)
layout.properties[TransitionEndEvent] = listeners

View File

@ -384,20 +384,24 @@ func (table *tableViewData) set(tag string, value any) bool {
table.cellSelectedListener = listeners
case TableRowClickedEvent:
listeners := table.valueToRowListeners(value)
if listeners == nil {
listeners, ok := valueToEventListeners[TableView, int](value)
if !ok {
notCompatibleType(tag, value)
return false
} else if listeners == nil {
listeners = []func(TableView, int){}
}
table.rowClickedListener = listeners
case TableRowSelectedEvent:
listeners := table.valueToRowListeners(value)
if listeners == nil {
listeners, ok := valueToEventListeners[TableView, int](value)
if !ok {
notCompatibleType(tag, value)
return false
} else if listeners == nil {
listeners = []func(TableView, int){}
}
table.rowSelectedListener = []func(TableView, int){}
table.rowSelectedListener = listeners
case CellStyle:
if style, ok := value.(TableCellStyle); ok {
@ -731,61 +735,6 @@ func (table *tableViewData) valueToCellListeners(value any) []func(TableView, in
return nil
}
func (table *tableViewData) valueToRowListeners(value any) []func(TableView, int) {
if value == nil {
return []func(TableView, int){}
}
switch value := value.(type) {
case func(TableView, int):
return []func(TableView, int){value}
case func(int):
fn := func(_ TableView, index int) {
value(index)
}
return []func(TableView, int){fn}
case []func(TableView, int):
return value
case []func(int):
listeners := make([]func(TableView, int), len(value))
for i, val := range value {
if val == nil {
return nil
}
listeners[i] = func(_ TableView, index int) {
val(index)
}
}
return listeners
case []any:
listeners := make([]func(TableView, int), len(value))
for i, val := range value {
if val == nil {
return nil
}
switch val := val.(type) {
case func(TableView, int):
listeners[i] = val
case func(int):
listeners[i] = func(_ TableView, index int) {
val(index)
}
default:
return nil
}
}
return listeners
}
return nil
}
func (table *tableViewData) htmlTag() string {
return "table"
}

View File

@ -210,10 +210,12 @@ func (tabsLayout *tabsLayoutData) set(tag string, value any) bool {
tabsLayout.tabListener = listeners
case TabCloseEvent:
listeners := tabsLayout.valueToCloseListeners(value)
if listeners == nil {
listeners, ok := valueToEventListeners[TabsLayout, int](value)
if !ok {
notCompatibleType(tag, value)
return false
} else if listeners == nil {
listeners = []func(TabsLayout, int){}
}
tabsLayout.tabCloseListener = listeners
@ -433,61 +435,6 @@ func (tabsLayout *tabsLayoutData) valueToTabListeners(value any) []func(TabsLayo
return nil
}
func (tabsLayout *tabsLayoutData) valueToCloseListeners(value any) []func(TabsLayout, int) {
if value == nil {
return []func(TabsLayout, int){}
}
switch value := value.(type) {
case func(TabsLayout, int):
return []func(TabsLayout, int){value}
case func(int):
fn := func(_ TabsLayout, index int) {
value(index)
}
return []func(TabsLayout, int){fn}
case []func(TabsLayout, int):
return value
case []func(int):
listeners := make([]func(TabsLayout, int), len(value))
for i, val := range value {
if val == nil {
return nil
}
listeners[i] = func(_ TabsLayout, index int) {
val(index)
}
}
return listeners
case []any:
listeners := make([]func(TabsLayout, int), len(value))
for i, val := range value {
if val == nil {
return nil
}
switch val := val.(type) {
case func(TabsLayout, int):
listeners[i] = val
case func(int):
listeners[i] = func(_ TabsLayout, index int) {
val(index)
}
default:
return nil
}
}
return listeners
}
return nil
}
func (tabsLayout *tabsLayoutData) tabsLocation() int {
tabs, _ := enumProperty(tabsLayout, Tabs, tabsLayout.session, 0)
return tabs

View File

@ -223,57 +223,14 @@ func (picker *timePickerData) set(tag string, value any) bool {
}
case TimeChangedEvent:
switch value := value.(type) {
case func(TimePicker, time.Time):
picker.timeChangedListeners = []func(TimePicker, time.Time){value}
case func(time.Time):
fn := func(_ TimePicker, time time.Time) {
value(time)
}
picker.timeChangedListeners = []func(TimePicker, time.Time){fn}
case []func(TimePicker, time.Time):
picker.timeChangedListeners = value
case []func(time.Time):
listeners := make([]func(TimePicker, time.Time), len(value))
for i, val := range value {
if val == nil {
notCompatibleType(tag, val)
return false
}
listeners[i] = func(_ TimePicker, time time.Time) {
val(time)
}
}
picker.timeChangedListeners = listeners
case []any:
listeners := make([]func(TimePicker, time.Time), len(value))
for i, val := range value {
if val == nil {
notCompatibleType(tag, val)
return false
}
switch val := val.(type) {
case func(TimePicker, time.Time):
listeners[i] = val
case func(time.Time):
listeners[i] = func(_ TimePicker, time time.Time) {
val(time)
}
default:
notCompatibleType(tag, val)
return false
}
}
picker.timeChangedListeners = listeners
listeners, ok := valueToEventListeners[TimePicker, time.Time](value)
if !ok {
notCompatibleType(tag, value)
return false
} else if listeners == nil {
listeners = []func(TimePicker, time.Time){}
}
picker.timeChangedListeners = listeners
picker.propertyChangedEvent(tag)
return true
@ -458,15 +415,5 @@ func GetTimePickerValue(view View, subviewID string) time.Time {
// If there are no listeners then the empty list is returned
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetTimeChangedListeners(view View, subviewID string) []func(TimePicker, time.Time) {
if subviewID != "" {
view = ViewByID(view, subviewID)
}
if view != nil {
if value := view.Get(TimeChangedEvent); value != nil {
if listeners, ok := value.([]func(TimePicker, time.Time)); ok {
return listeners
}
}
}
return []func(TimePicker, time.Time){}
return getEventListeners[TimePicker, time.Time](view, subviewID, TimeChangedEvent)
}

View File

@ -90,131 +90,6 @@ type TouchEvent struct {
MetaKey bool
}
func valueToTouchListeners(value any) ([]func(View, TouchEvent), bool) {
if value == nil {
return nil, true
}
switch value := value.(type) {
case func(View, TouchEvent):
return []func(View, TouchEvent){value}, true
case func(TouchEvent):
fn := func(_ View, event TouchEvent) {
value(event)
}
return []func(View, TouchEvent){fn}, true
case func(View):
fn := func(view View, _ TouchEvent) {
value(view)
}
return []func(View, TouchEvent){fn}, true
case func():
fn := func(View, TouchEvent) {
value()
}
return []func(View, TouchEvent){fn}, true
case []func(View, TouchEvent):
if len(value) == 0 {
return nil, true
}
for _, fn := range value {
if fn == nil {
return nil, false
}
}
return value, true
case []func(TouchEvent):
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(View, TouchEvent), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(_ View, event TouchEvent) {
v(event)
}
}
return listeners, true
case []func(View):
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(View, TouchEvent), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(view View, _ TouchEvent) {
v(view)
}
}
return listeners, true
case []func():
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(View, TouchEvent), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(View, TouchEvent) {
v()
}
}
return listeners, true
case []any:
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(View, TouchEvent), count)
for i, v := range value {
if v == nil {
return nil, false
}
switch v := v.(type) {
case func(View, TouchEvent):
listeners[i] = v
case func(TouchEvent):
listeners[i] = func(_ View, event TouchEvent) {
v(event)
}
case func(View):
listeners[i] = func(view View, _ TouchEvent) {
v(view)
}
case func():
listeners[i] = func(View, TouchEvent) {
v()
}
default:
return nil, false
}
}
return listeners, true
}
return nil, false
}
var touchEvents = map[string]struct{ jsEvent, jsFunc string }{
TouchStart: {jsEvent: "ontouchstart", jsFunc: "touchStartEvent"},
TouchEnd: {jsEvent: "ontouchend", jsFunc: "touchEndEvent"},
@ -223,7 +98,7 @@ var touchEvents = map[string]struct{ jsEvent, jsFunc string }{
}
func (view *viewData) setTouchListener(tag string, value any) bool {
listeners, ok := valueToTouchListeners(value)
listeners, ok := valueToEventListeners[View, TouchEvent](value)
if !ok {
notCompatibleType(tag, value)
return false
@ -251,20 +126,6 @@ func (view *viewData) removeTouchListener(tag string) {
}
}
func getTouchListeners(view View, subviewID string, tag string) []func(View, TouchEvent) {
if subviewID != "" {
view = ViewByID(view, subviewID)
}
if view != nil {
if value := view.Get(tag); value != nil {
if result, ok := value.([]func(View, TouchEvent)); ok {
return result
}
}
}
return []func(View, TouchEvent){}
}
func touchEventsHtml(view View, buffer *strings.Builder) {
for tag, js := range touchEvents {
if value := view.getRaw(tag); value != nil {
@ -309,7 +170,7 @@ func (event *TouchEvent) init(data DataObject) {
}
func handleTouchEvents(view View, tag string, data DataObject) {
listeners := getTouchListeners(view, "", tag)
listeners := getEventListeners[View, TouchEvent](view, "", tag)
if len(listeners) == 0 {
return
}
@ -325,23 +186,23 @@ func handleTouchEvents(view View, tag string, data DataObject) {
// GetTouchStartListeners returns the "touch-start" listener list. If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetTouchStartListeners(view View, subviewID string) []func(View, TouchEvent) {
return getTouchListeners(view, subviewID, TouchStart)
return getEventListeners[View, TouchEvent](view, subviewID, TouchStart)
}
// GetTouchEndListeners returns the "touch-end" listener list. If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetTouchEndListeners(view View, subviewID string) []func(View, TouchEvent) {
return getTouchListeners(view, subviewID, TouchEnd)
return getEventListeners[View, TouchEvent](view, subviewID, TouchEnd)
}
// GetTouchMoveListeners returns the "touch-move" listener list. If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetTouchMoveListeners(view View, subviewID string) []func(View, TouchEvent) {
return getTouchListeners(view, subviewID, TouchMove)
return getEventListeners[View, TouchEvent](view, subviewID, TouchMove)
}
// GetTouchCancelListeners returns the "touch-cancel" listener list. If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetTouchCancelListeners(view View, subviewID string) []func(View, TouchEvent) {
return getTouchListeners(view, subviewID, TouchCancel)
return getEventListeners[View, TouchEvent](view, subviewID, TouchCancel)
}