added menu item lists (Cocoa implementation)

Mon, 31 Mar 2014 20:22:16 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Mon, 31 Mar 2014 20:22:16 +0200
changeset 14
e2fd132ab781
parent 13
2dbc56c2323b
child 15
7a36f91c22f7

added menu item lists (Cocoa implementation)

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/objs.mk file | annotate | diff | comparison | revisions
ui/cocoa/stock.h file | annotate | diff | comparison | revisions
ui/cocoa/stock.m file | annotate | diff | comparison | revisions
ui/cocoa/toolbar.m 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
ui/common/context.h file | annotate | diff | comparison | revisions
ui/common/objs.mk file | annotate | diff | comparison | revisions
ui/common/types.c file | annotate | diff | comparison | revisions
ui/common/types.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	Sat Mar 29 19:12:07 2014 +0100
+++ b/application/main.c	Mon Mar 31 20:22:16 2014 +0200
@@ -43,6 +43,8 @@
 
 UiInteger check1;
 
+UiList *list;
+
 void action_new(UiEvent *event, void *data) {
     UiObject *window = ui_window("Mod1", NULL);
     //ui_window_addint(window, "check1");
@@ -60,6 +62,8 @@
     TestWindowData *wd = event->window;
     printf("Text: {%s}\n", ui_getval(wd->text));
     ui_setval(wd->text, "--------");
+    
+    ui_list_append(list, "abc");
 }
 
 void action_close(UiEvent *event, void *data) {
@@ -92,10 +96,18 @@
     ui_text_redo(&wd->text);
 }
 
+void action_document(UiEvent *event, void *data) {
+    UiList *documents = data;
+}
+
 
 int main(int argc, char** argv) {
     ui_init("app1", argc, argv);
     
+    list = ui_list_new();
+    ui_list_append(list, "file1.txt");
+    ui_list_append(list, "hello.txt");
+    ui_list_append(list, "main.c");
     
     ui_menu("File");
     ui_menuitem("New", action_new, NULL);
@@ -103,16 +115,19 @@
     ui_menuseparator();
     ui_menuitem("Dokument 1", action_doc1, NULL);
     ui_menuitem("Dokument 2", action_doc2, NULL);
+    void ui_menuseparator();
     ui_menuseparator();
     ui_checkitem_nv("Check", "check1");
     //ui_checkitem("Check", action_open, NULL);
     ui_menuitem("Close", action_close, NULL);
+    void ui_menuseparator();
+    ui_menuitem_list(list, action_document, list);
     
     
     
     ui_toolitem_st("new", UI_STOCK_NEW, action_new, NULL);
-    ui_toolitem_st("open", UI_STOCK_OPEN, action_open, NULL);
-    ui_toolitem_st("save", UI_STOCK_SAVE, action_save, NULL);
+    ui_toolitem_st("open", UI_STOCK_GO_BACK, action_open, NULL);
+    ui_toolitem_st("save", UI_STOCK_GO_FORWARD, action_save, NULL);
     ui_toolitem_st("close", UI_STOCK_CLOSE, action_close, NULL);
     ui_toolitem_st("undo", UI_STOCK_UNDO, action_undo, NULL);
     ui_toolitem_st("redo", UI_STOCK_REDO, action_redo, NULL);
--- a/ui/cocoa/menu.h	Sat Mar 29 19:12:07 2014 +0100
+++ b/ui/cocoa/menu.h	Mon Mar 31 20:22:16 2014 +0200
@@ -30,26 +30,46 @@
 #import "toolkit.h"
 #import "../../ucx/list.h"
 
+typedef struct UiAbstractMenuItem {
+    int  (*update)(id window, void *item);
+    void *item_data;
+} UiAbstractMenuItem;
+
 typedef struct UiMenuItem {
-    NSMenuItem *item;
-    int        state;
+    NSMenuItem  *item;
+    int         state;
 } UiMenuItem;
 
 typedef struct UiStateItem {
-    NSMenuItem *item;
-    char       *var;
+    NSMenuItem  *item;
+    char        *var;
 } UiStateItem;
 
+typedef struct UiMenuItemList {
+    NSMenu      *menu;
+    NSMenuItem  *first;
+    UiList      *list;
+    int         index;
+    int         oldcount;
+    ui_callback callback;
+    void        *data;
+} UiMenuItemList;
+
 @interface UiMenuDelegate : NSObject <NSMenuDelegate> {
-    UcxList *items;
+    UcxList *items; // UiStateItem*
+    UcxList *itemlists; // UiMenuItemList*
 }
 
-- (void)menuNeedsUpdate:(NSMenu*) menu;
+- (void) menuNeedsUpdate:(NSMenu*) menu;
 
 - (void) addItem:(NSMenuItem*) item var: (char*)name;
 
+- (void) addList:(UiList*) list menu:(NSMenu*)menu index: (int)i callback: (ui_callback)f data:(void*) data;
+
 - (UcxList*) items;
 
+- (UcxList*) lists;
+
 @end
 
 
@@ -58,3 +78,6 @@
 
 int ui_menuitem_get(UiInteger *i);
 void ui_menuitem_set(UiInteger *i, int value);
+
+int ui_update_item(id window, void *data);
+int ui_update_item_list(id window, void *data);
--- a/ui/cocoa/menu.m	Sat Mar 29 19:12:07 2014 +0100
+++ b/ui/cocoa/menu.m	Mon Mar 31 20:22:16 2014 +0200
@@ -37,6 +37,7 @@
 
 - (UiMenuDelegate*) init {
     items = NULL;
+    itemlists = NULL;
     return self;
 }
 
@@ -52,16 +53,34 @@
     items = ucx_list_append(items, i);
 }
 
