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 5d83ff729f355940bf1e81086d234139c699ce38
Author: [email protected] <[email protected]>
AuthorDate: Wed Apr 1 19:43:14 2026 -0600

    feat(ego-gen): generate part accessors for all EFL widgets
    
    Widgets with declared parts now generate typed accessor methods.
    Panes.First()/Second() and Popup.Backwall() are the active examples.
    
    Fix two generator bugs found during regeneration:
    - Deduplicate C helper functions via UniquePartHelpers when multiple
      parts share the same part class (e.g. Panes first/second both use
      Efl.Ui.Panes_Part, previously causing duplicate static function defs)
    - Use the correct C type (e.g. double) instead of void* in generated
      helper signatures for numeric part properties like split_ratio_min
    - Auto-populate UniquePartHelpers in GenerateClass for backward compat
      with tests that construct ClassData directly
    
    Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
---
 cmd/ego-gen/generator.go            |  9 +++-
 cmd/ego-gen/main.go                 |  1 +
 cmd/ego-gen/part.go                 | 31 +++++++++++++
 cmd/ego-gen/templates/class.go.tmpl | 12 +++--
 efl/ui/panes.go                     | 90 +++++++++++++++++++++++++++++++++++++
 efl/ui/popup.go                     | 33 ++++++++++++++
 6 files changed, 168 insertions(+), 8 deletions(-)

diff --git a/cmd/ego-gen/generator.go b/cmd/ego-gen/generator.go
index e31360f..4c7b7c0 100644
--- a/cmd/ego-gen/generator.go
+++ b/cmd/ego-gen/generator.go
@@ -42,7 +42,8 @@ type ClassData struct {
 	GlobalFunctions []GlobalFunctionData // package-level functions with no Eo receiver
 	CallbackTypes   []CallbackTypeData   // distinct callback typedefs used by this class
 	HasCallbacks    bool                 // true if CallbackTypes is non-empty (controls imports/trampolines)
-	Parts           []PartData           // declared widget parts with accessors
+	Parts            []PartData           // declared widget parts with accessors
+	UniquePartHelpers []PartMethodData     // deduplicated C helper entries across all parts (for C preamble)
 }
 
 // ConstructorData describes a constructor option for an EFL class. Each entry
