added document tabview (GTK, Motif)

Tue, 22 Jul 2014 09:51:17 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Tue, 22 Jul 2014 09:51:17 +0200
changeset 52
25e5390cce41
parent 51
42506e19eb6b
child 53
62205699cd0e

added document tabview (GTK, Motif)

application/main.c file | annotate | diff | comparison | revisions
ui/common/context.c file | annotate | diff | comparison | revisions
ui/common/context.h file | annotate | diff | comparison | revisions
ui/common/document.c file | annotate | diff | comparison | revisions
ui/common/document.h file | annotate | diff | comparison | revisions
ui/common/object.c file | annotate | diff | comparison | revisions
ui/gtk/button.c file | annotate | diff | comparison | revisions
ui/gtk/container.c file | annotate | diff | comparison | revisions
ui/gtk/container.h file | annotate | diff | comparison | revisions
ui/gtk/menu.c file | annotate | diff | comparison | revisions
ui/gtk/toolkit.c file | annotate | diff | comparison | revisions
ui/gtk/tree.c file | annotate | diff | comparison | revisions
ui/motif/button.c file | annotate | diff | comparison | revisions
ui/motif/container.c file | annotate | diff | comparison | revisions
ui/motif/container.h file | annotate | diff | comparison | revisions
ui/motif/list.c file | annotate | diff | comparison | revisions
ui/motif/menu.c file | annotate | diff | comparison | revisions
ui/motif/toolkit.c file | annotate | diff | comparison | revisions
ui/motif/tree.c file | annotate | diff | comparison | revisions
ui/ui/toolkit.h file | annotate | diff | comparison | revisions
--- a/application/main.c	Fri Jun 13 10:39:54 2014 +0200
+++ b/application/main.c	Tue Jul 22 09:51:17 2014 +0200
@@ -39,6 +39,10 @@
     char *mail;
 } Person;
 
+typedef struct Document {
+    UiText text;
+} Document;
+
 void action_close(UiEvent *event, void *data) {
     ui_close(event->obj);
 }
