From 2f07584b372b67b549be9d39b452fad865309dd3 Mon Sep 17 00:00:00 2001 From: Alexei Anoshenko <2277098+anoshenko@users.noreply.github.com> Date: Thu, 19 Jun 2025 17:31:39 +0300 Subject: [PATCH] Added binding to View.String() --- dragAndDrop.go | 54 +++++++++++++ events.go | 119 +++------------------------ events1arg.go | 10 +++ events2arg.go | 10 +++ mediaPlayer.go | 10 +++ viewStyle.go | 216 +++++++++++++++++++++++++++++++++++++++++++------ 6 files changed, 286 insertions(+), 133 deletions(-) diff --git a/dragAndDrop.go b/dragAndDrop.go index f0fa70e..0c1a006 100644 --- a/dragAndDrop.go +++ b/dragAndDrop.go @@ -84,7 +84,16 @@ const ( // Fired when the user starts dragging an element or text selection. // // General listener format: + // func(view rui.View, event rui.DragAndDropEvent). // + // where: + // - view - Interface of a view which generated this event, + // - event - event parameters. + // + // Allowed listener formats: + // func(view rui.View) + // func(rui.DragAndDropEvent) + // func() DragStartEvent PropertyName = "drag-start-event" // DragEndEvent is the constant for "drag-end-event" property tag. @@ -93,7 +102,16 @@ const ( // Fired when a drag operation ends (by releasing a mouse button or hitting the escape key). // // General listener format: + // func(view rui.View, event rui.DragAndDropEvent). // + // where: + // - view - Interface of a view which generated this event, + // - event - event parameters. + // + // Allowed listener formats: + // func(view rui.View) + // func(rui.DragAndDropEvent) + // func() DragEndEvent PropertyName = "drag-end-event" // DragEnterEvent is the constant for "drag-enter-event" property tag. @@ -102,7 +120,16 @@ const ( // Fired when a dragged element or text selection enters a valid drop target. // // General listener format: + // func(view rui.View, event rui.DragAndDropEvent). // + // where: + // - view - Interface of a view which generated this event, + // - event - event parameters. + // + // Allowed listener formats: + // func(view rui.View) + // func(rui.DragAndDropEvent) + // func() DragEnterEvent PropertyName = "drag-enter-event" // DragLeaveEvent is the constant for "drag-leave-event" property tag. @@ -111,7 +138,16 @@ const ( // Fired when a dragged element or text selection leaves a valid drop target. // // General listener format: + // func(view rui.View, event rui.DragAndDropEvent). // + // where: + // - view - Interface of a view which generated this event, + // - event - event parameters. + // + // Allowed listener formats: + // func(view rui.View) + // func(rui.DragAndDropEvent) + // func() DragLeaveEvent PropertyName = "drag-leave-event" // DragOverEvent is the constant for "drag-over-event" property tag. @@ -120,7 +156,16 @@ const ( // Fired when an element or text selection is being dragged over a valid drop target (every few hundred milliseconds). // // General listener format: + // func(view rui.View, event rui.DragAndDropEvent). // + // where: + // - view - Interface of a view which generated this event, + // - event - event parameters. + // + // Allowed listener formats: + // func(view rui.View) + // func(rui.DragAndDropEvent) + // func() DragOverEvent PropertyName = "drag-over-event" // DropEvent is the constant for "drop-event" property tag. @@ -129,7 +174,16 @@ const ( // Fired when an element or text selection is dropped on a valid drop target. // // General listener format: + // func(view rui.View, event rui.DragAndDropEvent). // + // where: + // - view - Interface of a view which generated this event, + // - event - event parameters. + // + // Allowed listener formats: + // func(view rui.View) + // func(rui.DragAndDropEvent) + // func() DropEvent PropertyName = "drop-event" // DropEffectUndefined - the value of the "drop-effect" and "drop-effect-allowed" properties: the value is not defined (default value). diff --git a/events.go b/events.go index 21b232f..204fe0f 100644 --- a/events.go +++ b/events.go @@ -156,115 +156,6 @@ func (data *noArgListenerBinding[V]) rawListener() any { return data.name } -/* -func valueToNoArgEventListeners[V any](view View, value any) ([]func(V), bool) { - if value == nil { - return nil, true - } - - switch value := value.(type) { - case string: - fn := func(arg V) { - 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(arg) { - args = []reflect.Value{reflect.ValueOf(arg)} - } - } - - if args != nil { - method.Call(args) - } else { - ErrorLogF(`Unsupported prototype of "%s" method`, value) - } - } - return []func(V){fn}, true - - case func(V): - return []func(V){value}, true - - case func(): - fn := func(V) { - value() - } - return []func(V){fn}, true - - case []func(V): - 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(V), count) - for i, v := range value { - if v == nil { - return nil, false - } - listeners[i] = func(V) { - v() - } - } - return listeners, true - - case []any: - count := len(value) - if count == 0 { - return nil, true - } - listeners := make([]func(V), count) - for i, v := range value { - if v == nil { - return nil, false - } - switch v := v.(type) { - case func(V): - listeners[i] = v - - case func(): - listeners[i] = func(V) { - v() - } - - default: - return nil, false - } - } - return listeners, true - } - - return nil, false -} -*/ - func valueToNoArgEventListeners[V View](value any) ([]noArgListener[V], bool) { if value == nil { return nil, true @@ -356,3 +247,13 @@ func getNoArgEventRawListeners[V View](view View, subviewID []string, tag Proper } return result } + +func getNoArgBinding[V View](listeners []noArgListener[V]) string { + for _, listener := range listeners { + raw := listener.rawListener() + if text, ok := raw.(string); ok && text != "" { + return text + } + } + return "" +} diff --git a/events1arg.go b/events1arg.go index 8e233d0..02ad212 100644 --- a/events1arg.go +++ b/events1arg.go @@ -257,3 +257,13 @@ func getOneArgEventRawListeners[V View, E any](view View, subviewID []string, ta } return result } + +func getOneArgBinding[V View, E any](listeners []oneArgListener[V, E]) string { + for _, listener := range listeners { + raw := listener.rawListener() + if text, ok := raw.(string); ok && text != "" { + return text + } + } + return "" +} diff --git a/events2arg.go b/events2arg.go index 8608a28..54aeea2 100644 --- a/events2arg.go +++ b/events2arg.go @@ -330,3 +330,13 @@ func getTwoArgEventRawListeners[V View, E any](view View, subviewID []string, ta } 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 "" +} diff --git a/mediaPlayer.go b/mediaPlayer.go index 41db0e6..c2a48de 100644 --- a/mediaPlayer.go +++ b/mediaPlayer.go @@ -1628,3 +1628,13 @@ func valueToMediaPlayerErrorListeners(value any) ([]mediaPlayerErrorListener, bo return nil, false } + +func getMediaPlayerErrorListenerBinding(listeners []mediaPlayerErrorListener) string { + for _, listener := range listeners { + raw := listener.rawListener() + if text, ok := raw.(string); ok && text != "" { + return text + } + } + return "" +} diff --git a/viewStyle.go b/viewStyle.go index 4986545..2d269ac 100644 --- a/viewStyle.go +++ b/viewStyle.go @@ -2,9 +2,10 @@ package rui import ( "fmt" - "sort" + "slices" "strconv" "strings" + "time" ) // ViewStyle interface of the style of view @@ -551,26 +552,118 @@ func viewStyleGet(style Properties, tag PropertyName) any { } func supportedPropertyValue(value any) bool { - switch value.(type) { - case string: + switch value := value.(type) { + case string, bool, float32, float64, int, stringWriter, fmt.Stringer: + return true + case []string: - case bool: - case float32: - case float64: - case int: - case stringWriter: - case fmt.Stringer: + return len(value) > 0 + case []ShadowProperty: + return len(value) > 0 + case []View: + return len(value) > 0 + case []any: + return len(value) > 0 + case []BackgroundElement: + return len(value) > 0 + case []BackgroundGradientPoint: + return len(value) > 0 + case []BackgroundGradientAngle: + return len(value) > 0 + case map[PropertyName]AnimationProperty: + return len(value) > 0 + + case []noArgListener[View]: + return getNoArgBinding(value) != "" + + case []noArgListener[ImageView]: + return getNoArgBinding(value) != "" + + case []noArgListener[MediaPlayer]: + return getNoArgBinding(value) != "" + + case []oneArgListener[View, KeyEvent]: + return getOneArgBinding(value) != "" + + case []oneArgListener[View, MouseEvent]: + return getOneArgBinding(value) != "" + + case []oneArgListener[View, TouchEvent]: + return getOneArgBinding(value) != "" + + case []oneArgListener[View, PointerEvent]: + return getOneArgBinding(value) != "" + + case []oneArgListener[View, PropertyName]: + return getOneArgBinding(value) != "" + + case []oneArgListener[View, string]: + return getOneArgBinding(value) != "" + + case []oneArgListener[View, Frame]: + return getOneArgBinding(value) != "" + + case []oneArgListener[View, DragAndDropEvent]: + return getOneArgBinding(value) != "" + + case []oneArgListener[Checkbox, bool]: + return getOneArgBinding(value) != "" + + case []oneArgListener[FilePicker, []FileInfo]: + return getOneArgBinding(value) != "" + + case []oneArgListener[ListView, int]: + return getOneArgBinding(value) != "" + + case []oneArgListener[ListView, []int]: + return getOneArgBinding(value) != "" + + case []oneArgListener[MediaPlayer, float64]: + return getOneArgBinding(value) != "" + + case []oneArgListener[TableView, int]: + return getOneArgBinding(value) != "" + + case []oneArgListener[TabsLayout, int]: + return getOneArgBinding(value) != "" + + case []twoArgListener[ColorPicker, Color]: + return getTwoArgBinding(value) != "" + + case []twoArgListener[DatePicker, time.Time]: + return getTwoArgBinding(value) != "" + + case []twoArgListener[TimePicker, time.Time]: + return getTwoArgBinding(value) != "" + + case []twoArgListener[DropDownList, int]: + return getTwoArgBinding(value) != "" + + case []twoArgListener[EditView, string]: + return getTwoArgBinding(value) != "" + + case []twoArgListener[NumberPicker, float64]: + return getTwoArgBinding(value) != "" + + case []twoArgListener[TableView, int]: + return getTwoArgBinding(value) != "" + + case []twoArgListener[TabsLayout, int]: + return getTwoArgBinding(value) != "" + + case []mediaPlayerErrorListener: + return getMediaPlayerErrorListenerBinding(value) != "" + default: return false } - return true } func writePropertyValue(buffer *strings.Builder, tag PropertyName, value any, indent string) { @@ -791,9 +884,7 @@ func writePropertyValue(buffer *strings.Builder, tag PropertyName, value any, in for tag := range value { tags = append(tags, tag) } - sort.Slice(tags, func(i, j int) bool { - return tags[i] < tags[j] - }) + slices.Sort(tags) buffer.WriteString("[\n") indent2 := indent + "\t" for _, tag := range tags { @@ -806,6 +897,87 @@ func writePropertyValue(buffer *strings.Builder, tag PropertyName, value any, in buffer.WriteString(indent) buffer.WriteRune(']') } + + case []noArgListener[View]: + buffer.WriteString(getNoArgBinding(value)) + + case []noArgListener[ImageView]: + buffer.WriteString(getNoArgBinding(value)) + + case []noArgListener[MediaPlayer]: + buffer.WriteString(getNoArgBinding(value)) + + case []oneArgListener[View, KeyEvent]: + buffer.WriteString(getOneArgBinding(value)) + + case []oneArgListener[View, MouseEvent]: + buffer.WriteString(getOneArgBinding(value)) + + case []oneArgListener[View, TouchEvent]: + buffer.WriteString(getOneArgBinding(value)) + + case []oneArgListener[View, PointerEvent]: + buffer.WriteString(getOneArgBinding(value)) + + case []oneArgListener[View, PropertyName]: + buffer.WriteString(getOneArgBinding(value)) + + case []oneArgListener[View, string]: + buffer.WriteString(getOneArgBinding(value)) + + case []oneArgListener[View, Frame]: + buffer.WriteString(getOneArgBinding(value)) + + case []oneArgListener[View, DragAndDropEvent]: + buffer.WriteString(getOneArgBinding(value)) + + case []oneArgListener[Checkbox, bool]: + buffer.WriteString(getOneArgBinding(value)) + + case []oneArgListener[FilePicker, []FileInfo]: + buffer.WriteString(getOneArgBinding(value)) + + case []oneArgListener[ListView, int]: + buffer.WriteString(getOneArgBinding(value)) + + case []oneArgListener[ListView, []int]: + buffer.WriteString(getOneArgBinding(value)) + + case []oneArgListener[MediaPlayer, float64]: + buffer.WriteString(getOneArgBinding(value)) + + case []oneArgListener[TableView, int]: + buffer.WriteString(getOneArgBinding(value)) + + case []oneArgListener[TabsLayout, int]: + buffer.WriteString(getOneArgBinding(value)) + + case []twoArgListener[ColorPicker, Color]: + buffer.WriteString(getTwoArgBinding(value)) + + case []twoArgListener[DatePicker, time.Time]: + buffer.WriteString(getTwoArgBinding(value)) + + case []twoArgListener[TimePicker, time.Time]: + buffer.WriteString(getTwoArgBinding(value)) + + case []twoArgListener[DropDownList, int]: + buffer.WriteString(getTwoArgBinding(value)) + + case []twoArgListener[EditView, string]: + buffer.WriteString(getTwoArgBinding(value)) + + case []twoArgListener[NumberPicker, float64]: + buffer.WriteString(getTwoArgBinding(value)) + + case []twoArgListener[TableView, int]: + buffer.WriteString(getTwoArgBinding(value)) + + case []twoArgListener[TabsLayout, int]: + buffer.WriteString(getTwoArgBinding(value)) + + case []mediaPlayerErrorListener: + buffer.WriteString(getMediaPlayerErrorListenerBinding(value)) } } @@ -815,19 +987,15 @@ func writeViewStyle(name string, view Properties, buffer *strings.Builder, inden indent += "\t" writeProperty := func(tag PropertyName, value any) { - for _, exclude := range excludeTags { - if exclude == tag { - return + if !slices.Contains(excludeTags, tag) { + if supportedPropertyValue(value) { + buffer.WriteString(indent) + buffer.WriteString(string(tag)) + buffer.WriteString(" = ") + writePropertyValue(buffer, tag, value, indent) + buffer.WriteString(",\n") } } - - if supportedPropertyValue(value) { - buffer.WriteString(indent) - buffer.WriteString(string(tag)) - buffer.WriteString(" = ") - writePropertyValue(buffer, tag, value, indent) - buffer.WriteString(",\n") - } } tags := view.AllTags()