--- a/ui/cocoa/MainWindow.m Thu Apr 17 11:18:57 2025 +0200 +++ b/ui/cocoa/MainWindow.m Thu Apr 17 17:51:07 2025 +0200 @@ -33,11 +33,11 @@ #import <objc/runtime.h> #import "EventData.h" +#import "menu.h" @implementation MainWindow - (MainWindow*)init:(UiObject*)obj { - self.uiobj = obj; NSRect frame = NSMakeRect(300, 200, 600, 500); self = [self initWithContentRect:frame @@ -65,6 +65,51 @@ return self; } +@end + + + +@implementation MainWindowController + +- (MainWindowController*)initWithWindow:(UiObject*)obj window:(NSWindow*)window { + self = [super initWithWindow:window]; + _uiobj = obj; + + // bind all stateful menu items (checkbox, radiobuttons, lists) + self.checkItemStates = [[NSMutableDictionary alloc] init]; + NSArray *menuBindItems = ui_get_binding_items(); // returns all items that require binding + for(MenuItem *item in menuBindItems) { + if(item.checkItem) { + // simple check item (ui_menu_toggleitem_create) + UiVar *var = uic_widget_var(obj->ctx, obj->ctx, NULL, item.checkItem->varname, UI_VAR_INTEGER); + // create the state object for this item/window + MenuCheckItem *state = [[MenuCheckItem alloc] init]; + state.mainWindow = self; + state.var = var; + if(var) { + // bind toggle item + UiInteger *i = var->value; + state.state = (int)i->value; + i->obj = (__bridge void*)state; + i->get = ui_menu_check_item_get; + i->set = ui_menu_check_item_set; + } else { + state.state = 0; + } + [_checkItemStates setObject:state forKey:item.itemId]; + } else if(item.radioItem) { + // bind radio item + + } + } + + return self; +} + +- (void) windowDidLoad { + [self.window setNextResponder:self]; +} + - (void)menuItemAction:(id)sender { EventData *event = objc_getAssociatedObject(sender, "eventdata"); if(event) { @@ -73,4 +118,57 @@ } } +- (void)menuCheckItemAction:(id)sender { + NSMenuItem *menuItem = sender; + MenuItem *item = objc_getAssociatedObject(sender, "menuitem"); + if(!item || !item.checkItem) { + return; + } + UiMenuCheckItem *it = item.checkItem; + + MenuCheckItem *state = [_checkItemStates objectForKey:item.itemId]; + state.state = state.state == NSControlStateValueOff ? NSControlStateValueOn : NSControlStateValueOff; + menuItem.state = state.state; + + if(it->callback) { + UiEvent event; + event.obj = _uiobj; + event.window = event.obj->window; + event.document = event.obj->ctx->document; + event.eventdata = state.var ? state.var->value : NULL; + event.intval = state.state; + it->callback(&event, it->userdata); + } +} + +- (BOOL) validateMenuItem:(NSMenuItem *) menuItem { + MenuItem *item = objc_getAssociatedObject(menuItem, "menuitem"); + if(item) { + MenuCheckItem *state = [_checkItemStates objectForKey:item.itemId]; + if(state) { + menuItem.state = state.state; + } else { + menuItem.state = NSControlStateValueOff; + } + } + + return YES; +} + @end + +@implementation MenuCheckItem + +@end + +int64_t ui_menu_check_item_get(UiInteger *i) { + MenuCheckItem *state = (__bridge MenuCheckItem*)i->obj; + i->value = state.state; + return i->value; +} + +void ui_menu_check_item_set(UiInteger *i, int64_t value) { + MenuCheckItem *state = (__bridge MenuCheckItem*)i->obj; + i->value = value; + state.state = (int)value; +}