2 #include <WINGs/WINGsP.h>
3 #include <X11/cursorfont.h>
6 #include "wtableview.h"
8 const char *WMTableViewSelectionDidChangeNotification = "WMTableViewSelectionDidChangeNotification";
10 struct W_TableColumn {
20 WMTableColumnDelegate *delegate;
26 static void handleResize(W_ViewDelegate * self, WMView * view);
28 static void rearrangeHeader(WMTableView * table);
30 static WMRange rowsInRect(WMTableView * table, WMRect rect);
32 WMTableColumn *WMCreateTableColumn(char *title)
34 WMTableColumn *col = wmalloc(sizeof(WMTableColumn));
44 col->title = wstrdup(title);
54 void WMSetTableColumnId(WMTableColumn * column, void *id)
59 void *WMGetTableColumnId(WMTableColumn * column)
64 void WMSetTableColumnWidth(WMTableColumn * column, unsigned width)
66 if (column->maxWidth == 0)
67 column->width = WMAX(column->minWidth, width);
69 column->width = WMAX(column->minWidth, WMIN(column->maxWidth, width));
72 rearrangeHeader(column->table);
76 void WMSetTableColumnDelegate(WMTableColumn * column, WMTableColumnDelegate * delegate)
78 column->delegate = delegate;
81 void WMSetTableColumnConstraints(WMTableColumn * column, unsigned minWidth, unsigned maxWidth)
83 wassertr(maxWidth == 0 || minWidth <= maxWidth);
85 column->minWidth = minWidth;
86 column->maxWidth = maxWidth;
88 if (column->width < column->minWidth)
89 WMSetTableColumnWidth(column, column->minWidth);
90 else if (column->width > column->maxWidth && column->maxWidth != 0)
91 WMSetTableColumnWidth(column, column->maxWidth);
94 void WMSetTableColumnEditable(WMTableColumn * column, Bool flag)
96 column->editable = ((flag == 0) ? 0 : 1);
99 WMTableView *WMGetTableColumnTableView(WMTableColumn * column)
101 return column->table;
116 WMPixmap *viewBuffer;
121 WMArray *selectedRows;
132 Cursor splitterCursor;
136 WMTableViewDelegate *delegate;
146 unsigned headerHeight;
151 unsigned drawsGrid:1;
152 unsigned canSelectRow:1;
153 unsigned canSelectMultiRows:1;
154 unsigned canDeselectRow:1;
156 unsigned int hasVScroller:1;
157 unsigned int hasHScroller:1;
160 static W_Class tableClass = 0;
162 static W_ViewDelegate viewDelegate = {
170 static void reorganizeInterior(WMTableView * table);
172 static void handleEvents(XEvent * event, void *data);
173 static void handleTableEvents(XEvent * event, void *data);
174 static void repaintTable(WMTableView * table);
176 static WMSize getTotalSize(WMTableView * table)
181 /* get width from columns */
183 for (i = 0; i < WMGetArrayItemCount(table->columns); i++) {
184 WMTableColumn *column;
186 column = WMGetFromArray(table->columns, i);
188 size.width += column->width;
191 /* get height from rows */
192 size.height = table->rows * table->rowHeight;
197 static WMRect getVisibleRect(WMTableView * table)
199 WMSize size = getTotalSize(table);
202 if (table->vscroll) {
203 rect.size.height = size.height * WMGetScrollerKnobProportion(table->vscroll);
204 rect.pos.y = (size.height - rect.size.height) * WMGetScrollerValue(table->vscroll);
206 rect.size.height = size.height;
210 if (table->hscroll) {
211 rect.size.width = size.width * WMGetScrollerKnobProportion(table->hscroll);
212 rect.pos.x = (size.width - rect.size.width) * WMGetScrollerValue(table->hscroll);
214 rect.size.width = size.width;
221 static void scrollToPoint(WMTableView * table, int x, int y)
223 WMSize size = getTotalSize(table);
227 if (table->hscroll) {
228 if (size.width > W_VIEW_WIDTH(table->tableView)) {
229 prop = (float)W_VIEW_WIDTH(table->tableView) / (float)size.width;
230 value = (float)x / (float)(size.width - W_VIEW_WIDTH(table->tableView));
235 WMSetScrollerParameters(table->hscroll, value, prop);
238 if (table->vscroll) {
239 if (size.height > W_VIEW_HEIGHT(table->tableView)) {
240 prop = (float)W_VIEW_HEIGHT(table->tableView) / (float)size.height;
241 value = (float)y / (float)(size.height - W_VIEW_HEIGHT(table->tableView));
247 WMSetScrollerParameters(table->vscroll, value, prop);
250 if (table->editingRow >= 0) {
251 for (i = 0; i < WMGetArrayItemCount(table->columns); i++) {
252 WMTableColumn *column;
254 column = WMGetFromArray(table->columns, i);
256 if (column->delegate && column->delegate->beginCellEdit)
257 (*column->delegate->beginCellEdit) (column->delegate, column, table->editingRow);
264 static void adjustScrollers(WMTableView * table)
266 WMSize size = getTotalSize(table);
267 WMSize vsize = WMGetViewSize(table->tableView);
271 if (table->hscroll) {
272 if (size.width <= vsize.width) {
276 oprop = WMGetScrollerKnobProportion(table->hscroll);
279 ovalue = WMGetScrollerValue(table->hscroll);
281 prop = (float)vsize.width / (float)size.width;
282 value = prop * ovalue / oprop;
284 WMSetScrollerParameters(table->hscroll, value, prop);
287 if (table->vscroll) {
288 if (size.height <= vsize.height) {
292 oprop = WMGetScrollerKnobProportion(table->vscroll);
295 ovalue = WMGetScrollerValue(table->vscroll);
297 prop = (float)vsize.height / (float)size.height;
298 value = prop * ovalue / oprop;
300 WMSetScrollerParameters(table->vscroll, value, prop);
304 static void doScroll(WMWidget * self, void *data)
306 WMTableView *table = (WMTableView *) data;
310 WMSize ts = getTotalSize(table);
312 value = WMGetScrollerValue(self);
314 if (table->hscroll == (WMScroller *) self) {
315 vpsize = W_VIEW_WIDTH(table->tableView);
318 vpsize = W_VIEW_HEIGHT(table->tableView);
322 switch (WMGetScrollerHitPart(self)) {
323 case WSDecrementWheel:
324 case WSDecrementLine:
325 value -= (float)table->rowHeight / size;
328 WMSetScrollerParameters(self, value, WMGetScrollerKnobProportion(self));
332 case WSIncrementWheel:
333 case WSIncrementLine:
334 value += (float)table->rowHeight / size;
337 WMSetScrollerParameters(self, value, WMGetScrollerKnobProportion(self));
345 case WSDecrementPage:
346 value -= vpsize / size;
349 WMSetScrollerParameters(self, value, WMGetScrollerKnobProportion(self));
353 case WSIncrementPage:
354 value += vpsize / size;
357 WMSetScrollerParameters(self, value, WMGetScrollerKnobProportion(self));
366 if (table->editingRow >= 0) {
368 for (i = 0; i < WMGetArrayItemCount(table->columns); i++) {
369 WMTableColumn *column;
371 column = WMGetFromArray(table->columns, i);
373 if (column->delegate && column->delegate->beginCellEdit)
374 (*column->delegate->beginCellEdit) (column->delegate, column, table->editingRow);
378 if (table->hscroll == self) {
381 WMRect rect = getVisibleRect(table);
383 for (i = 0; i < WMGetArrayItemCount(table->columns); i++) {
384 WMTableColumn *column;
387 column = WMGetFromArray(table->columns, i);
389 WMMoveWidget(column->titleW, x - rect.pos.x, 0);
391 x += W_VIEW_WIDTH(WMWidgetView(column->titleW)) + 1;
393 splitter = WMGetFromArray(table->splitters, i);
394 W_MoveView(splitter, x - rect.pos.x - 1, 0);
399 static void splitterHandler(XEvent * event, void *data)
401 WMTableColumn *column = (WMTableColumn *) data;
402 WMTableView *table = column->table;
406 WMScreen *scr = WMWidgetScreen(table);
408 Display *dpy = WMScreenDisplay(scr);
409 int h = WMWidgetHeight(table) - 22;
410 Window w = WMViewXID(table->view);
412 pos = WMGetViewPosition(WMWidgetView(column->titleW));
414 offsX = pos.x + column->width;
418 XDrawLine(dpy, w, gc, cx + 20, 0, cx + 20, h);
423 WMMaskEvent(dpy, ButtonMotionMask | ButtonReleaseMask, &ev);
429 if (column->width + ev.xmotion.x < column->minWidth)
430 cx = pos.x + column->minWidth;
431 else if (column->maxWidth > 0 && column->width + ev.xmotion.x > column->maxWidth)
432 cx = pos.x + column->maxWidth;
434 cx = offsX + ev.xmotion.x;
436 XDrawLine(dpy, w, gc, ox + 20, 0, ox + 20, h);
437 XDrawLine(dpy, w, gc, cx + 20, 0, cx + 20, h);
441 column->width = cx - pos.x;
447 XDrawLine(dpy, w, gc, cx + 20, 0, cx + 20, h);
448 rearrangeHeader(table);
452 static void realizeTable(void *data, WMNotification * notif)
457 WMTableView *WMCreateTableView(WMWidget * parent)
459 WMTableView *table = wmalloc(sizeof(WMTableView));
460 WMScreen *scr = WMWidgetScreen(parent);
462 memset(table, 0, sizeof(WMTableView));
465 tableClass = W_RegisterUserWidget();
467 table->widgetClass = tableClass;
469 table->view = W_CreateView(W_VIEW(parent));
472 table->view->self = table;
474 table->view->delegate = &viewDelegate;
476 table->headerHeight = 20;
478 table->hscroll = WMCreateScroller(table);
479 WMSetScrollerAction(table->hscroll, doScroll, table);
480 WMMoveWidget(table->hscroll, 1, 2 + table->headerHeight);
481 WMMapWidget(table->hscroll);
483 table->hasHScroller = 1;
485 table->vscroll = WMCreateScroller(table);
486 WMSetScrollerArrowsPosition(table->vscroll, WSAMaxEnd);
487 WMSetScrollerAction(table->vscroll, doScroll, table);
488 WMMoveWidget(table->vscroll, 1, 2 + table->headerHeight);
489 WMMapWidget(table->vscroll);
491 table->hasVScroller = 1;
493 table->header = WMCreateFrame(table);
494 WMMoveWidget(table->header, 22, 2);
495 WMMapWidget(table->header);
496 WMSetFrameRelief(table->header, WRFlat);
498 table->corner = WMCreateLabel(table);
499 WMResizeWidget(table->corner, 20, table->headerHeight);
500 WMMoveWidget(table->corner, 2, 2);
501 WMMapWidget(table->corner);
502 WMSetLabelRelief(table->corner, WRRaised);
503 WMSetWidgetBackgroundColor(table->corner, scr->darkGray);
505 table->tableView = W_CreateView(table->view);
506 if (!table->tableView)
508 table->tableView->self = table;
509 W_MapView(table->tableView);
511 WMAddNotificationObserver(realizeTable, table, WMViewRealizedNotification, table->tableView);
513 table->tableView->flags.dontCompressExpose = 1;
515 table->gridColor = WMCreateNamedColor(scr, "#cccccc", False);
516 /* table->gridColor = WMGrayColor(scr); */
521 table->backColor = WMWhiteColor(scr);
523 gcv.foreground = WMColorPixel(table->gridColor);
525 gcv.line_style = LineOnOffDash;
526 table->gridGC = XCreateGC(WMScreenDisplay(scr), W_DRAWABLE(scr), GCForeground, &gcv);
529 table->editingRow = -1;
530 table->clickedRow = -1;
532 table->drawsGrid = 1;
533 table->rowHeight = 16;
535 table->tableWidth = 1;
537 table->columns = WMCreateArray(4);
538 table->splitters = WMCreateArray(4);
540 table->selectedRows = WMCreateArray(16);
542 table->splitterCursor = XCreateFontCursor(WMScreenDisplay(scr), XC_sb_h_double_arrow);
544 table->canSelectRow = 1;
546 WMCreateEventHandler(table->view, ExposureMask | StructureNotifyMask, handleEvents, table);
548 WMCreateEventHandler(table->tableView, ExposureMask | ButtonPressMask |
549 ButtonReleaseMask | ButtonMotionMask, handleTableEvents, table);
551 WMResizeWidget(table, 50, 50);
556 if (table->tableView)
557 W_DestroyView(table->tableView);
559 W_DestroyView(table->view);
564 void WMAddTableViewColumn(WMTableView * table, WMTableColumn * column)
566 WMScreen *scr = WMWidgetScreen(table);
568 column->table = table;
570 WMAddToArray(table->columns, column);
572 if (!column->titleW) {
573 column->titleW = WMCreateLabel(table);
574 WMSetLabelRelief(column->titleW, WRRaised);
575 WMSetLabelFont(column->titleW, scr->boldFont);
576 WMSetLabelTextColor(column->titleW, scr->white);
577 WMSetWidgetBackgroundColor(column->titleW, scr->darkGray);
578 WMSetLabelText(column->titleW, column->title);
579 W_ReparentView(WMWidgetView(column->titleW), WMWidgetView(table->header), 0, 0);
580 if (W_VIEW_REALIZED(table->view))
581 WMRealizeWidget(column->titleW);
582 WMMapWidget(column->titleW);
586 WMView *splitter = W_CreateView(WMWidgetView(table->header));
588 W_SetViewBackgroundColor(splitter, WMWhiteColor(scr));
590 if (W_VIEW_REALIZED(table->view))
591 W_RealizeView(splitter);
593 W_ResizeView(splitter, 2, table->headerHeight);
596 W_SetViewCursor(splitter, table->splitterCursor);
597 WMCreateEventHandler(splitter, ButtonPressMask | ButtonReleaseMask, splitterHandler, column);
599 WMAddToArray(table->splitters, splitter);
602 rearrangeHeader(table);
605 void WMSetTableViewHeaderHeight(WMTableView * table, unsigned height)
607 table->headerHeight = height;
609 handleResize(NULL, table->view);
612 void WMSetTableViewDelegate(WMTableView * table, WMTableViewDelegate * delegate)
614 table->delegate = delegate;
617 void WMSetTableViewAction(WMTableView * table, WMAction * action, void *clientData)
619 table->action = action;
621 table->clientData = clientData;
624 void *WMGetTableViewClickedColumn(WMTableView * table)
626 return table->clickedColumn;
629 int WMGetTableViewClickedRow(WMTableView * table)
631 return table->clickedRow;
634 WMArray *WMGetTableViewSelectedRows(WMTableView * table)
636 return table->selectedRows;
639 WMView *WMGetTableViewDocumentView(WMTableView * table)
641 return table->tableView;
644 void *WMTableViewDataForCell(WMTableView * table, WMTableColumn * column, int row)
646 return (*table->delegate->valueForCell) (table->delegate, column, row);
649 void WMSetTableViewDataForCell(WMTableView * table, WMTableColumn * column, int row, void *data)
651 (*table->delegate->setValueForCell) (table->delegate, column, row, data);
654 WMRect WMTableViewRectForCell(WMTableView * table, WMTableColumn * column, int row)
660 rect.pos.y = row * table->rowHeight;
661 rect.size.height = table->rowHeight;
663 for (i = 0; i < WMGetArrayItemCount(table->columns); i++) {
665 col = WMGetFromArray(table->columns, i);
668 rect.size.width = col->width;
672 rect.pos.x += col->width;
676 WMRect r = getVisibleRect(table);
678 rect.pos.y -= r.pos.y;
679 rect.pos.x -= r.pos.x;
685 void WMSetTableViewDataSource(WMTableView * table, void *source)
687 table->dataSource = source;
690 void *WMGetTableViewDataSource(WMTableView * table)
692 return table->dataSource;
695 void WMSetTableViewHasHorizontalScroller(WMTableView * tPtr, Bool flag)
698 if (tPtr->hasHScroller)
700 tPtr->hasHScroller = 1;
702 tPtr->hscroll = WMCreateScroller(tPtr);
703 WMSetScrollerAction(tPtr->hscroll, doScroll, tPtr);
704 WMSetScrollerArrowsPosition(tPtr->hscroll, WSAMaxEnd);
705 /* make it a horiz. scroller */
706 WMResizeWidget(tPtr->hscroll, 1, 2);
708 if (W_VIEW_REALIZED(tPtr->view)) {
709 WMRealizeWidget(tPtr->hscroll);
712 reorganizeInterior(tPtr);
714 WMMapWidget(tPtr->hscroll);
716 if (!tPtr->hasHScroller)
718 tPtr->hasHScroller = 0;
720 WMUnmapWidget(tPtr->hscroll);
721 WMDestroyWidget(tPtr->hscroll);
722 tPtr->hscroll = NULL;
724 reorganizeInterior(tPtr);
729 /* not supported by now */
730 void WMSetTableViewHasVerticalScroller(WMTableView * tPtr, Bool flag)
733 if (tPtr->hasVScroller)
735 tPtr->hasVScroller = 1;
737 tPtr->vscroll = WMCreateScroller(tPtr);
738 WMSetScrollerAction(tPtr->vscroll, doScroll, tPtr);
739 WMSetScrollerArrowsPosition(tPtr->vscroll, WSAMaxEnd);
740 /* make it a vert. scroller */
741 WMResizeWidget(tPtr->vscroll, 1, 2);
743 if (W_VIEW_REALIZED(tPtr->view)) {
744 WMRealizeWidget(tPtr->vscroll);
747 reorganizeInterior(tPtr);
749 WMMapWidget(tPtr->vscroll);
751 if (!tPtr->hasVScroller)
753 tPtr->hasVScroller = 0;
755 WMUnmapWidget(tPtr->vscroll);
756 WMDestroyWidget(tPtr->vscroll);
757 tPtr->vscroll = NULL;
759 reorganizeInterior(tPtr);
764 void WMSetTableViewBackgroundColor(WMTableView * table, WMColor * color)
766 W_SetViewBackgroundColor(table->tableView, color);
768 if (table->backColor)
769 WMReleaseColor(table->backColor);
771 table->backColor = WMRetainColor(color);
776 void WMSetTableViewGridColor(WMTableView * table, WMColor * color)
778 WMReleaseColor(table->gridColor);
779 table->gridColor = WMRetainColor(color);
780 XSetForeground(WMScreenDisplay(WMWidgetScreen(table)), table->gridGC, WMColorPixel(color));
784 void WMSetTableViewRowHeight(WMTableView * table, int height)
786 table->rowHeight = height;
791 void WMScrollTableViewRowToVisible(WMTableView * table, int row)
793 WMScroller *scroller;
798 rect = getVisibleRect(table);
799 range = rowsInRect(table, rect);
801 scroller = table->vscroll;
803 if (row < range.position) {
804 newY = row * table->rowHeight - rect.size.height / 2;
805 } else if (row >= range.position + range.count) {
806 newY = row * table->rowHeight - rect.size.height / 2;
810 tmp = table->rows * table->rowHeight - rect.size.height;
811 newY = WMAX(0, WMIN(newY, tmp));
813 scrollToPoint(table, rect.pos.x, newY);
816 static void drawGrid(WMTableView * table, WMRect rect)
818 WMScreen *scr = WMWidgetScreen(table);
819 Display *dpy = WMScreenDisplay(scr);
824 Drawable d = WMGetPixmapXID(table->viewBuffer);
825 GC gc = table->gridGC;
828 char dashl[1] = { 1 };
830 XSetDashes(dpy, gc, 0, dashl, 1);
832 y1 = (rect.pos.y / table->rowHeight - 1) * table->rowHeight;
833 y2 = y1 + (rect.size.height / table->rowHeight + 2) * table->rowHeight;
836 y2 = W_VIEW_HEIGHT(table->tableView);
839 for (i = 0; i < WMGetArrayItemCount(table->columns); i++) {
840 WMTableColumn *column;
842 XDrawLine(dpy, d, gc, xx, y1, xx, y2);
844 column = WMGetFromArray(table->columns, i);
847 XDrawLine(dpy, d, gc, xx, y1, xx, y2);
850 x2 = rect.size.width;
855 XSetDashes(dpy, gc, (rect.pos.x & 1), dashl, 1);
858 y1 = -rect.pos.y % table->rowHeight;
859 y2 = y1 + rect.size.height + table->rowHeight;
861 for (i = y1; i <= y2; i += table->rowHeight) {
862 XDrawLine(dpy, d, gc, x1, i, x2, i);
866 static WMRange columnsInRect(WMTableView * table, WMRect rect)
868 WMTableColumn *column;
871 int totalColumns = WMGetArrayItemCount(table->columns);
876 for (i = 0; i < totalColumns; i++) {
877 column = WMGetFromArray(table->columns, i);
879 if (rect.pos.x >= pos && rect.pos.x < pos + column->width) {
885 if (pos > rect.pos.x + rect.size.width) {
890 pos += column->width;
892 range.count = WMAX(1, WMIN(range.count, totalColumns - range.position));
896 static WMRange rowsInRect(WMTableView * table, WMRect rect)
899 int rh = table->rowHeight;
902 dif = rect.pos.y % rh;
904 range.position = WMAX(0, (rect.pos.y - dif) / rh);
905 range.count = WMAX(1, WMIN((rect.size.height + dif) / rh, table->rows));
910 static void drawRow(WMTableView * table, int row, WMRect clipRect)
913 WMRange cols = columnsInRect(table, clipRect);
914 WMTableColumn *column;
915 Drawable d = WMGetPixmapXID(table->viewBuffer);
917 for (i = cols.position; i < cols.position + cols.count; i++) {
918 column = WMGetFromArray(table->columns, i);
920 if (!column->delegate || !column->delegate->drawCell)
923 if (WMFindInArray(table->selectedRows, NULL, (void *)(uintptr_t) row) != WANotFound)
924 (*column->delegate->drawSelectedCell) (column->delegate, column, row, d);
926 (*column->delegate->drawCell) (column->delegate, column, row, d);
931 static void drawFullRow(WMTableView * table, int row)
934 WMTableColumn *column;
935 Drawable d = WMGetPixmapXID(table->viewBuffer);
937 for (i = 0; i < WMGetArrayItemCount(table->columns); i++) {
938 column = WMGetFromArray(table->columns, i);
940 if (!column->delegate || !column->delegate->drawCell)
943 if (WMFindInArray(table->selectedRows, NULL, (void *)row) != WANotFound)
944 (*column->delegate->drawSelectedCell) (column->delegate, column, row, d);
946 (*column->delegate->drawCell) (column->delegate, column, row, d);
951 static void setRowSelected(WMTableView * table, unsigned row, Bool flag)
955 if (WMFindInArray(table->selectedRows, NULL, (void *)(uintptr_t) row) != WANotFound) {
957 WMRemoveFromArray(table->selectedRows, (void *)(uintptr_t) row);
962 WMAddToArray(table->selectedRows, (void *)(uintptr_t) row);
966 if (repaint && row < table->rows) {
967 /*drawFullRow(table, row); */
972 static void repaintTable(WMTableView * table)
976 WMScreen *scr = WMWidgetScreen(table);
979 if (!table->delegate || !W_VIEW_REALIZED(table->view))
982 wassertr(table->delegate->numberOfRows);
984 if (!table->viewBuffer) {
985 table->viewBuffer = WMCreatePixmap(scr,
986 W_VIEW_WIDTH(table->tableView),
987 W_VIEW_HEIGHT(table->tableView), WMScreenDepth(scr), 0);
990 XFillRectangle(scr->display,
991 WMGetPixmapXID(table->viewBuffer),
992 WMColorGC(table->backColor), 0, 0,
993 W_VIEW_WIDTH(table->tableView), W_VIEW_HEIGHT(table->tableView));
995 rect = getVisibleRect(table);
997 if (table->drawsGrid) {
998 drawGrid(table, rect);
1001 rows = rowsInRect(table, rect);
1002 for (i = rows.position; i < WMIN(rows.position + rows.count + 1, table->rows); i++) {
1003 drawRow(table, i, rect);
1006 XSetWindowBackgroundPixmap(scr->display, table->tableView->window, WMGetPixmapXID(table->viewBuffer));
1007 XClearWindow(scr->display, table->tableView->window);
1010 static void stopRowEdit(WMTableView * table, int row)
1013 WMTableColumn *column;
1015 table->editingRow = -1;
1016 for (i = 0; i < WMGetArrayItemCount(table->columns); i++) {
1017 column = WMGetFromArray(table->columns, i);
1019 if (column->delegate && column->delegate->endCellEdit)
1020 (*column->delegate->endCellEdit) (column->delegate, column, row);
1024 void WMEditTableViewRow(WMTableView * table, int row)
1027 WMTableColumn *column;
1029 if (table->editingRow >= 0) {
1030 stopRowEdit(table, table->editingRow);
1033 table->editingRow = row;
1038 for (i = 0; i < WMGetArrayItemCount(table->columns); i++) {
1039 column = WMGetFromArray(table->columns, i);
1041 if (column->delegate && column->delegate->beginCellEdit)
1042 (*column->delegate->beginCellEdit) (column->delegate, column, row);
1046 void WMSelectTableViewRow(WMTableView * table, int row)
1048 if (table->clickedRow >= 0)
1049 setRowSelected(table, table->clickedRow, False);
1051 if (row >= table->rows) {
1055 setRowSelected(table, row, True);
1056 table->clickedRow = row;
1059 (*table->action) (table, table->clientData);
1060 WMPostNotificationName(WMTableViewSelectionDidChangeNotification, table, NULL);
1063 void WMReloadTableView(WMTableView * table)
1065 if (table->editingRow >= 0)
1066 stopRowEdit(table, table->editingRow);
1068 /* when this is called, nothing in the table can be assumed to be
1069 * like the last time we accessed it (ie, rows might have disappeared) */
1071 WMEmptyArray(table->selectedRows);
1073 if (table->clickedRow >= 0) {
1075 (*table->action) (table, table->clientData);
1076 WMPostNotificationName(WMTableViewSelectionDidChangeNotification, table, NULL);
1077 table->clickedRow = -1;
1080 if (table->delegate && table->delegate->numberOfRows) {
1083 rows = (*table->delegate->numberOfRows) (table->delegate, table);
1085 if (rows != table->rows) {
1087 handleResize(table->view->delegate, table->view);
1089 repaintTable(table);
1094 void WMNoteTableViewNumberOfRowsChanged(WMTableView * table)
1096 WMReloadTableView(table);
1099 static void handleTableEvents(XEvent * event, void *data)
1101 WMTableView *table = (WMTableView *) data;
1104 switch (event->type) {
1106 if (event->xbutton.button == Button1) {
1107 WMRect rect = getVisibleRect(table);
1109 row = (event->xbutton.y + rect.pos.y) / table->rowHeight;
1110 if (row != table->clickedRow) {
1111 setRowSelected(table, table->clickedRow, False);
1112 setRowSelected(table, row, True);
1113 table->clickedRow = row;
1114 table->dragging = 1;
1116 table->dragging = 1;
1122 if (table->dragging && event->xmotion.y >= 0) {
1123 WMRect rect = getVisibleRect(table);
1125 row = (event->xmotion.y + rect.pos.y) / table->rowHeight;
1126 if (table->clickedRow != row && row >= 0 && row < table->rows) {
1127 setRowSelected(table, table->clickedRow, False);
1128 setRowSelected(table, row, True);
1129 table->clickedRow = row;
1135 if (event->xbutton.button == Button1) {
1137 (*table->action) (table, table->clientData);
1138 WMPostNotificationName(WMTableViewSelectionDidChangeNotification, table, NULL);
1139 table->dragging = 0;
1145 static void handleEvents(XEvent * event, void *data)
1147 WMTableView *table = (WMTableView *) data;
1148 WMScreen *scr = WMWidgetScreen(table);
1150 switch (event->type) {
1152 W_DrawRelief(scr, W_VIEW_DRAWABLE(table->view), 0, 0,
1153 W_VIEW_WIDTH(table->view), W_VIEW_HEIGHT(table->view), WRSunken);
1158 static void handleResize(W_ViewDelegate * self, WMView * view)
1160 reorganizeInterior(view->self);
1163 static void reorganizeInterior(WMTableView * table)
1167 WMSize size = getTotalSize(table);
1168 WMView *view = table->view;
1170 int hsThickness, vsThickness;
1173 vsThickness = WMWidgetWidth(table->vscroll);
1175 hsThickness = WMWidgetHeight(table->hscroll);
1177 width = W_VIEW_WIDTH(view) - 2;
1178 height = W_VIEW_HEIGHT(view) - 3;
1180 height -= table->headerHeight; /* table header */
1183 WMResizeWidget(table->corner, 20, table->headerHeight);
1185 WMMoveWidget(table->vscroll, 1, table->headerHeight + 1);
1186 WMResizeWidget(table->vscroll, 20, height + 1);
1188 if (table->hscroll) {
1189 WMMoveWidget(table->hscroll, vsThickness, W_VIEW_HEIGHT(view) - hsThickness - 1);
1190 WMResizeWidget(table->hscroll, width - (vsThickness + 1), hsThickness);
1194 WMResizeWidget(table->header, width - (vsThickness + 1), table->headerHeight);
1196 if (table->viewBuffer) {
1197 WMReleasePixmap(table->viewBuffer);
1198 table->viewBuffer = NULL;
1201 width -= vsThickness;
1202 height -= hsThickness;
1204 vw = WMIN(size.width, width);
1205 vh = WMIN(size.height, height);
1207 W_MoveView(table->tableView, vsThickness + 1, 1 + table->headerHeight + 1);
1208 W_ResizeView(table->tableView, WMAX(vw, 1), WMAX(vh, 1) + 1);
1210 adjustScrollers(table);
1212 repaintTable(table);
1215 static void rearrangeHeader(WMTableView * table)
1220 /*WMRect rect = WMGetScrollViewVisibleRect(table->scrollView); */
1224 count = WMGetArrayItemCount(table->columns);
1225 for (i = 0; i < count; i++) {
1226 WMTableColumn *column = WMGetFromArray(table->columns, i);
1227 WMView *splitter = WMGetFromArray(table->splitters, i);
1229 WMMoveWidget(column->titleW, width, 0);
1230 WMResizeWidget(column->titleW, column->width - 1, table->headerHeight);
1232 width += column->width;
1233 W_MoveView(splitter, width - 1, 0);
1236 wassertr(table->delegate && table->delegate->numberOfRows);
1238 table->rows = table->delegate->numberOfRows(table->delegate, table);
1240 table->tableWidth = width + 1;
1242 handleResize(table->view->delegate, table->view);