add combobox (Cocoa)

Sun, 24 Aug 2025 11:14:31 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 24 Aug 2025 11:14:31 +0200
changeset 717
c35b2f18841c
parent 716
99386f34efc9
child 718
06eec75a6fd5

add combobox (Cocoa)

make/xcode/toolkit/toolkit/main.m file | annotate | diff | comparison | revisions
ui/cocoa/list.h file | annotate | diff | comparison | revisions
ui/cocoa/list.m file | annotate | diff | comparison | revisions
--- a/make/xcode/toolkit/toolkit/main.m	Sun Aug 24 10:15:41 2025 +0200
+++ b/make/xcode/toolkit/toolkit/main.m	Sun Aug 24 11:14:31 2025 +0200
@@ -37,6 +37,7 @@
 typedef struct MyDocument {
     UiInteger *tbtoggle;
     UiList *list1;
+    UiList *list2;
 } MyDocument;
 
 MyDocument* create_doc(void) {
@@ -48,6 +49,15 @@
     ui_list_append(doc->list1, "Item 2");
     ui_list_append(doc->list1, "Item 3");
     ui_list_append(doc->list1, "Item 4");
+    
+    doc->list2 = ui_list_new(ctx, "list2");
+    ui_list_append(doc->list2, "Option 1");
+    ui_list_append(doc->list2, "Option 2");
+    ui_list_append(doc->list2, "Option 3");
+    ui_list_append(doc->list2, "Option 4");
+    ui_list_append(doc->list2, "Option 5");
+    ui_list_append(doc->list2, "Option 6");
+    
     return doc;
 }
 
@@ -97,6 +107,8 @@
     
     
     ui_vbox(obj, .spacing = 0, .fill = UI_OFF) {
+        ui_combobox(obj, .varname = "list2");
+        
         ui_textfield(obj, .varname = "textfield1");
         ui_radiobutton(obj, .label = "V Button 1", .varname = "radio1");
         ui_radiobutton(obj, .label = "V Button 2", .varname = "radio1");
--- a/ui/cocoa/list.h	Sun Aug 24 10:15:41 2025 +0200
+++ b/ui/cocoa/list.h	Sun Aug 24 11:14:31 2025 +0200
@@ -32,6 +32,26 @@
 
 #import "ListDataSource.h"
 
+@interface UiDropDown : NSObject<NSComboBoxDelegate>
+
+@property UiObject *obj;
+@property ui_callback onactivate;
+@property void *onactivatedata;
+@property ui_callback onselection;
+@property void *onselectiondata;
+@property ui_getvaluefunc2 getvalue;
+@property void *getvaluedata;
+@property UiVar *var;
+@property (weak) NSComboBox *combobox;
+
+- (id)init:(UiObject*)obj;
+
+@end
+
 void ui_tableview_update(UiList *list, int i);
 UiListSelection ui_tableview_getselection(UiList *list);
 void ui_tableview_setselection(UiList *list, UiListSelection selection);
+
+void ui_dropdown_update(UiList *list, int i);
+UiListSelection ui_dropdown_getselection(UiList *list);
+void ui_dropdown_setselection(UiList *list, UiListSelection selection);
--- a/ui/cocoa/list.m	Sun Aug 24 10:15:41 2025 +0200
+++ b/ui/cocoa/list.m	Sun Aug 24 11:14:31 2025 +0200
@@ -214,3 +214,143 @@
 }
 
 