+- (void) addList:(UiList*) list menu:(NSMenu*)menu index: (int)i callback: (ui_callback)f data:(void*) data {
+    UiMenuItemList *itemList = malloc(sizeof(UiMenuItemList));
+    itemList->list = list;
+    itemList->menu = menu;
+    itemList->first = NULL;
+    itemList->index = i;
+    itemList->oldcount = 0;
+    itemList->callback = f;
+    itemList->data = data;
+    itemlists = ucx_list_append(itemlists, itemList);
+}
+
 - (UcxList*) items {
     return items;
 }
 
+- (UcxList*) lists {
+    return itemlists;
+    
+}
+
 @end
 
 
 
 
 static NSMenu *currentMenu = NULL;
+static int currentItemIndex = 0;
 static UiMenuDelegate *delegate;
 
 void ui_menu_init() {
@@ -83,6 +102,7 @@
     
     [[NSApp mainMenu] setSubmenu:menu forItem:menuItem];
     currentMenu = menu;
+    currentItemIndex = 0;
 }
 
 void ui_menuitem(char *label, ui_callback f, void *data) {
@@ -94,6 +114,7 @@
     [item setTarget:event];
     
     //[delegate addItem: item];
+    currentItemIndex++;
 }
 
 void ui_checkitem(char *label, ui_callback f, void *data) {
@@ -105,6 +126,7 @@
     [item setTarget:event];
     
     [delegate addItem: item var:NULL];
+    currentItemIndex++;
 }
 
 void ui_checkitem_nv(char *label, char *vname) {
@@ -116,10 +138,16 @@
     [item setTarget:event];
     
     [delegate addItem: item var:vname];
+    currentItemIndex++;
 }
 
 void ui_menuseparator() {
-    
+    [currentMenu addItem: [NSMenuItem separatorItem]];
+    currentItemIndex++;
+}
+
+void ui_menuitem_list (UiList *items, ui_callback f, void *data) {
+    [delegate addList:items menu:currentMenu index:currentItemIndex callback:f data:data];
 }
 
 
@@ -136,3 +164,38 @@
     i->value = value;
     item->state = value;
 }
