#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "tree.h"
#include "container.h"
#include "../common/object.h"
#include "../common/context.h"
#include <cx/utils.h>
#include <cx/compare.h>
#include <cx/printf.h>
UIWIDGET ui_table_var(UiObject *obj, UiVar *var, UiModel *model, UiListCallbacks cb) {
Arg args[
32];
int n =
0;
UiContainer *ct = uic_get_current_container(obj);
Widget parent = ct->prepare(ct, args, &n,
TRUE);
XtSetArg(args[n], XmNscrollingPolicy, XmAUTOMATIC);
n++;
XtSetArg(args[n], XmNshadowThickness,
0);
n++;
Widget scrollw = XmCreateScrolledWindow(parent,
"scroll_win", args, n);
ct->add(ct, scrollw);
XtManageChild(scrollw);
XmStringTable header = (XmStringTable)XtMalloc(
model->columns *
sizeof(XmString));
for(
int i=
0;i<model->columns;i++) {
header[i] = XmStringCreateLocalized(model->titles[i]);
}
n =
0;
XtSetArg(args[n], XmNdetailColumnHeading, header);
n++;
XtSetArg(args[n], XmNdetailColumnHeadingCount, model->columns);
n++;
XtSetArg(args[n], XmNlayoutType, XmDETAIL);
n++;
XtSetArg(args[n], XmNentryViewType, XmSMALL_ICON);
n++;
XtSetArg(args[n], XmNselectionPolicy, XmSINGLE_SELECT);
n++;
XtSetArg(args[n], XmNwidth,
600);
n++;
Widget container = XmCreateContainer(scrollw,
"table", args, n);
XtManageChild(container);
UiTreeEventData *event = ui_malloc(obj->ctx,
sizeof(UiTreeEventData));
event->obj = obj;
event->activate = cb.activate;
event->selection = cb.selection;
event->userdata = cb.userdata;
event->last_selection =
NULL;
if(cb.selection) {
XtAddCallback(
container,
XmNselectionCallback,
(XtCallbackProc)ui_table_select_callback,
event);
}
if(cb.activate) {
XtAddCallback(
container,
XmNdefaultActionCallback,
(XtCallbackProc)ui_table_action_callback,
event);
}
UiList *list = var->value;
void *data = list->first(list);
int width =
0;
while(data) {
int w = ui_add_icon_gadget(container, model, data);
if(w > width) {
width = w;
}
data = list->next(list);
}
UiTableView *tableview = cxMalloc(obj->ctx->allocator,
sizeof(UiTableView));
tableview->widget = container;
tableview->var = var;
tableview->model = model;
XtVaSetValues(container, XmNwidth, width,
NULL);
for(
int i=
0;i<model->columns;i++) {
XmStringFree(header[i]);
}
XtFree((
char*)header);
return scrollw;
}
UIWIDGET ui_table(UiObject *obj, UiList *data, UiModel *model, UiListCallbacks cb) {
UiVar *var = malloc(
sizeof(UiVar));
var->value = data;
var->type =
UI_VAR_SPECIAL;
return ui_table_var(obj, var, model, cb);
}
void ui_table_update(UiEvent *event, UiTableView *view) {
Widget *children;
int nc;
XtVaGetValues(
view->widget,
XmNchildren,
&children,
XmNnumChildren,
&nc,
NULL);
for(
int i=
0;i<nc;i++) {
XtDestroyWidget(children[i]);
}
UiList *list = view->var->value;
void *data = list->first(list);
int width =
0;
while(data) {
int w = ui_add_icon_gadget(view->widget, view->model, data);
if(w > width) {
width = w;
}
data = list->next(list);
}
}
#define UI_COL_CHAR_WIDTH 12
int ui_add_icon_gadget(Widget container, UiModel *model,
void *data) {
int width =
50;
if(model->columns ==
0) {
return width;
}
XmString label =
NULL;
Arg args[
8];
Boolean f;
if(model->types[
0] !=
12345678) {
char *str = ui_type_to_string(
model->types[
0],
model->getvalue(data,
0),
&f);
width += strlen(str) *
UI_COL_CHAR_WIDTH;
XmString label = XmStringCreateLocalized(str);
XtSetArg(args[
0], XmNlabelString, label);
if(f) {
free(str);
}
}
else {
}
XmStringTable details = (XmStringTable)XtMalloc(
(model->columns -
1) *
sizeof(XmString));
for(
int i=
1;i<model->columns;i++) {
char *str = ui_type_to_string(
model->types[i],
model->getvalue(data, i),
&f);
width += strlen(str) *
UI_COL_CHAR_WIDTH;
details[i -
1] = XmStringCreateLocalized(str);
if(f) {
free(str);
}
}
XtSetArg(args[
1], XmNdetail, details);
XtSetArg(args[
2], XmNdetailCount, model->columns -
1);
XtSetArg(args[
3], XmNshadowThickness,
0);
Widget item = XmCreateIconGadget(container,
"table_item", args,
4);
XtManageChild(item);
XmStringFree(label);
for(
int i=
0;i<model->columns-
1;i++) {
XmStringFree(details[i]);
}
XtFree((
char*)details);
return width;
}
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;
cxmutstr str = cx_asprintf(
"%d", *val);
return str.ptr;
}
case UI_ICON:
break;
case UI_ICON_TEXT:
break;
}
*free =
FALSE;
return NULL;
}
void ui_table_action_callback(
Widget widget,
UiTreeEventData *event,
XmContainerSelectCallbackStruct *sel)
{
UiListSelection *selection = ui_list_selection(sel);
UiEvent e;
e.obj = event->obj;
e.window = event->obj->window;
e.document = event->obj->ctx->document;
e.eventdata = selection;
e.intval = selection->count >
0 ? selection->rows[
0] : -
1;
event->activate(&e, event->userdata);
free(event->last_selection->rows);
free(event->last_selection);
event->last_selection = selection;
}
void ui_table_select_callback(
Widget widget,
UiTreeEventData *event,
XmContainerSelectCallbackStruct *sel)
{
UiListSelection *selection = ui_list_selection(sel);
if(!ui_compare_list_selection(selection, event->last_selection)) {
UiEvent e;
e.obj = event->obj;
e.window = event->obj->window;
e.document = event->obj->ctx->document;
e.eventdata = selection;
e.intval = selection->count >
0 ? selection->rows[
0] : -
1;
event->selection(&e, event->userdata);
}
if(event->last_selection) {
free(event->last_selection->rows);
free(event->last_selection);
}
event->last_selection = selection;
}
UiListSelection* ui_list_selection(XmContainerSelectCallbackStruct *xs) {
UiListSelection *selection = malloc(
sizeof(UiListSelection));
selection->count = xs->selected_item_count;
selection->rows = calloc(selection->count,
sizeof(
int));
for(
int i=
0;i<selection->count;i++) {
int index;
XtVaGetValues(xs->selected_items[i], XmNpositionIndex, &index,
NULL);
selection->rows[i] = index;
}
return selection;
}
Boolean ui_compare_list_selection(UiListSelection *s1, UiListSelection *s2) {
if(!s1 || !s2) {
return FALSE;
}
if(s1->count != s2->count) {
return FALSE;
}
for(
int i=
0;i<s1->count;i++) {
if(s1->rows[i] != s2->rows[i]) {
return FALSE;
}
}
return TRUE;
}