@@ -67,6 +71,8 @@
 
 void action_button(UiEvent *event, void *data) {
     printf("button: %d\n", event->intval);
+    char *s = ui_gettext(event->obj, "text");
+    printf("{%s}\n", s);    
 }
 
 int main(int argc, char** argv) { 
@@ -81,7 +87,7 @@
     ui_menuitem_st(UI_STOCK_CLOSE, action_close, NULL);
     ui_checkitem("Check", action_button, NULL);
     
-    ui_toolitem_toggle_st("button", UI_STOCK_GO_BACK, action_button, NULL);
+    ui_toolitem_st("button", UI_STOCK_GO_BACK, action_button, NULL);
     ui_toolbar_add_default("button");
     
     printf("create window\n");
@@ -109,10 +115,26 @@
     ui_list_append(list, p3);
     ui_list_append(list, p4);
     
-    ui_sidebar(window);
-    ui_table(window, list, model);
-    ui_end(window);
-    ui_textarea(window, NULL);
+    //ui_sidebar(window);
+    //ui_table(window, list, model);
+    //ui_end(window);
+    
+    UiTabbedPane *view = ui_tabbed_document_view(window);
+    
+    UiObject *tab1 = ui_document_tab(view);
+    Document *doc1 = ui_document_new(1024);
+    UiContext *ctx1 = ui_document_context(doc1);
+    ui_document_regtext(doc1, "text", &doc1->text);
+    ui_textarea_nv(tab1, "text");
+    ui_set_document(tab1, doc1);
+    
+    
+    UiObject *tab2 = ui_document_tab(view);
+    Document *doc2 = ui_document_new(1024);
+    UiContext *ctx2 = ui_document_context(doc2);
+    ui_document_regtext(doc2, "text", &doc2->text);
+    ui_textarea_nv(tab2, "text");
+    ui_set_document(tab2, doc2);
     
     ui_show(window);
     ui_main();
--- a/ui/common/context.c	Fri Jun 13 10:39:54 2014 +0200
+++ b/ui/common/context.c	Tue Jul 22 09:51:17 2014 +0200
@@ -38,21 +38,104 @@
 
 UiContext* uic_context(UiObject *toplevel, UcxMempool *mp) {
     UiContext *ctx = ucx_mempool_malloc(mp, sizeof(UiContext));
+    ctx->parent = NULL;
     ctx->mempool = mp;
-    
+    ctx->document = NULL;
     ctx->obj = toplevel;
     ctx->vars = ucx_map_new_a(mp->allocator, 16);
     ctx->groups = NULL;
     ctx->group_widgets = NULL;
     
+    ctx->set_document = uic_context_set_document;
+    ctx->detach_document = uic_context_detach_document;
+    
 #ifdef UI_GTK
-    ctx->accel_group = gtk_accel_group_new();
-    gtk_window_add_accel_group(GTK_WINDOW(toplevel->widget), ctx->accel_group);
+    if(toplevel->widget) {
+        ctx->accel_group = gtk_accel_group_new();
+        gtk_window_add_accel_group(GTK_WINDOW(toplevel->widget), ctx->accel_group);
+    }
 #endif
     
     return ctx;
 }
 
+void uic_context_set_document(UiContext *ctx, void *document) {
+    UiContext *docctx = ui_document_context(document);
+    if(!docctx) {
+        return;
+    }
+    docctx->obj = ctx->obj;
+    
+    if(ctx->document) {
+        uic_context_detach_document(ctx, ctx->document);
+    }
+    //obj->document = document;
+    ctx->document = document;
+    
+    UcxMapIterator i = ucx_map_iterator(docctx->vars);
+    UiVar *var;
+    UCX_MAP_FOREACH(key, var, i) {
+        UiVar *v = ucx_map_get(ctx->vars, key);
+        if(v) {
+            if(v->isextern) {
+                fprintf(
+                        stderr,
+                        "UI Error: external variable cannot be moved\n");
+                return;
+            }
+            // check type
+            if(var->type != v->type) {
+                fprintf(stderr, "UI Error: var has incompatible type.\n");
+                return;
+            }
+            
+            // copy value
+            uic_move_var(v, var, 1);
+            var->from = v->from;
+            
+            // TODO: free var struct
+            ucx_map_remove(ctx->vars, key);
+        }
+    }
+}
+
+void uic_context_detach_document(UiContext *ctx, void *document) {
+    UiContext *docctx = ui_document_context(document);
+    if(!docctx) {
+        fprintf(
+                stderr,
+                "UiError: ui_detach_document: document is not registered\n");
+        return;
+    }
+    if(ctx->document != document) {
+        fprintf(stderr, "UiError: ui_detach_document: wrong document\n");
+        return;
+    }
+    
+    UcxMapIterator i = ucx_map_iterator(docctx->vars);
+    UiVar *var;
+    UCX_MAP_FOREACH(key, var, i) {
+        if(var->from && var->from != docctx->vars) {
+            // this var is bind to an outer widget, so we move it          
+            UcxAllocator *a = var->from->allocator;
+            UiVar *newvar = a->malloc(a->pool, sizeof(UiVar));
+            newvar->value = uic_create_value(a, var->type);
+            uic_move_var(var, newvar, 0);
+            newvar->type = var->type;
+            newvar->from = var->from;
+            newvar->isextern = 0;
+            
+            ucx_map_put(var->from, key, newvar);
+            
+            //ucx_map_remove(doc->vars, key); // TODO: dont remove!
+        }
+    }
+    
+    docctx->obj->ctx->document = NULL;
+    
+    docctx->obj = NULL;
+}
+
 UiVar* uic_get_var(UiContext *ctx, char *name) {
     // check document variables first
     UiVar *var = NULL;
@@ -133,7 +216,7 @@
             UiText *t = to->value;
             char *tvalue = t->value;
             memcpy(t, f, sizeof(UiText));
-            if(set) {
+            if(set && tvalue) {
                 t->set(t, tvalue);
             } else {
                 f->value = f->get(f);
@@ -269,6 +352,55 @@
     return 0;
 }
 
+char* ui_getstr(UiObject *obj, char *name) {
+    UiVar *var = uic_get_var(obj->ctx, name);
+    if(var) {
+        if(var->type == UI_VAR_STRING) {
+            UiString *s = var->value;
+            if(s->get) {
+                return s->get(s);
+            } else {
+                fprintf(
+                        stderr,
+                        "UI Error: variable %s is not connected.\n",
+                        name);
+            }
+        } else {
+            fprintf(
+                    stderr,
+                    "UI Error: requested variable %s is not an string.\n",
+                    name);
+        }
+    } else {
+        fprintf(stderr, "UI Error: unkown variable %s.\n", name);
+    }
+    return NULL;
+}
+
+char* ui_gettext(UiObject *obj, char *name) {
+    UiVar *var = uic_get_var(obj->ctx, name);
+    if(var) {
+        if(var->type == UI_VAR_TEXT) {
+            UiText *s = var->value;
+            if(s->get) {
+                return s->get(s);
+            } else {
+                fprintf(
+                        stderr,
+                        "UI Error: variable %s is not connected.\n",
+                        name);
+            }
+        } else {
+            fprintf(
+                    stderr,
+                    "UI Error: requested variable %s is not an string.\n",
+                    name);
+        }
+    } else {
+        fprintf(stderr, "UI Error: unkown variable %s.\n", name);
+    }
+    return NULL;
+}
 
 
 
--- a/ui/common/context.h	Fri Jun 13 10:39:54 2014 +0200
+++ b/ui/common/context.h	Tue Jul 22 09:51:17 2014 +0200
@@ -44,6 +44,7 @@
 typedef struct UiGroupWidget UiGroupWidget;
 
 struct UiContext {
+    UiContext     *parent;
     UiObject      *obj;
     UcxMempool    *mempool;
     UcxMap        *vars; // key: char*  value: UiVar*
@@ -51,6 +52,9 @@
     UcxList       *groups; // int list
     UcxList       *group_widgets; // UiGroupWidget* list
     
+    void (*set_document)(UiContext *ctx, void *document);
+    void (*detach_document)(UiContext *ctx, void *document);
+    
 #ifdef UI_GTK
     GtkAccelGroup *accel_group;
 #endif
@@ -85,6 +89,10 @@
 };
 
 UiContext* uic_context(UiObject *toplevel, UcxMempool *mp);
+
+void uic_context_set_document(UiContext *ctx, void *document);
+void uic_context_detach_document(UiContext *ctx, void *document);
+
 UiVar* uic_get_var(UiContext *ctx, char *name);
 UiVar* uic_connect_var(UiContext *ctx, char *name, int type);
 void uic_move_var(UiVar *from, UiVar *to, int set);
@@ -101,6 +109,7 @@
 void uic_check_group_widgets(UiContext *ctx);
 void uic_add_group_widget(UiContext *ctx, void *widget, UcxList *groups);
 
+
 #ifdef	__cplusplus
 }
 #endif
--- a/ui/common/document.c	Fri Jun 13 10:39:54 2014 +0200
+++ b/ui/common/document.c	Tue Jul 22 09:51:17 2014 +0200
@@ -39,91 +39,48 @@
 }
 
 void ui_set_document(UiObject *obj, void *document) {
-    UiContext *ctx = ucx_map_get(documents, ucx_key(&document, sizeof(void*)));
-    if(!ctx) {
-        return;
-    }
-    ctx->obj = obj;
-    
-    if(obj->document) {
-        ui_detach_document(obj, obj->document);
-    }
-    obj->document = document;
-    obj->ctx->document = document;
-    
-    UcxMapIterator i = ucx_map_iterator(ctx->vars);
-    UiVar *var;
-    UCX_MAP_FOREACH(key, var, i) {
-        UiVar *v = ucx_map_get(obj->ctx->vars, key);
-        if(v) {
-            if(v->isextern) {
-                fprintf(
-                        stderr,
-                        "UI Error: external variable cannot be moved\n");
-                return;
-            }
-            // check type
-            if(var->type != v->type) {
-                fprintf(stderr, "UI Error: var has incompatible type.\n");
-                return;
-            }
-            
-            // copy value
-            uic_move_var(v, var, 1);
-            var->from = v->from;
-            
-            // TODO: free var struct
-            ucx_map_remove(obj->ctx->vars, key);
-        }
-    }
-    
+    obj->ctx->set_document(obj->ctx, document);
 }
 
 void ui_detach_document(UiObject *obj, void *document) {
-    UiContext *ctx = ucx_map_get(documents, ucx_key(&document, sizeof(void*)));
+    obj->ctx->detach_document(obj->ctx, document);
+}
+
+void* ui_get_document(UiObject *obj) {
+    return obj->ctx->document;
+}
+
+void ui_set_subdocument(void *document, void *sub) {
+    UiContext *ctx = ui_document_context(document);
     if(!ctx) {
-        fprintf(
-                stderr,
-                "UiError: ui_detach_document: document is not registered\n");
-        return;
-    }
-    if(obj->document != document) {
-        fprintf(stderr, "UiError: ui_detach_document: wrong document\n");
-        return;
+        fprintf(stderr, "UI Error: pointer is not a document\n");
     }
-    
-    UcxMapIterator i = ucx_map_iterator(ctx->vars);
-    UiVar *var;
-    UCX_MAP_FOREACH(key, var, i) {
-        if(var->from && var->from != ctx->vars) {
-            // this var is bind to an outer widget, so we move it          
-            UcxAllocator *a = var->from->allocator;
-            UiVar *newvar = a->malloc(a->pool, sizeof(UiVar));
-            newvar->value = uic_create_value(a, var->type);
-            uic_move_var(var, newvar, 0);
-            newvar->type = var->type;
-            newvar->from = var->from;
-            newvar->isextern = 0;
-            
-            ucx_map_put(var->from, key, newvar);
-            
-            //ucx_map_remove(doc->vars, key); // TODO: dont remove!
-        }
+    uic_context_set_document(ctx, sub);
+}
+
+void ui_detach_subdocument(void *document, void *sub) {
+    UiContext *ctx = ui_document_context(document);
+    if(!ctx) {
+        fprintf(stderr, "UI Error: pointer is not a document\n");
     }
-    
-    ctx->obj->document = NULL;
-    ctx->obj->ctx->document = NULL;
-    
-    ctx->obj = NULL;
+    uic_context_detach_document(ctx, sub);
+}
+
+void* ui_get_subdocument(void *document) {
+    UiContext *ctx = ui_document_context(document);
+    if(!ctx) {
+        fprintf(stderr, "UI Error: pointer is not a document\n");
+    }
+    return ctx->document;
 }
 
 void* ui_document_new(size_t size) {
     UcxMempool *mp = ucx_mempool_new(256);
-    UiContext *ctx = ucx_mempool_malloc(mp, sizeof(UiContext));
-    ctx->obj = NULL;
+    UiContext *ctx = ucx_mempool_calloc(mp, 1, sizeof(UiContext));
+    ctx->set_document = uic_context_set_document;
+    ctx->detach_document = uic_context_detach_document;
     ctx->mempool = mp;
     ctx->vars = ucx_map_new_a(mp->allocator, 16);
-    //uidoc->subdocument = NULL;
     
     void *document = ucx_mempool_calloc(mp, 1, size);
     ucx_map_put(documents, ucx_key(&document, sizeof(void*)), ctx);
@@ -192,7 +149,7 @@
 void ui_document_regtext(void *doc, char *name, UiText *text) {
     UiContext *ctx = ui_document_context(doc);
     if(ctx) {
-        uic_reg_var(doc, name, UI_VAR_TEXT, sizeof(UiText), text);
+        uic_reg_var(ctx, name, UI_VAR_TEXT, sizeof(UiText), text);
     }
 }
 
@@ -203,6 +160,6 @@
         UiListPtr *lp = ui_document_malloc(doc, sizeof(UiListPtr));
         lv->listptr = lp;
         lp->list = list;
-        uic_reg_var(doc, name, UI_VAR_LIST, sizeof(UiListPtr), lv);
+        uic_reg_var(ctx, name, UI_VAR_LIST, sizeof(UiListPtr), lv);
     }
 }
--- a/ui/common/document.h	Fri Jun 13 10:39:54 2014 +0200
+++ b/ui/common/document.h	Tue Jul 22 09:51:17 2014 +0200
@@ -40,7 +40,6 @@
 void uic_document_addvar(void *doc, char *name, int type, size_t vs);
 
 
-
 #ifdef	__cplusplus
 }
 #endif
