ui/cocoa/window.m

changeset 0
2483f517c562
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/window.m	Sun Jan 21 16:30:18 2024 +0100
@@ -0,0 +1,220 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2012 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#import "window.h"
+#import "menu.h"
+#import "toolbar.h"
+#import "container.h"
+#import <ucx/mempool.h>
+#import "../common/context.h"
+
+static int window_default_width = 600;
+static int window_default_height = 500;
+
+@implementation UiCocoaWindow
+
+- (UiCocoaWindow*) init: (NSRect)frame object: (UiObject*)obj {
+    self = [self initWithContentRect:frame
+                           styleMask:NSTitledWindowMask |
+                                     NSResizableWindowMask |
+                                     NSClosableWindowMask |
+                                     NSMiniaturizableWindowMask
+                             backing:NSBackingStoreBuffered
+                               defer:false];
+    
+    uiobj = obj;
+    UcxAllocator *allocator = uiobj->ctx->mempool->allocator;
+    menus = ucx_map_new_a(allocator, 8);
+    items = ucx_map_new_a(allocator, 64);
+    
+    return self;
+}
+
+- (UiObject*) object {
+    return uiobj;
+}
+
+- (void)  setObject:(UiObject*)obj {
+    uiobj = obj;
+}
+
+- (void) setMenuItems:(UcxList*)menuItems {
+    UcxAllocator *allocator = uiobj->ctx->mempool->allocator;
+    
+    UCX_FOREACH(elm, menuItems) {
+        UiStateItem *item = elm->data;
+        NSMenu *menu = [item->item menu];
+        
+        // create UiMenuItem which represents an NSMenuItem for a Window
+        UiMenuItem *windowItem = ucx_mempool_malloc(uiobj->ctx->mempool, sizeof(UiMenuItem));
+        windowItem->item = item->item;
+        windowItem->state = 0;
+        if(item->var) {
+            // bind value
+            UiVar *var = uic_connect_var(uiobj->ctx, item->var, UI_VAR_INTEGER);
+            if(var) {
+                UiInteger *value = var->value;
+                value->obj = windowItem;
+                value->get = ui_menuitem_get;
+                value->set = ui_menuitem_set;
+                value = 0;
+            } else {
+                // TODO: error
+            }
+        }
+        
+        // add item
+        UiAbstractMenuItem *abstractItem = malloc(sizeof(UiAbstractMenuItem));
+        abstractItem->update = ui_update_item;
+        abstractItem->item_data = windowItem;
+        UcxList *itemList = ucx_map_get(menus, ucx_key(&menu, sizeof(void*)));
+        itemList = ucx_list_append_a(allocator, itemList, abstractItem);
+        ucx_map_put(menus, ucx_key(&menu, sizeof(void*)), itemList);
+        
+        ucx_map_put(items, ucx_key(&windowItem->item, sizeof(void*)), windowItem);
+    }
+}
+
+- (void) setMenuItemLists:(UcxList*)itemLists {
+    UcxAllocator *allocator = uiobj->ctx->mempool->allocator;
+    
+    UCX_FOREACH(elm, itemLists) {
+        UiMenuItemList *list = elm->data;
+        
+        UiAbstractMenuItem *abstractItem = malloc(sizeof(UiAbstractMenuItem));
+        abstractItem->update = ui_update_item_list;
+        abstractItem->item_data = list;
+        
+        UcxList *itemList = ucx_map_get(menus, ucx_key(&list->menu, sizeof(void*)));
+        itemList = ucx_list_append_a(allocator, itemList, abstractItem);
+        ucx_map_put(menus, ucx_key(&list->menu, sizeof(void*)), itemList);
+        
+    }
+}
+
+- (UiMenuItem*) getMenuItem:(NSMenuItem*)item {
+    return ucx_map_get(items, ucx_key(&item, sizeof(void*)));
+}
+
+- (void) updateMenu:(NSMenu*)menu {
+    UcxList *itemList = ucx_map_get(menus, ucx_key(&menu, sizeof(void*)));
+    UCX_FOREACH(elm, itemList) {
+        UiAbstractMenuItem *item = elm->data;
+        item->update(self, item->item_data);
+    }
+    
+    // update group items
+    // TODO: use only one loop for all items
+    int ngroups = 0;
+    int *groups = ui_active_groups(uiobj->ctx, &ngroups);
+    
+    NSArray *groupItems = [menu itemArray];
+    int count = [groupItems count];
+    for(int i=0;i<count;i++) {
+        id item = [groupItems objectAtIndex:i];
+        if([item class] == [UiGroupMenuItem class]) {
+            [item checkGroups: groups count:ngroups];
+        }
+    }
+    free(groups);
+}
+
+@end
+
+
+/* ------------------------------ public API ------------------------------ */
+
+UiObject* ui_window(char *title, void *window_data) {
+    UcxMempool *mp = ucx_mempool_new(256);
+    UiObject *obj = ucx_mempool_calloc(mp, 1, sizeof(UiObject));
+    obj->ctx = uic_context(obj, mp);
+    
+    // create native window
+    NSRect frame = NSMakeRect(
+                              300,
+                              200,
+                              window_default_width,
+                              window_default_height);
+    
+    /*
+    UiCocoaWindow *window = [[UiCocoaWindow alloc] initWithContentRect:frame
+                                styleMask:NSTitledWindowMask | NSResizableWindowMask |
+                                NSClosableWindowMask | NSMiniaturizableWindowMask
+                                backing:NSBackingStoreBuffered
+                                defer:false];
+    */
+    UiCocoaWindow *window = [[UiCocoaWindow alloc] init:frame object:obj];
+    
+    NSString *titleStr = [[NSString alloc] initWithUTF8String:title];
+    [window setTitle:titleStr];
+    
+    UiMenuDelegate *menuDelegate = ui_menu_delegate();
+    [window setMenuItems: [menuDelegate items]];
+    [window setMenuItemLists: [menuDelegate lists]];
+    
+    NSToolbar *toolbar = ui_create_toolbar(obj);
+    [window setToolbar: toolbar];
+    
+    obj->widget = (NSView*)window;
+    obj->window = window_data;
+    obj->container = ui_window_container(obj, window);
+    
+    
+    return obj;
+}
+
+void ui_close(UiObject *obj) {
+    // TODO
+}
+
+char* ui_openfiledialog(UiObject *obj) {
+    NSOpenPanel* op = [NSOpenPanel openPanel];
+    if ([op runModal] == NSOKButton) {
+        NSArray *urls = [op URLs];
+        NSURL *url = [urls objectAtIndex:0];
+        
+        const char *str = [[url path] UTF8String];
+        return (char*)strdup(str);
+    }
+    return NULL;
+}
+
+char* ui_savefiledialog(UiObject *obj) {
+    NSSavePanel* sp = [NSSavePanel savePanel];
+    if ([sp runModal] == NSOKButton) {
+        NSURL *url = [sp URL];
+        
+        const char *str = [[url path] UTF8String];
+        return (char*)strdup(str);
+    }
+    return NULL;
+}

mercurial