added table view (Motif)

Thu, 15 May 2014 20:06:28 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Thu, 15 May 2014 20:06:28 +0200
changeset 39
4e66271541e8
parent 38
8ccdde37275b
child 40
caa0df8ed095

added table view (Motif)

application/main.c file | annotate | diff | comparison | revisions
ui/common/context.c file | annotate | diff | comparison | revisions
ui/common/types.c file | annotate | diff | comparison | revisions
ui/motif/objs.mk file | annotate | diff | comparison | revisions
ui/motif/toolbar.c file | annotate | diff | comparison | revisions
ui/motif/tree.c file | annotate | diff | comparison | revisions
ui/motif/tree.h file | annotate | diff | comparison | revisions
ui/ui/tree.h file | annotate | diff | comparison | revisions
--- a/application/main.c	Thu May 15 17:17:58 2014 +0200
+++ b/application/main.c	Thu May 15 20:06:28 2014 +0200
@@ -33,206 +33,60 @@
 #include <ucx/buffer.h>
 #include <ucx/utils.h>
 
-typedef struct TestDocument {
-    UiInteger check1;
-} TestDocument;
 
-typedef struct TestWindowData {
-    TestDocument *doc1;
-    TestDocument *doc2;
-    UiText       text;
-} TestWindowData;
-
-UiInteger check1;
-
-UiList *list;
-
-///*
-
-void action_new(UiEvent *event, void *data) {
-    UiObject *window = ui_window("Mod1", NULL);
-    //ui_window_addint(window, "check1");
-    ui_show(window);
-    if(event->eventdata)  {
-        printf("%s\n", event->eventdata);
-    }
-}
-
-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;
-    TestWindowData *wd = event->window;
-    printf("check1: %s\n", ui_getval(doc->check1) ? "true" : "false");
-    
-    char *path = ui_openfiledialog(event->obj);
-    if(path) {
-        UcxBuffer *buf = ucx_buffer_new(NULL, 4096, UCX_BUFFER_AUTOEXTEND);
-        FILE *file = fopen(path, "r");
-        if(file) {
-            ucx_stream_hcopy(file, buf, fread, ucx_buffer_write);
-            ucx_buffer_putc(buf, '\0');
-            ui_setval(wd->text, buf->space);
-            fclose(file);
-        }
-        ucx_buffer_free(buf);
-    }
-}
-
-void action_save(UiEvent *event, void *data) {
-    TestWindowData *wd = event->window;
-    printf("Text: {%s}\n", ui_getval(wd->text));
-    ui_setval(wd->text, uistr("hello"));
-    
-    ui_list_append(list, "abc");
-    ui_notify(list->observers, NULL);
-}
+typedef struct Person {
+    char *name;
+    char *mail;
+} Person;
 
 void action_close(UiEvent *event, void *data) {
-    exit(0);
+    ui_close(event->obj);
 }
 