@@ -248,6 +249,7 @@ type PartMethodData struct {
 	GoReturnType string // for getters
 	GoParamName  string // for setters
 	GoParamType  string // for setters
+	CType        string // C type for the value param/return (e.g. "double", "int")
 	IsEoParam    bool   // true if param is efl.Objecter
 	IsString     bool   // true if param/return is string
 	IsBool       bool   // true if return is bool
@@ -337,6 +339,11 @@ func NewGenerator(templateDir, outputDir string) (*Generator, error) {
 // GenerateClass renders the class template for data and writes the result to
 // outputDir/<packagename>/<snake_case_name>.go.
 func (g *Generator) GenerateClass(data ClassData) error {
+	// Auto-populate UniquePartHelpers from Parts when the caller has not set it.
+	// This ensures tests that construct ClassData directly still get C helpers emitted.
+	if len(data.UniquePartHelpers) == 0 && len(data.Parts) > 0 {
+		data.UniquePartHelpers = deduplicatePartHelpers(data.Parts)
+	}
 	return g.generate("class.go.tmpl", data.PackageName, toSnake(data.GoName), data)
 }
 
diff --git a/cmd/ego-gen/main.go b/cmd/ego-gen/main.go
index 3c3cd0d..6741cc9 100644
--- a/cmd/ego-gen/main.go
+++ b/cmd/ego-gen/main.go
@@ -821,6 +821,7 @@ func buildClassData(c *Class, pkgOptionNames map[string]map[string]bool) (ClassD
 		CallbackTypes:       callbackTypes,
 		HasCallbacks:        len(callbackTypes) > 0,
 		Parts:               parts,
+		UniquePartHelpers:   deduplicatePartHelpers(parts),
 		HasColor:            hasColorProperty(properties) || hasColorMethod(methods) || hasColorParts(parts),
 		HasImageTypes:       hasImageTypesProperty(properties) || hasImageTypesMethod(methods) || hasImageTypesIndexed(indexedProperties) || hasImageTypesIterator(iteratorMethods) || hasImageTypesConstructors(constructors) || hasImageTypesConstructors(propertyOptions),
 		HasTime:             hasTimeProperty(properties),
diff --git a/cmd/ego-gen/part.go b/cmd/ego-gen/part.go
index 2b325a0..d30ecbf 100644
--- a/cmd/ego-gen/part.go
+++ b/cmd/ego-gen/part.go
@@ -44,12 +44,23 @@ func partMethodsForClass(partClass *Class) []PartMethodData {
 			}
 		}
 
+		// Determine the raw C type for use in generated C helper signatures.
+		var rawCType string
+		if vals := f.PropertyValues(FunctionPropGet); len(vals) == 1 {
+			if pt := vals[0].Type(); pt != nil {
+				rawCType = pt.CType()
+			}
+		} else if rt := f.ReturnType(FunctionPropGet); rt != nil {
+			rawCType = rt.CType()
+		}
+
 		if hasGet && goType != "" {
 			methods = append(methods, PartMethodData{
 				GoName:       goGetter,
 				CHelper:      "_ego_part_" + cGetName,
 				IsGetter:     true,
 				GoReturnType: goType,
+				CType:        rawCType,
 				IsString:     isString,
 				IsBool:       isBool,
 				IsColor:      isColor,
@@ -74,6 +85,7 @@ func partMethodsForClass(partClass *Class) []PartMethodData {
 				IsSetter:    true,
 				GoParamName: "val",
 				GoParamType: paramType,
+				CType:       rawCType,
 				IsEoParam:   isEo,
 				IsString:    isString,
 				IsBool:      isBool,
@@ -126,3 +138,22 @@ func buildPartsData(c *Class, goName string, existingNames map[string]bool) []Pa
 
 	return result
 }
+
+// deduplicatePartHelpers collects all PartMethodData entries across all parts
+// and returns a deduplicated slice keyed by CHelper name. This is used to emit
+// C helper functions exactly once in the preamble even when multiple parts share
+// the same part class (and therefore have identical helper names).
+func deduplicatePartHelpers(parts []PartData) []PartMethodData {
+	seen := make(map[string]bool)
+	var unique []PartMethodData
+	for _, p := range parts {
+		for _, m := range p.PartMethods {
+			if seen[m.CHelper] {
+				continue
+			}
+			seen[m.CHelper] = true
+			unique = append(unique, m)
+		}
+	}
+	return unique
+}
diff --git a/cmd/ego-gen/templates/class.go.tmpl b/cmd/ego-gen/templates/class.go.tmpl
index 9238186..50bb18b 100644
--- a/cmd/ego-gen/templates/class.go.tmpl
+++ b/cmd/ego-gen/templates/class.go.tmpl
@@ -125,8 +125,7 @@ extern void {{.GoTrampolineName}}(void *data{{range .Params}}, {{.CType}} {{.GoN
 {{- end}}
 {{- end}}
 
-{{- range .Parts}}
-{{- range .PartMethods}}
+{{- range .UniquePartHelpers}}
 {{- if .IsGetter}}
 {{- if .IsString}}
 static const char *{{.CHelper}}(const Eo *obj, const char *part_name) {
@@ -145,8 +144,8 @@ static Eo *{{.CHelper}}(const Eo *obj, const char *part_name) {
     return {{trimPrefix .CHelper "_ego_part_"}}(efl_part(obj, part_name));
 }
 {{- else}}
-static void *{{.CHelper}}(const Eo *obj, const char *part_name) {
-    return (void *)(uintptr_t){{trimPrefix .CHelper "_ego_part_"}}(efl_part(obj, part_name));
+static {{.CType}} {{.CHelper}}(const Eo *obj, const char *part_name) {
+    return {{trimPrefix .CHelper "_ego_part_"}}(efl_part(obj, part_name));
 }
 {{- end}}
 {{- else if .IsSetter}}
@@ -167,13 +166,12 @@ static void {{.CHelper}}(Eo *obj, const char *part_name, Eo *val) {
     {{trimPrefix .CHelper "_ego_part_"}}(efl_part(obj, part_name), val);
 }
 {{- else}}
-static void {{.CHelper}}(Eo *obj, const char *part_name, void *val) {
+static void {{.CHelper}}(Eo *obj, const char *part_name, {{.CType}} val) {
     {{trimPrefix .CHelper "_ego_part_"}}(efl_part(obj, part_name), val);
 }
 {{- end}}
 {{- end}}
 {{- end}}
-{{- end}}
 
 {{- range .Properties}}
 {{- if and .HasGet (isPointerType .GoType)}}
@@ -1280,7 +1278,7 @@ func (p {{$part.ProxyTypeName}}) {{$m.GoName}}({{$m.GoParamName}} efl.Objecter)
 func (p {{$part.ProxyTypeName}}) {{$m.GoName}}({{$m.GoParamName}} {{$m.GoParamType}}) {
     cName := C.CString(p.name)
     defer C.free(unsafe.Pointer(cName))
-    C.{{$m.CHelper}}((*C.Eo)(p.parent), cName, {{$m.GoParamName}})
+    C.{{$m.CHelper}}((*C.Eo)(p.parent), cName, C.{{cTypeToCgo $m.CType}}({{$m.GoParamName}}))
 }
 {{- end}}
 {{- end}}
diff --git a/efl/ui/panes.go b/efl/ui/panes.go
index 71609ec..c2afb2f 100644
--- a/efl/ui/panes.go
+++ b/efl/ui/panes.go
@@ -97,6 +97,18 @@ typedef Eo Efl_Ui_Widget;
 // Declare the class_get function directly rather than including the full .eo.h
 // header, which may reference types from other .eo files that are not included.
 extern const Efl_Class *efl_ui_panes_class_get(void);
+static Eina_Bool _ego_part_efl_ui_panes_part_hint_min_allow_get(const Eo *obj, const char *part_name) {
+    return efl_ui_panes_part_hint_min_allow_get(efl_part(obj, part_name));
+}
+static void _ego_part_efl_ui_panes_part_hint_min_allow_set(Eo *obj, const char *part_name, Eina_Bool val) {
+    efl_ui_panes_part_hint_min_allow_set(efl_part(obj, part_name), val);
+}
+static double _ego_part_efl_ui_panes_part_split_ratio_min_get(const Eo *obj, const char *part_name) {
+    return efl_ui_panes_part_split_ratio_min_get(efl_part(obj, part_name));
+}
+static void _ego_part_efl_ui_panes_part_split_ratio_min_set(Eo *obj, const char *part_name, double val) {
+    efl_ui_panes_part_split_ratio_min_set(efl_part(obj, part_name), val);
+}
 // _ego_get_efl_ui_layout_orientation_get wraps the getter, casting the return value through
 // uintptr_t so that both pointer and integer returns become void *.
 // This prevents C type conflicts when Eolian's type differs from the header.
@@ -290,3 +302,81 @@ func (o *Panes) OnLongpressed(fn func(value int)) efl.Handle {
 			fn(int(*(*C.int)(info)))
 		})
 }
+
+// panesFirstPart provides access to the "first" part of Panes.
+type panesFirstPart struct {
+	parent unsafe.Pointer
+	name   string
+}
+
+// First returns the first part of Panes.
+func (o *Panes) First() panesFirstPart {
+	return panesFirstPart{parent: o.Eo(), name: "first"}
+}
+
+func (p panesFirstPart) HintMinAllow() bool {
+	cName := C.CString(p.name)
+	defer C.free(unsafe.Pointer(cName))
+	return C._ego_part_efl_ui_panes_part_hint_min_allow_get((*C.Eo)(p.parent), cName) != 0
+}
+
+func (p panesFirstPart) SetHintMinAllow(val bool) {
+	cName := C.CString(p.name)
+	defer C.free(unsafe.Pointer(cName))
+	var cVal C.Eina_Bool
+	if val {
+		cVal = 1
+	}
+	C._ego_part_efl_ui_panes_part_hint_min_allow_set((*C.Eo)(p.parent), cName, cVal)
+}
+
+func (p panesFirstPart) SplitRatioMin() float64 {
+	cName := C.CString(p.name)
+	defer C.free(unsafe.Pointer(cName))
+	return float64(C._ego_part_efl_ui_panes_part_split_ratio_min_get((*C.Eo)(p.parent), cName))
+}
+
+func (p panesFirstPart) SetSplitRatioMin(val float64) {
+	cName := C.CString(p.name)
+	defer C.free(unsafe.Pointer(cName))
+	C._ego_part_efl_ui_panes_part_split_ratio_min_set((*C.Eo)(p.parent), cName, C.double(val))
+}
+
+// panesSecondPart provides access to the "second" part of Panes.
+type panesSecondPart struct {
+	parent unsafe.Pointer
+	name   string
+}
+
+// Second returns the second part of Panes.
+func (o *Panes) Second() panesSecondPart {
+	return panesSecondPart{parent: o.Eo(), name: "second"}
+}
+
+func (p panesSecondPart) HintMinAllow() bool {
+	cName := C.CString(p.name)
+	defer C.free(unsafe.Pointer(cName))
+	return C._ego_part_efl_ui_panes_part_hint_min_allow_get((*C.Eo)(p.parent), cName) != 0
+}
+
+func (p panesSecondPart) SetHintMinAllow(val bool) {
+	cName := C.CString(p.name)
+	defer C.free(unsafe.Pointer(cName))
+	var cVal C.Eina_Bool
+	if val {
+		cVal = 1
+	}
+	C._ego_part_efl_ui_panes_part_hint_min_allow_set((*C.Eo)(p.parent), cName, cVal)
+}
+
+func (p panesSecondPart) SplitRatioMin() float64 {
+	cName := C.CString(p.name)
+	defer C.free(unsafe.Pointer(cName))
+	return float64(C._ego_part_efl_ui_panes_part_split_ratio_min_get((*C.Eo)(p.parent), cName))
+}
+
+func (p panesSecondPart) SetSplitRatioMin(val float64) {
+	cName := C.CString(p.name)
+	defer C.free(unsafe.Pointer(cName))
+	C._ego_part_efl_ui_panes_part_split_ratio_min_set((*C.Eo)(p.parent), cName, C.double(val))
+}
diff --git a/efl/ui/popup.go b/efl/ui/popup.go
index fc64a6e..85cc80d 100644
--- a/efl/ui/popup.go
+++ b/efl/ui/popup.go
@@ -106,6 +106,12 @@ typedef Eo Efl_Ui_Widget;
 // Declare the class_get function directly rather than including the full .eo.h
 // header, which may reference types from other .eo files that are not included.
 extern const Efl_Class *efl_ui_popup_class_get(void);
+static Eina_Bool _ego_part_efl_ui_popup_part_backwall_repeat_events_get(const Eo *obj, const char *part_name) {
+    return efl_ui_popup_part_backwall_repeat_events_get(efl_part(obj, part_name));
+}
+static void _ego_part_efl_ui_popup_part_backwall_repeat_events_set(Eo *obj, const char *part_name, Eina_Bool val) {
+    efl_ui_popup_part_backwall_repeat_events_set(efl_part(obj, part_name), val);
+}
 // _ego_get_efl_ui_popup_align_get wraps the getter, casting the return value through
 // uintptr_t so that both pointer and integer returns become void *.
 // This prevents C type conflicts when Eolian's type differs from the header.
@@ -595,3 +601,30 @@ func (o *Popup) OnDirtyLogicFreezeChanged(fn func(value bool)) efl.Handle {
 			fn(*(*C.Eina_Bool)(info) != 0)
 		})
 }
+
+// popupBackwallPart provides access to the "backwall" part of Popup.
+type popupBackwallPart struct {
+	parent unsafe.Pointer
+	name   string
+}
+
+// Backwall returns the backwall part of Popup.
+func (o *Popup) Backwall() popupBackwallPart {
+	return popupBackwallPart{parent: o.Eo(), name: "backwall"}
+}
+
+func (p popupBackwallPart) RepeatEvents() bool {
+	cName := C.CString(p.name)
+	defer C.free(unsafe.Pointer(cName))
+	return C._ego_part_efl_ui_popup_part_backwall_repeat_events_get((*C.Eo)(p.parent), cName) != 0
+}
+
+func (p popupBackwallPart) SetRepeatEvents(val bool) {
+	cName := C.CString(p.name)
+	defer C.free(unsafe.Pointer(cName))
+	var cVal C.Eina_Bool
+	if val {
+		cVal = 1
+	}
+	C._ego_part_efl_ui_popup_part_backwall_repeat_events_set((*C.Eo)(p.parent), cName, cVal)
+}

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

Reply via email to