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(maxWidth
== 0 || 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
;
132 WMPixmap
*viewBuffer
;
137 WMArray
*selectedRows
;
148 Cursor splitterCursor
;
152 WMTableViewDelegate
*delegate
;
162 unsigned headerHeight
;
167 unsigned drawsGrid
:1;
168 unsigned canSelectRow
:1;
169 unsigned canSelectMultiRows
:1;
170 unsigned canDeselectRow
:1;
173 static W_Class tableClass
= 0;
176 static W_ViewDelegate viewDelegate
= {
188 static void handleEvents(XEvent
*event
, void *data
);
189 static void handleTableEvents(XEvent
*event
, void *data
);
190 static void repaintTable(WMTableView
*table
);
192 static WMSize
getTotalSize(WMTableView
*table
)
197 /* get width from columns */
199 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
200 WMTableColumn
*column
;
202 column
= WMGetFromArray(table
->columns
, i
);
204 size
.width
+= column
->width
;
207 /* get height from rows */
208 size
.height
= table
->rows
* table
->rowHeight
;
214 static WMRect
getVisibleRect(WMTableView
*table
)
216 WMSize size
= getTotalSize(table
);
219 rect
.size
.height
= size
.height
* WMGetScrollerKnobProportion(table
->vscroll
);
220 rect
.size
.width
= size
.width
* WMGetScrollerKnobProportion(table
->hscroll
);
222 rect
.pos
.x
= (size
.width
- rect
.size
.width
) * WMGetScrollerValue(table
->hscroll
);
223 rect
.pos
.y
= (size
.height
- rect
.size
.height
) * WMGetScrollerValue(table
->vscroll
);
229 static void scrollToPoint(WMTableView
*table
, int x
, int y
)
231 WMSize size
= getTotalSize(table
);
235 if (size
.width
> W_VIEW_WIDTH(table
->tableView
)) {
236 prop
= (float)W_VIEW_WIDTH(table
->tableView
) / (float)size
.width
;
237 value
= (float)x
/ (float)(size
.width
- W_VIEW_WIDTH(table
->tableView
));
242 WMSetScrollerParameters(table
->hscroll
, value
, prop
);
245 if (size
.height
> W_VIEW_HEIGHT(table
->tableView
)) {
246 prop
= (float)W_VIEW_HEIGHT(table
->tableView
) / (float)size
.height
;
247 value
= (float)y
/ (float)(size
.height
- W_VIEW_HEIGHT(table
->tableView
));
253 WMSetScrollerParameters(table
->vscroll
, value
, prop
);
257 if (table
->editingRow
>= 0) {
258 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
259 WMTableColumn
*column
;
261 column
= WMGetFromArray(table
->columns
, i
);
263 if (column
->delegate
&& column
->delegate
->beginCellEdit
)
264 (*column
->delegate
->beginCellEdit
)(column
->delegate
, column
,
273 static void adjustScrollers(WMTableView
*table
)
275 WMSize size
= getTotalSize(table
);
276 WMSize vsize
= WMGetViewSize(table
->tableView
);
280 if (size
.width
<= vsize
.width
) {
284 oprop
= WMGetScrollerKnobProportion(table
->hscroll
);
287 ovalue
= WMGetScrollerValue(table
->hscroll
);
289 prop
= (float)vsize
.width
/(float)size
.width
;
290 value
= prop
*ovalue
/ oprop
;
292 WMSetScrollerParameters(table
->hscroll
, value
, prop
);
294 if (size
.height
<= vsize
.height
) {
298 oprop
= WMGetScrollerKnobProportion(table
->vscroll
);
299 oprop
= WMGetScrollerKnobProportion(table
->hscroll
);
302 ovalue
= WMGetScrollerValue(table
->vscroll
);
304 prop
= (float)vsize
.height
/(float)size
.height
;
305 value
= prop
*ovalue
/ oprop
;
307 WMSetScrollerParameters(table
->vscroll
, value
, prop
);
311 static void doScroll(WMWidget
*self
, void *data
)
313 WMTableView
*table
= (WMTableView
*)data
;
317 WMSize ts
= getTotalSize(table
);
319 value
= WMGetScrollerValue(self
);
321 if (table
->hscroll
== (WMScroller
*)self
) {
322 vpsize
= W_VIEW_WIDTH(table
->tableView
);
325 vpsize
= W_VIEW_HEIGHT(table
->tableView
);
329 switch (WMGetScrollerHitPart(self
)) {
330 case WSDecrementWheel
:
331 case WSDecrementLine
:
332 value
-= (float)table
->rowHeight
/ size
;
335 WMSetScrollerParameters(self
, value
,
336 WMGetScrollerKnobProportion(self
));
340 case WSIncrementWheel
:
341 case WSIncrementLine
:
342 value
+= (float)table
->rowHeight
/ size
;
345 WMSetScrollerParameters(self
, value
,
346 WMGetScrollerKnobProportion(self
));
354 case WSDecrementPage
:
355 value
-= vpsize
/ size
;
358 WMSetScrollerParameters(self
, value
,
359 WMGetScrollerKnobProportion(self
));
363 case WSIncrementPage
:
364 value
+= vpsize
/ size
;
367 WMSetScrollerParameters(self
, value
,
368 WMGetScrollerKnobProportion(self
));
378 if (table
->editingRow
>= 0) {
380 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
381 WMTableColumn
*column
;
383 column
= WMGetFromArray(table
->columns
, i
);
385 if (column
->delegate
&& column
->delegate
->beginCellEdit
)
386 (*column
->delegate
->beginCellEdit
)(column
->delegate
, column
,
392 if (table
->hscroll
== self
) {
395 WMRect rect
= getVisibleRect(table
);
397 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
398 WMTableColumn
*column
;
401 column
= WMGetFromArray(table
->columns
, i
);
403 WMMoveWidget(column
->titleW
, x
- rect
.pos
.x
, 0);
405 x
+= W_VIEW_WIDTH(WMWidgetView(column
->titleW
)) + 1;
407 splitter
= WMGetFromArray(table
->splitters
, i
);
408 W_MoveView(splitter
, x
- rect
.pos
.x
- 1, 0);
414 static void splitterHandler(XEvent
*event
, void *data
)
416 WMTableColumn
*column
= (WMTableColumn
*)data
;
417 WMTableView
*table
= column
->table
;
421 WMScreen
*scr
= WMWidgetScreen(table
);
423 Display
*dpy
= WMScreenDisplay(scr
);
424 int h
= WMWidgetHeight(table
) - 22;
425 Window w
= WMViewXID(table
->view
);
427 pos
= WMGetViewPosition(WMWidgetView(column
->titleW
));
429 offsX
= pos
.x
+ column
->width
;
433 XDrawLine(dpy
, w
, gc
, cx
+20, 0, cx
+20, h
);
438 WMMaskEvent(dpy
, ButtonMotionMask
|ButtonReleaseMask
, &ev
);
444 if (column
->width
+ ev
.xmotion
.x
< column
->minWidth
)
445 cx
= pos
.x
+ column
->minWidth
;
446 else if (column
->maxWidth
> 0
447 && column
->width
+ ev
.xmotion
.x
> column
->maxWidth
)
448 cx
= pos
.x
+ column
->maxWidth
;
450 cx
= offsX
+ ev
.xmotion
.x
;
452 XDrawLine(dpy
, w
, gc
, ox
+20, 0, ox
+20, h
);
453 XDrawLine(dpy
, w
, gc
, cx
+20, 0, cx
+20, h
);
457 column
->width
= cx
- pos
.x
;
463 XDrawLine(dpy
, w
, gc
, cx
+20, 0, cx
+20, h
);
464 rearrangeHeader(table
);
469 static void realizeTable(void *data
, WMNotification
*notif
)
475 WMTableView
*WMCreateTableView(WMWidget
*parent
)
477 WMTableView
*table
= wmalloc(sizeof(WMTableView
));
478 WMScreen
*scr
= WMWidgetScreen(parent
);
480 memset(table
, 0, sizeof(WMTableView
));
483 tableClass
= W_RegisterUserWidget();
485 table
->widgetClass
= tableClass
;
487 table
->view
= W_CreateView(W_VIEW(parent
));
490 table
->view
->self
= table
;
492 table
->view
->delegate
= &viewDelegate
;
494 table
->headerHeight
= 20;
496 table
->hscroll
= WMCreateScroller(table
);
497 WMSetScrollerAction(table
->hscroll
, doScroll
, table
);
498 WMMoveWidget(table
->hscroll
, 1, 2+table
->headerHeight
);
499 WMMapWidget(table
->hscroll
);
501 table
->vscroll
= WMCreateScroller(table
);
502 WMSetScrollerArrowsPosition(table
->vscroll
, WSAMaxEnd
);
503 WMSetScrollerAction(table
->vscroll
, doScroll
, table
);
504 WMMoveWidget(table
->vscroll
, 1, 2+table
->headerHeight
);
505 WMMapWidget(table
->vscroll
);
508 table
->header
= WMCreateFrame(table
);
509 WMMoveWidget(table
->header
, 22, 2);
510 WMMapWidget(table
->header
);
511 WMSetFrameRelief(table
->header
, WRFlat
);
513 table
->corner
= WMCreateLabel(table
);
514 WMResizeWidget(table
->corner
, 20, table
->headerHeight
);
515 WMMoveWidget(table
->corner
, 2, 2);
516 WMMapWidget(table
->corner
);
517 WMSetLabelRelief(table
->corner
, WRRaised
);
518 WMSetWidgetBackgroundColor(table
->corner
, scr
->darkGray
);
521 table
->tableView
= W_CreateView(table
->view
);
522 if (!table
->tableView
)
524 table
->tableView
->self
= table
;
525 W_MapView(table
->tableView
);
527 WMAddNotificationObserver(realizeTable
, table
, WMViewRealizedNotification
,
530 table
->tableView
->flags
.dontCompressExpose
= 1;
532 table
->gridColor
= WMCreateNamedColor(scr
, "#cccccc", False
);
533 /* table->gridColor = WMGrayColor(scr);*/
538 table
->backColor
= WMWhiteColor(scr
);
540 gcv
.foreground
= WMColorPixel(table
->gridColor
);
542 gcv
.line_style
= LineOnOffDash
;
543 table
->gridGC
= XCreateGC(WMScreenDisplay(scr
), W_DRAWABLE(scr
),
547 table
->editingRow
= -1;
548 table
->clickedRow
= -1;
550 table
->drawsGrid
= 1;
551 table
->rowHeight
= 16;
553 table
->tableWidth
= 1;
555 table
->columns
= WMCreateArray(4);
556 table
->splitters
= WMCreateArray(4);
558 table
->selectedRows
= WMCreateArray(16);
560 table
->splitterCursor
= XCreateFontCursor(WMScreenDisplay(scr
),
561 XC_sb_h_double_arrow
);
563 table
->canSelectRow
= 1;
565 WMCreateEventHandler(table
->view
, ExposureMask
|StructureNotifyMask
,
566 handleEvents
, table
);
568 WMCreateEventHandler(table
->tableView
, ExposureMask
|ButtonPressMask
|
569 ButtonReleaseMask
|ButtonMotionMask
,
570 handleTableEvents
, table
);
572 WMResizeWidget(table
, 50, 50);
577 if (table
->tableView
)
578 W_DestroyView(table
->tableView
);
580 W_DestroyView(table
->view
);
586 void WMAddTableViewColumn(WMTableView
*table
, WMTableColumn
*column
)
588 WMScreen
*scr
= WMWidgetScreen(table
);
590 column
->table
= table
;
592 WMAddToArray(table
->columns
, column
);
594 if (!column
->titleW
) {
595 column
->titleW
= WMCreateLabel(table
);
596 WMSetLabelRelief(column
->titleW
, WRRaised
);
597 WMSetLabelFont(column
->titleW
, scr
->boldFont
);
598 WMSetLabelTextColor(column
->titleW
, scr
->white
);
599 WMSetWidgetBackgroundColor(column
->titleW
, scr
->darkGray
);
600 WMSetLabelText(column
->titleW
, column
->title
);
601 W_ReparentView(WMWidgetView(column
->titleW
),
602 WMWidgetView(table
->header
), 0, 0);
603 if (W_VIEW_REALIZED(table
->view
))
604 WMRealizeWidget(column
->titleW
);
605 WMMapWidget(column
->titleW
);
609 WMView
*splitter
= W_CreateView(WMWidgetView(table
->header
));
611 W_SetViewBackgroundColor(splitter
, WMWhiteColor(scr
));
613 if (W_VIEW_REALIZED(table
->view
))
614 W_RealizeView(splitter
);
616 W_ResizeView(splitter
, 2, table
->headerHeight
);
619 W_SetViewCursor(splitter
, table
->splitterCursor
);
620 WMCreateEventHandler(splitter
, ButtonPressMask
|ButtonReleaseMask
,
621 splitterHandler
, column
);
623 WMAddToArray(table
->splitters
, splitter
);
626 rearrangeHeader(table
);
630 void WMSetTableViewHeaderHeight(WMTableView
*table
, unsigned height
)
632 table
->headerHeight
= height
;
634 handleResize(NULL
, table
->view
);
638 void WMSetTableViewDelegate(WMTableView
*table
, WMTableViewDelegate
*delegate
)
640 table
->delegate
= delegate
;
644 void WMSetTableViewAction(WMTableView
*table
, WMAction
*action
, void *clientData
)
646 table
->action
= action
;
648 table
->clientData
= clientData
;
652 void *WMGetTableViewClickedColumn(WMTableView
*table
)
654 return table
->clickedColumn
;
658 int WMGetTableViewClickedRow(WMTableView
*table
)
660 return table
->clickedRow
;
664 WMArray
*WMGetTableViewSelectedRows(WMTableView
*table
)
666 return table
->selectedRows
;
670 WMView
*WMGetTableViewDocumentView(WMTableView
*table
)
672 return table
->tableView
;
676 void *WMTableViewDataForCell(WMTableView
*table
, WMTableColumn
*column
,
679 return (*table
->delegate
->valueForCell
)(table
->delegate
, column
, row
);
683 void WMSetTableViewDataForCell(WMTableView
*table
, WMTableColumn
*column
,
686 (*table
->delegate
->setValueForCell
)(table
->delegate
, column
, row
, data
);
690 WMRect
WMTableViewRectForCell(WMTableView
*table
, WMTableColumn
*column
,
697 rect
.pos
.y
= row
* table
->rowHeight
;
698 rect
.size
.height
= table
->rowHeight
;
700 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
702 col
= WMGetFromArray(table
->columns
, i
);
705 rect
.size
.width
= col
->width
;
709 rect
.pos
.x
+= col
->width
;
713 WMRect r
= getVisibleRect(table
);
715 rect
.pos
.y
-= r
.pos
.y
;
716 rect
.pos
.x
-= r
.pos
.x
;
723 void WMSetTableViewDataSource(WMTableView
*table
, void *source
)
725 table
->dataSource
= source
;
729 void *WMGetTableViewDataSource(WMTableView
*table
)
731 return table
->dataSource
;
735 void WMSetTableViewBackgroundColor(WMTableView
*table
, WMColor
*color
)
737 W_SetViewBackgroundColor(table
->tableView
, color
);
739 if (table
->backColor
)
740 WMReleaseColor(table
->backColor
);
742 table
->backColor
= WMRetainColor(color
);
748 void WMSetTableViewGridColor(WMTableView
*table
, WMColor
*color
)
750 WMReleaseColor(table
->gridColor
);
751 table
->gridColor
= WMRetainColor(color
);
752 XSetForeground(WMScreenDisplay(WMWidgetScreen(table
)), table
->gridGC
,
753 WMColorPixel(color
));
759 void WMSetTableViewRowHeight(WMTableView
*table
, int height
)
761 table
->rowHeight
= height
;
767 void WMScrollTableViewRowToVisible(WMTableView
*table
, int row
)
769 WMScroller
*scroller
;
774 rect
= getVisibleRect(table
);
775 range
= rowsInRect(table
, rect
);
777 scroller
= table
->vscroll
;
779 if (row
< range
.position
) {
780 newY
= row
* table
->rowHeight
- rect
.size
.height
/ 2;
781 } else if (row
>= range
.position
+ range
.count
) {
782 newY
= row
* table
->rowHeight
- rect
.size
.height
/ 2;
786 tmp
= table
->rows
*table
->rowHeight
- rect
.size
.height
;
787 newY
= WMAX(0, WMIN(newY
, tmp
));
789 scrollToPoint(table
, rect
.pos
.x
, newY
);
794 static void drawGrid(WMTableView
*table
, WMRect rect
)
796 WMScreen
*scr
= WMWidgetScreen(table
);
797 Display
*dpy
= WMScreenDisplay(scr
);
802 Drawable d
= WMGetPixmapXID(table
->viewBuffer
);
803 GC gc
= table
->gridGC
;
808 XSetDashes(dpy
, gc
, 0, dashl
, 1);
810 y1
= (rect
.pos
.y
/table
->rowHeight
- 1)*table
->rowHeight
;
811 y2
= y1
+ (rect
.size
.height
/table
->rowHeight
+2)*table
->rowHeight
;
814 y2
= W_VIEW_HEIGHT(table
->tableView
);
817 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
818 WMTableColumn
*column
;
820 XDrawLine(dpy
, d
, gc
, xx
, y1
, xx
, y2
);
822 column
= WMGetFromArray(table
->columns
, i
);
825 XDrawLine(dpy
, d
, gc
, xx
, y1
, xx
, y2
);
828 x2
= rect
.size
.width
;
833 XSetDashes(dpy
, gc
, (rect
.pos
.x
&1), dashl
, 1);
836 y1
= -rect
.pos
.y
%table
->rowHeight
;
837 y2
= y1
+ rect
.size
.height
+ table
->rowHeight
;
839 for (i
= y1
; i
<= y2
; i
+= table
->rowHeight
) {
840 XDrawLine(dpy
, d
, gc
, x1
, i
, x2
, i
);
845 static WMRange
columnsInRect(WMTableView
*table
, WMRect rect
)
847 WMTableColumn
*column
;
850 int totalColumns
= WMGetArrayItemCount(table
->columns
);
855 for (i
= 0; i
< totalColumns
; i
++) {
856 column
= WMGetFromArray(table
->columns
, i
);
858 if (width
<= rect
.pos
.x
&& width
+ column
->width
> rect
.pos
.x
) {
864 if (width
> rect
.pos
.x
+ rect
.size
.width
) {
868 width
+= column
->width
;
870 range
.count
= WMAX(1, WMIN(range
.count
, totalColumns
- range
.position
));
875 static WMRange
rowsInRect(WMTableView
*table
, WMRect rect
)
878 int rh
= table
->rowHeight
;
881 dif
= rect
.pos
.y
% rh
;
883 range
.position
= WMAX(0, (rect
.pos
.y
- dif
) / rh
);
884 range
.count
= WMAX(1, WMIN((rect
.size
.height
+ dif
) / rh
, table
->rows
));
890 static void drawRow(WMTableView
*table
, int row
, WMRect clipRect
)
893 WMRange cols
= columnsInRect(table
, clipRect
);
894 WMTableColumn
*column
;
895 Drawable d
= WMGetPixmapXID(table
->viewBuffer
);
897 for (i
= cols
.position
; i
< cols
.position
+cols
.count
; i
++) {
898 column
= WMGetFromArray(table
->columns
, i
);
900 if (!column
->delegate
|| !column
->delegate
->drawCell
)
903 if (WMFindInArray(table
->selectedRows
, NULL
, (void*)row
) != WANotFound
)
904 (*column
->delegate
->drawSelectedCell
)(column
->delegate
, column
, row
, d
);
906 (*column
->delegate
->drawCell
)(column
->delegate
, column
, row
, d
);
911 static void drawFullRow(WMTableView
*table
, int row
)
914 WMTableColumn
*column
;
915 Drawable d
= WMGetPixmapXID(table
->viewBuffer
);
917 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
918 column
= WMGetFromArray(table
->columns
, i
);
920 if (!column
->delegate
|| !column
->delegate
->drawCell
)
923 if (WMFindInArray(table
->selectedRows
, NULL
, (void*)row
) != WANotFound
)
924 (*column
->delegate
->drawSelectedCell
)(column
->delegate
, column
, row
, d
);
926 (*column
->delegate
->drawCell
)(column
->delegate
, column
, row
, d
);
931 static void setRowSelected(WMTableView
*table
, unsigned row
, Bool flag
)
935 if (WMFindInArray(table
->selectedRows
, NULL
, (void*)row
) != WANotFound
) {
937 WMRemoveFromArray(table
->selectedRows
, (void*)row
);
942 WMAddToArray(table
->selectedRows
, (void*)row
);
946 if (repaint
&& row
< table
->rows
) {
947 //drawFullRow(table, row);
953 static void repaintTable(WMTableView
*table
)
957 WMScreen
*scr
= WMWidgetScreen(table
);
960 if (!table
->delegate
|| !W_VIEW_REALIZED(table
->view
))
963 wassertr(table
->delegate
->numberOfRows
);
965 if (!table
->viewBuffer
) {
966 table
->viewBuffer
= WMCreatePixmap(scr
,
967 W_VIEW_WIDTH(table
->tableView
),
968 W_VIEW_HEIGHT(table
->tableView
),
969 WMScreenDepth(scr
), 0);
972 XFillRectangle(scr
->display
,
973 WMGetPixmapXID(table
->viewBuffer
),
974 WMColorGC(table
->backColor
), 0, 0,
975 W_VIEW_WIDTH(table
->tableView
),
976 W_VIEW_HEIGHT(table
->tableView
));
978 rect
= getVisibleRect(table
);
980 if (table
->drawsGrid
) {
981 drawGrid(table
, rect
);
984 rows
= rowsInRect(table
, rect
);
985 for (i
= rows
.position
;
986 i
< WMIN(rows
.position
+rows
.count
+ 1, table
->rows
);
988 drawRow(table
, i
, rect
);
991 XSetWindowBackgroundPixmap(scr
->display
, table
->tableView
->window
,
992 WMGetPixmapXID(table
->viewBuffer
));
993 XClearWindow(scr
->display
, table
->tableView
->window
);
997 static void stopRowEdit(WMTableView
*table
, int row
)
1000 WMTableColumn
*column
;
1002 table
->editingRow
= -1;
1003 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
1004 column
= WMGetFromArray(table
->columns
, i
);
1006 if (column
->delegate
&& column
->delegate
->endCellEdit
)
1007 (*column
->delegate
->endCellEdit
)(column
->delegate
, column
, row
);
1013 void WMEditTableViewRow(WMTableView
*table
, int row
)
1016 WMTableColumn
*column
;
1018 if (table
->editingRow
>= 0) {
1019 stopRowEdit(table
, table
->editingRow
);
1022 table
->editingRow
= row
;
1027 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
1028 column
= WMGetFromArray(table
->columns
, i
);
1030 if (column
->delegate
&& column
->delegate
->beginCellEdit
)
1031 (*column
->delegate
->beginCellEdit
)(column
->delegate
, column
, row
);
1036 void WMSelectTableViewRow(WMTableView
*table
, int row
)
1038 if (table
->clickedRow
>= 0)
1039 setRowSelected(table
, table
->clickedRow
, False
);
1041 if (row
>= table
->rows
) {
1045 setRowSelected(table
, row
, True
);
1046 table
->clickedRow
= row
;
1049 (*table
->action
)(table
, table
->clientData
);
1050 WMPostNotificationName(WMTableViewSelectionDidChangeNotification
,
1055 void WMReloadTableView(WMTableView
*table
)
1057 WMRect rect
= getVisibleRect(table
);
1059 if (table
->editingRow
>= 0)
1060 stopRowEdit(table
, table
->editingRow
);
1062 /* when this is called, nothing in the table can be assumed to be
1063 * like the last time we accessed it (ie, rows might have disappeared) */
1065 WMEmptyArray(table
->selectedRows
);
1067 if (table
->clickedRow
>= 0) {
1068 table
->clickedRow
= -1;
1071 (*table
->action
)(table
, table
->clientData
);
1072 WMPostNotificationName(WMTableViewSelectionDidChangeNotification
,
1076 if (table
->delegate
&& table
->delegate
->numberOfRows
) {
1079 rows
= (*table
->delegate
->numberOfRows
)(table
->delegate
, table
);
1081 if (rows
!= table
->rows
) {
1083 handleResize(table
->view
->delegate
, table
->view
);
1085 repaintTable(table
);
1091 void WMNoteTableViewNumberOfRowsChanged(WMTableView
*table
)
1093 WMReloadTableView(table
);
1097 static void handleTableEvents(XEvent
*event
, void *data
)
1099 WMTableView
*table
= (WMTableView
*)data
;
1102 switch (event
->type
) {
1104 if (event
->xbutton
.button
== Button1
) {
1105 WMRect rect
= getVisibleRect(table
);
1107 row
= (event
->xbutton
.y
+ rect
.pos
.y
)/table
->rowHeight
;
1108 if (row
!= table
->clickedRow
) {
1109 setRowSelected(table
, table
->clickedRow
, False
);
1110 setRowSelected(table
, row
, True
);
1111 table
->clickedRow
= row
;
1112 table
->dragging
= 1;
1114 table
->dragging
= 1;
1120 if (table
->dragging
&& event
->xmotion
.y
>= 0) {
1121 WMRect rect
= getVisibleRect(table
);
1123 row
= (event
->xmotion
.y
+ rect
.pos
.y
)/table
->rowHeight
;
1124 if (table
->clickedRow
!= row
&& row
>= 0 && row
< table
->rows
) {
1125 setRowSelected(table
, table
->clickedRow
, False
);
1126 setRowSelected(table
, row
, True
);
1127 table
->clickedRow
= row
;
1133 if (event
->xbutton
.button
== Button1
) {
1135 (*table
->action
)(table
, table
->clientData
);
1136 WMPostNotificationName(WMTableViewSelectionDidChangeNotification
,
1138 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
),
1160 static void handleResize(W_ViewDelegate
*self
, WMView
*view
)
1164 WMTableView
*table
= view
->self
;
1165 WMSize size
= getTotalSize(table
);
1166 WMScreen
*scr
= WMWidgetScreen(table
);
1169 width
= W_VIEW_WIDTH(view
) - 2;
1170 height
= W_VIEW_HEIGHT(view
) - 3;
1172 height
-= table
->headerHeight
; /* table header */
1175 WMResizeWidget(table
->corner
, 20, table
->headerHeight
);
1177 WMMoveWidget(table
->vscroll
, 1, table
->headerHeight
+ 1);
1178 WMResizeWidget(table
->vscroll
, 20, height
+ 1);
1180 WMMoveWidget(table
->hscroll
, 20, W_VIEW_HEIGHT(view
) - 20 - 1);
1181 WMResizeWidget(table
->hscroll
, width
-20+1, 20);
1184 WMResizeWidget(table
->header
, width
- 21, table
->headerHeight
);
1186 if (table
->viewBuffer
) {
1187 WMReleasePixmap(table
->viewBuffer
);
1188 table
->viewBuffer
= NULL
;
1194 vw
= WMIN(size
.width
, width
);
1195 vh
= WMIN(size
.height
, height
);
1197 W_MoveView(table
->tableView
, 21, 1+table
->headerHeight
+1);
1198 W_ResizeView(table
->tableView
, WMAX(vw
, 1), WMAX(vh
, 1)+1);
1200 adjustScrollers(table
);
1202 repaintTable(table
);
1206 static void rearrangeHeader(WMTableView
*table
)
1211 /*WMRect rect = WMGetScrollViewVisibleRect(table->scrollView);*/
1215 count
= WMGetArrayItemCount(table
->columns
);
1216 for (i
= 0; i
< count
; i
++) {
1217 WMTableColumn
*column
= WMGetFromArray(table
->columns
, i
);
1218 WMView
*splitter
= WMGetFromArray(table
->splitters
, i
);
1220 WMMoveWidget(column
->titleW
, width
, 0);
1221 WMResizeWidget(column
->titleW
, column
->width
-1, table
->headerHeight
);
1223 width
+= column
->width
;
1224 W_MoveView(splitter
, width
-1, 0);
1227 wassertr(table
->delegate
&& table
->delegate
->numberOfRows
);
1229 table
->rows
= table
->delegate
->numberOfRows(table
->delegate
, table
);
1231 table
->tableWidth
= width
+ 1;
1233 handleResize(table
->view
->delegate
, table
->view
);