Wed, 22 Apr 2026 19:29:26 +0200
implement textfield onchange events (Cocoa)
| make/xcode/toolkit/toolkit/main.m | file | annotate | diff | comparison | revisions | |
| ui/cocoa/EventData.h | file | annotate | diff | comparison | revisions | |
| ui/cocoa/EventData.m | file | annotate | diff | comparison | revisions | |
| ui/cocoa/button.m | file | annotate | diff | comparison | revisions | |
| ui/cocoa/text.h | file | annotate | diff | comparison | revisions | |
| ui/cocoa/text.m | file | annotate | diff | comparison | revisions |
--- a/make/xcode/toolkit/toolkit/main.m Wed Apr 22 10:07:54 2026 +0200 +++ b/make/xcode/toolkit/toolkit/main.m Wed Apr 22 19:29:26 2026 +0200 @@ -141,6 +141,10 @@ printf("action test\n"); } +void textfield_changed(UiEvent *event, void *userdata) { + printf("textfield changed\n"); +} + void application_startup(UiEvent *event, void *data) { UiObject *obj = ui_splitview_window("My Window", TRUE); //WindowData *wdata = ui_malloc(obj->ctx, sizeof(WindowData)); @@ -180,6 +184,7 @@ ui_button(obj, .label = "Test Button", .action = "test"); ui_button(obj, .label = "Test Button", .action = "test"); ui_button(obj, .label = "Test Button", .action = "test"); + ui_textfield(obj, .onchange = textfield_changed); } } }
--- a/ui/cocoa/EventData.h Wed Apr 22 10:07:54 2026 +0200 +++ b/ui/cocoa/EventData.h Wed Apr 22 19:29:26 2026 +0200 @@ -29,7 +29,7 @@ #import "../ui/toolkit.h" #import "../common/context.h" -typedef void(*get_eventdata_func)(id sender, UiVar *var, void **eventdata, int *value); +typedef void(*get_eventdata_func)(id sender, UiVar *var, void **eventdata, int *eventdatatype, int *value); @interface EventData : NSObject @property UiObject *obj;
--- a/ui/cocoa/EventData.m Wed Apr 22 10:07:54 2026 +0200 +++ b/ui/cocoa/EventData.m Wed Apr 22 19:29:26 2026 +0200 @@ -70,7 +70,7 @@ event.intval = 0; event.set = ui_get_setop(); if(_get_eventdata) { - _get_eventdata(sender, _var, &event.eventdata, &event.intval); + _get_eventdata(sender, _var, &event.eventdata, &event.eventdatatype, &event.intval); } if(self.callback) { self.callback(&event, self.userdata);
--- a/ui/cocoa/button.m Wed Apr 22 10:07:54 2026 +0200 +++ b/ui/cocoa/button.m Wed Apr 22 19:29:26 2026 +0200 @@ -64,7 +64,7 @@ } -static void togglebutton_eventdata(id button, UiVar *var, void **eventdata, int *value) { +static void togglebutton_eventdata(id button, UiVar *var, void **eventdata, int *eventdatatype, int *value) { NSButton *btn = (NSButton*)button; NSControlStateValue state = btn.state; *value = (int)state; @@ -137,7 +137,7 @@ return togglebutton_create(obj, args, NSButtonTypeSwitch); } -static void switch_eventdata(id button, UiVar *var, void **eventdata, int *value) { +static void switch_eventdata(id button, UiVar *var, void **eventdata, int *eventdatatype, int *value) { NSSwitch *btn = (NSSwitch*)button; NSControlStateValue state = btn.state; *value = (int)state; @@ -207,10 +207,10 @@ @end -static void radiobutton_eventdata(id button, UiVar *var, void **eventdata, int *value) { +static void radiobutton_eventdata(id button, UiVar *var, void **eventdata, int *eventdatatype, int *value) { if(var) { - UiInteger *value = var->value; - NSMutableArray *buttons = (__bridge NSMutableArray*)value->obj; + UiInteger *i = var->value; + NSMutableArray *buttons = (__bridge NSMutableArray*)i->obj; for(UiRadioButton *b in buttons) { if(b != button) { b.direct_state = YES;
--- a/ui/cocoa/text.h Wed Apr 22 10:07:54 2026 +0200 +++ b/ui/cocoa/text.h Wed Apr 22 19:29:26 2026 +0200 @@ -47,3 +47,15 @@ char* ui_textfield_get(UiString *s); void ui_textfield_set(UiString *s, const char *value); + +@interface TextFieldDelegate : NSObject<NSTextFieldDelegate> + +@property UiObject *obj; +@property UiVar *var; +@property ui_callback onchange; +@property void *onchangedata; +@property NSString *onchange_action; + +- (id)init:(UiObject*)obj var:(UiVar*)var; + +@end
--- a/ui/cocoa/text.m Wed Apr 22 10:07:54 2026 +0200 +++ b/ui/cocoa/text.m Wed Apr 22 19:29:26 2026 +0200 @@ -29,6 +29,7 @@ #import "text.h" #import "EventData.h" #import "container.h" +#import "action.h" #import <objc/runtime.h> UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args) { @@ -186,6 +187,10 @@ /* -------------------------- TextField -------------------------- */ +static void textfield_geteventdata(id sender, UiVar *var, void **eventdata, int *eventdatatype, int *value) { + +} + static UIWIDGET textfield_create(UiObject *obj, UiTextFieldArgs *args, BOOL password, BOOL frameless) { NSTextField *textfield; if(password) { @@ -222,6 +227,27 @@ s->set = ui_textfield_set; } + if(args->onactivate || args->onactivate_action) { + EventData *event = [[EventData alloc] init:args->onactivate userdata:args->onactivatedata action:args->onactivate_action]; + event.get_eventdata = textfield_geteventdata; + event.obj = obj; + textfield.target = event; + textfield.action = @selector(handleEventWithEventData:); + objc_setAssociatedObject(textfield, "eventdata", event, OBJC_ASSOCIATION_RETAIN); + ui_cocoa_view_bind_action(obj->ctx, textfield, args->onactivate_action); + } + + if(args->onchange || args->onchange_action) { + TextFieldDelegate *tfd = [[TextFieldDelegate alloc]init:obj var:var]; + tfd.onchange = args->onchange; + tfd.onchangedata = args->onchangedata; + if(args->onchange_action) { + tfd.onchange_action = [[NSString alloc]initWithUTF8String:args->onchange_action]; + } + objc_setAssociatedObject(textfield, "delegate", tfd, OBJC_ASSOCIATION_RETAIN); + textfield.delegate = tfd; + } + return (__bridge void*)textfield; } @@ -306,3 +332,41 @@ NSRange selectedRange = [editor selectedRange]; return (int)selectedRange.location; } + + +/* -------------------- textfield delegate -------------------- */ + +@implementation TextFieldDelegate + +- (id)init:(UiObject*)obj var:(UiVar*)var { + self.obj = obj; + self.var = var; + return self; +} + +- (void)controlTextDidChange:(NSNotification *)obj { + UiString *value = _var ? _var->value : NULL; + + UiEvent e; + e.obj = _obj; + e.window = e.obj->window; + e.document = e.obj->ctx->document; + e.eventdata = value; + e.eventdatatype = value ? UI_EVENT_DATA_STRING_VALUE : 0; + e.intval = 0; + e.set = ui_get_setop(); + + if(_onchange) { + _onchange(&e, _onchangedata); + } + + if(_var) { + ui_notify_evt(value->observers, &e); + } + + if(_onchange_action) { + uic_action_callback(&e, _onchange_action.UTF8String); + } +} + +@end