This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch main
in repository ego.

View the commit online.

commit 88bab8695de35cebafb82b147e895ad2b7c4e909
Author: [email protected] <[email protected]>
AuthorDate: Tue Mar 31 15:40:35 2026 -0600

    feat(ego-gen): map EFL (r,g,b,a) color tuples to color.RGBA
    
    Detect 4-param r,g,b,a int patterns in multi-value properties
    and collapse to image/color.RGBA. Getters return color.RGBA,
    setters accept color.RGBA. Applied to regular and indexed
    property templates with conditional import.
    
    Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
---
 cmd/ego-gen/generator.go            |  5 +++
 cmd/ego-gen/generator_test.go       | 75 +++++++++++++++++++++++++++++++++++++
 cmd/ego-gen/main.go                 | 28 ++++++++++++++
 cmd/ego-gen/templates/class.go.tmpl | 51 +++++++++++++++++++++++--
 4 files changed, 155 insertions(+), 4 deletions(-)

diff --git a/cmd/ego-gen/generator.go b/cmd/ego-gen/generator.go
index e1eb223..3ac986f 100644
--- a/cmd/ego-gen/generator.go
+++ b/cmd/ego-gen/generator.go
@@ -35,6 +35,7 @@ type ClassData struct {
 	IndexedProperties []IndexedPropertyData // indexed properties with key params
 	IteratorMethods      []IteratorMethodData  // methods returning Eina_Iterator
 	HasIterators         bool                  // true if IteratorMethods is non-empty (controls import)
+	HasColor             bool                  // true if any property uses color.RGBA (controls import)
 	IteratorStructTypes  []IteratorMethodData  // one entry per distinct struct elem type (for C helpers)
 	GlobalFunctions []GlobalFunctionData // package-level functions with no Eo receiver
 	CallbackTypes   []CallbackTypeData   // distinct callback typedefs used by this class
@@ -114,6 +115,9 @@ type PropertyData struct {
 	// IsMultiValue is true when the property has more than one value parameter.
 	// The getter returns multiple Go values and the setter takes multiple params.
 	IsMultiValue bool
+	// IsColor is true when the multi-value property is an (r, g, b, a int) color
+	// tuple that should be collapsed into a color.RGBA value.
+	IsColor bool
 	// MultiGetValues holds the getter out-params (may differ from MultiSetValues
 	// for get-only properties like cell_size).
 	MultiGetValues []MultiValueData
@@ -148,6 +152,7 @@ type IndexedPropertyData struct {
 
 	// Multi-value fields:
 	IsMultiValue   bool
+	IsColor        bool // true when multi-value is an (r,g,b,a) color tuple → color.RGBA
 	MultiGetValues []MultiValueData
 	MultiSetValues []MultiValueData
 }
diff --git a/cmd/ego-gen/generator_test.go b/cmd/ego-gen/generator_test.go
index b35c97c..36e8b0a 100644
--- a/cmd/ego-gen/generator_test.go
+++ b/cmd/ego-gen/generator_test.go
@@ -1330,3 +1330,78 @@ func TestGenerateClass_EinaValueParam(t *testing.T) {
 		}
 	}
 }
+
+func TestGenerateClass_ColorProperty(t *testing.T) {
+	g, outDir := newTestGenerator(t)
+
+	data := ClassData{
+		PackageName:   "gfx",
+		GoName:        "ColorMixin",
+		EolianName:    "Efl.Gfx.Color",
+		CClassName:    "EFL_GFX_COLOR_CLASS",
+		CClassGetFunc: "efl_gfx_color_class_get",
+		CPrefix:       "efl_gfx_color",
+		EOHeaderFile:  "efl_gfx_color.eo.h",
+		IsAbstract:    true,
+		HasColor:      true,
+		Properties: []PropertyData{
+			{
+				GoGetter:     "Color",
+				GoSetter:     "SetColor",
+				CGetName:     "efl_gfx_color_get",
+				CSetName:     "efl_gfx_color_set",
+				HasGet:       true,
+				HasSet:       true,
+				IsMultiValue: true,
+				IsColor:      true,
+				MultiGetValues: []MultiValueData{
+					{GoName: "R", LowerGoName: "r", GoType: "int", CType: "int"},
+					{GoName: "G", LowerGoName: "g", GoType: "int", CType: "int"},
+					{GoName: "B", LowerGoName: "b", GoType: "int", CType: "int"},
+					{GoName: "A", LowerGoName: "a", GoType: "int", CType: "int"},
+				},
+				MultiSetValues: []MultiValueData{
+					{GoName: "R", LowerGoName: "r", GoType: "int", CType: "int"},
+					{GoName: "G", LowerGoName: "g", GoType: "int", CType: "int"},
+					{GoName: "B", LowerGoName: "b", GoType: "int", CType: "int"},
+					{GoName: "A", LowerGoName: "a", GoType: "int", CType: "int"},
+				},
+			},
+		},
+	}
+
+	if err := g.GenerateClass(data); err != nil {
+		t.Fatalf("GenerateClass: %v", err)
+	}
+
+	outFile := filepath.Join(outDir, "gfx", "color_mixin.go")
+	content, err := os.ReadFile(outFile)
+	if err != nil {
+		t.Fatalf("output file not found at %s: %v", outFile, err)
+	}
+
+	src := string(content)
+
+	mustContain := []string{
+		`"image/color"`,
+		"func (o *ColorMixin) Color() color.RGBA",
+		"uint8(cR)",
+		"func (o *ColorMixin) SetColor(c color.RGBA)",
+		"C.int(c.R)",
+	}
+
+	mustNotContain := []string{
+		"(r int, g int, b int, a int)",
+	}
+
+	for _, want := range mustContain {
+		if !strings.Contains(src, want) {
+			t.Errorf("output missing expected pattern %q\nfile content:\n%s", want, src)
+		}
+	}
+	for _, banned := range mustNotContain {
+		if strings.Contains(src, banned) {
+			t.Errorf("output contains banned pattern %q", banned)
+		}
+	}
+}
diff --git a/cmd/ego-gen/main.go b/cmd/ego-gen/main.go
index 69f6b3f..aeb7fa6 100644
--- a/cmd/ego-gen/main.go
+++ b/cmd/ego-gen/main.go
@@ -910,9 +910,21 @@ func buildClassData(c *Class, pkgOptionNames map[string]map[string]bool) (ClassD
 		GlobalFunctions:     globalFunctions,
 		CallbackTypes:       callbackTypes,
 		HasCallbacks:        len(callbackTypes) > 0,
+		HasColor:            hasColorProperty(properties),
 	}, nil
 }
 