--- a/ui/common/object.c	Fri Jun 13 10:39:54 2014 +0200
+++ b/ui/common/object.c	Tue Jul 22 09:51:17 2014 +0200
@@ -66,6 +66,9 @@
 }
 
 UiObject* uic_current_obj(UiObject *toplevel) {
+    if(!toplevel) {
+        return NULL;
+    }
     UiObject *obj = toplevel;
     while(obj->next) {
         obj = obj->next;
--- a/ui/gtk/button.c	Fri Jun 13 10:39:54 2014 +0200
+++ b/ui/gtk/button.c	Tue Jul 22 09:51:17 2014 +0200
@@ -70,7 +70,7 @@
     UiEvent e;
     e.obj = event->obj;
     e.window = event->obj->window;
-    e.document = event->obj->document;
+    e.document = event->obj->ctx->document;
     e.eventdata = NULL;
     e.intval = event->value;
     event->callback(&e, event->userdata);
@@ -80,7 +80,7 @@
     UiEvent e;
     e.obj = event->obj;
     e.window = event->obj->window;
-    e.document = event->obj->document;
+    e.document = event->obj->ctx->document;
     e.eventdata = NULL;
     e.intval = gtk_toggle_tool_button_get_active(widget);
     event->callback(&e, event->userdata);
--- a/ui/gtk/container.c	Fri Jun 13 10:39:54 2014 +0200
+++ b/ui/gtk/container.c	Tue Jul 22 09:51:17 2014 +0200
@@ -101,3 +101,74 @@
 void ui_box_add(UiContainer *ct, GtkWidget *widget) {
     gtk_box_pack_start(GTK_BOX(ct->widget), widget, TRUE, TRUE, 0);
 }
+
+
+
+
+static void page_change(GtkNotebook *notebook, GtkWidget *page, guint page_num, gpointer data) {
+    GQuark q = g_quark_from_static_string("ui.tab.object");
+    UiObject *tab = g_object_get_qdata(G_OBJECT(page), q);
+    if(!tab) {
+        return;
+    }
+    
+    printf("page_change: %d\n", page_num);
+    UiContext *ctx = tab->ctx;
+    ctx->parent->set_document(ctx->parent, ctx->document);
+}
+
+UiTabbedPane* ui_tabbed_document_view(UiObject *obj) {
+    GtkWidget *tabview = gtk_notebook_new();
+    gtk_notebook_set_show_border(GTK_NOTEBOOK(tabview), FALSE);
+    
+    g_signal_connect(
+                tabview,
+                "switch-page",
+                G_CALLBACK(page_change),
+                NULL);
+    
+    UiContainer *ct = uic_get_current_container(obj);
+    ct->add(ct, tabview);
+    
+    UiTabbedPane *tabbedpane = ui_malloc(obj->ctx, sizeof(UiTabbedPane));
+    tabbedpane->ctx = uic_current_obj(obj)->ctx;
+    tabbedpane->widget = tabview;
+    tabbedpane->document = NULL;
+    
+    return tabbedpane;
+}
+
+UiObject* ui_document_tab(UiTabbedPane *view) {
+    GtkWidget *frame = gtk_alignment_new(0.5, 0.5, 1, 1);
+    // TODO: label
+    gtk_notebook_append_page(GTK_NOTEBOOK(view->widget), frame, NULL);
+    
+    UiObject *tab = ui_malloc(view->ctx, sizeof(UiObject));
+    tab->widget = NULL; // initialization for uic_context()
+    tab->ctx = uic_context(tab, view->ctx->mempool);
+    tab->ctx->parent = view->ctx;
+    tab->ctx->set_document = ui_tab_set_document;
+    tab->ctx->detach_document = ui_tab_detach_document;
+    tab->widget = frame;
+    tab->window = view->ctx->obj->window;
+    tab->container = ui_frame_container(tab, frame);
+    tab->next = NULL;
+    
+    GQuark q = g_quark_from_static_string("ui.tab.object");
+    g_object_set_qdata(G_OBJECT(frame), q, tab);
+    
+    return tab;
+}
+
+void ui_tab_set_document(UiContext *ctx, void *document) {
+    if(ctx->parent->document) {
+        //ctx->parent->detach_document(ctx->parent, ctx->parent->document);
+    }
+    uic_context_set_document(ctx, document);
+    //uic_context_set_document(ctx->parent, document);
+    //ctx->parent->document = document;
+}
+
+void ui_tab_detach_document(UiContext *ctx, void *document) {
+    uic_context_detach_document(ctx->parent, document);
+}
--- a/ui/gtk/container.h	Fri Jun 13 10:39:54 2014 +0200
+++ b/ui/gtk/container.h	Tue Jul 22 09:51:17 2014 +0200
@@ -37,6 +37,8 @@
 
 typedef void (*ui_container_add_f)(UiContainer*, GtkWidget*);
 
+typedef struct UiDocumentView UiDocumentView;
+
 struct UiContainer {
     GtkWidget *widget;
     void (*add)(UiContainer*, GtkWidget*);
@@ -50,6 +52,11 @@
 
 void ui_box_add(UiContainer *ct, GtkWidget *widget);
 
+
+UiObject* ui_add_document_tab(UiDocumentView *view);
+void ui_tab_set_document(UiContext *ctx, void *document);
+void ui_tab_detach_document(UiContext *ctx, void *document);
+
 #ifdef	__cplusplus
 }
 #endif
--- a/ui/gtk/menu.c	Fri Jun 13 10:39:54 2014 +0200
+++ b/ui/gtk/menu.c	Tue Jul 22 09:51:17 2014 +0200
@@ -440,7 +440,7 @@
     UiEvent evt;
     evt.obj = event->obj;
     evt.window = event->obj->window;
-    evt.document = event->obj->document;
+    evt.document = event->obj->ctx->document;
     evt.eventdata = NULL;
     evt.intval = event->value;
     event->callback(&evt, event->userdata);    
@@ -450,7 +450,7 @@
     UiEvent evt;
     evt.obj = event->obj;
     evt.window = event->obj->window;
-    evt.document = event->obj->document;
+    evt.document = event->obj->ctx->document;
     evt.eventdata = NULL;
     evt.intval = gtk_check_menu_item_get_active(ci);
     event->callback(&evt, event->userdata);    
--- a/ui/gtk/toolkit.c	Fri Jun 13 10:39:54 2014 +0200
+++ b/ui/gtk/toolkit.c	Tue Jul 22 09:51:17 2014 +0200
@@ -98,7 +98,7 @@
     UiEvent event;
     event.obj = job->obj;
     event.window = job->obj->window;
-    event.document = job->obj->document;
+    event.document = job->obj->ctx->document;
     event.intval = 0;
     event.eventdata = NULL;
 
--- a/ui/gtk/tree.c	Fri Jun 13 10:39:54 2014 +0200
+++ b/ui/gtk/tree.c	Tue Jul 22 09:51:17 2014 +0200
@@ -239,7 +239,7 @@
     UiEvent e;
     e.obj = event->obj;
     e.window = event->obj->window;
-    e.document = event->obj->document;
+    e.document = event->obj->ctx->document;
     e.eventdata = selection;
     e.intval = selection->count > 0 ? selection->rows[0] : -1;
     event->activate(&e, event->userdata);
@@ -256,7 +256,7 @@
     UiEvent e;
     e.obj = event->obj;
     e.window = event->obj->window;
-    e.document = event->obj->document;
+    e.document = event->obj->ctx->document;
     e.eventdata = selection;
     e.intval = selection->count > 0 ? selection->rows[0] : -1;
     event->selection(&e, event->userdata);
--- a/ui/motif/button.c	Fri Jun 13 10:39:54 2014 +0200
+++ b/ui/motif/button.c	Tue Jul 22 09:51:17 2014 +0200
@@ -99,7 +99,7 @@
     UiEvent e;
     e.obj = event->obj;
     e.window = event->obj->window;
-    e.document = event->obj->document;
+    e.document = event->obj->ctx->document;
     e.intval = event->value;
     event->callback(&e, event->user_data);
 }
--- a/ui/motif/container.c	Fri Jun 13 10:39:54 2014 +0200
+++ b/ui/motif/container.c	Tue Jul 22 09:51:17 2014 +0200
@@ -81,3 +81,143 @@
     
     return sidebar;
 }