+
+
+int ui_update_item(UiCocoaWindow *window, void *data) {
+    UiMenuItem *item = data;
+    [item->item setState: item->state];
+    return 0;
+}
+
+int ui_update_item_list(UiCocoaWindow *window, void *data) {
+    printf("update list\n");
+    
+    UiMenuItemList *itemList = data;
+    UiList *list = itemList->list;
+    
+    printf("oldcount: %d\n", itemList->oldcount);
+    for(int r=0;r<itemList->oldcount;r++) {
+        [itemList->menu removeItemAtIndex:itemList->index];
+    }
+    
+    char *str = ui_list_first(list);
+    int i = itemList->index;
+    [itemList->menu insertItem: [NSMenuItem separatorItem] atIndex: i];
+    i++;
+    do {
+        NSString *title = [[NSString alloc] initWithUTF8String:str];
+        NSMenuItem *item = [[NSMenuItem alloc]initWithTitle:title action:@selector(handleStateEvent:) keyEquivalent:@""];
+        
+        [itemList->menu insertItem:item atIndex:i];
+        i++;
+    } while ((str = ui_list_next(list)));
+    
+    itemList->oldcount = i - itemList->index;
+    
+    return 0;
+}
--- a/ui/cocoa/objs.mk	Sat Mar 29 19:12:07 2014 +0100
+++ b/ui/cocoa/objs.mk	Mon Mar 31 20:22:16 2014 +0200
@@ -32,6 +32,7 @@
 COCOAOBJ = toolkit.o
 COCOAOBJ += window.o
 COCOAOBJ += menu.o
+COCOAOBJ += stock.o
 COCOAOBJ += toolbar.o
 COCOAOBJ += container.o
 COCOAOBJ += text.o
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/stock.h	Mon Mar 31 20:22:16 2014 +0200
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+#import "toolkit.h"
+#import "../ui/stock.h"
+#import "../../ucx/map.h"
+
+typedef struct UiStockItem {
+    NSString *label;
+    NSImage  *image;
+} UiStockItem;
+
+void ui_stock_init();
+
+void ui_add_stock_item(char *stock_id, NSString *label, NSImage *image);
+
+UiStockItem* ui_get_stock_item(char *stock_id);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/stock.m	Mon Mar 31 20:22:16 2014 +0200
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+#import <stdio.h>
+#import <stdlib.h>
+
+#import "stock.h"
+
+static UcxMap *stock_items;
+
+void ui_stock_init() {
+    stock_items = ucx_map_new(64);
+    
+    ui_add_stock_item(UI_STOCK_NEW, @"New", nil);
+    ui_add_stock_item(UI_STOCK_OPEN, @"Open", nil);
+    ui_add_stock_item(UI_STOCK_SAVE, @"Save", nil);
+    ui_add_stock_item(UI_STOCK_SAVE_AS, @"Save as ...", nil);
+    ui_add_stock_item(UI_STOCK_CLOSE, @"Close", nil);
+    ui_add_stock_item(UI_STOCK_UNDO, @"Undo", nil);
+    ui_add_stock_item(UI_STOCK_REDO, @"Redo", nil);
+    
+    ui_add_stock_item(UI_STOCK_GO_BACK, @"Back", [NSImage imageNamed: NSImageNameGoLeftTemplate]);
+    ui_add_stock_item(UI_STOCK_GO_FORWARD, @"Forward", [NSImage imageNamed: NSImageNameGoRightTemplate]);
+}
+
+void ui_add_stock_item(char *stock_id, NSString *label, NSImage *image) {
+    UiStockItem *i = malloc(sizeof(UiStockItem));
+    i->label = label;
+    i->image = image;
+    
+    ucx_map_cstr_put(stock_items, stock_id, i);
+}
+
+UiStockItem* ui_get_stock_item(char *stock_id) {
+    return ucx_map_cstr_get(stock_items, stock_id);
+}
--- a/ui/cocoa/toolbar.m	Sat Mar 29 19:12:07 2014 +0100
+++ b/ui/cocoa/toolbar.m	Mon Mar 31 20:22:16 2014 +0200
@@ -31,6 +31,7 @@
 #import <string.h>
 
 #import "toolbar.h"
+#import "stock.h"
 
 
 static UiToolbarDelegate* toolbar_delegate;
