ui/cocoa/MainWindow.m

changeset 571
f6e92de49959
parent 570
a2df724b4cb9
child 677
04bcb1930fbf
--- a/ui/cocoa/MainWindow.m	Thu Apr 17 17:51:07 2025 +0200
+++ b/ui/cocoa/MainWindow.m	Thu Apr 17 18:49:25 2025 +0200
@@ -75,31 +75,52 @@
     self = [super initWithWindow:window];
     _uiobj = obj;
     
+    self.checkItemStates = [[NSMutableDictionary alloc] init];
+    self.radioItems = [[NSMutableDictionary alloc] init];
+    
     // 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) {
+        if(item.checkItem || item.radioItem) {
             // simple check item (ui_menu_toggleitem_create)
-            UiVar *var = uic_widget_var(obj->ctx, obj->ctx, NULL, item.checkItem->varname, UI_VAR_INTEGER);
+            UiVar *var = uic_widget_var(obj->ctx, obj->ctx, NULL, item.checkItem ? item.checkItem->varname : item.radioItem->varname, UI_VAR_INTEGER);
             // create the state object for this item/window
-            MenuCheckItem *state = [[MenuCheckItem alloc] init];
+            MenuItemState *state = [[MenuItemState 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;
+                if(item.checkItem) {
+                    // bind toggle item
+                    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 {
+                    // bind radio item
+                    NSMutableArray *rgroup = nil;
+                    if(i->obj) {
+                        rgroup = (__bridge NSMutableArray*)i->obj;
+                    } else {
+                        // create a new rgroup array and register it in the window
+                        rgroup = [[NSMutableArray alloc] init];
+                        NSString *varname = [[NSString alloc] initWithUTF8String:item.radioItem->varname];
+                        [_radioItems setObject:rgroup forKey:varname];
+                        i->obj = (__bridge void*)rgroup;
+                    }
+                    i->get = ui_menu_radio_item_get;
+                    i->set = ui_menu_radio_item_set;
+                    [rgroup addObject:state]; // add this item state to the radio group
+                    // i->value can contain a non-zero value, which means a specific radiobutton
+                    // should be pre-selected
+                    if(i->value == rgroup.count) {
+                        state.state = NSControlStateValueOn;
+                    }
+                }
             } else {
                 state.state = 0;
             }
             [_checkItemStates setObject:state forKey:item.itemId];
-        } else if(item.radioItem) {
-            // bind radio item
-            
         }
     }
     
@@ -124,12 +145,12 @@
     if(!item || !item.checkItem) {
         return;
     }
-    UiMenuCheckItem *it = item.checkItem;
     
-    MenuCheckItem *state = [_checkItemStates objectForKey:item.itemId];
+    MenuItemState *state = [_checkItemStates objectForKey:item.itemId];
     state.state = state.state == NSControlStateValueOff ? NSControlStateValueOn : NSControlStateValueOff;
     menuItem.state = state.state;
     
+    UiMenuCheckItem *it = item.checkItem;
     if(it->callback) {
         UiEvent event;
         event.obj = _uiobj;
@@ -141,10 +162,54 @@
     }
 }
 
+- (void)menuRadioItemAction:(id)sender {
+    NSMenuItem *menuItem = sender;
+    MenuItem *item = objc_getAssociatedObject(sender, "menuitem");
+    if(!item || !item.radioItem) {
+        return;
+    }
+    
+    UiMenuRadioItem *it = item.radioItem;
+    if(!it->varname) {
+        return;
+    }
+    
+    MenuItemState *state = [_checkItemStates objectForKey:item.itemId]; // current state of this menu item
+    
+    NSString *varname = [[NSString alloc] initWithUTF8String:it->varname];
+    NSArray *radioGroup = [_radioItems objectForKey:varname];
+    if(!radioGroup) {
+        return;
+    }
+    int index = 1;
+    int value = 0;
+    for(MenuItemState *g in radioGroup) {
+        if(g == state) {
+            menuItem.state = NSControlStateValueOn;
+            g.state = NSControlStateValueOn;
+            value = index;
+        } else {
+            menuItem.state = NSControlStateValueOff;
+            g.state = NSControlStateValueOff;
+        }
+    }
+    
+    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 = value;
+        it->callback(&event, it->userdata);
+    }
+}
+
+
 - (BOOL) validateMenuItem:(NSMenuItem *) menuItem {
     MenuItem *item = objc_getAssociatedObject(menuItem, "menuitem");
     if(item) {
-        MenuCheckItem *state = [_checkItemStates objectForKey:item.itemId];
+        MenuItemState *state = [_checkItemStates objectForKey:item.itemId];
         if(state) {
             menuItem.state = state.state;
         } else {
@@ -157,18 +222,42 @@
 
 @end
 
-@implementation MenuCheckItem
+@implementation MenuItemState
 
 @end
 
 int64_t ui_menu_check_item_get(UiInteger *i) {
-    MenuCheckItem *state = (__bridge MenuCheckItem*)i->obj;
+    MenuItemState *state = (__bridge MenuItemState*)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;
+    MenuItemState *state = (__bridge MenuItemState*)i->obj;
     i->value = value;
     state.state = (int)value;
 }
+
+int64_t ui_menu_radio_item_get(UiInteger *i) {
+    NSArray *rgroup = (__bridge NSArray*)i->obj;
+    i->value = 0;
+    int index = 1;
+    for(MenuItemState *state in rgroup) {
+        if(state.state == NSControlStateValueOn) {
+            i->value = index;
+            break;
+        }
+        index++;
+    }
+    return i->value;
+}
+
+void ui_menu_radio_item_set(UiInteger *i, int64_t value) {
+    NSArray *rgroup = (__bridge NSArray*)i->obj;
+    i->value = 0;
+    int index = 1;
+    for(MenuItemState *state in rgroup) {
+        state.state = value == index;
+        index++;
+    }
+}

mercurial