+
+UiTabbedPane* ui_tabbed_document_view(UiObject *obj) {
+    int n = 0;
+    Arg args[16];
+    
+    UiContainer *ct = uic_get_current_container(obj);
+    Widget parent = ct->add(ct, args, &n);
+    
+    Widget tabview = XmCreateForm(parent, "tabview_form", args, n);
+    XtManageChild(tabview);
+    
+    XtSetArg(args[0], XmNorientation, XmHORIZONTAL);
+    XtSetArg(args[1], XmNpacking, XmPACK_TIGHT);
+    XtSetArg(args[2], XmNspacing, 1);
+    XtSetArg(args[3], XmNleftAttachment, XmATTACH_FORM);
+    XtSetArg(args[4], XmNrightAttachment, XmATTACH_FORM);
+    XtSetArg(args[5], XmNtopAttachment, XmATTACH_FORM);
+    Widget tabbar = XmCreateRowColumn(tabview, "toolbar", args, 6);
+    XtManageChild(tabbar);
+    
+    XtSetArg(args[0], XmNleftAttachment, XmATTACH_FORM);
+    XtSetArg(args[1], XmNrightAttachment, XmATTACH_FORM);
+    XtSetArg(args[2], XmNtopAttachment, XmATTACH_WIDGET);
+    XtSetArg(args[3], XmNtopWidget, tabbar);
+    XtSetArg(args[4], XmNbottomAttachment, XmATTACH_FORM);
+    XtSetArg(args[5], XmNshadowThickness, 0);
+    Widget tabct = XmCreateForm(tabview, "tabview", args, 6);
+    XtManageChild(tabct);
+    
+    MotifTabbedPane *tabbedpane = ui_malloc(obj->ctx, sizeof(MotifTabbedPane));
+    tabbedpane->view.ctx = uic_current_obj(obj)->ctx;
+    tabbedpane->view.widget = tabct;
+    tabbedpane->view.document = NULL;
+    tabbedpane->tabbar = tabbar;
+    //tabbedpane->form = tabview;
+    tabbedpane->tabs = NULL;
+    tabbedpane->current = NULL;
+    
+    return &tabbedpane->view;
+}
+
+UiObject* ui_document_tab(UiTabbedPane *view) {
+    MotifTabbedPane *v = (MotifTabbedPane*)view;
+    int n = 0;
+    Arg args[16];
+    
+    // hide the current tab content
+    if(v->current) {
+        XtUnmanageChild(v->current->content->widget);
+    }
+    
+    UiTab *tab = ui_malloc(view->ctx, sizeof(UiTab));
+    
+    // create the new tab content
+    XtSetArg(args[0], XmNshadowThickness, 0);
+    XtSetArg(args[1], XmNleftAttachment, XmATTACH_FORM);
+    XtSetArg(args[2], XmNrightAttachment, XmATTACH_FORM);
+    XtSetArg(args[3], XmNtopAttachment, XmATTACH_FORM);
+    XtSetArg(args[4], XmNbottomAttachment, XmATTACH_FORM);
+    XtSetArg(args[5], XmNuserData, tab);
+    Widget frame = XmCreateFrame(view->widget, "tab", args, 6);
+    XtManageChild(frame);
+    
+    UiObject *content = ui_malloc(view->ctx, sizeof(UiObject));
+    content->widget = NULL; // initialization for uic_context()
+    content->ctx = uic_context(content, view->ctx->mempool);
+    content->ctx->parent = view->ctx;
+    content->ctx->set_document = ui_tab_set_document;
+    content->ctx->detach_document = ui_tab_detach_document;
+    content->widget = frame;
+    content->window = view->ctx->obj->window;
+    content->container = ui_frame_container(content, frame);
+    content->next = NULL;
+    
+    // add tab button 
+    XmString label = XmStringCreateLocalized("tab");
+    XtSetArg(args[0], XmNlabelString, label);
+    XtSetArg(args[1], XmNshadowThickness, 1);
+    XtSetArg(args[2], XmNtraversalOn, FALSE);
+    Widget button = XmCreatePushButton(v->tabbar, "tab_button", args, 3);
+    XtManageChild(button);
+    XtAddCallback(
+        button,
+        XmNactivateCallback,
+        (XtCallbackProc)ui_tab_button_callback,
+        tab);
+    
+    tab->tabbedpane = v;
+    tab->content = content;
+    tab->tab_button = button;
+    
+    v->tabs = ucx_list_append_a(view->ctx->mempool->allocator, v->tabs, tab);
+    v->current = tab;
+    ui_change_tab(v, tab);
+    
+    return content;
+}
+
+void ui_tab_button_callback(Widget widget, UiTab *tab, XtPointer d) {
+    MotifTabbedPane *t = tab->tabbedpane;
+    if(t->current) {
+        XtUnmanageChild(t->current->content->widget);
+    }
+    XtManageChild(tab->content->widget);
+    
+    t->current = tab;
+    ui_change_tab(t, tab);
+}
+
+void ui_change_tab(MotifTabbedPane *pane, UiTab *tab) {
+    UiContext *ctx = tab->content->ctx;
+    ctx->parent->set_document(ctx->parent, ctx->document);
+}
+
+void ui_tab_set_document(UiContext *ctx, void *document) {
+    if(ctx->parent->document) {
+        //ctx->parent->detach_document(ctx->parent, ctx->parent->document);
+    }
+    uic_context_set_document(ctx, document);
+    //uic_context_set_document(ctx->parent, document);
+    //ctx->parent->document = document;
+    
+    UiTab *tab = NULL;
+    XtVaGetValues(
+            ctx->obj->widget,
+            XmNuserData,
+            &tab,
+            NULL);
+    if(tab) {
+        if(tab->tabbedpane->current == tab) {
+            ctx->parent->set_document(ctx->parent, ctx->document);
+        }
+    } else {
+        fprintf(stderr, "UiError: ui_bar_set_document: Cannot set document");
+    }
+}
+
+void ui_tab_detach_document(UiContext *ctx, void *document) {
+    uic_context_detach_document(ctx->parent, document);
+}
--- a/ui/motif/container.h	Fri Jun 13 10:39:54 2014 +0200
+++ b/ui/motif/container.h	Tue Jul 22 09:51:17 2014 +0200
@@ -30,22 +30,43 @@
 #define	CONTAINER_H
 
 #include "../ui/toolkit.h"