@@ -55,22 +56,17 @@
 - (NSToolbarItem *) createItem:(NSToolbar*)toolbar
                     identifier:(NSString*)identifier
 {
-    /*
     UiStockItem *s = ui_get_stock_item(stockid);
     if(s == nil) {
         printf("cannot find stock item\n");
         return nil;
     }
-    if([s buttonImage] == nil && [s itemImage] == nil) {
-        return nil;
-    }
-    */
     
     NSToolbarItem *item = [[[NSToolbarItem alloc] initWithItemIdentifier:
                             identifier] autorelease];
     //[item setLabel:[s label]];
     //[item setPaletteLabel:[s label]];
-    [item setLabel:@"Add"];
+    [item setLabel:s->label];
     [item setPaletteLabel:@"Operation"];
     
     // create button ...
@@ -78,7 +74,12 @@
     //NSSearchField *sf = [[NSSearchField alloc]initWithFrame:frame];
     NSButton *button = [[NSButton alloc]initWithFrame:frame];
     //[button setImage:[s buttonImage]];
-    [button setImage:[NSImage imageNamed: NSImageNameAddTemplate]];
+    //[button setImage:[NSImage imageNamed: NSImageNameAddTemplate]];
+    if(s->image) {
+        [button setImage:s->image];
+    } else {
+        [button setImage:[NSImage imageNamed: NSImageNameRemoveTemplate]];
+    }
     [button setBezelStyle: NSTexturedRoundedBezelStyle];
     [item setView:button];
     
--- a/ui/cocoa/toolkit.m	Sat Mar 29 19:12:07 2014 +0100
+++ b/ui/cocoa/toolkit.m	Mon Mar 31 20:22:16 2014 +0200
@@ -38,7 +38,7 @@
 #import "window.h"
 #import "menu.h"
 #import "toolbar.h"
-
+#import "stock.h"
 
 NSAutoreleasePool *pool;
 
@@ -56,8 +56,7 @@
     uic_docmgr_init();
     ui_menu_init();
     ui_toolbar_init();
-    // load item stock
-    // ui_init_stock();
+    ui_stock_init();
 }
 
 void ui_show(UiObject *obj) {
--- a/ui/cocoa/window.h	Sat Mar 29 19:12:07 2014 +0100
+++ b/ui/cocoa/window.h	Mon Mar 31 20:22:16 2014 +0200
@@ -30,18 +30,22 @@
 #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   *menus; // key: NSMenu value: UcxList of UiMenuItem
     UcxMap   *items; // key: NSMenuItem value: UiMenuItem
 }
 
+- (UiCocoaWindow*) init: (NSRect)frame object: (UiObject*)obj;
 - (UiObject*) object;
 - (void) setObject:(UiObject*)obj;
 - (void) setMenuItems:(UcxList*)menuItems;
+- (void) setMenuItemLists:(UcxList*)itemLists;
 - (UiMenuItem*) getMenuItem:(NSMenuItem*)item;
 - (void) updateMenu:(NSMenu*)menu;
 
--- a/ui/cocoa/window.m	Sat Mar 29 19:12:07 2014 +0100
+++ b/ui/cocoa/window.m	Mon Mar 31 20:22:16 2014 +0200
@@ -40,6 +40,23 @@
 
 @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;
 }
@@ -50,8 +67,6 @@
 
 - (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;
@@ -76,14 +91,34 @@
         }
         
         // 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, windowItem);
+        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*)));
 }
@@ -91,9 +126,8 @@
 - (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];
+        UiAbstractMenuItem *item = elm->data;
+        item->update(self, item->item_data);
     }
 }
 
@@ -114,18 +148,21 @@
                               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];
     
-    [window setObject: 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();
     [window setToolbar: toolbar];
--- a/ui/common/context.h	Sat Mar 29 19:12:07 2014 +0100
+++ b/ui/common/context.h	Mon Mar 31 20:22:16 2014 +0200
@@ -26,8 +26,8 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef VALUE_H
-#define	VALUE_H
+#ifndef UIC_CONTEXT_H
+#define	UIC_CONTEXT_H
 
 #include "../ui/toolkit.h"
 #include "../../ucx/map.h"
@@ -67,5 +67,5 @@
 }
 #endif
 
-#endif	/* VALUE_H */
+#endif	/* UIC_CONTEXT_H */
 
--- a/ui/common/objs.mk	Sat Mar 29 19:12:07 2014 +0100
+++ b/ui/common/objs.mk	Mon Mar 31 20:22:16 2014 +0200
@@ -32,8 +32,10 @@
 COMMON_OBJ = context.o
 COMMON_OBJ += document.o
 COMMON_OBJ += object.o
+COMMON_OBJ += types.o
 #COMMON_OBJ = observer.o
 #COMMON_OBJ += list.o
 
