added menu item lists (GTK)

Tue, 01 Apr 2014 11:53:10 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Tue, 01 Apr 2014 11:53:10 +0200
changeset 16
a499c8a72c15
parent 15
7a36f91c22f7
child 17
db95c0104937

added menu item lists (GTK)

application/main.c file | annotate | diff | comparison | revisions
ui/common/types.c file | annotate | diff | comparison | revisions
ui/gtk/button.c file | annotate | diff | comparison | revisions
ui/gtk/menu.c file | annotate | diff | comparison | revisions
ui/gtk/menu.h file | annotate | diff | comparison | revisions
ui/gtk/toolkit.h file | annotate | diff | comparison | revisions
ui/ui/toolkit.h file | annotate | diff | comparison | revisions
--- a/application/main.c	Tue Apr 01 11:50:32 2014 +0200
+++ b/application/main.c	Tue Apr 01 11:53:10 2014 +0200
@@ -64,6 +64,7 @@
     ui_setval(wd->text, "--------");
     
     ui_list_append(list, "abc");
+    ui_notify(list->observers, NULL);
 }
 
 void action_close(UiEvent *event, void *data) {
--- a/ui/common/types.c	Tue Apr 01 11:50:32 2014 +0200
+++ b/ui/common/types.c	Tue Apr 01 11:53:10 2014 +0200
@@ -65,7 +65,13 @@
 void ui_notify_except(UiObserver *observer, UiObserver *exc, void *data) {
     while(observer) {
         if(observer != exc) {
-            observer->callback(data, observer->data);
+            UiEvent evt;
+            evt.obj = NULL;
+            evt.window = NULL;
+            evt.document = NULL;
+            evt.eventdata = data;
+            evt.intval = 0;
+            observer->callback(&evt, observer->data);
         }
         observer = observer->next;
     }
--- a/ui/gtk/button.c	Tue Apr 01 11:50:32 2014 +0200
+++ b/ui/gtk/button.c	Tue Apr 01 11:53:10 2014 +0200
@@ -44,6 +44,7 @@
         event->obj = obj;
         event->user_data = data;
         event->callback = f;
+        event->value = 0;
 
         g_signal_connect(
                 button,
@@ -64,6 +65,7 @@
     e.obj = event->obj;
     e.window = event->obj->window;
     e.document = event->obj->document;
-    e.intval = 0;
+    e.eventdata = NULL;
+    e.intval = event->value;
     event->callback(&e, event->user_data);
 }
--- a/ui/gtk/menu.c	Tue Apr 01 11:50:32 2014 +0200
+++ b/ui/gtk/menu.c	Tue Apr 01 11:53:10 2014 +0200
@@ -28,14 +28,15 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <inttypes.h>
 
 #include "menu.h"
 #include "toolkit.h"
 #include "../common/context.h"
 #include "../ui/window.h"
 
-UcxList *menus;
-UcxList *current;
+static UcxList *menus;
+static UcxList *current;
 
 void ui_menu(char *label) {
     // free current menu hierarchy
@@ -75,7 +76,7 @@
         return;
     }
     current = ucx_list_remove(current, current);
-    UcxList *c = current;
+    //UcxList *c = current;
 }
 
 void ui_menuitem(char *label, ui_callback f, void *userdata) {
@@ -135,6 +136,21 @@
     cm->items = ucx_list_append(cm->items, item);
 }
 
+void ui_menuitem_list(UiList *items, ui_callback f, void *userdata) {
+    if(!current) {
+        return;
+    }
+    
+    UiMenuItemList *item = malloc(sizeof(UiMenuItemList));
+    item->item.add_to = (ui_menu_add_f)add_menuitem_list_widget;
+    item->callback = f;
+    item->userdata = userdata;
+    item->list = items;
+    
+    UiMenu *cm = current->data;
+    cm->items = ucx_list_append(cm->items, item);
+}
+
 // private menu functions
 GtkWidget *ui_create_menubar(UiObject *obj) {
     if(menus == NULL) {
@@ -146,7 +162,7 @@
     UcxList *ls = menus;
     while(ls) {
         UiMenu *menu = ls->data;
-        menu->item.add_to(mb, &menu->item, obj);
+        menu->item.add_to(mb, 0, &menu->item, obj);
         
         ls = ls->next;
     }
@@ -154,7 +170,7 @@
     return mb;
 }
 
-void add_menu_widget(GtkWidget *parent, UiMenuItemI *item, UiObject *obj) {
+void add_menu_widget(GtkWidget *parent, int i, UiMenuItemI *item, UiObject *obj) {
     UiMenu *menu = (UiMenu*)item;
     
     GtkWidget *menu_widget = gtk_menu_new();
@@ -162,17 +178,19 @@
     gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), menu_widget);
     
     UcxList *ls = menu->items;
+    int index = 0;
     while(ls) {
         UiMenuItemI *i = ls->data;
-        i->add_to(menu_widget, i, obj);
+        i->add_to(menu_widget, index, i, obj);
         
         ls = ls->next;
+        index++;
     }
     
     gtk_menu_shell_append(GTK_MENU_SHELL(parent), menu_item);
 }
 
-void add_menuitem_widget(GtkWidget *parent, UiMenuItemI *item, UiObject *obj) {
+void add_menuitem_widget(GtkWidget *parent, int index, UiMenuItemI *item, UiObject *obj) {
     UiMenuItem *i = (UiMenuItem*)item;
     
     //GtkWidget *widget = gtk_menu_item_new_with_label(i->title);
@@ -183,6 +201,7 @@
         event->obj = obj;
         event->user_data = i->userdata;
         event->callback = i->callback;
+        event->value = 0;
 
         g_signal_connect(
                 widget,
@@ -196,6 +215,7 @@
 
 void add_menuitem_st_widget(
         GtkWidget *parent,
+        int index,
         UiMenuItemI *item,
         UiObject *obj)
 {
@@ -208,6 +228,7 @@
         event->obj = obj;
         event->user_data = i->userdata;
         event->callback = i->callback;
+        event->value = 0;
 
         g_signal_connect(
                 widget,
@@ -221,6 +242,7 @@
 
 void add_menuseparator_widget(
         GtkWidget *parent,
+        int index,
         UiMenuItemI *item,
         UiObject *obj)
 {
@@ -229,7 +251,7 @@
             gtk_separator_menu_item_new());
 }
 
-void add_checkitem_widget(GtkWidget *p, UiMenuItemI *item, UiObject *obj) {
+void add_checkitem_widget(GtkWidget *p, int index, UiMenuItemI *item, UiObject *obj) {
     UiCheckItem *ci = (UiCheckItem*)item;
     GtkWidget *widget = gtk_check_menu_item_new_with_mnemonic(ci->label);
     gtk_menu_shell_append(GTK_MENU_SHELL(p), widget);
@@ -239,6 +261,7 @@
         event->obj = obj;
         event->user_data = ci->userdata;
         event->callback = ci->callback;
+        event->value = 0;
 
         g_signal_connect(
                 widget,
@@ -248,7 +271,7 @@
     }
 }
 
-void add_checkitemnv_widget(GtkWidget *p, UiMenuItemI *item, UiObject *obj) {
+void add_checkitemnv_widget(GtkWidget *p, int index, UiMenuItemI *item, UiObject *obj) {
     UiCheckItemNV *ci = (UiCheckItemNV*)item;
     GtkWidget *widget = gtk_check_menu_item_new_with_mnemonic(ci->label);
     gtk_menu_shell_append(GTK_MENU_SHELL(p), widget);
@@ -265,14 +288,86 @@
     }
 }
 
+void add_menuitem_list_widget(GtkWidget *p, int index, UiMenuItemI *item, UiObject *obj) {
+    UiMenuItemList *il = (UiMenuItemList*)item;
+    UcxMempool *mp = obj->ctx->mempool;
+    
+    UiActiveMenuItemList *ls = ucx_mempool_malloc(
+            mp,
+            sizeof(UiActiveMenuItemList));
+    
+    ls->object = obj;
+    ls->menu = GTK_MENU_SHELL(p);
+    ls->index = index;
+    ls->oldcount = 0;
+    ls->list = il->list;
+    ls->callback = il->callback;
+    ls->userdata = il->userdata;
+    
+    ls->list->observers = ui_add_observer(
+            ls->list->observers,
+            (ui_callback)ui_update_menuitem_list,
+            ls);
+    
+    ui_update_menuitem_list(NULL, ls);
+}
 
 
+void ui_update_menuitem_list(UiEvent *event, UiActiveMenuItemList *list) {    
+    // remove old items
+    if(list->oldcount > 0) {
+        int i = 0;
+        GList *mi = gtk_container_get_children(GTK_CONTAINER(list->menu));
+        while(mi) {
+            if(i >= list->index && i < list->index + list->oldcount) {
+                gtk_container_remove(GTK_CONTAINER(list->menu), mi->data);
+            }
+            mi = mi->next;
+            i++;
+        }
+    }
+    
+    char *str = ui_list_first(list->list);
+    if(str) {
+        GtkWidget *widget = gtk_separator_menu_item_new();
+        gtk_menu_shell_insert(list->menu, widget, list->index);
+        gtk_widget_show(widget);
+    }
+    int i = 1;
+    while(str) {
+        GtkWidget *widget = gtk_menu_item_new_with_label(str);
+        gtk_menu_shell_insert(list->menu, widget, list->index + i);
+        gtk_widget_show(widget);
+        
+        if(list->callback) {
+            // TODO: use mempool
+            UiEventData *event = malloc(sizeof(UiEventData));
+            event->obj = list->object;
+            event->user_data = list->userdata;
+            event->callback = list->callback;
+            event->value = i - 1;
+
+            g_signal_connect(
+                widget,
+                "activate",
+                G_CALLBACK(ui_menu_event_wrapper),
+                event);
+        }
+        
+        str = ui_list_next(list->list);
+        i++;
+    }
+    
+    list->oldcount = i;
+}
+
 void ui_menu_event_wrapper(GtkMenuItem *item, UiEventData *event) {
     UiEvent evt;
     evt.obj = event->obj;
     evt.window = event->obj->window;
     evt.document = event->obj->document;
-    evt.intval = 0;
+    evt.eventdata = NULL;
+    evt.intval = event->value;
     event->callback(&evt, event->user_data);    
 }
 
@@ -281,6 +376,7 @@
     evt.obj = event->obj;
     evt.window = event->obj->window;
     evt.document = event->obj->document;
+    evt.eventdata = NULL;
     evt.intval = gtk_check_menu_item_get_active(ci);
     event->callback(&evt, event->user_data);    
 }
--- a/ui/gtk/menu.h	Tue Apr 01 11:50:32 2014 +0200
+++ b/ui/gtk/menu.h	Tue Apr 01 11:53:10 2014 +0200
@@ -43,8 +43,11 @@
 typedef struct UiStMenuItem     UiStMenuItem;
 typedef struct UiCheckItem      UiCheckItem;
 typedef struct UiCheckItemNV    UiCheckItemNV;
+typedef struct UiMenuItemList   UiMenuItemList;
 
-typedef GtkWidget*(*ui_menu_add_f)(GtkWidget *, UiMenuItemI*, UiObject*);
+typedef struct UiActiveMenuItemList UiActiveMenuItemList;
+
+typedef GtkWidget*(*ui_menu_add_f)(GtkWidget *, int, UiMenuItemI*, UiObject*);
     
 struct UiMenuItemI {
     ui_menu_add_f  add_to;
@@ -84,15 +87,34 @@
     char           *varname;
 };
 
+struct UiMenuItemList {
+    UiMenuItemI    item;
+    ui_callback    callback;
+    void           *userdata;
+    UiList         *list;
+};
+
+struct UiActiveMenuItemList {
+    UiObject     *object;
+    GtkMenuShell *menu;
+    int          index;
+    int          oldcount;
+    UiList       *list;
+    ui_callback  callback;
+    void         *userdata;
+};
+
 GtkWidget *ui_create_menubar(UiObject *obj);
 
-void add_menu_widget(GtkWidget *parent, UiMenuItemI *item, UiObject *obj);
-void add_menuitem_widget(GtkWidget *parent, UiMenuItemI *item, UiObject *obj);
-void add_menuitem_st_widget(GtkWidget *p, UiMenuItemI *item, UiObject *obj);
-void add_menuseparator_widget(GtkWidget *p, UiMenuItemI *item, UiObject *obj);
-void add_checkitem_widget(GtkWidget *p, UiMenuItemI *item, UiObject *obj);
-void add_checkitemnv_widget(GtkWidget *p, UiMenuItemI *item, UiObject *obj);
+void add_menu_widget(GtkWidget *parent, int i, UiMenuItemI *item, UiObject *obj);
+void add_menuitem_widget(GtkWidget *parent, int i, UiMenuItemI *item, UiObject *obj);
+void add_menuitem_st_widget(GtkWidget *p, int i, UiMenuItemI *item, UiObject *obj);
+void add_menuseparator_widget(GtkWidget *p, int i, UiMenuItemI *item, UiObject *obj);
+void add_checkitem_widget(GtkWidget *p, int i, UiMenuItemI *item, UiObject *obj);
+void add_checkitemnv_widget(GtkWidget *p, int i, UiMenuItemI *item, UiObject *obj);
+void add_menuitem_list_widget(GtkWidget *p, int i, UiMenuItemI *item, UiObject *obj);
 
+void ui_update_menuitem_list(UiEvent *event, UiActiveMenuItemList *list);
 void ui_menu_event_wrapper(GtkMenuItem *item, UiEventData *event);
 void ui_menu_event_toggled(GtkCheckMenuItem *ci, UiEventData *event);
 int ui_checkitem_get(UiInteger *i);
--- a/ui/gtk/toolkit.h	Tue Apr 01 11:50:32 2014 +0200
+++ b/ui/gtk/toolkit.h	Tue Apr 01 11:53:10 2014 +0200
@@ -41,6 +41,7 @@
     UiObject    *obj;
     ui_callback callback;
     void        *user_data;
+    int         value;
 } UiEventData;
 
 
--- a/ui/ui/toolkit.h	Tue Apr 01 11:50:32 2014 +0200
+++ b/ui/ui/toolkit.h	Tue Apr 01 11:53:10 2014 +0200
@@ -108,6 +108,7 @@
     UiObject *obj;
     void     *document;
     void     *window;
+    void     *eventdata;
     int      intval;
 };
 

mercurial