added groups for menu items (Cocoa)

Wed, 02 Apr 2014 20:31:47 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Wed, 02 Apr 2014 20:31:47 +0200
changeset 20
2dda1ad6dc7a
parent 19
f8f22eb0b575
child 21
012418e7dc90

added groups for menu items (Cocoa)

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/window.m file | annotate | diff | comparison | revisions
ui/common/context.c file | annotate | diff | comparison | revisions
ui/common/context.h file | annotate | diff | comparison | revisions
ui/ui/menu.h file | annotate | diff | comparison | revisions
ui/ui/toolkit.h file | annotate | diff | comparison | revisions
--- a/application/main.c	Wed Apr 02 13:21:11 2014 +0200
+++ b/application/main.c	Wed Apr 02 20:31:47 2014 +0200
@@ -114,6 +114,7 @@
     ui_menu("File");
     ui_menuitem_st(UI_STOCK_NEW, action_new, NULL);
     ui_menuitem_st(UI_STOCK_OPEN, action_open, NULL);
+    ui_menuitem_stgr(UI_STOCK_SAVE, action_save, NULL, 1, -1);
     ui_menuseparator();
     ui_menuitem("Dokument 1", action_doc1, NULL);
     ui_menuitem("Dokument 2", action_doc2, NULL);
@@ -121,15 +122,11 @@
     
     ui_checkitem_nv("Check", "check1");
     //ui_checkitem("Check", action_open, NULL);
-<<<<<<< local
     
-=======
-    ui_menuitem_st(UI_STOCK_CLOSE, action_close, NULL);
->>>>>>> other
     void ui_menuseparator();
     ui_menuitem_list(list, action_document, list);
     ui_menuseparator();
-    ui_menuitem("Close", action_close, NULL);
+    ui_menuitem_st(UI_STOCK_CLOSE, action_close, NULL);
     
     
     ui_toolitem_st("new", UI_STOCK_NEW, action_new, NULL);
--- a/ui/cocoa/menu.h	Wed Apr 02 13:21:11 2014 +0200
+++ b/ui/cocoa/menu.h	Wed Apr 02 20:31:47 2014 +0200
@@ -72,6 +72,17 @@
 
 @end
 
+@interface UiGroupMenuItem : NSMenuItem {
+    NSMutableArray *groups;
+}
+
+- (id)initWithTitle:(NSString*)title action:(SEL)action keyEquivalent:(NSString*)s;
+
+- (void) addGroup:(int)group;
+
+- (void) checkGroups:(int*)g count:(int)n;
+
+@end
 
 void ui_menu_init();
 UiMenuDelegate* ui_menu_delegate();
--- a/ui/cocoa/menu.m	Wed Apr 02 13:21:11 2014 +0200
+++ b/ui/cocoa/menu.m	Wed Apr 02 20:31:47 2014 +0200
@@ -29,6 +29,7 @@
 #import <stdio.h>
 #import <stdlib.h>
 #import <string.h>
+#import <stdarg.h>
 
 #import "menu.h"
 #import "window.h"
@@ -78,6 +79,43 @@
 @end
 
 
+@implementation UiGroupMenuItem
+
+- (id)initWithTitle:(NSString*)title action:(SEL)action keyEquivalent:(NSString*)s {
+    [super initWithTitle:title action:action keyEquivalent:s];
+    groups = [[NSMutableArray alloc]initWithCapacity: 16];
+    return self;
+}
+
+- (void) addGroup:(int)group {
+    NSNumber *groupNumber = [NSNumber numberWithInteger:group];
+    [groups addObject:groupNumber];
+}
+
+- (void) checkGroups:(int*)g count:(int)n {
+    int c = [groups count];
+    
+    char *check = calloc(1, c);
+    for(int i=0;i<n;i++) {
+        for(int k=0;k<c;k++) {
+            NSNumber *groupNumber = [groups objectAtIndex:k];
+            if([groupNumber intValue] == g[i]) {
+                check[k] = 1;
+                break;
+            }
+        }
+    }
+    
+    for(int j=0;j<c;j++) {
+        if(check[j] == 0) {
+            [self setEnabled:NO];
+            return;
+        }
+    }
+    [self setEnabled:YES];
+}
+
+@end
 
 
 static NSMenu *currentMenu = NULL;
@@ -100,6 +138,7 @@
     NSMenuItem *menuItem = [[NSApp mainMenu] addItemWithTitle:str
                                                        action:nil keyEquivalent:@""];
     [menu setDelegate: delegate];
+    [menu setAutoenablesItems:NO];
     
     [[NSApp mainMenu] setSubmenu:menu forItem:menuItem];
     currentMenu = menu;
@@ -107,23 +146,53 @@
 }
 
 void ui_menuitem(char *label, ui_callback f, void *data) {
-    EventWrapper *event = [[EventWrapper alloc]initWithData:data callback:f];
-    NSString *str = [[NSString alloc] initWithUTF8String:label];
+    ui_menuitem_gr(label, f, data, -1);
+}
+
+void ui_menuitem_st(char *stockid, ui_callback f, void *data) {
+    ui_menuitem_stgr(stockid, f, data, -1);
+}
+
+void ui_menuitem_gr(char *label, ui_callback f, void *userdata, ...) {
+    // create menu item
+    EventWrapper *event = [[EventWrapper alloc]initWithData:userdata callback:f];
+    NSString *title = [[NSString alloc] initWithUTF8String:label];
+    UiGroupMenuItem *item = [[UiGroupMenuItem alloc]initWithTitle:title action:@selector(handleEvent:) keyEquivalent:@""];
+    [item setTarget:event];
     
-    NSMenuItem *item = [currentMenu addItemWithTitle:str
-                                              action:@selector(handleEvent:) keyEquivalent:@""];
-    [item setTarget:event];
+    // add groups
+    va_list ap;
+    va_start(ap, userdata);
+    int group;
+    while((group = va_arg(ap, int)) != -1) {
+        [item addGroup: group];
+    }
+    
+    
+    [currentMenu addItem:item];
     
     currentItemIndex++;
 }
 