+
 TOOLKITOBJS += $(COMMON_OBJ:%=$(COMMON_OBJPRE)%)
 TOOLKITSOURCE += $(COMMON_OBJ:%.o=common/%.c)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/common/types.c	Mon Mar 31 20:22:16 2014 +0200
@@ -0,0 +1,142 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2014 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 "../../ucx/list.h"
+#include "types.h"
+
+UiObserver* ui_observer_new(ui_callback f, void *data) {
+    UiObserver *observer = malloc(sizeof(UiObserver));
+    observer->callback = f;
+    observer->data = data;
+    observer->next = NULL;
+    return observer;
+}
+
+UiObserver* ui_obsvlist_add(UiObserver *list, UiObserver *observer) {
+    if(!list) {
+        return observer;
+    } else {
+        UiObserver *l = list;
+        while(l->next) {
+            l = l->next;
+        }
+        l->next = observer;
+        return list;
+    }
+}
+
+UiObserver* ui_add_observer(UiObserver *list, ui_callback f, void *data) {
+    UiObserver *observer = ui_observer_new(f, data);
+    return ui_obsvlist_add(list, observer);
+}
+
+void ui_notify(UiObserver *observer, void *data) {
+    ui_notify_except(observer, NULL, data);
+}
+
+void ui_notify_except(UiObserver *observer, UiObserver *exc, void *data) {
+    while(observer) {
+        if(observer != exc) {
+            observer->callback(data, observer->data);
+        }
+        observer = observer->next;
+    }
+}
+
+/* --------------------------- UiList --------------------------- */
+
+UiList* ui_list_new() {
+    UiList *list = malloc(sizeof(UiList));
+    list->first = ui_list_first;
+    list->next = ui_list_next;
+    list->get = ui_list_get;
+    list->count = ui_list_count;
+    list->observers = NULL;
+    
+    list->data = NULL;
+    list->iter = NULL;
+    
+    return list;
+}
+
+void ui_list_free(UiList *list) {
+    ucx_list_free(list->data);
+    free(list);
+}
+
+void* ui_list_first(UiList *list) {
+    UcxList *elm = list->data;
+    list->iter = elm;
+    return elm ? elm->data : NULL;
+}
+
+void* ui_list_next(UiList *list) {
+    UcxList *elm = list->iter;
+    if(elm) {
+        elm = elm->next;
+        if(elm) {
+            list->iter = elm;
+            return elm->data;
+        }
+    }
+    return NULL;
+}
+
+void* ui_list_get(UiList *list, int i) {
+    UcxList *elm = ucx_list_get(list->data, i);
+    if(elm) {
+        list->iter = elm;
+        return elm->data;
+    } else {
+        return NULL;
+    }
+}
+
+int ui_list_count(UiList *list) {
+    UcxList *elm = list->data;
+    return (int)ucx_list_size(elm);
+}
+
+void ui_list_append(UiList *list, void *data) {
+    list->data = ucx_list_append(list->data, data);
+}
+
+void ui_list_prepend(UiList *list, void *data) {
+    list->data = ucx_list_prepend(list->data, data);
+}
+
+void ui_list_addobsv(UiList *list, ui_callback f, void *data) {
+    list->observers = ui_add_observer(list->observers, f, data);
+}
+
+void ui_list_notify(UiList *list) {
+    ui_notify(list->observers, list);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/common/types.h	Mon Mar 31 20:22:16 2014 +0200
@@ -0,0 +1,62 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2014 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.
+ */
+
+#ifndef UIC_TYPES_H
+#define	UIC_TYPES_H
+
+#include "../ui/toolkit.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+UiObserver* ui_observer_new(ui_callback f, void *data);
+UiObserver* ui_obsvlist_add(UiObserver *list, UiObserver *observer);
+UiObserver* ui_add_observer(UiObserver *list, ui_callback f, void *data);
+void ui_notify(UiObserver *observer, void *data);
+void ui_notify_except(UiObserver *observer, UiObserver *exc, void *data);
+    
+
+UiList* ui_list_new();
+void* ui_list_first(UiList *list);
+void* ui_list_next(UiList *list);
+void* ui_list_get(UiList *list, int i);
+int   ui_list_count(UiList *list);
+void  ui_list_append(UiList *list, void *data);
+void  ui_list_prepend(UiList *list, void *data);
+void  ui_list_addobsv(UiList *list, ui_callback f, void *data);
+void  ui_list_notify(UiList *list);
+*/
+    
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* UIC_TYPES_H */
+
--- a/ui/ui/menu.h	Sat Mar 29 19:12:07 2014 +0100
+++ b/ui/ui/menu.h	Mon Mar 31 20:22:16 2014 +0200
@@ -46,6 +46,8 @@
 void ui_checkitem(char *label, ui_callback f, void *userdata);
 void ui_checkitem_nv(char *label, char *vname);
 
+void ui_menuitem_list(UiList *items, ui_callback f, void *userdata);
+
 #ifdef	__cplusplus
 }
 #endif