-void action_doc1(UiEvent *event, void *data) {
-    TestWindowData *wdata = event->window;
-    if(event->obj->document != wdata->doc1) {
-        ui_set_document(event->obj, wdata->doc1);
-    }
-    ui_unset_group(event->obj->ctx, 1);
-}
-
-void action_doc2(UiEvent *event, void *data) {
-    TestWindowData *wdata = event->window;
-    if(event->obj->document != wdata->doc2) {
-        ui_set_document(event->obj, wdata->doc2);
+char* person_getvalue(Person *p, int column) {
+    switch(column) {
+        case 0: return p->name;
+        case 1: return p->mail;
     }
-    ui_set_group(event->obj->ctx, 1);
-}
-
-void action_undo(UiEvent *event, void *data) {
-    printf("undo\n");
-    TestWindowData *wd = event->window;
-    ui_text_undo(&wd->text);
-}
-
-void action_redo(UiEvent *event, void *data) {
-    printf("redo\n");
-    TestWindowData *wd = event->window;
-    ui_text_redo(&wd->text);
-}
-
-void action_document(UiEvent *event, void *data) {
-    UiList *documents = data;
-    printf("selected document: %d\n", event->intval);
+    return NULL;
 }
 
-void action_cut(UiEvent *event, void *data) {
-    printf("cut\n");
-}
-
-void action_copy(UiEvent *event, void *data) {
-    printf("copy\n");
-    TestWindowData *wd = event->window;
-    int begin;
-    int end;
-    wd->text.selection(&wd->text, &begin, &end);
-    char *selection = wd->text.getsubstr(&wd->text, begin, end);
-    ui_clipboard_set(selection);
-}
-
-void action_paste(UiEvent *event, void *data) {
-    printf("paste\n");
-    TestWindowData *wd = event->window;
-    char *str = ui_clipboard_get();
-    if(str) {
-        int pos = wd->text.position(&wd->text);
-        wd->text.insert(&wd->text, pos, str);
-        free(str);
-    }
-}
-
-void action_delete(UiEvent *event, void *data) {
-    printf("delete\n");
-}
-
-//*/
-
 int main(int argc, char** argv) { 
     ui_init("app1", argc, argv);
     ui_locales_dir("/opt/app1/locales");
     ui_load_lang_def(NULL, "en_EN");
     //ui_openfilefunc(action_new, NULL);
     
-    ///*
-    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_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);
-    
-    ui_menuseparator();
-    
-    ui_checkitem_nv("Check", "check1");
-    //ui_checkitem("Check", action_open, NULL);
-    
-    void ui_menuseparator();
-    ui_menuitem_list(list, action_document, list);
-    ui_menuseparator();
-    ui_menuitem_st(UI_STOCK_CLOSE, action_close, NULL);
-    
-    ui_menu("Edit");
-    ui_menuitem_stgr(UI_STOCK_CUT, action_cut, NULL, UI_GROUP_SELECTION, -1);
-    ui_menuitem_stgr(UI_STOCK_COPY, action_copy, NULL, UI_GROUP_SELECTION, -1);
-    ui_menuitem_st(UI_STOCK_PASTE, action_paste, NULL);
-    ui_menuitem_stgr(UI_STOCK_DELETE, action_delete, NULL, UI_GROUP_SELECTION, -1);
     
     
-    ui_toolitem_st("new", UI_STOCK_NEW, action_new, NULL);
-    ui_toolitem_st("open", UI_STOCK_GO_BACK, action_open, NULL);
-    ui_toolitem_stgr("save", UI_STOCK_GO_FORWARD, action_save, NULL, 1, -1);
-    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);
-    
-    ui_toolbar_add_default("new");
-    ui_toolbar_add_default("open");
-    ui_toolbar_add_default("save");
-    ui_toolbar_add_default("close");
-    ui_toolbar_add_default("undo");
-    ui_toolbar_add_default("redo");
-    //*/
-    
-    //ui_menu("File");
-    //ui_menuitem("New", NULL, NULL);
-    //ui_menuitem("Close", NULL, NULL);
-    //ui_menu("Edit");
-    //ui_menuitem("Preferences", NULL, NULL);
+    ui_menu("File");
+    ui_menuitem_st(UI_STOCK_CLOSE, action_close, NULL);
     
     printf("create window\n");
-    UiObject *window = ui_window("Mod0", NULL);  
-    TestWindowData *wdata = calloc(1, sizeof(TestWindowData));
-    window->window = wdata;
+    UiObject *window = ui_window("Mod0", NULL);
     
-    TestDocument *doc1 = ui_document_new(sizeof(TestDocument));
-    TestDocument *doc2 = ui_document_new(sizeof(TestDocument));
-    ui_document_regint(doc1, "check1", &doc1->check1);
-    ui_document_regint(doc2, "check1", &doc2->check1);
-    wdata->doc1 = doc1;
-    wdata->doc2 = doc2;
+    UiModelInfo *model = ui_model_info(window->ctx, UI_STRING, "Name", UI_STRING, "Email", -1);
+    model->getvalue = (ui_model_getvalue_f)person_getvalue;
+    UiList *list = ui_list_new();
+    Person *p1 = ui_malloc(window->ctx, sizeof(Person));
+    Person *p2 = ui_malloc(window->ctx, sizeof(Person));
+    Person *p3 = ui_malloc(window->ctx, sizeof(Person));
+    Person *p4 = ui_malloc(window->ctx, sizeof(Person));
+    p1->name = "Some Name";
+    p1->mail = "mail@host.com";
+    p2->name = "Other Person";
+    p2->mail = "other.person@provider.com";
+    p3->name = "My Self";
+    p3->mail = "my@self.org";
+    p4->name = "Gregory House";
+    p4->mail = "greg@pp";
+    ui_list_append(list, p1);
+    ui_list_append(list, p2);
+    ui_list_append(list, p3);
+    ui_list_append(list, p4);
+    ui_table(window, list, model);
     
-    ui_set_document(window, doc1);
     
-    //ui_button(window, "OK", action_open, NULL);
-    ui_textarea(window, &wdata->text);
-    
-    //ui_window_addint(window, "check1");
     ui_show(window);
     ui_main();
     
--- a/ui/common/context.c	Thu May 15 17:17:58 2014 +0200
+++ b/ui/common/context.c	Thu May 15 20:06:28 2014 +0200
@@ -368,4 +368,5 @@
 
 void* ui_realloc(UiContext *ctx, void *ptr, size_t size) {
     return ctx ? ucx_mempool_realloc(ctx->mempool, ptr, size) : NULL;
-}
\ No newline at end of file
+}
+
--- a/ui/common/types.c	Thu May 15 17:17:58 2014 +0200
+++ b/ui/common/types.c	Thu May 15 20:06:28 2014 +0200
@@ -28,9 +28,12 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdarg.h>
 
 #include "../../ucx/list.h"