-void ui_menuitem_st(char *stockid, ui_callback f, void *data) {
-    EventWrapper *event = [[EventWrapper alloc]initWithData:data callback:f];
+void ui_menuitem_stgr(char *stockid, ui_callback f, void *userdata, ...) {
+    // create menu item
+    EventWrapper *event = [[EventWrapper alloc]initWithData:userdata callback:f];
     UiStockItem *si = ui_get_stock_item(stockid);
+    UiGroupMenuItem *item = [[UiGroupMenuItem alloc]initWithTitle:si->label
+                                action:@selector(handleEvent:)
+                                keyEquivalent:si->keyEquivalent];
+    [item setTarget:event];
     
-    NSMenuItem *item = [currentMenu addItemWithTitle:si->label
-                           action:@selector(handleEvent:) keyEquivalent:si->keyEquivalent];
-    [item setTarget:event];
+    // add groups
+    va_list ap;
+    va_start(ap, userdata);
+    int group;
+    while((group = va_arg(ap, int)) != -1) {
+        [item addGroup: group];
+    }
+    
+    
+    [currentMenu addItem:item];
     
     currentItemIndex++;
 }
--- a/ui/cocoa/window.m	Wed Apr 02 13:21:11 2014 +0200
+++ b/ui/cocoa/window.m	Wed Apr 02 20:31:47 2014 +0200
@@ -129,6 +129,20 @@
         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];
+        }
+    }
 }
 
 @end
--- a/ui/common/context.c	Wed Apr 02 13:21:11 2014 +0200
+++ b/ui/common/context.c	Wed Apr 02 20:31:47 2014 +0200
@@ -29,6 +29,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <inttypes.h>
 
 #include "context.h"
 #include "../ui/window.h"
@@ -41,6 +42,7 @@
     
     ctx->toplevel = toplevel;
     ctx->vars = ucx_map_new_a(mp->allocator, 16);
+    ctx->groups = NULL;
     
 #ifdef UI_GTK
     ctx->accel_group = gtk_accel_group_new();
@@ -149,3 +151,32 @@
     return 0;
 }
 
+
+
+
+void ui_set_group(UiContext *ctx, int group) {
+    if(ucx_list_find(ctx->groups, (void*)(intptr_t)group, NULL, NULL) == -1) {
+        ctx->groups = ucx_list_append_a(ctx->mempool->allocator, ctx->groups, (void*)(intptr_t)group);
+    }
+}
+
+void ui_unset_group(UiContext *ctx, int group) {
+    int i = ucx_list_find(ctx->groups, (void*)(intptr_t)group, NULL, NULL);
+    if(i != -1) {
+        UcxList *elm = ucx_list_get(ctx->groups, i);
+        ctx->groups = ucx_list_remove_a(ctx->mempool->allocator, ctx->groups, elm);
+    }
+}
+
+int* ui_active_groups(UiContext *ctx, int *ngroups) {
+    int nelm = ucx_list_size(ctx->groups);
+    int *groups = calloc(sizeof(int), nelm);
+    
+    int i = 0;
+    UCX_FOREACH(elm, ctx->groups) {
+        groups[i++] = (int)elm->data;
+    }
+    
+    *ngroups = nelm;
+    return groups;
+}
--- a/ui/common/context.h	Wed Apr 02 13:21:11 2014 +0200
+++ b/ui/common/context.h	Wed Apr 02 20:31:47 2014 +0200
@@ -32,6 +32,7 @@
 #include "../ui/toolkit.h"
 #include "../../ucx/map.h"
 #include "../../ucx/mempool.h"
+#include "../../ucx/list.h"
 
 #ifdef	__cplusplus
 extern "C" {
@@ -43,6 +44,7 @@
     UiObject      *toplevel;
     UcxMempool    *mempool;
     UcxMap        *vars; // key: char*  value: UiVar*
+    UcxList       *groups; // int list
     
 #ifdef UI_GTK
     GtkAccelGroup *accel_group;
@@ -67,6 +69,7 @@
 void* uic_create_value(UcxAllocator *a, int type);
 
 
+
 #ifdef	__cplusplus
 }
 #endif
--- a/ui/ui/menu.h	Wed Apr 02 13:21:11 2014 +0200
+++ b/ui/ui/menu.h	Wed Apr 02 20:31:47 2014 +0200
@@ -41,6 +41,9 @@
 
 void ui_menuitem(char *label, ui_callback f, void *userdata);
 void ui_menuitem_st(char *stockid, ui_callback f, void *userdata);
+void ui_menuitem_gr(char *label, ui_callback f, void *userdata, ...);
+void ui_menuitem_stgr(char *stockid, ui_callback f, void *userdata, ...);
+
 void ui_menuseparator();
 
 void ui_checkitem(char *label, ui_callback f, void *userdata);
--- a/ui/ui/toolkit.h	Wed Apr 02 13:21:11 2014 +0200
+++ b/ui/ui/toolkit.h	Wed Apr 02 20:31:47 2014 +0200
@@ -195,8 +195,9 @@
 int ui_getint(UiObject *obj, char *name);
 
     
-    
-    
+void ui_set_group(UiContext *ctx, int group);
+void ui_unset_group(UiContext *ctx, int group);
+int* ui_active_groups(UiContext *ctx, int *ngroups);
     
 // types
 UiObserver* ui_observer_new(ui_callback f, void *data);

mercurial