+#include <ucx/list.h>
 
 #ifdef	__cplusplus
 extern "C" {
 #endif
 
+typedef struct MotifTabbedPane MotifTabbedPane;
+typedef struct UiTab           UiTab;
+
 typedef Widget (*ui_container_add_f)(UiContainer*, Arg*, int*);
 
 struct UiContainer {
     Widget widget;
     Widget (*add)(UiContainer*, Arg *, int*);
 };
+
+struct MotifTabbedPane {
+    UiTabbedPane view;
+    Widget       tabbar;
+    UcxList      *tabs;
+    UiTab        *current;
+};
+
+struct UiTab {
+    MotifTabbedPane *tabbedpane;
+    UiObject        *content;
+    Widget          tab_button;
+};
     
 
 UiContainer* ui_frame_container(UiObject *obj, Widget frame);
 Widget ui_frame_container_add(UiContainer *ct, Arg *args, int *n);
+void ui_tab_button_callback(Widget widget, UiTab *tab, XtPointer d);
+void ui_change_tab(MotifTabbedPane *pane, UiTab *tab);
 
+void ui_tab_set_document(UiContext *ctx, void *document);
+void ui_tab_detach_document(UiContext *ctx, void *document);
 
 
 #ifdef	__cplusplus
--- a/ui/motif/list.c	Fri Jun 13 10:39:54 2014 +0200
+++ b/ui/motif/list.c	Tue Jul 22 09:51:17 2014 +0200
@@ -154,7 +154,7 @@
     UiEvent e;
     e.obj = event->event.obj;
     e.window = event->event.obj->window;
-    e.document = event->event.obj->document;
+    e.document = event->event.obj->ctx->document;
     e.eventdata = event->list->list->get(event->list->list, cbs->item_position - 1);
     e.intval = cbs->item_position - 1;
     event->event.callback(&e, event->event.user_data);
--- a/ui/motif/menu.c	Fri Jun 13 10:39:54 2014 +0200
+++ b/ui/motif/menu.c	Tue Jul 22 09:51:17 2014 +0200
@@ -521,7 +521,7 @@
     UiEvent e;
     e.obj = event->obj;
     e.window = event->obj->window;
-    e.document = event->obj->document;
+    e.document = event->obj->ctx->document;
     e.intval = 0;
     event->callback(&e, event->user_data);    
 }