--- a/ui/ui/toolkit.h	Sat Mar 29 19:12:07 2014 +0100
+++ b/ui/ui/toolkit.h	Mon Mar 31 20:22:16 2014 +0200
@@ -55,12 +55,14 @@
 #endif
 
 /* public types */
-typedef struct UiObject UiObject;
-typedef struct UiEvent UiEvent;
+typedef struct UiObject   UiObject;
+typedef struct UiEvent    UiEvent;
+typedef struct UiObserver UiObserver;
 
 typedef struct UiInteger UiInteger;
 typedef struct UiString  UiString;
 typedef struct UiText    UiText;
+typedef struct UiList    UiList;
 
 /* private types */
 typedef struct UiContext   UiContext;
@@ -73,7 +75,7 @@
 #define ui_insert(text, begin, str) (text).insert(&(text), begin, str)
 
     
-typedef void(*ui_callback)(UiEvent*, void*); // event, user data
+typedef void(*ui_callback)(UiEvent*, void*); /* event, user data */
 
 struct UiObject {
     /*
@@ -109,6 +111,12 @@
     int      intval;
 };
 
+struct UiObserver {
+    ui_callback callback;
+    void *data;
+    UiObserver *next;
+};
+
 struct UiInteger {
     int  (*get)(UiInteger*);
     void (*set)(UiInteger*, int);
@@ -128,11 +136,32 @@
     char* (*get)(UiText*);
     char* (*getsubstr)(UiText*, int, int); // text, begin, end
     void  (*insert)(UiText*, int, char*);
-    char* value;
+    char  *value;
     void  *obj;
     void  *undomgr;
     // TODO: selection, undo, replace, ...
 };
+    
+/*
+ * abstract list
+ */
+struct UiList {
+    /* get the first element */
+    void*(*first)(UiList *list);
+    /* get the next element */
+    void*(*next)(UiList *list);
+    /* get the nth element */
+    void*(*get)(UiList *list, int i);
+    /* get the number of elements */
+    int(*count)(UiList *list);
+    /* list of observers */
+    UiObserver *observers;
+    /* iterator changes after first() next() and get() */
+    void *iter;
+    /* private - implementation dependent */
+    void *data;
+    
+};
 
 void ui_init(char *appname, int argc, char **argv);
 void ui_exitfunc(ui_callback f, void *udata);
@@ -163,6 +192,27 @@
 // new:
 int ui_getint(UiObject *obj, char *name);
 
+    
+    
+    
+    
+// types
+UiObserver* ui_observer_new(ui_callback f, void *data);
+UiObserver* ui_obsvlist_add(UiObserver *list, UiObserver *observer);
+UiObserver* ui_add_observer(UiObserver *list, ui_callback f, void *data);
+void ui_notify(UiObserver *observer, void *data);
+void ui_notify_except(UiObserver *observer, UiObserver *exc, void *data);
+
+
+UiList* ui_list_new();
+void* ui_list_first(UiList *list);
+void* ui_list_next(UiList *list);
+void* ui_list_get(UiList *list, int i);
+int   ui_list_count(UiList *list);
+void  ui_list_append(UiList *list, void *data);
+void  ui_list_prepend(UiList *list, void *data);
+void  ui_list_addobsv(UiList *list, ui_callback f, void *data);
+void  ui_list_notify(UiList *list);
 
 
 #ifdef	__cplusplus

mercurial