added Cocoa implementation for menu check items (with bugs)

Fri, 28 Mar 2014 20:03:01 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Fri, 28 Mar 2014 20:03:01 +0100
changeset 10
6f263196f916
parent 8
84a541c6e093
child 11
979c0e0ee853

added Cocoa implementation for menu check items (with bugs)

application/main.c file | annotate | diff | comparison | revisions
ui/cocoa/menu.h file | annotate | diff | comparison | revisions
ui/cocoa/menu.m file | annotate | diff | comparison | revisions
ui/cocoa/toolkit.h file | annotate | diff | comparison | revisions
ui/cocoa/toolkit.m file | annotate | diff | comparison | revisions
ui/cocoa/window.h file | annotate | diff | comparison | revisions
ui/cocoa/window.m file | annotate | diff | comparison | revisions
--- a/application/main.c	Wed Mar 26 15:53:43 2014 +0100
+++ b/application/main.c	Fri Mar 28 20:03:01 2014 +0100
@@ -50,6 +50,7 @@
 }
 
 void action_open(UiEvent *event, void *data) {
+    //printf("check1: %s\n", event->intval ? "true" : "false");
     //printf("check1: %s\n", ui_getint(event->obj, "check1") ? "true" : "false");
     TestDocument *doc = event->document;
     printf("check1: %s\n", ui_getval(doc->check1) ? "true" : "false");
@@ -82,13 +83,13 @@
 void action_undo(UiEvent *event, void *data) {
     printf("undo\n");
     TestWindowData *wd = event->window;
-    ui_text_undo(&wd->text);
+    //ui_text_undo(&wd->text);
 }
 
 void action_redo(UiEvent *event, void *data) {
     printf("redo\n");
     TestWindowData *wd = event->window;
-    ui_text_redo(&wd->text);
+    //ui_text_redo(&wd->text);
 }
 
 
@@ -104,6 +105,7 @@
     ui_menuitem("Dokument 2", action_doc2, NULL);
     ui_menuseparator();
     ui_checkitem_nv("Check", "check1");
+    //ui_checkitem("Check", action_open, NULL);
     ui_menuitem("Close", action_close, NULL);
     
     
--- a/ui/cocoa/menu.h	Wed Mar 26 15:53:43 2014 +0100
+++ b/ui/cocoa/menu.h	Fri Mar 28 20:03:01 2014 +0100
@@ -26,7 +26,35 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "../ui/menu.h"
+#import "../ui/menu.h"
 #import "toolkit.h"
+#import "../../ucx/list.h"
+
+typedef struct UiMenuItem {
+    NSMenuItem *item;
+    int        state;
+} UiMenuItem;
+
+typedef struct UiStateItem {
+    NSMenuItem *item;
+    char       *var;
+} UiStateItem;
+
+@interface UiMenuDelegate : NSObject <NSMenuDelegate> {
+    UcxList *items;
+}
+
+- (void)menuNeedsUpdate:(NSMenu*) menu;
+
+- (void) addItem:(NSMenuItem*) item var: (char*)name;
+
+- (UcxList*) items;
+
+@end
 
 
+void ui_menu_init();
+UiMenuDelegate* ui_menu_delegate();
+
+int ui_menuitem_get(UiInteger *i);
+void ui_menuitem_set(UiInteger *i, int value);
--- a/ui/cocoa/menu.m	Wed Mar 26 15:53:43 2014 +0100
+++ b/ui/cocoa/menu.m	Fri Mar 28 20:03:01 2014 +0100
@@ -31,9 +31,47 @@
 #import <string.h>
 
 #import "menu.h"
+#import "window.h"
+
+@implementation UiMenuDelegate 
+
+- (UiMenuDelegate*) init {
+    items = NULL;
+    return self;
+}
+
+- (void) menuNeedsUpdate:(NSMenu *) menu {
+    NSWindow *activeWindow = [NSApp keyWindow];
+    [(UiCocoaWindow*)activeWindow updateMenu: menu];
+}
+
+- (void) addItem:(NSMenuItem*) item var: (char*)name {
+    UiStateItem *i = malloc(sizeof(UiStateItem));
+    i->item = item;
+    i->var = name;
+    items = ucx_list_append(items, i);
+}
+
+- (UcxList*) items {
+    return items;
+}
+
+@end
+
+
 
 
 static NSMenu *currentMenu = NULL;
+static UiMenuDelegate *delegate;
+
+void ui_menu_init() {
+    delegate = [[UiMenuDelegate alloc]init];
+}
+
+UiMenuDelegate* ui_menu_delegate() {
+    return delegate;
+}
+
 
 void ui_menu(char *title) {
     NSString *str = [[NSString alloc] initWithUTF8String:title];
@@ -41,6 +79,7 @@
     NSMenu *menu = [[NSMenu alloc] initWithTitle: str];
     NSMenuItem *menuItem = [[NSApp mainMenu] addItemWithTitle:str
                                                        action:nil keyEquivalent:@""];
+    [menu setDelegate: delegate];
     
     [[NSApp mainMenu] setSubmenu:menu forItem:menuItem];
     currentMenu = menu;
@@ -53,14 +92,30 @@
     NSMenuItem *item = [currentMenu addItemWithTitle:str
                                               action:@selector(handleEvent:) keyEquivalent:@""];
     [item setTarget:event];
+    
+    //[delegate addItem: item];
 }
 
-void ui_checkitem(char *label, ui_callback f, void *userdata) {
+void ui_checkitem(char *label, ui_callback f, void *data) {
+    EventWrapper *event = [[EventWrapper alloc]initWithData:data callback:f];
+    NSString *str = [[NSString alloc] initWithUTF8String:label];
     
+    NSMenuItem *item = [currentMenu addItemWithTitle:str
+                                              action:@selector(handleStateEvent:) keyEquivalent:@""];
+    [item setTarget:event];
+    
+    [delegate addItem: item var:NULL];
 }
 
 void ui_checkitem_nv(char *label, char *vname) {
+    EventWrapper *event = [[EventWrapper alloc]initWithData:NULL callback:NULL];
+    NSString *str = [[NSString alloc] initWithUTF8String:label];
     
+    NSMenuItem *item = [currentMenu addItemWithTitle:str
+                                              action:@selector(handleStateEvent:) keyEquivalent:@""];
+    [item setTarget:event];
+    
+    [delegate addItem: item var:vname];
 }
 
 void ui_menuseparator() {
@@ -68,3 +123,15 @@
 }
 
 
+
+int ui_menuitem_get(UiInteger *i) {
+    UiMenuItem *item = i->obj;
+    i->value = [item->item state];
+    return i->value;
+}
+
+void ui_menuitem_set(UiInteger *i, int value) {
+    UiMenuItem *item = i->obj;
+    [item->item setState: value];
+    i->value = value;
+}
--- a/ui/cocoa/toolkit.h	Wed Mar 26 15:53:43 2014 +0100
+++ b/ui/cocoa/toolkit.h	Fri Mar 28 20:03:01 2014 +0100
@@ -45,5 +45,8 @@
 - (void) setCallback: (ui_callback)f;
 
 - (BOOL)handleEvent:(id)sender;
+- (BOOL)handleStateEvent:(id)sender;
 
 @end
+
+
--- a/ui/cocoa/toolkit.m	Wed Mar 26 15:53:43 2014 +0100
+++ b/ui/cocoa/toolkit.m	Fri Mar 28 20:03:01 2014 +0100
@@ -36,6 +36,7 @@
 
 #import "toolkit.h"
 #import "window.h"
+#import "menu.h"
 #import "toolbar.h"
 
 
@@ -53,6 +54,7 @@
     
     
     uic_docmgr_init();
+    ui_menu_init();
     ui_toolbar_init();
     // load item stock
     // ui_init_stock();
@@ -118,4 +120,32 @@
     return true;
 }
 
+- (BOOL)handleStateEvent:(id)sender {
+    NSWindow *activeWindow = [NSApp keyWindow];
+    NSMenuItem *item = (NSMenuItem*)sender;
+    int state = [item state] ? NSOffState : NSOnState;
+    
+    UiEvent event;
+    event.intval = state;
+    if([activeWindow class] == [UiCocoaWindow class]) {
+        event.obj = [(UiCocoaWindow*)activeWindow object];
+        event.window = event.obj->window;
+        event.document = event.obj->document;
+        // update state in window data
+        UiMenuItem *wmi = [(UiCocoaWindow*)activeWindow getMenuItem: sender];
+        wmi->state = state;
+    } else {
+        event.window = NULL;
+        event.document = NULL;
+    }
+    if(callback) {
+        callback(&event, data);
+    }
+    [item setState: state];
+    
+    return true;
+}
+
 @end
+
+
--- a/ui/cocoa/window.h	Wed Mar 26 15:53:43 2014 +0100
+++ b/ui/cocoa/window.h	Fri Mar 28 20:03:01 2014 +0100
@@ -28,13 +28,21 @@
 
 #import <Cocoa/Cocoa.h>
 #import "../ui/window.h"
+#import "../../ucx/list.h"
+#import "../../ucx/map.h"
+#import "menu.h"
 
 
 @interface UiCocoaWindow : NSWindow {
     UiObject *uiobj;
+    UcxMap   *menus;     // key: NSMenu value: UcxList of UiMenuItem
+    UcxMap   *items; // key: NSMenuItem value: UiMenuItem
 }
 
 - (UiObject*) object;
-- (void)  setObject:(UiObject*)obj;
+- (void) setObject:(UiObject*)obj;
+- (void) setMenuItems:(UcxList*)menuItems;
+- (UiMenuItem*) getMenuItem:(NSMenuItem*)item;
+- (void) updateMenu:(NSMenu*)menu;
 
 @end
--- a/ui/cocoa/window.m	Wed Mar 26 15:53:43 2014 +0100
+++ b/ui/cocoa/window.m	Fri Mar 28 20:03:01 2014 +0100
@@ -29,6 +29,7 @@
 #include <stdio.h>
 
 #import "window.h"
+#import "menu.h"
 #import "toolbar.h"
 #import "container.h"
 #import "../../ucx/mempool.h"
@@ -47,6 +48,55 @@
     uiobj = obj;
 }
 
+- (void) setMenuItems:(UcxList*)menuItems {
+    UcxAllocator *allocator = uiobj->ctx->mempool->allocator;
+    menus = ucx_map_new_a(allocator, 8);
+    items = ucx_map_new_a(allocator, 64);
+    
+    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
+        UcxList *itemList = ucx_map_get(menus, ucx_key(&menu, sizeof(void*)));
+        itemList = ucx_list_append_a(allocator, itemList, windowItem);
+        ucx_map_put(menus, ucx_key(&menu, sizeof(void*)), itemList);
+        
+        ucx_map_put(items, ucx_key(&windowItem->item, sizeof(void*)), windowItem);
+    }
+}
+
+- (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) {
+        UiMenuItem *item = elm->data;
+        
+        [item->item setState: item->state];
+    }
+}
+
 @end
 
 
@@ -74,6 +124,9 @@
     NSString *titleStr = [[NSString alloc] initWithUTF8String:title];
     [window setTitle:titleStr];
     
+    UiMenuDelegate *menuDelegate = ui_menu_delegate();
+    [window setMenuItems: [menuDelegate items]];
+    
     NSToolbar *toolbar = ui_create_toolbar();
     [window setToolbar: toolbar];
     

mercurial