+#include "../ui/tree.h"
 #include "types.h"
+#include "context.h"
 
 UiObserver* ui_observer_new(ui_callback f, void *data) {
     UiObserver *observer = malloc(sizeof(UiObserver));
@@ -146,3 +149,53 @@
 void ui_list_notify(UiList *list) {
     ui_notify(list->observers, list);
 }
+
+
+typedef struct {
+    int  type;
+    char *name;
+} UiColumn;
+
+UiModelInfo* ui_model_info(UiContext *ctx, ...) {
+    UiModelInfo *info = ui_calloc(ctx, 1, sizeof(UiModelInfo));
+    
+    va_list ap;
+    va_start(ap, ctx);
+    
+    UcxList *cols = NULL;
+    int type;
+    while((type = va_arg(ap, int)) != -1) {
+        char *name = va_arg(ap, char*);
+        
+        UiColumn *column = malloc(sizeof(UiColumn));
+        column->type = type;
+        column->name = name;
+        
+        cols = ucx_list_append(cols, column);
+    }
+    
+    va_end(ap);
+    
+    size_t len = ucx_list_size(cols);
+    info->columns = len;
+    info->types = ui_calloc(ctx, len, sizeof(UiModelType));
+    info->titles = ui_calloc(ctx, len, sizeof(char*));
+    
+    int i = 0;
+    UCX_FOREACH(elm, cols) {
+        UiColumn *c = elm->data;
+        info->types[i] = c->type;
+        info->titles[i] = c->name;
+        free(c);
+        i++;
+    }
+    ucx_list_free(cols);
+    
+    return info;
+}
+
+void ui_model_info_free(UiContext *ctx, UiModelInfo *mi) {
+    ucx_mempool_free(ctx->mempool, mi->types);
+    ucx_mempool_free(ctx->mempool, mi->titles);
+    ucx_mempool_free(ctx->mempool, mi);
+}
--- a/ui/motif/objs.mk	Thu May 15 17:17:58 2014 +0200
+++ b/ui/motif/objs.mk	Thu May 15 20:06:28 2014 +0200
@@ -38,6 +38,7 @@
 MOTIFOBJ += button.o
 MOTIFOBJ += text.o
 MOTIFOBJ += list.o
+MOTIFOBJ += tree.o
 
 TOOLKITOBJS = $(MOTIFOBJ:%=$(MOTIF_OBJPRE)%)
 TOOLKITSOURCE = $(MOTIFOBJ:%.o=motif/%.c)
--- a/ui/motif/toolbar.c	Thu May 15 17:17:58 2014 +0200
+++ b/ui/motif/toolbar.c	Thu May 15 20:06:28 2014 +0200
@@ -218,16 +218,16 @@
 }
 
 void add_toolitem_st_widget(Widget parent, UiStToolItem *item, UiObject *obj) {
-    Arg args[4];
+    Arg args[8];
     
     UiStockItem *stock_item = ui_get_stock_item(item->stockid);
-    
+     
     XmString label = XmStringCreateLocalized(stock_item->label);
     XtSetArg(args[0], XmNlabelString, label);
     XtSetArg(args[1], XmNshadowThickness, 1);
     XtSetArg(args[2], XmNtraversalOn, FALSE);
     Widget button = XmCreatePushButton(parent, "toolbar_button", args, 3);
-    
+ 
     XmStringFree(label);
     
     if(item->callback) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/motif/tree.c	Thu May 15 20:06:28 2014 +0200
@@ -0,0 +1,150 @@
+/*
+ * 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 <string.h>
+
+#include "tree.h"
+
+#include "container.h"
+#include "../common/object.h"
+#include "../../ucx/utils.h"
+
+UIWIDGET ui_table(UiObject *obj, UiList *model, UiModelInfo *modelinfo) {
+    // TODO: check if modelinfo is complete
+    
+    Arg args[16];
+    int n = 0;
+    
+    // create table headers
+    XmStringTable header = (XmStringTable)XtMalloc(
+            modelinfo->columns * sizeof(XmString));
+    for(int i=0;i<modelinfo->columns;i++) {
+        header[i] = XmStringCreateLocalized(modelinfo->titles[i]);
+    }
+    XtSetArg(args[n], XmNdetailColumnHeading, header);
+    n++;
+    XtSetArg(args[n], XmNdetailColumnHeadingCount, modelinfo->columns);
+    n++;
+    
+    // set res
+    XtSetArg(args[n], XmNlayoutType, XmDETAIL);
+    n++;
+    XtSetArg(args[n], XmNentryViewType, XmSMALL_ICON);
+    n++;
+    XtSetArg(args[n], XmNselectionPolicy, XmSINGLE_SELECT);
+    n++;
+    
+    // create widget
+    UiContainer *ct = uic_get_current_container(obj);
+    Widget parent = ct->add(ct, args, &n);
+    
+    Widget container = XmCreateContainer(parent, "table", args, n);
+    XtManageChild(container);
+    
+    // add initial data
+    void *data = model->first(model);
+    while(data) {
+        ui_add_icon_gadget(container, modelinfo, data);
+        data = model->next(model);
+    }
+    
+    // cleanup
+    for(int i=0;i<modelinfo->columns;i++) {
+        XmStringFree(header[i]);
+    }
+    XtFree((char*)header);
+    
+    return container;
+}
+
+void ui_add_icon_gadget(Widget container, UiModelInfo *modelinfo, void *data) {
+    if(modelinfo->columns == 0) {
+        return;
+    }
+    
+    XmString label = NULL;
+    Arg args[8];
+    Boolean f;
+    // first column
+    if(modelinfo->types[0] != 12345678) { // TODO: icon/label type
+        char *str = ui_type_to_string(
+                modelinfo->types[0],
+                modelinfo->getvalue(data, 0),
+                &f);
+        XmString label = XmStringCreateLocalized(str);
+        XtSetArg(args[0], XmNlabelString, label);
+        if(f) {
+            free(str);
+        }
+    } else {
+        // TODO
+    }
+            
+    // remaining columns are the icon gadget details
+    XmStringTable details = (XmStringTable)XtMalloc(
+            (modelinfo->columns - 1) * sizeof(XmString));
+    for(int i=1;i<modelinfo->columns;i++) {
+        char *str = ui_type_to_string(
+                modelinfo->types[i],
+                modelinfo->getvalue(data, i),
+                &f);
+        details[i - 1] = XmStringCreateLocalized(str);
+        if(f) {
+            free(str);
+        }
+    }
+    XtSetArg(args[1], XmNdetail, details);
+    XtSetArg(args[2], XmNdetailCount, modelinfo->columns - 1);
+    
+    // create widget
+    Widget item = XmCreateIconGadget(container, "table_item", args, 3);
+    XtManageChild(item);
+    
+    // cleanup
+    XmStringFree(label);
+    for(int i=0;i<modelinfo->columns-1;i++) {
+        XmStringFree(details[i]);
+    }
+    XtFree((char*)details);
+}
+
+char* ui_type_to_string(UiModelType type, void *data, Boolean *free) {
+    switch(type) {
+        case UI_STRING: *free = FALSE; return data;
+        case UI_INTEGER: {
+            *free = TRUE;
+            int *val = data;
+            sstr_t str = ucx_asprintf(ucx_default_allocator(), "%d", *val);
+            return str.ptr;
+        }
+    }
+    *free = FALSE;
+    return NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/motif/tree.h	Thu May 15 20:06:28 2014 +0200
@@ -0,0 +1,47 @@
+/*
+ * 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 TREE_H
+#define	TREE_H
+
+#include "../ui/tree.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+void ui_add_icon_gadget(Widget container, UiModelInfo *modelinfo, void *data);
+char* ui_type_to_string(UiModelType type, void *data, Boolean *free);
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* TREE_H */
+
--- a/ui/ui/tree.h	Thu May 15 17:17:58 2014 +0200
+++ b/ui/ui/tree.h	Thu May 15 20:06:28 2014 +0200
@@ -35,10 +35,61 @@
 extern "C" {
 #endif
 
+typedef struct UiModelInfo UiModelInfo;
+
+typedef enum UiModelType UiModelType;
+
+enum UiModelType {
+    UI_STRING = 0,
+    UI_INTEGER
+};
+
+struct UiModelInfo {
+    /*
+     * number of columns
+     */
+    int columns;
+    
+    /*
+     * array of column types
+     * array length is the number of columns
+     */
+    UiModelType *types;
+    
+    /*
+     * array of column titles
+     * array length is the number of columns
+     */
+    char **titles;
+    
+    /*
+     * function for translatring model data to view data
+     * first argument is a pointer from the model (UiList, UiTree)
+     * second argument is the column index
+     * TODO: return
+     */
+    void*(*getvalue)(void*, int);
+    
+    /*
+     * selection callback
+     */
+    ui_callback callback;
+    
+    /*
+     * userdata for callback
+     */
+    void *userdata;
+};
+
+UiModelInfo* ui_model_info(UiContext *ctx, ...);
+void ui_model_info_free(UiContext *ctx, UiModelInfo *mi);
+
 UIWIDGET ui_listview(UiObject *obj, UiList *list, ui_model_getvalue_f getvalue, ui_callback f, void *udata);
 UIWIDGET ui_listview_str(UiObject *obj, UiList *list, ui_callback f, void *udata);
 UIWIDGET ui_listview_nv(UiObject *obj, char *listname, ui_model_getvalue_f getvalue, ui_callback f, void *udata);
 
+UIWIDGET ui_table(UiObject *obj, UiList *model, UiModelInfo *modelinfo);
+
 #ifdef	__cplusplus
 }
 #endif

mercurial