# HG changeset patch # User Olaf Wintermann # Date 1400177188 -7200 # Node ID 4e66271541e89ed26bfc6371847fef0f8e42e34a # Parent 8ccdde37275b8e0e1ac8a03a26c83d7c8bd88757 added table view (Motif) diff -r 8ccdde37275b -r 4e66271541e8 application/main.c --- 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 #include -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(); diff -r 8ccdde37275b -r 4e66271541e8 ui/common/context.c --- 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 +} + diff -r 8ccdde37275b -r 4e66271541e8 ui/common/types.c --- 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 #include +#include #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); +} diff -r 8ccdde37275b -r 4e66271541e8 ui/motif/objs.mk --- 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) diff -r 8ccdde37275b -r 4e66271541e8 ui/motif/toolbar.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) { diff -r 8ccdde37275b -r 4e66271541e8 ui/motif/tree.c --- /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 +#include +#include + +#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;icolumns;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;icolumns;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;icolumns;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;icolumns-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; +} diff -r 8ccdde37275b -r 4e66271541e8 ui/motif/tree.h --- /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 */ + diff -r 8ccdde37275b -r 4e66271541e8 ui/ui/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