+// hasColorProperty reports whether any property in the slice has IsColor set,
+// used to decide whether to import "image/color" in the generated file.
+func hasColorProperty(props []PropertyData) bool {
+	for _, p := range props {
+		if p.IsColor {
+			return true
+		}
+	}
+	return false
+}
+
 // deduplicateIteratorStructTypes returns one representative IteratorMethodData
 // per distinct StructCType among methods with ElemIsStruct == true. This is
 // used to generate one set of C field-accessor helpers per struct type, rather
@@ -933,6 +945,21 @@ func deduplicateIteratorStructTypes(methods []IteratorMethodData) []IteratorMeth
 	return result
 }
 
+// isColorPattern reports whether a slice of MultiValueData represents an
+// EFL (r, g, b, a int) color tuple that should map to color.RGBA.
+func isColorPattern(vals []MultiValueData) bool {
+	if len(vals) != 4 {
+		return false
+	}
+	names := [4]string{"r", "g", "b", "a"}
+	for i, v := range vals {
+		if v.LowerGoName != names[i] || v.GoType != "int" {
+			return false
+		}
+	}
+	return true
+}
+
 // isSimpleCgoType reports whether a C type can be used directly in a cgo call
 // as a plain integer/float value. These are the types that can safely appear as
 // multiple return values or multiple parameters without needing any C wrapper.
@@ -1042,6 +1069,7 @@ func buildPropertyData(f *Function, cPrefix string) (PropertyData, error) {
 				HasGet:         hasGet && len(getMulti) > 0,
 				HasSet:         hasSet && len(setMulti) > 0,
 				IsMultiValue:   true,
+				IsColor:        isColorPattern(getMulti) || isColorPattern(setMulti),
 				MultiGetValues: getMulti,
 				MultiSetValues: setMulti,
 			}, nil
