@@ -732,13 +732,32 @@ pub fn interfaceScriptClient(self: webui, event_number: usize, script_content: [
732732 if (! success ) return WebUIError .ScriptError ;
733733}
734734
735- /// a very convenient function for binding callback.
736- /// you just need to pase a function to get param.
737- /// no need to care webui param api.
735+ /// binding function: Creates a binding between an HTML element and a callback function
736+ /// - element: A null-terminated string identifying the HTML element(s) to bind to
737+ /// - callback: A function to be called when the bound event triggers
738+ ///
739+ /// This function performs compile-time validation on the callback function to ensure it:
740+ /// 1. Is a proper function (not another type)
741+ /// 2. Returns void
742+ /// 3. Is not generic
743+ /// 4. Does not use variable arguments
744+ ///
745+ /// The callback function can accept various parameter types:
746+ /// - Event: Gets the full event object
747+ /// - *Event: Gets a pointer to the event object
748+ /// - bool: Converted from event data
749+ /// - int types: Converted from event data
750+ /// - float types: Converted from event data
751+ /// - [:0]const u8: For null-terminated string data
752+ /// - [*]const u8: For raw pointer data
753+ ///
754+ /// Returns:
755+ /// - The binding ID that can be used to unbind later
738756pub fn binding (self : webui , element : [:0 ]const u8 , comptime callback : anytype ) ! usize {
739757 const T = @TypeOf (callback );
740758 const TInfo = @typeInfo (T );
741759
760+ // Verify the callback is a function
742761 if (TInfo != .@"fn" ) {
743762 const err_msg = std .fmt .comptimePrint (
744763 "callback's type ({}), it must be a function!" ,
@@ -748,6 +767,7 @@ pub fn binding(self: webui, element: [:0]const u8, comptime callback: anytype) !
748767 }
749768
750769 const fnInfo = TInfo .@"fn" ;
770+ // Verify return type is void
751771 if (fnInfo .return_type != void ) {
752772 const err_msg = std .fmt .comptimePrint (
753773 "callback's return type ({}), it must be void!" ,
@@ -756,6 +776,7 @@ pub fn binding(self: webui, element: [:0]const u8, comptime callback: anytype) !
756776 @compileError (err_msg );
757777 }
758778
779+ // Verify function is not generic
759780 if (fnInfo .is_generic ) {
760781 const err_msg = std .fmt .comptimePrint (
761782 "callback's type ({}), it can not be a generic function!" ,
@@ -764,6 +785,7 @@ pub fn binding(self: webui, element: [:0]const u8, comptime callback: anytype) !
764785 @compileError (err_msg );
765786 }
766787
788+ // Verify function does not use varargs
767789 if (fnInfo .is_var_args ) {
768790 const err_msg = std .fmt .comptimePrint (
769791 "callback's type ({}), it can not have variable args!" ,
@@ -775,14 +797,17 @@ pub fn binding(self: webui, element: [:0]const u8, comptime callback: anytype) !
775797 const tmp_struct = struct {
776798 const tup_t = fnParamsToTuple (fnInfo .params );
777799
800+ // Event handler that will convert parameters and call the user's callback
778801 fn handle (e : * Event ) void {
779802 var param_tup : tup_t = undefined ;
780803
781804 var index : usize = 0 ;
805+ // Process each parameter of the callback function
782806 inline for (fnInfo .params , 0.. fnInfo .params .len ) | param , i | {
783807 if (param .type ) | tt | {
784808 const paramTInfo = @typeInfo (tt );
785809 switch (paramTInfo ) {
810+ // Handle struct type parameters (only Event is allowed)
786811 .@"struct" = > {
787812 if (tt == Event ) {
788813 param_tup [i ] = e .* ;
@@ -795,29 +820,36 @@ pub fn binding(self: webui, element: [:0]const u8, comptime callback: anytype) !
795820 @compileError (err_msg );
796821 }
797822 },
823+ // Convert boolean values
798824 .bool = > {
799825 const res = e .getBoolAt (i - index );
800826 param_tup [i ] = res ;
801827 },
828+ // Convert integer values with appropriate casting
802829 .int = > {
803830 const res = e .getIntAt (i - index );
804831 param_tup [i ] = @intCast (res );
805832 },
833+ // Convert floating point values
806834 .float = > {
807835 const res = e .getFloatAt (i - index );
808836 param_tup [i ] = res ;
809837 },
838+ // Handle pointer types with special cases
810839 .pointer = > | pointer | {
840+ // Handle null-terminated string slices
811841 if (pointer .size == .slice and pointer .child == u8 and pointer .is_const == true ) {
812842 if (pointer .sentinel ()) | sentinel | {
813843 if (sentinel == 0 ) {
814844 const str_ptr = e .getStringAt (i - index );
815845 param_tup [i ] = str_ptr ;
816846 }
817847 }
848+ // Handle Event pointers
818849 } else if (pointer .size == .one and pointer .child == Event ) {
819850 param_tup [i ] = e ;
820851 index += 1 ;
852+ // Handle raw byte pointers
821853 } else if (pointer .size == .many and pointer .child == u8 and pointer .is_const == true and pointer .sentinel () == null ) {
822854 const raw_ptr = e .getRawAt (i - index );
823855 param_tup [i ] = raw_ptr ;
@@ -829,6 +861,7 @@ pub fn binding(self: webui, element: [:0]const u8, comptime callback: anytype) !
829861 @compileError (err_msg );
830862 }
831863 },
864+ // Reject unsupported types
832865 else = > {
833866 const err_msg = std .fmt .comptimePrint (
834867 "type is ({}), only support these types: Event, Bool, Int, Float, []u8!" ,
@@ -842,10 +875,12 @@ pub fn binding(self: webui, element: [:0]const u8, comptime callback: anytype) !
842875 }
843876 }
844877
878+ // Call the user's callback with the properly converted parameters
845879 @call (.auto , callback , param_tup );
846880 }
847881 };
848882
883+ // Create the actual binding with the webui backend
849884 return self .bind (element , tmp_struct .handle );
850885}
851886
0 commit comments