3 #include <WINGs/WINGsP.h>
4 #include <X11/cursorfont.h>
6 #include "wtableview.h"
9 const char *WMTableViewSelectionDidChangeNotification
= "WMTableViewSelectionDidChangeNotification";
12 struct W_TableColumn
{
22 WMTableColumnDelegate
*delegate
;
30 static void handleResize(W_ViewDelegate
*self
, WMView
*view
);
32 static void rearrangeHeader(WMTableView
*table
);
34 static WMRange
rowsInRect(WMTableView
*table
, WMRect rect
);
37 WMTableColumn
*WMCreateTableColumn(char *title
)
39 WMTableColumn
*col
= wmalloc(sizeof(WMTableColumn
));
49 col
->title
= wstrdup(title
);
60 void WMSetTableColumnId(WMTableColumn
*column
, void *id
)
66 void *WMGetTableColumnId(WMTableColumn
*column
)
72 void WMSetTableColumnWidth(WMTableColumn
*column
, unsigned width
)
74 if (column
->maxWidth
== 0)
75 column
->width
= WMAX(column
->minWidth
, width
);
77 column
->width
= WMAX(column
->minWidth
, WMIN(column
->maxWidth
, width
));
80 rearrangeHeader(column
->table
);
85 void WMSetTableColumnDelegate(WMTableColumn
*column
,
86 WMTableColumnDelegate
*delegate
)
88 column
->delegate
= delegate
;
92 void WMSetTableColumnConstraints(WMTableColumn
*column
,
93 unsigned minWidth
, unsigned maxWidth
)
95 wassertr(minWidth
<= maxWidth
);
97 column
->minWidth
= minWidth
;
98 column
->maxWidth
= maxWidth
;
100 if (column
->width
< column
->minWidth
)
101 WMSetTableColumnWidth(column
, column
->minWidth
);
102 else if (column
->width
> column
->maxWidth
|| column
->maxWidth
== 0)
103 WMSetTableColumnWidth(column
, column
->maxWidth
);
107 void WMSetTableColumnEditable(WMTableColumn
*column
, Bool flag
)
109 column
->editable
= flag
;
113 WMTableView
*WMGetTableColumnTableView(WMTableColumn
*column
)
115 return column
->table
;
128 WMScrollView
*scrollView
;
134 WMArray
*selectedRows
;
143 Cursor splitterCursor
;
147 WMTableViewDelegate
*delegate
;
157 unsigned headerHeight
;
162 unsigned drawsGrid
:1;
163 unsigned canSelectRow
:1;
164 unsigned canSelectMultiRows
:1;
165 unsigned canDeselectRow
:1;
168 static W_Class tableClass
= 0;
171 static W_ViewDelegate viewDelegate
= {
183 static void handleEvents(XEvent
*event
, void *data
);
184 static void handleTableEvents(XEvent
*event
, void *data
);
187 static void scrollObserver(void *self
, WMNotification
*notif
)
189 WMTableView
*table
= (WMTableView
*)self
;
193 rect
= WMGetScrollViewVisibleRect(table
->scrollView
);
196 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
197 WMTableColumn
*column
;
200 column
= WMGetFromArray(table
->columns
, i
);
202 WMMoveWidget(column
->titleW
, x
- rect
.pos
.x
, 0);
204 x
+= W_VIEW_WIDTH(WMWidgetView(column
->titleW
)) + 1;
206 splitter
= WMGetFromArray(table
->splitters
, i
);
207 W_MoveView(splitter
, x
- rect
.pos
.x
- 1, 0);
212 static void splitterHandler(XEvent
*event
, void *data
)
214 WMTableColumn
*column
= (WMTableColumn
*)data
;
215 WMTableView
*table
= column
->table
;
219 WMScreen
*scr
= WMWidgetScreen(table
);
221 Display
*dpy
= WMScreenDisplay(scr
);
222 int h
= WMWidgetHeight(table
) - 22;
223 Window w
= WMViewXID(table
->view
);
225 pos
= WMGetViewPosition(WMWidgetView(column
->titleW
));
227 offsX
= pos
.x
+ column
->width
;
231 XDrawLine(dpy
, w
, gc
, cx
+20, 0, cx
+20, h
);
236 WMMaskEvent(dpy
, ButtonMotionMask
|ButtonReleaseMask
, &ev
);
241 if (column
->width
+ ev
.xmotion
.x
< column
->minWidth
)
242 cx
= pos
.x
+ column
->minWidth
;
244 cx
= offsX
+ ev
.xmotion
.x
;
246 if (column
->maxWidth
> 0) {
247 if (column
->width
+ ev
.xmotion
.x
> column
->maxWidth
)
248 cx
= pos
.x
+ column
->maxWidth
;
250 cx
= offsX
+ ev
.xmotion
.x
;
253 XDrawLine(dpy
, w
, gc
, ox
+20, 0, ox
+20, h
);
254 XDrawLine(dpy
, w
, gc
, cx
+20, 0, cx
+20, h
);
258 column
->width
= cx
- pos
.x
;
259 rearrangeHeader(table
);
265 XDrawLine(dpy
, w
, gc
, cx
+20, 0, cx
+20, h
);
270 WMTableView
*WMCreateTableView(WMWidget
*parent
)
272 WMTableView
*table
= wmalloc(sizeof(WMTableView
));
273 WMScreen
*scr
= WMWidgetScreen(parent
);
275 memset(table
, 0, sizeof(WMTableView
));
278 tableClass
= W_RegisterUserWidget();
280 table
->widgetClass
= tableClass
;
282 table
->view
= W_CreateView(W_VIEW(parent
));
285 table
->view
->self
= table
;
287 table
->view
->delegate
= &viewDelegate
;
289 table
->headerHeight
= 20;
291 table
->scrollView
= WMCreateScrollView(table
);
292 if (!table
->scrollView
)
294 WMResizeWidget(table
->scrollView
, 10, 10);
295 WMSetScrollViewHasVerticalScroller(table
->scrollView
, True
);
296 WMSetScrollViewHasHorizontalScroller(table
->scrollView
, True
);
298 WMScroller
*scroller
;
299 scroller
= WMGetScrollViewHorizontalScroller(table
->scrollView
);
300 WMAddNotificationObserver(scrollObserver
, table
,
301 WMScrollerDidScrollNotification
,
304 WMMoveWidget(table
->scrollView
, 1, 2+table
->headerHeight
);
305 WMMapWidget(table
->scrollView
);
307 table
->header
= WMCreateFrame(table
);
308 WMMoveWidget(table
->header
, 22, 2);
309 WMMapWidget(table
->header
);
310 WMSetFrameRelief(table
->header
, WRFlat
);
312 table
->corner
= WMCreateLabel(table
);
313 WMResizeWidget(table
->corner
, 20, table
->headerHeight
);
314 WMMoveWidget(table
->corner
, 2, 2);
315 WMMapWidget(table
->corner
);
316 WMSetLabelRelief(table
->corner
, WRRaised
);
317 WMSetWidgetBackgroundColor(table
->corner
, scr
->darkGray
);
320 table
->tableView
= W_CreateView(W_VIEW(parent
));
321 if (!table
->tableView
)
323 table
->tableView
->self
= table
;
324 W_ResizeView(table
->tableView
, 100, 1000);
325 W_MapView(table
->tableView
);
327 table
->tableView
->flags
.dontCompressExpose
= 1;
329 table
->gridColor
= WMCreateNamedColor(scr
, "#cccccc", False
);
330 /* table->gridColor = WMGrayColor(scr);*/
335 gcv
.foreground
= WMColorPixel(table
->gridColor
);
337 gcv
.line_style
= LineOnOffDash
;
338 table
->gridGC
= XCreateGC(WMScreenDisplay(scr
), W_DRAWABLE(scr
),
342 table
->editingRow
= -1;
343 table
->clickedRow
= -1;
345 table
->drawsGrid
= 1;
346 table
->rowHeight
= 16;
348 WMSetScrollViewLineScroll(table
->scrollView
, table
->rowHeight
);
350 table
->tableWidth
= 1;
352 table
->columns
= WMCreateArray(4);
353 table
->splitters
= WMCreateArray(4);
355 table
->selectedRows
= WMCreateArray(16);
357 table
->splitterCursor
= XCreateFontCursor(WMScreenDisplay(scr
),
358 XC_sb_h_double_arrow
);
360 table
->canSelectRow
= 1;
362 WMCreateEventHandler(table
->view
, ExposureMask
|StructureNotifyMask
,
363 handleEvents
, table
);
365 WMCreateEventHandler(table
->tableView
, ExposureMask
|ButtonPressMask
|
366 ButtonReleaseMask
|ButtonMotionMask
,
367 handleTableEvents
, table
);
369 WMSetScrollViewContentView(table
->scrollView
, table
->tableView
);
374 if (table
->scrollView
)
375 WMDestroyWidget(table
->scrollView
);
376 if (table
->tableView
)
377 W_DestroyView(table
->tableView
);
379 W_DestroyView(table
->view
);
385 void WMAddTableViewColumn(WMTableView
*table
, WMTableColumn
*column
)
389 WMScreen
*scr
= WMWidgetScreen(table
);
392 column
->table
= table
;
394 WMAddToArray(table
->columns
, column
);
396 if (!column
->titleW
) {
397 column
->titleW
= WMCreateLabel(table
);
398 WMSetLabelRelief(column
->titleW
, WRRaised
);
399 WMSetLabelFont(column
->titleW
, scr
->boldFont
);
400 WMSetLabelTextColor(column
->titleW
, scr
->white
);
401 WMSetWidgetBackgroundColor(column
->titleW
, scr
->darkGray
);
402 WMSetLabelText(column
->titleW
, column
->title
);
403 W_ReparentView(WMWidgetView(column
->titleW
),
404 WMWidgetView(table
->header
), 0, 0);
405 if (W_VIEW_REALIZED(table
->view
))
406 WMRealizeWidget(column
->titleW
);
407 WMMapWidget(column
->titleW
);
411 WMView
*splitter
= W_CreateView(WMWidgetView(table
->header
));
413 W_SetViewBackgroundColor(splitter
, WMWhiteColor(scr
));
415 if (W_VIEW_REALIZED(table
->view
))
416 W_RealizeView(splitter
);
418 W_ResizeView(splitter
, 2, table
->headerHeight
-1);
421 W_SetViewCursor(splitter
, table
->splitterCursor
);
422 WMCreateEventHandler(splitter
, ButtonPressMask
|ButtonReleaseMask
,
423 splitterHandler
, column
);
425 WMAddToArray(table
->splitters
, splitter
);
428 rearrangeHeader(table
);
432 void WMSetTableViewHeaderHeight(WMTableView
*table
, unsigned height
)
434 table
->headerHeight
= height
;
436 handleResize(NULL
, table
->view
);
440 void WMSetTableViewDelegate(WMTableView
*table
, WMTableViewDelegate
*delegate
)
442 table
->delegate
= delegate
;
446 void WMSetTableViewAction(WMTableView
*table
, WMAction
*action
, void *clientData
)
448 table
->action
= action
;
450 table
->clientData
= clientData
;
454 void *WMGetTableViewClickedColumn(WMTableView
*table
)
456 return table
->clickedColumn
;
460 int WMGetTableViewClickedRow(WMTableView
*table
)
462 return table
->clickedRow
;
466 WMArray
*WMGetTableViewSelectedRows(WMTableView
*table
)
468 return table
->selectedRows
;
472 WMView
*WMGetTableViewDocumentView(WMTableView
*table
)
474 return table
->tableView
;
478 void *WMTableViewDataForCell(WMTableView
*table
, WMTableColumn
*column
,
481 return (*table
->delegate
->valueForCell
)(table
->delegate
, column
, row
);
485 void WMSetTableViewDataForCell(WMTableView
*table
, WMTableColumn
*column
,
488 (*table
->delegate
->setValueForCell
)(table
->delegate
, column
, row
, data
);
492 WMRect
WMTableViewRectForCell(WMTableView
*table
, WMTableColumn
*column
,
499 rect
.pos
.y
= row
* table
->rowHeight
;
500 rect
.size
.height
= table
->rowHeight
;
502 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
504 col
= WMGetFromArray(table
->columns
, i
);
507 rect
.size
.width
= col
->width
;
511 rect
.pos
.x
+= col
->width
;
517 void WMSetTableViewDataSource(WMTableView
*table
, void *source
)
519 table
->dataSource
= source
;
523 void *WMGetTableViewDataSource(WMTableView
*table
)
525 return table
->dataSource
;
529 void WMSetTableViewBackgroundColor(WMTableView
*table
, WMColor
*color
)
531 W_SetViewBackgroundColor(table
->tableView
, color
);
535 void WMSetTableViewGridColor(WMTableView
*table
, WMColor
*color
)
537 WMReleaseColor(table
->gridColor
);
538 table
->gridColor
= WMRetainColor(color
);
539 XSetForeground(WMScreenDisplay(WMWidgetScreen(table
)), table
->gridGC
,
540 WMColorPixel(color
));
545 void WMSetTableViewRowHeight(WMTableView
*table
, int height
)
547 table
->rowHeight
= height
;
549 WMRedisplayWidget(table
);
553 void WMScrollTableViewRowToVisible(WMTableView
*table
, int row
)
555 WMScroller
*scroller
;
560 rect
= WMGetScrollViewVisibleRect(table
->scrollView
);
561 range
= rowsInRect(table
, rect
);
563 scroller
= WMGetScrollViewVerticalScroller(table
->scrollView
);
565 if (row
< range
.position
) {
566 newY
= row
* table
->rowHeight
- rect
.size
.height
/ 2;
567 } else if (row
>= range
.position
+ range
.count
) {
568 newY
= row
* table
->rowHeight
- rect
.size
.height
/ 2;
572 tmp
= table
->rows
*table
->rowHeight
- rect
.size
.height
;
573 newY
= WMAX(0, WMIN(newY
, tmp
));
574 WMScrollViewScrollPoint(table
->scrollView
, rect
.pos
.x
, newY
);
579 static void drawGrid(WMTableView
*table
, WMRect rect
)
581 WMScreen
*scr
= WMWidgetScreen(table
);
582 Display
*dpy
= WMScreenDisplay(scr
);
587 Drawable d
= W_VIEW_DRAWABLE(table
->tableView
);
588 GC gc
= table
->gridGC
;
593 XSetDashes(dpy
, gc
, 0, dashl
, 1);
595 y1
= (rect
.pos
.y
/table
->rowHeight
- 1)*table
->rowHeight
;
596 y2
= y1
+ (rect
.size
.height
/table
->rowHeight
+2)*table
->rowHeight
;
599 y2
= W_VIEW_HEIGHT(table
->tableView
);
602 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
603 WMTableColumn
*column
;
605 if (xx
>= rect
.pos
.x
&& xx
<= rect
.pos
.x
+rect
.size
.width
) {
606 XDrawLine(dpy
, d
, gc
, xx
, y1
, xx
, y2
);
608 column
= WMGetFromArray(table
->columns
, i
);
611 XDrawLine(dpy
, d
, gc
, xx
, y1
, xx
, y2
);
615 x2
= WMIN(x1
+ rect
.size
.width
, xx
);
620 XSetDashes(dpy
, gc
, (rect
.pos
.x
&1), dashl
, 1);
623 y1
= rect
.pos
.y
- rect
.pos
.y
%table
->rowHeight
;
624 y2
= y1
+ rect
.size
.height
+ table
->rowHeight
;
626 for (i
= y1
; i
<= y2
; i
+= table
->rowHeight
) {
627 XDrawLine(dpy
, d
, gc
, x1
, i
, x2
, i
);
632 static WMRange
columnsInRect(WMTableView
*table
, WMRect rect
)
634 WMTableColumn
*column
;
637 int totalColumns
= WMGetArrayItemCount(table
->columns
);
642 for (i
= 0; i
< totalColumns
; i
++) {
643 column
= WMGetFromArray(table
->columns
, i
);
645 if (width
<= rect
.pos
.x
&& width
+ column
->width
> rect
.pos
.x
) {
651 if (width
> rect
.pos
.x
+ rect
.size
.width
) {
655 width
+= column
->width
;
657 range
.count
= WMAX(1, WMIN(range
.count
, totalColumns
- range
.position
));
662 static WMRange
rowsInRect(WMTableView
*table
, WMRect rect
)
665 int rh
= table
->rowHeight
;
668 dif
= rect
.pos
.y
% rh
;
670 range
.position
= WMAX(0, (rect
.pos
.y
- dif
) / rh
);
671 range
.count
= WMAX(1, WMIN((rect
.size
.height
+ dif
) / rh
, table
->rows
));
677 static void drawRow(WMTableView
*table
, int row
, WMRect clipRect
)
680 WMRange cols
= columnsInRect(table
, clipRect
);
681 WMTableColumn
*column
;
683 for (i
= cols
.position
; i
< cols
.position
+cols
.count
; i
++) {
684 column
= WMGetFromArray(table
->columns
, i
);
686 wassertr(column
->delegate
&& column
->delegate
->drawCell
);
688 if (WMFindInArray(table
->selectedRows
, NULL
, (void*)row
) != WANotFound
)
689 (*column
->delegate
->drawSelectedCell
)(column
->delegate
, column
, row
);
691 (*column
->delegate
->drawCell
)(column
->delegate
, column
, row
);
696 static void drawFullRow(WMTableView
*table
, int row
)
699 WMTableColumn
*column
;
701 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
702 column
= WMGetFromArray(table
->columns
, i
);
704 wassertr(column
->delegate
&& column
->delegate
->drawCell
);
706 if (WMFindInArray(table
->selectedRows
, NULL
, (void*)row
) != WANotFound
)
707 (*column
->delegate
->drawSelectedCell
)(column
->delegate
, column
, row
);
709 (*column
->delegate
->drawCell
)(column
->delegate
, column
, row
);
714 static void setRowSelected(WMTableView
*table
, unsigned row
, Bool flag
)
718 if (WMFindInArray(table
->selectedRows
, NULL
, (void*)row
) != WANotFound
) {
720 WMRemoveFromArray(table
->selectedRows
, (void*)row
);
725 WMAddToArray(table
->selectedRows
, (void*)row
);
729 if (repaint
&& row
< table
->rows
) {
730 drawFullRow(table
, row
);
735 static void repaintTable(WMTableView
*table
, int x
, int y
,
736 int width
, int height
)
742 wassertr(table
->delegate
&& table
->delegate
->numberOfRows
);
743 i
= (*table
->delegate
->numberOfRows
)(table
->delegate
, table
);
745 if (i
!= table
->rows
) {
747 W_ResizeView(table
->tableView
, table
->tableWidth
,
748 table
->rows
* table
->rowHeight
+ 1);
752 if (x
>= table
->tableWidth
-1)
755 rect
.pos
= wmkpoint(x
,y
);
756 rect
.size
= wmksize(width
, height
);
758 if (table
->drawsGrid
) {
759 drawGrid(table
, rect
);
762 rows
= rowsInRect(table
, rect
);
763 for (i
= rows
.position
;
764 i
< WMIN(rows
.position
+rows
.count
+ 1, table
->rows
);
766 drawRow(table
, i
, rect
);
771 static void stopRowEdit(WMTableView
*table
, int row
)
774 WMTableColumn
*column
;
776 table
->editingRow
= -1;
777 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
778 column
= WMGetFromArray(table
->columns
, i
);
780 if (column
->delegate
&& column
->delegate
->endCellEdit
)
781 (*column
->delegate
->endCellEdit
)(column
->delegate
, column
, row
);
787 void WMEditTableViewRow(WMTableView
*table
, int row
)
790 WMTableColumn
*column
;
792 if (table
->editingRow
>= 0) {
793 stopRowEdit(table
, table
->editingRow
);
796 table
->editingRow
= row
;
801 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
802 column
= WMGetFromArray(table
->columns
, i
);
804 if (column
->delegate
&& column
->delegate
->beginCellEdit
)
805 (*column
->delegate
->beginCellEdit
)(column
->delegate
, column
, row
);
810 void WMSelectTableViewRow(WMTableView
*table
, int row
)
812 if (table
->clickedRow
>= 0)
813 setRowSelected(table
, table
->clickedRow
, False
);
815 if (row
>= table
->rows
) {
819 setRowSelected(table
, row
, True
);
820 table
->clickedRow
= row
;
823 (*table
->action
)(table
, table
->clientData
);
824 WMPostNotificationName(WMTableViewSelectionDidChangeNotification
,
829 void WMReloadTableView(WMTableView
*table
)
831 WMRect rect
= WMGetScrollViewVisibleRect(table
->scrollView
);
833 if (table
->editingRow
>= 0)
834 stopRowEdit(table
, table
->editingRow
);
836 /* when this is called, nothing in the table can be assumed to be
837 * like the last time we accessed it (ie, rows might have disappeared) */
839 WMEmptyArray(table
->selectedRows
);
841 if (table
->clickedRow
>= 0) {
842 table
->clickedRow
= -1;
845 (*table
->action
)(table
, table
->clientData
);
846 WMPostNotificationName(WMTableViewSelectionDidChangeNotification
,
850 repaintTable(table
, 0, 0,
851 W_VIEW_WIDTH(table
->tableView
), rect
.size
.height
);
855 void WMNoteTableViewNumberOfRowsChanged(WMTableView
*table
)
857 WMReloadTableView(table
);
861 static void handleTableEvents(XEvent
*event
, void *data
)
863 WMTableView
*table
= (WMTableView
*)data
;
866 switch (event
->type
) {
868 if (event
->xbutton
.button
== Button1
) {
869 row
= event
->xbutton
.y
/table
->rowHeight
;
870 if (row
!= table
->clickedRow
) {
871 setRowSelected(table
, table
->clickedRow
, False
);
872 setRowSelected(table
, row
, True
);
873 table
->clickedRow
= row
;
880 if (table
->dragging
&& event
->xmotion
.y
>= 0) {
881 row
= event
->xmotion
.y
/table
->rowHeight
;
882 if (table
->clickedRow
!= row
&& row
>= 0) {
883 setRowSelected(table
, table
->clickedRow
, False
);
884 setRowSelected(table
, row
, True
);
885 table
->clickedRow
= row
;
891 if (event
->xbutton
.button
== Button1
) {
893 (*table
->action
)(table
, table
->clientData
);
894 WMPostNotificationName(WMTableViewSelectionDidChangeNotification
,
901 repaintTable(table
, event
->xexpose
.x
, event
->xexpose
.y
,
902 event
->xexpose
.width
, event
->xexpose
.height
);
908 static void handleEvents(XEvent
*event
, void *data
)
910 WMTableView
*table
= (WMTableView
*)data
;
911 WMScreen
*scr
= WMWidgetScreen(table
);
913 switch (event
->type
) {
915 W_DrawRelief(scr
, W_VIEW_DRAWABLE(table
->view
), 0, 0,
916 W_VIEW_WIDTH(table
->view
), W_VIEW_HEIGHT(table
->view
),
919 if (event
->xexpose
.serial
== 0) {
920 WMRect rect
= WMGetScrollViewVisibleRect(table
->scrollView
);
922 repaintTable(table
, rect
.pos
.x
, rect
.pos
.y
,
923 rect
.size
.width
, rect
.size
.height
);
930 static void handleResize(W_ViewDelegate
*self
, WMView
*view
)
934 WMTableView
*table
= view
->self
;
936 width
= W_VIEW_WIDTH(view
) - 2;
937 height
= W_VIEW_HEIGHT(view
) - 3;
939 height
-= table
->headerHeight
; /* table header */
942 WMResizeWidget(table
->corner
, 20, table
->headerHeight
);
944 if (table
->scrollView
) {
945 WMMoveWidget(table
->scrollView
, 1, table
->headerHeight
+ 2);
946 WMResizeWidget(table
->scrollView
, width
, height
);
949 WMResizeWidget(table
->header
, width
- 21, table
->headerHeight
);
953 static void rearrangeHeader(WMTableView
*table
)
958 WMRect rect
= WMGetScrollViewVisibleRect(table
->scrollView
);
962 count
= WMGetArrayItemCount(table
->columns
);
963 for (i
= 0; i
< count
; i
++) {
964 WMTableColumn
*column
= WMGetFromArray(table
->columns
, i
);
965 WMView
*splitter
= WMGetFromArray(table
->splitters
, i
);
967 WMMoveWidget(column
->titleW
, width
, 0);
968 WMResizeWidget(column
->titleW
, column
->width
-1, table
->headerHeight
);
970 width
+= column
->width
;
971 W_MoveView(splitter
, width
-1, 0);
974 wassertr(table
->delegate
&& table
->delegate
->numberOfRows
);
976 table
->rows
= table
->delegate
->numberOfRows(table
->delegate
, table
);
978 W_ResizeView(table
->tableView
, width
+1,
979 table
->rows
* table
->rowHeight
+ 1);
981 table
->tableWidth
= width
+ 1;