diff --git a/cmd/ego-gen/templates/class.go.tmpl b/cmd/ego-gen/templates/class.go.tmpl
index 78ab935..0ca1d69 100644
--- a/cmd/ego-gen/templates/class.go.tmpl
+++ b/cmd/ego-gen/templates/class.go.tmpl
@@ -269,6 +269,9 @@ import (
 {{- if .HasIterators}}
     "iter"
 {{- end}}
+{{- if .HasColor}}
+    "image/color"
+{{- end}}
 
     "git.enlightenment.org/cedric/ego/efl"
 {{- if and .ParentPkg (ne .ParentPkg .PackageName) (ne .ParentPkg "efl")}}
@@ -369,7 +372,16 @@ func {{$opt.GoOptionName}}(val {{$opt.StructGoType}}) efl.Option {
 {{- range $prop := .Properties}}
 {{- if $prop.HasGet}}
 
-{{- if $prop.IsMultiValue}}
+{{- if and $prop.IsMultiValue $prop.IsColor}}
+// {{$prop.GoGetter}} returns the {{$prop.GoGetter}} color of the {{$.GoName}}.
+func (o *{{$.GoName}}) {{$prop.GoGetter}}() color.RGBA {
+{{- range $v := $prop.MultiGetValues}}
+    var c{{$v.GoName}} C.int
+{{- end}}
+    C.{{$prop.CGetName}}((*C.Eo)(o.Eo()){{range $prop.MultiGetValues}}, &c{{.GoName}}{{end}})
+    return color.RGBA{R: uint8(cR), G: uint8(cG), B: uint8(cB), A: uint8(cA)}
+}
+{{- else if $prop.IsMultiValue}}
 // {{$prop.GoGetter}} returns the {{$prop.GoGetter}} property of the {{$.GoName}}.
 func (o *{{$.GoName}}) {{$prop.GoGetter}}() ({{range $i, $v := $prop.MultiGetValues}}{{if $i}}, {{end}}{{$v.LowerGoName}} {{if needsStringConversion $v.CType}}string{{else if $v.IsEo}}unsafe.Pointer{{else}}{{$v.GoType}}{{end}}{{end}}) {
 {{- range $v := $prop.MultiGetValues}}
@@ -412,7 +424,12 @@ func (o *{{$.GoName}}) {{$prop.GoGetter}}() {{$prop.GoType}} {
 {{- end}}
 {{- if $prop.HasSet}}
 
-{{- if $prop.IsMultiValue}}
+{{- if and $prop.IsMultiValue $prop.IsColor}}
+// {{$prop.GoSetter}} sets the {{$prop.GoGetter}} color of the {{$.GoName}}.
+func (o *{{$.GoName}}) {{$prop.GoSetter}}(c color.RGBA) {
+    C.{{$prop.CSetName}}((*C.Eo)(o.Eo()), C.int(c.R), C.int(c.G), C.int(c.B), C.int(c.A))
+}
+{{- else if $prop.IsMultiValue}}
 // {{$prop.GoSetter}} sets the {{$prop.GoGetter}} property of the {{$.GoName}}.
 func (o *{{$.GoName}}) {{$prop.GoSetter}}({{range $i, $v := $prop.MultiSetValues}}{{if $i}}, {{end}}{{$v.LowerGoName}} {{if needsStringConversion $v.CType}}string{{else if $v.IsEo}}efl.Objecter{{else}}{{$v.GoType}}{{end}}{{end}}) {
 {{- range $v := $prop.MultiSetValues}}
@@ -603,7 +620,22 @@ func (o *{{$.GoName}}) {{$ip.GoAccessorMethod}}({{range $i, $k := $ip.Keys}}{{if
 }
 
 {{- if $ip.HasGet}}
-{{- if $ip.IsMultiValue}}
+{{- if and $ip.IsMultiValue $ip.IsColor}}
+// Get returns the color for the captured key(s).
+func (p {{$ip.AccessorTypeName}}) Get() color.RGBA {
+{{- range $ip.Keys}}
+{{- if needsStringConversion .CType}}
+    c{{.GoName}} := C.CString(p.{{.GoName}})
+    defer C.free(unsafe.Pointer(c{{.GoName}}))
+{{- end}}
+{{- end}}
+{{- range $v := $ip.MultiGetValues}}
+    var c{{$v.GoName}} C.int
+{{- end}}
+    C.{{$ip.CGetName}}(p.obj{{range $ip.Keys}}, {{template "indexedKeyArg" .}}{{end}}{{range $ip.MultiGetValues}}, &c{{.GoName}}{{end}})
+    return color.RGBA{R: uint8(cR), G: uint8(cG), B: uint8(cB), A: uint8(cA)}
+}
+{{- else if $ip.IsMultiValue}}
 // Get returns the values for the captured key(s).
 func (p {{$ip.AccessorTypeName}}) Get() ({{range $i, $v := $ip.MultiGetValues}}{{if $i}}, {{end}}{{$v.LowerGoName}} {{if needsStringConversion $v.CType}}string{{else if $v.IsEo}}unsafe.Pointer{{else}}{{$v.GoType}}{{end}}{{end}}) {
 {{- range $ip.Keys}}
@@ -660,7 +692,18 @@ func (p {{$ip.AccessorTypeName}}) Get() {{if $ip.IsStruct}}{{$ip.StructGoType}}{
 {{- end}}
 
 {{- if $ip.HasSet}}
-{{- if $ip.IsMultiValue}}
+{{- if and $ip.IsMultiValue $ip.IsColor}}
+// Set sets the color for the captured key(s).
+func (p {{$ip.AccessorTypeName}}) Set(c color.RGBA) {
+{{- range $ip.Keys}}
+{{- if needsStringConversion .CType}}
+    c{{.GoName}} := C.CString(p.{{.GoName}})
+    defer C.free(unsafe.Pointer(c{{.GoName}}))
+{{- end}}
+{{- end}}
+    C.{{$ip.CSetName}}(p.obj{{range $ip.Keys}}, {{template "indexedKeyArg" .}}{{end}}, C.int(c.R), C.int(c.G), C.int(c.B), C.int(c.A))
+}
+{{- else if $ip.IsMultiValue}}
 // Set sets the values for the captured key(s).
 func (p {{$ip.AccessorTypeName}}) Set({{range $i, $v := $ip.MultiSetValues}}{{if $i}}, {{end}}{{$v.LowerGoName}} {{if needsStringConversion $v.CType}}string{{else if $v.IsEo}}efl.Objecter{{else}}{{$v.GoType}}{{end}}{{end}}) {
 {{- range $ip.Keys}}

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to