--- a/ui/motif/toolkit.c	Fri Jun 13 10:39:54 2014 +0200
+++ b/ui/motif/toolkit.c	Tue Jul 22 09:51:17 2014 +0200
@@ -180,7 +180,7 @@
     UiEvent event;
     event.obj = job->obj;
     event.window = job->obj->window;
-    event.document = job->obj->document;
+    event.document = job->obj->ctx->document;
     event.intval = 0;
     event.eventdata = NULL;
 
--- a/ui/motif/tree.c	Fri Jun 13 10:39:54 2014 +0200
+++ b/ui/motif/tree.c	Tue Jul 22 09:51:17 2014 +0200
@@ -35,6 +35,7 @@
 
 #include "container.h"
 #include "../common/object.h"
+#include "../common/context.h"
 #include "../../ucx/utils.h"
 
 UIWIDGET ui_table(UiObject *obj, UiList *model, UiModelInfo *modelinfo) {
@@ -218,7 +219,7 @@
     UiEvent e;
     e.obj = event->obj;
     e.window = event->obj->window;
-    e.document = event->obj->document;
+    e.document = event->obj->ctx->document;
     e.eventdata = selection;
     e.intval = selection->count > 0 ? selection->rows[0] : -1;
     event->activate(&e, event->userdata);
@@ -238,7 +239,7 @@
         UiEvent e;
         e.obj = event->obj;
         e.window = event->obj->window;
-        e.document = event->obj->document;
+        e.document = event->obj->ctx->document;
         e.eventdata = selection;
         e.intval = selection->count > 0 ? selection->rows[0] : -1;
         event->selection(&e, event->userdata);
--- a/ui/ui/toolkit.h	Fri Jun 13 10:39:54 2014 +0200
+++ b/ui/ui/toolkit.h	Tue Jul 22 09:51:17 2014 +0200
@@ -80,6 +80,8 @@
 typedef struct UiContext   UiContext;
 typedef struct UiContainer UiContainer;
 
+typedef struct UiTabbedPane UiTabbedPane;
+
 #define ui_getval(val) (val).get(&(val))
 #define ui_setval(val, v) (val).set(&(val), v)
 
@@ -110,7 +112,7 @@
     /*
      * current document
      */
-    void        *document;
+    //void        *document;
     
     /*
      * window context (private)
@@ -128,6 +130,23 @@
     UiObject    *next;
 };
 
+struct UiTabbedPane {
+    /*
+     * native widget
+     */
+    UIWIDGET  widget;
+    
+    /*
+     * current document
+     */
+    void      *document;
+    
+    /*
+     * parent context
+     */
+    UiContext *ctx;
+};
+
 struct UiEvent {
     UiObject *obj;
     void     *document;
@@ -212,8 +231,22 @@
 UIWIDGET ui_sidebar(UiObject *obj);
 void ui_end(UiObject *obj);
 
+
+
+
+UiTabbedPane* ui_tabbed_document_view(UiObject *obj);
+
+UiObject* ui_document_tab(UiTabbedPane *view);
+
+
+
+
 void ui_set_document(UiObject *obj, void *document);
 void ui_detach_document(UiObject *obj, void *document);
+void* ui_get_document(UiObject *obj);
+void ui_set_subdocument(void *document, void *sub);
+void ui_detach_subdocument(void *document, void *sub);
+void* ui_get_subdocument(void *document);
 
 void* ui_document_new(size_t size);
 void  ui_document_destroy(void *doc);
@@ -237,6 +270,8 @@
 
 // new:
 int ui_getint(UiObject *obj, char *name);
+char *ui_getstr(UiObject *obj, char *name);
+char* ui_gettext(UiObject *obj, char *name);
 
 
 void ui_set_group(UiContext *ctx, int group);

mercurial