--- a/ui/motif/container.c Fri Nov 29 22:21:36 2024 +0100 +++ b/ui/motif/container.c Thu Dec 12 20:01:43 2024 +0100 @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2014 Olaf Wintermann. All rights reserved. + * Copyright 2024 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: @@ -34,751 +34,189 @@ #include "../common/context.h" #include "../common/object.h" -#include <cx/array_list.h> -#include <cx/linked_list.h> -#include <cx/compare.h> - -#define UI_GRID_MAX_COLUMNS 512 - -static UiBool ui_lb2bool(UiLayoutBool b) { - return b == UI_LAYOUT_TRUE ? TRUE : FALSE; -} - -static UiLayoutBool ui_bool2lb(UiBool b) { - return b ? UI_LAYOUT_TRUE : UI_LAYOUT_FALSE; -} - +#include "Grid.h" -UiContainer* ui_frame_container(UiObject *obj, Widget frame) { - UiContainer *ct = cxCalloc( - obj->ctx->allocator, - 1, - sizeof(UiContainer)); - ct->widget = frame; - ct->prepare = ui_frame_container_prepare; - ct->add = ui_frame_container_add; - return ct; -} - -Widget ui_frame_container_prepare(UiContainer *ct, Arg *args, int *n, UiBool fill) { - return ct->widget; -} - -void ui_frame_container_add(UiContainer *ct, Widget widget) { - ui_reset_layout(ct->layout); - ct->current = widget; -} - +/* ---------------------------- Box Container ---------------------------- */ -UiContainer* ui_box_container(UiObject *obj, Widget box, int margin, int spacing, UiBoxOrientation orientation) { - UiBoxContainer *ct = cxCalloc( - obj->ctx->allocator, - 1, - sizeof(UiBoxContainer)); - ct->container.widget = box; - ct->container.prepare = ui_box_container_prepare; - ct->container.add = ui_box_container_add; - ct->orientation = orientation; - ct->margin = margin; - ct->spacing = spacing; - return (UiContainer*)ct; -} - -Widget ui_box_container_prepare(UiContainer *ct, Arg *args, int *n, UiBool fill) { - UiBoxContainer *bc = (UiBoxContainer*)ct; - if(ct->layout.fill != UI_LAYOUT_UNDEFINED) { - fill = ui_lb2bool(ct->layout.fill); - } +static UIWIDGET box_create(UiObject *obj, UiContainerArgs args, UiBoxOrientation orientation) { + UiContainerPrivate *ctn = ui_obj_container(obj); + UI_APPLY_LAYOUT(ctn->layout, args); - if(bc->has_fill && fill) { - fprintf(stderr, "UiError: container has 2 filled widgets"); - fill = FALSE; - } - if(fill) { - bc->has_fill = TRUE; - } + Arg xargs[16]; + int n = 0; - int a = *n; - // determine fixed and dynamic attachments - void *f1; - void *f2; - void *d1; - void *d2; - void *w1; - void *w2; - if(bc->orientation == UI_BOX_VERTICAL) { - f1 = XmNleftAttachment; - f2 = XmNrightAttachment; - d1 = XmNtopAttachment; - d2 = XmNbottomAttachment; - w1 = XmNtopWidget; - w2 = XmNbottomWidget; - - // margin/spacing - XtSetArg(args[a], XmNleftOffset, bc->margin); a++; - XtSetArg(args[a], XmNrightOffset, bc->margin); a++; - - XtSetArg(args[a], XmNtopOffset, bc->prev_widget ? bc->spacing : bc->margin); a++; + if(orientation == UI_BOX_VERTICAL) { + //XtSetArg(xargs[n], gridRowSpacing, args.spacing); n++; } else { - f1 = XmNtopAttachment; - f2 = XmNbottomAttachment; - d1 = XmNleftAttachment; - d2 = XmNrightAttachment; - w1 = XmNleftWidget; - w2 = XmNrightWidget; - - // margin/spacing - XtSetArg(args[a], XmNtopOffset, bc->margin); a++; - XtSetArg(args[a], XmNbottomOffset, bc->margin); a++; - - XtSetArg(args[a], XmNleftOffset, bc->prev_widget ? bc->spacing : bc->margin); a++; - } - XtSetArg(args[a], f1, XmATTACH_FORM); a++; - XtSetArg(args[a], f2, XmATTACH_FORM); a++; - - if(fill) { - XtSetArg(args[a], d2, XmATTACH_FORM); a++; - } - if(bc->prev_widget) { - XtSetArg(args[a], d1, XmATTACH_WIDGET); a++; - XtSetArg(args[a], w1, bc->prev_widget); a++; - } else { - XtSetArg(args[a], d1, XmATTACH_FORM); a++; - } - - *n = a; - return ct->widget; -} - -void ui_box_container_add(UiContainer *ct, Widget widget) { - UiBoxContainer *bc = (UiBoxContainer*)ct; - // determine dynamic attachments - void *d1; - void *d2; - void *w1; - void *w2; - if(bc->orientation == UI_BOX_VERTICAL) { - d1 = XmNtopAttachment; - d2 = XmNbottomAttachment; - w1 = XmNtopWidget; - w2 = XmNbottomWidget; - - } else { - d1 = XmNleftAttachment; - d2 = XmNrightAttachment; - w1 = XmNleftWidget; - w2 = XmNrightWidget; - } - - if(bc->prev_widget) { - int v = 0; - XtVaGetValues(bc->prev_widget, d2, &v, NULL); - if(v == XmATTACH_FORM) { - XtVaSetValues( - bc->prev_widget, - d2, - XmATTACH_WIDGET, - w2, - widget, - NULL); - XtVaSetValues( - widget, - d1, - XmATTACH_NONE, - d2, - XmATTACH_FORM, - NULL); - } - } - bc->prev_widget = widget; - - ui_reset_layout(ct->layout); - ct->current = widget; -} - -UiContainer* ui_grid_container(UiObject *obj, Widget form, int columnspacing, int rowspacing) { - UiGridContainer *ct = cxCalloc( - obj->ctx->allocator, - 1, - sizeof(UiGridContainer)); - ct->container.widget = form; - ct->container.prepare = ui_grid_container_prepare; - ct->container.add = ui_grid_container_add; - ct->columnspacing = columnspacing; - ct->rowspacing = rowspacing; - ct->lines = cxLinkedListCreateSimple(CX_STORE_POINTERS); - return (UiContainer*)ct; -} - -void ui_grid_newline(UiGridContainer *grid) { - if(grid->current) { - grid->current = NULL; - } - grid->container.layout.newline = FALSE; -} - -Widget ui_grid_container_prepare(UiContainer *ct, Arg *args, int *n, UiBool fill) { - UiGridContainer *grid = (UiGridContainer*)ct; - if(ct->layout.newline) { - ui_grid_newline(grid); - } - return ct->widget; -} - -void ui_grid_container_add(UiContainer *ct, Widget widget) { - UiGridContainer *grid = (UiGridContainer*)ct; - - if(grid->current) { - cxListAdd(grid->current, widget); - } else { - grid->current = cxLinkedListCreateSimple(CX_STORE_POINTERS); - cxListAdd(grid->current, widget); - cxListAdd(grid->lines, grid->current); + //XtSetArg(xargs[n], gridColumnSpacing, args.spacing); n++; } - ui_reset_layout(ct->layout); - ct->current = widget; -} - -static void ui_grid_resize(Widget widget, XtPointer udata, XtPointer cdata) { - UiGridContainer *grid = udata; - - CxList *rowdim = cxArrayListCreateSimple(sizeof(int), grid->lines->size); - int coldim[UI_GRID_MAX_COLUMNS]; - memset(coldim, 0, UI_GRID_MAX_COLUMNS*sizeof(int)); - int numcol = 0; - - // get the minimum size of the columns and rows - int sumw = 0; - int sumh = 0; - CxIterator lineIterator = cxListIterator(grid->lines); - cx_foreach(CxList *, row, lineIterator) { - int rheight = 0; - int i=0; - int sum_width = 0; - CxIterator colIterator = cxListIterator(row); - cx_foreach(Widget, w, colIterator) { - int widget_width = 0; - int widget_height = 0; - XtVaGetValues( - w, - XmNwidth, - &widget_width, - XmNheight, - &widget_height, - NULL); - - // get the maximum height in this row - if(widget_height > rheight) { - rheight = widget_height; - } - - // get the maximum width in this column - if(widget_width > coldim[i]) { - coldim[i] = widget_width; - } - sum_width += widget_width; - if(sum_width > sumw) { - sumw = sum_width; - } - - i++; - if(i > numcol) { - numcol = i; - } - } - cxListAdd(rowdim, &rheight); - sumh += rheight; - } - - // check container size - int gwidth = 0; - int gheight = 0; - XtVaGetValues(widget, XmNwidth, &gwidth, XmNheight, &gheight, NULL); - if(gwidth < sumw || gheight < sumh) { - XtVaSetValues(widget, XmNwidth, sumw, XmNheight, sumh, NULL); - cxListDestroy(rowdim); - return; - } - - - // adjust the positions of all children - int y = 0; - lineIterator = cxListIterator(grid->lines); - cx_foreach(CxList *, row, lineIterator) { - int x = 0; - int i=0; - int *rowheight = cxListAt(rowdim, lineIterator.index); - CxIterator colIterator = cxListIterator(row); - cx_foreach(Widget, w, colIterator) { - XtVaSetValues( - w, - XmNx, x, - XmNy, y, - XmNwidth, coldim[i], - XmNheight, *rowheight, - NULL); - - x += coldim[i]; - i++; - } - y += *rowheight; - } + Widget parent = ctn->prepare(ctn, xargs, &n); + Widget grid = XtCreateManagedWidget(args.name ? args.name : "boxcontainer", gridClass, parent, xargs, n); + ctn->add(ctn, grid); - cxListDestroy(rowdim); -} - -UiContainer* ui_scrolledwindow_container(UiObject *obj, Widget scrolledwindow) { - UiContainer *ct = cxCalloc( - obj->ctx->allocator, - 1, - sizeof(UiContainer)); - ct->widget = scrolledwindow; - ct->prepare = ui_scrolledwindow_container_prepare; - ct->add = ui_scrolledwindow_container_add; - return ct; -} - -Widget ui_scrolledwindow_container_prepare(UiContainer *ct, Arg *args, int *n, UiBool fill) { - return ct->widget; -} - -void ui_scrolledwindow_container_add(UiContainer *ct, Widget widget) { - ui_reset_layout(ct->layout); - ct->current = widget; -} - - -UiContainer* ui_tabview_container(UiObject *obj, Widget frame) { - UiTabViewContainer *ct = cxCalloc( - obj->ctx->allocator, - 1, - sizeof(UiTabViewContainer)); - ct->context = obj->ctx; - ct->container.widget = frame; - ct->container.prepare = ui_tabview_container_prepare; - ct->container.add = ui_tabview_container_add; - ct->tabs = cxArrayListCreate(cxDefaultAllocator, cx_cmp_uintptr, CX_STORE_POINTERS, 16); - return (UiContainer*)ct; -} - -Widget ui_tabview_container_prepare(UiContainer *ct, Arg *args, int *n, UiBool fill) { - int a = *n; - XtSetArg(args[a], XmNleftAttachment, XmATTACH_FORM); a++; - XtSetArg(args[a], XmNrightAttachment, XmATTACH_FORM); a++; - XtSetArg(args[a], XmNtopAttachment, XmATTACH_FORM); a++; - XtSetArg(args[a], XmNbottomAttachment, XmATTACH_FORM); a++; - *n = a; - return ct->widget; -} - -void ui_tabview_container_add(UiContainer *ct, Widget widget) { - UiTabViewContainer *tabview = (UiTabViewContainer*)ct; - - if(tabview->current) { - XtUnmanageChild(tabview->current); - } - - tabview->current = widget; - cxListAdd(tabview->tabs, widget); - - ui_select_tab(ct->widget, 0); - ui_reset_layout(ct->layout); - ct->current = widget; -} - -UIWIDGET ui_box(UiObject *obj, int margin, int spacing, UiBoxOrientation orientation) { - UiContainer *ct = uic_get_current_container(obj); - - Arg args[16]; - int n = 0; - Widget parent = ct->prepare(ct, args, &n, TRUE); - Widget form = XmCreateForm(parent, "vbox", args, n); - ct->add(ct, form); - XtManageChild(form); - - UiObject *newobj = uic_object_new(obj, form); - newobj->container = ui_box_container(obj, form, margin, spacing, orientation); - uic_obj_add(obj, newobj); - - return form; -} - -UIWIDGET ui_vbox(UiObject *obj) { - return ui_box(obj, 0, 0, UI_BOX_VERTICAL); -} - -UIWIDGET ui_hbox(UiObject *obj) { - return ui_box(obj, 0, 0, UI_BOX_HORIZONTAL); -} - -UIWIDGET ui_vbox_sp(UiObject *obj, int margin, int spacing) { - return ui_box(obj, margin, spacing, UI_BOX_VERTICAL); -} - -UIWIDGET ui_hbox_sp(UiObject *obj, int margin, int spacing) { - return ui_box(obj, margin, spacing, UI_BOX_HORIZONTAL); -} - -UIWIDGET ui_grid(UiObject *obj) { - return ui_grid_sp(obj, 0, 0, 0); -} - -UIWIDGET ui_grid_sp(UiObject *obj, int margin, int columnspacing, int rowspacing) { - UiContainer *ct = uic_get_current_container(obj); - - Arg args[16]; - int n = 0; - Widget parent = ct->prepare(ct, args, &n, TRUE); - Widget grid = XmCreateDrawingArea(parent, "grid", args, n); - ct->add(ct, grid); - XtManageChild(grid); - - UiObject *newobj = uic_object_new(obj, grid); - newobj->container = ui_grid_container(obj, grid, columnspacing, rowspacing); - uic_obj_add(obj, newobj); - - XtAddCallback (grid, XmNresizeCallback , ui_grid_resize, newobj->container); + UiContainerX *container = ui_box_container(obj, grid, orientation); + uic_object_push_container(obj, container); return grid; } -UIWIDGET ui_scrolledwindow(UiObject *obj) { - UiContainer *ct = uic_get_current_container(obj); - - Arg args[16]; - int n = 0; - XtSetArg(args[n], XmNscrollingPolicy, XmAUTOMATIC); // TODO: dosn't work, use XmAPPLICATION_DEFINED - n++; - Widget parent = ct->prepare(ct, args, &n, TRUE); - Widget scrolledwindow = XmCreateScrolledWindow(parent, "scrolledwindow", args, n); - ct->add(ct, scrolledwindow); - XtManageChild(scrolledwindow); - - UiObject *newobj = uic_object_new(obj, scrolledwindow); - newobj->container = ui_scrolledwindow_container(obj, scrolledwindow); - uic_obj_add(obj, newobj); - - return scrolledwindow; +// public +UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs args) { + return box_create(obj, args, UI_BOX_VERTICAL); +} + +// public +UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs args) { + return box_create(obj, args, UI_BOX_HORIZONTAL); } -UIWIDGET ui_sidebar(UiObject *obj) { - UiContainer *ct = uic_get_current_container(obj); - - Arg args[16]; - int n = 0; - - XtSetArg(args[n], XmNorientation, XmHORIZONTAL); - n++; - - Widget parent = ct->prepare(ct, args, &n, TRUE); - Widget pane = XmCreatePanedWindow(parent, "pane", args, n); - ct->add(ct, pane); - XtManageChild(pane); - - // add sidebar widget - Widget sidebar = XmCreateForm(pane, "sidebar", args, 0); - XtManageChild(sidebar); - - UiObject *left = uic_object_new(obj, sidebar); - left->container = ui_box_container(left, sidebar, 0, 0, UI_BOX_VERTICAL); - - // add content widget - XtSetArg (args[0], XmNpaneMaximum, 8000); - Widget content = XmCreateForm(pane, "content_area", args, 1); - XtManageChild(content); - - UiObject *right = uic_object_new(obj, content); - right->container = ui_box_container(right, content, 0, 0, UI_BOX_VERTICAL); - - uic_obj_add(obj, right); - uic_obj_add(obj, left); - - return sidebar; +UiContainerX* ui_box_container(UiObject *obj, Widget grid, UiBoxOrientation orientation) { + UiBoxContainer *ctn = ui_malloc(obj->ctx, sizeof(UiBoxContainer)); + memset(ctn, 0, sizeof(UiBoxContainer)); + ctn->container.prepare = orientation == UI_BOX_VERTICAL ? ui_vbox_prepare : ui_hbox_prepare; + ctn->container.add = ui_box_container_add; + ctn->container.widget = grid; + ctn->n = 0; + return (UiContainerX*)ctn; } -UIWIDGET ui_tabview(UiObject *obj) { - UiContainer *ct = uic_get_current_container(obj); - - // create a simple frame as container widget - // when tabs are selected, the current child will be replaced by the - // the new tab widget - Arg args[16]; - int n = 0; - XtSetArg(args[n], XmNshadowType, XmSHADOW_ETCHED_OUT); - n++; - XtSetArg(args[n], XmNshadowThickness, 0); - n++; - Widget parent = ct->prepare(ct, args, &n, TRUE); - Widget form = XmCreateForm(parent, "tabview", args, n); - ct->add(ct, form); - XtManageChild(form); - - UiObject *tabviewobj = uic_object_new(obj, form); - tabviewobj->container = ui_tabview_container(obj, form); - uic_obj_add(obj, tabviewobj); - - XtVaSetValues(form, XmNuserData, tabviewobj->container, NULL); - - return form; +static Widget ui_box_container_prepare(UiBoxContainer *box, Arg *args, int *n) { + int a = *n; + box->n++; + return box->container.widget; } -void ui_tab(UiObject *obj, char *title) { - UiContainer *ct = uic_get_current_container(obj); - ct->layout.label = title; - - ui_vbox(obj); -} - -void ui_select_tab(UIWIDGET tabview, int tab) { - UiTabViewContainer *ct = NULL; - XtVaGetValues(tabview, XmNuserData, &ct, NULL); - if(ct) { - XtUnmanageChild(ct->current); - Widget w = cxListAt(ct->tabs, tab); - if(w) { - XtManageChild(w); - ct->current = w; - } else { - fprintf(stderr, "UiError: front tab index: %d\n", tab); - } - } else { - fprintf(stderr, "UiError: widget is not a tabview\n"); +Widget ui_vbox_prepare(UiContainerPrivate *ctn, Arg *args, int *n) { + UiBoxContainer *box = (UiBoxContainer*)ctn; + int a = *n; + XtSetArg(args[a], gridRow, box->n); a++; + if(box->container.layout.fill == UI_ON) { + XtSetArg(args[a], gridVExpand, TRUE); a++; + XtSetArg(args[a], gridVFill, TRUE); a++; } + XtSetArg(args[a], gridHExpand, TRUE); a++; + XtSetArg(args[a], gridHFill, TRUE); a++; + *n = a; + return ui_box_container_prepare(box, args, n); } - -/* document tabview */ - -static void ui_tabbar_resize(Widget widget, XtPointer udata, XtPointer cdata) { - MotifTabbedPane *v = (MotifTabbedPane*)udata; - - int width = 0; - int height = 0; - XtVaGetValues(widget, XmNwidth, &width, XmNheight, &height, NULL); - int button_width = width / 4; - int x = 0; - CxIterator tabIterator = cxListIterator(v->tabs); - cx_foreach(UiTab*, tab, tabIterator) { - XtVaSetValues( - tab->tab_button, - XmNx, x, - XmNy, 0, - XmNwidth, - button_width, - - NULL); - x += button_width; +Widget ui_hbox_prepare(UiContainerPrivate *ctn, Arg *args, int *n) { + UiBoxContainer *box = (UiBoxContainer*)ctn; + int a = *n; + XtSetArg(args[a], gridColumn, box->n); a++; + if(box->container.layout.fill == UI_ON) { + XtSetArg(args[a], gridHExpand, TRUE); a++; + XtSetArg(args[a], gridHFill, TRUE); a++; } - - if(height <= v->height) { - XtVaSetValues(widget, XmNheight, v->height + 4, NULL); - } + XtSetArg(args[a], gridVExpand, TRUE); a++; + XtSetArg(args[a], gridVFill, TRUE); a++; + *n = a; + return ui_box_container_prepare(box, args, n); } -static void ui_tabbar_expose(Widget widget, XtPointer udata, XtPointer cdata) { - MotifTabbedPane *v = (MotifTabbedPane*)udata; - XmDrawingAreaCallbackStruct *cbs = (XmDrawingAreaCallbackStruct *)cdata; - XEvent *event = cbs->event; - Display *dpy = XtDisplay(widget); - - XGCValues gcvals; - GC gc; - Pixel fgpix; - - int tab_x; - int tab_width; - XtVaGetValues(v->current->tab_button, XmNx, &tab_x, XmNwidth, &tab_width, XmNhighlightColor, &fgpix, NULL); - - gcvals.foreground = v->bg1; - gc = XCreateGC( dpy, XtWindow(widget), (GCForeground), &gcvals); - - int width = 0; - int height = 0; - XtVaGetValues(widget, XmNwidth, &width, XmNheight, &height, NULL); - XFillRectangle(dpy, XtWindow(widget), gc, 0, 0, width, height); - - gcvals.foreground = fgpix; - gc = XCreateGC( dpy, XtWindow(widget), (GCForeground), &gcvals); - - XFillRectangle(dpy, XtWindow(widget), gc, tab_x, 0, tab_width, height); +void ui_box_container_add(UiContainerPrivate *ctn, Widget widget) { + ui_reset_layout(ctn->layout); } -UiTabbedPane* ui_tabbed_document_view(UiObject *obj) { + +/* ---------------------------- Grid Container ---------------------------- */ + +// public +UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs args) { + Arg xargs[16]; int n = 0; - Arg args[16]; - - UiContainer *ct = uic_get_current_container(obj); - Widget parent = ct->prepare(ct, args, &n, TRUE); - - 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); - XtSetArg(args[6], XmNmarginWidth, 0); - XtSetArg(args[7], XmNmarginHeight, 0); - Widget tabbar = XmCreateDrawingArea(tabview, "tabbar", args, 8); - XtManageChild(tabbar); + XtSetArg(xargs[n], XmNbackground, 0); n++; - 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); + UiContainerPrivate *ctn = ui_obj_container(obj); + UI_APPLY_LAYOUT(ctn->layout, args); - 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->tabs = cxArrayListCreate(obj->ctx->allocator, cx_cmp_uintptr, CX_STORE_POINTERS, 16); - tabbedpane->current = NULL; - tabbedpane->height = 0; + Widget parent = ctn->prepare(ctn, xargs, &n); + Widget grid = XtCreateManagedWidget(args.name ? args.name : "gridcontainer", gridClass, parent, xargs, n); + ctn->add(ctn, grid); - XtAddCallback(tabbar, XmNresizeCallback , ui_tabbar_resize, tabbedpane); - XtAddCallback(tabbar, XmNexposeCallback, ui_tabbar_expose, tabbedpane); + UiContainerX *container = ui_grid_container(obj, grid); + uic_object_push_container(obj, container); - return &tabbedpane->view; + return grid; } -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); +UiContainerX* ui_grid_container(UiObject *obj, Widget grid) { + UiGridContainer *ctn = ui_malloc(obj->ctx, sizeof(UiGridContainer)); + memset(ctn, 0, sizeof(UiBoxContainer)); + ctn->container.prepare = ui_grid_container_prepare; + ctn->container.add = ui_grid_container_add; + ctn->container.widget = grid; + ctn->x = 0; + ctn->y = 0; + return (UiContainerX*)ctn; +} + +Widget ui_grid_container_prepare(UiContainerPrivate *ctn, Arg *args, int *n) { + UiGridContainer *grid = (UiGridContainer*)ctn; + if(ctn->layout.newline) { + grid->y++; + grid->x = 0; } - 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->mp); - content->ctx->parent = view->ctx; - content->ctx->attach_document = uic_context_attach_document; - content->ctx->detach_document2 = uic_context_detach_document2; - content->widget = frame; - content->window = view->ctx->obj->window; - content->container = ui_frame_container(content, frame); - content->next = NULL; - - // add tab button - cxListAdd(v->tabs, tab); + int a = *n; + XtSetArg(args[a], gridColumn, grid->x); a++; + XtSetArg(args[a], gridRow, grid->y); a++; + if(ctn->layout.colspan > 0) { + XtSetArg(args[a], gridColspan, ctn->layout.colspan); a++; + } + if(ctn->layout.rowspan > 0) { + XtSetArg(args[a], gridRowspan, ctn->layout.rowspan); a++; + } - XmString label = XmStringCreateLocalized("tab"); - XtSetArg(args[0], XmNlabelString, label); - XtSetArg(args[1], XmNshadowThickness, 0); - XtSetArg(args[2], XmNhighlightThickness, 0); - - Widget button = XmCreatePushButton(v->tabbar, "tab_button", args, 3); - tab->tabbedpane = v; - tab->content = content; - tab->tab_button = button; - XtManageChild(button); - XtAddCallback( - button, - XmNactivateCallback, - (XtCallbackProc)ui_tab_button_callback, - tab); - - if(v->height == 0) { - XtVaGetValues( - button, - XmNarmColor, - &v->bg1, - XmNbackground, - &v->bg2, - XmNheight, - &v->height, - NULL); - v->height += 2; // border + if(grid->container.layout.fill == UI_ON) { + grid->container.layout.hfill = TRUE; + grid->container.layout.vfill = TRUE; + grid->container.layout.hexpand = TRUE; + grid->container.layout.vexpand = TRUE; } - ui_change_tab(v, tab); - ui_tabbar_resize(v->tabbar, v, NULL); + if(grid->container.layout.hfill) { + XtSetArg(args[a], gridHFill, TRUE); a++; + } + if(grid->container.layout.vfill) { + XtSetArg(args[a], gridVFill, TRUE); a++; + } + if(grid->container.layout.hexpand) { + XtSetArg(args[a], gridHExpand, TRUE); a++; + } + if(grid->container.layout.vexpand) { + XtSetArg(args[a], gridVExpand, TRUE); a++; + } - 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); - XtVaSetValues(t->current->tab_button, XmNset, 0, NULL); - } - XtManageChild(tab->content->widget); - - ui_change_tab(t, tab); - + *n = a; + return ctn->widget; } -void ui_change_tab(MotifTabbedPane *pane, UiTab *tab) { - UiContext *ctx = tab->content->ctx; - ctx->parent->detach_document2(ctx->parent, pane->current->content->ctx->document); - ctx->parent->attach_document(ctx->parent, ctx->document); - - if(pane->current) { - XtVaSetValues(pane->current->tab_button, XmNshadowThickness, 0, XmNbackground, pane->bg1, NULL); - } - XtVaSetValues(tab->tab_button, XmNshadowThickness, 1, XmNbackground, pane->bg2, NULL); - - pane->current = tab; - pane->index = cxListFind(pane->tabs, tab); - printf("index: %d\n", pane->index); - - // redraw tabbar - Display *dpy = XtDisplay(pane->tabbar); - Window window = XtWindow(pane->tabbar); - if(dpy && window) { - XClearArea(dpy, XtWindow(pane->tabbar), 0, 0, 0, 0, TRUE); - XFlush(dpy); - } +void ui_grid_container_add(UiContainerPrivate *ctn, Widget widget) { + UiGridContainer *grid = (UiGridContainer*)ctn; + grid->x++; + ui_reset_layout(ctn->layout); } -void ui_tab_set_document(UiContext *ctx, void *document) { - if(ctx->parent->document) { - //ctx->parent->detach_document(ctx->parent, ctx->parent->document); - } - uic_context_attach_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->attach_document(ctx->parent, ctx->document); - } - } else { - fprintf(stderr, "UiError: ui_bar_set_document: Cannot set document"); - } + +/* -------------------- Container Helper Functions -------------------- */ + +void ui_container_begin_close(UiObject *obj) { + UiContainerPrivate *ct = ui_obj_container(obj); + ct->container.close = 1; } +int ui_container_finish(UiObject *obj) { + UiContainerPrivate *ct = ui_obj_container(obj); + if(ct->container.close) { + ui_end_new(obj); + return 0; + } + return 1; +} /* @@ -788,27 +226,7 @@ * */ -void ui_layout_fill(UiObject *obj, UiBool fill) { - UiContainer *ct = uic_get_current_container(obj); - ct->layout.fill = ui_bool2lb(fill); -} - -void ui_layout_hexpand(UiObject *obj, UiBool expand) { - UiContainer *ct = uic_get_current_container(obj); - ct->layout.hexpand = expand; -} - -void ui_layout_vexpand(UiObject *obj, UiBool expand) { - UiContainer *ct = uic_get_current_container(obj); - ct->layout.vexpand = expand; -} - -void ui_layout_gridwidth(UiObject *obj, int width) { - UiContainer *ct = uic_get_current_container(obj); - ct->layout.gridwidth = width; -} - void ui_newline(UiObject *obj) { - UiContainer *ct = uic_get_current_container(obj); + UiContainerPrivate *ct = ui_obj_container(obj); ct->layout.newline = TRUE; }