+/* --------------------------- DropDown --------------------------- */
+
+@implementation UiDropDown
+
+- (id)init:(UiObject*)obj {
+    _obj = obj;
+    return self;
+}
+
+- (void) comboBoxSelectionDidChange:(NSNotification *) notification {
+    int index = (int)_combobox.indexOfSelectedItem;
+    
+    void *eventdata = NULL;
+    if(_var) {
+        UiList *list = _var->value;
+        if(index >= 0) {
+            eventdata = list->get(list, index);
+        }
+    } else {
+        NSString *str = _combobox.objectValueOfSelectedItem;
+        if(str) {
+            eventdata = (void*)str.UTF8String;
+        }
+    }
+    
+    UiEvent event;
+    event.obj = _obj;
+    event.window = event.obj->window;
+    event.document = event.obj->ctx->document;
+    event.eventdata = eventdata;
+    event.eventdatatype = UI_EVENT_DATA_LIST_ELM;
+    event.intval = index;
+    
+    if(_onselection) {
+        _onselection(&event, _onselectiondata);
+    }
+    
+    if(_onactivate) {
+        _onactivate(&event, _onactivatedata);
+    }
+}
+
+@end
+
+UIWIDGET ui_combobox_create(UiObject* obj, UiListArgs *args) {
+    NSComboBox *dropdown = [[NSComboBox alloc] init];
+    dropdown.editable = NO;
+    
+    UiDropDown *uidropdown = [[UiDropDown alloc] init:obj];
+    objc_setAssociatedObject(dropdown, "ui_dropdown", uidropdown, OBJC_ASSOCIATION_RETAIN);
+    uidropdown.onactivate = args->onactivate;
+    uidropdown.onactivatedata = args->onactivatedata;
+    uidropdown.onselection = args->onselection;
+    uidropdown.onselectiondata = args->onselectiondata;
+    uidropdown.combobox = dropdown;
+    
+    if(!args->getvalue2) {
+        if(args->getvalue) {
+            args->getvalue2 = getvalue_wrapper;
+            args->getvalue2data = (void*)args->getvalue;
+        } else {
+            args->getvalue2 = str_getvalue;
+        }
+    }
+    uidropdown.getvalue = args->getvalue2;
+    uidropdown.getvaluedata = args->getvalue2data;
+    
+    UiLayout layout = UI_INIT_LAYOUT(args);
+    ui_container_add(obj, dropdown, &layout, FALSE);
+    
+    UiVar *var = uic_widget_var(obj->ctx, obj->ctx, args->list, args->varname, UI_VAR_LIST);
+    if(var) {
+        UiList *list = var->value;
+        list->obj = (__bridge void*)dropdown;
+        list->update = ui_dropdown_update;
+        list->getselection = ui_dropdown_getselection;
+        list->setselection = ui_dropdown_setselection;
+        ui_dropdown_update(list, -1);
+    } else {
+        for(int i=0;i<args->static_nelm;i++) {
+            char *str = args->static_elements[i];
+            NSString *item = [[NSString alloc] initWithUTF8String:str];
+            [dropdown addItemWithObjectValue:item];
+        }
+    }
+    
+    uidropdown.var = var;
+    
+    return (__bridge void*)dropdown;
+}
+
+void ui_dropdown_update(UiList *list, int i) {
+    NSComboBox *combobox = (__bridge NSComboBox*)list->obj;
+    UiDropDown *dropdown = objc_getAssociatedObject(combobox, "ui_dropdown");
+    if(dropdown) {
+        [combobox removeAllItems];
+        
+        ui_getvaluefunc2 getvalue = dropdown.getvalue;
+        void *getvaluedata = dropdown.getvaluedata;
+        
+        int index = 0;
+        void *elm = list->first(list);
+        while(elm) {
+            UiBool freeResult = FALSE;
+            char *str = getvalue(list, elm, index, 0, getvaluedata, &freeResult);
+            if(str) {
+                NSString *item = [[NSString alloc] initWithUTF8String:str];
+                [combobox addItemWithObjectValue:item];
+            }
+            if(freeResult) {
+                free(str);
+            }
+            elm = list->next(list);
+            index++;
+        }
+    } else {
+        fprintf(stderr, "Error: obj is not a dropdown\n");
+    }
+}
+
+UiListSelection ui_dropdown_getselection(UiList *list) {
+    UiListSelection sel = { 0, NULL };
+    NSComboBox *combobox = (__bridge NSComboBox*)list->obj;
+    NSInteger index = combobox.indexOfSelectedItem;
+    if(index >= 0) {
+        sel.rows = malloc(sizeof(int));
+        sel.count = 1;
+        sel.rows[0] = (int)index;
+    }
+    return sel;
+}
+
+void ui_dropdown_setselection(UiList *list, UiListSelection selection) {
+    NSComboBox *combobox = (__bridge NSComboBox*)list->obj;
+    if(selection.count > 0) {
+        [combobox selectItemAtIndex:selection.rows[0]];
+    } else {
+        [combobox selectItemAtIndex: -1];
+    }
+}

mercurial