3 #include <WINGs/WINGsP.h>
4 #include <X11/cursorfont.h>
7 #include "wtableview.h"
10 const char *WMTableViewSelectionDidChangeNotification
= "WMTableViewSelectionDidChangeNotification";
13 struct W_TableColumn
{
23 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
);
38 WMCreateTableColumn(char *title
)
40 WMTableColumn
*col
= wmalloc(sizeof(WMTableColumn
));
50 col
->title
= wstrdup(title
);
62 WMSetTableColumnId(WMTableColumn
*column
, void *id
)
69 WMGetTableColumnId(WMTableColumn
*column
)
76 WMSetTableColumnWidth(WMTableColumn
*column
, unsigned width
)
78 if (column
->maxWidth
== 0)
79 column
->width
= WMAX(column
->minWidth
, width
);
81 column
->width
= WMAX(column
->minWidth
, WMIN(column
->maxWidth
, width
));
84 rearrangeHeader(column
->table
);
90 WMSetTableColumnDelegate(WMTableColumn
*column
, WMTableColumnDelegate
*delegate
)
92 column
->delegate
= delegate
;
97 WMSetTableColumnConstraints(WMTableColumn
*column
, unsigned minWidth
,
100 wassertr(maxWidth
== 0 || minWidth
<= maxWidth
);
102 column
->minWidth
= minWidth
;
103 column
->maxWidth
= maxWidth
;
105 if (column
->width
< column
->minWidth
)
106 WMSetTableColumnWidth(column
, column
->minWidth
);
107 else if (column
->width
> column
->maxWidth
&& column
->maxWidth
!= 0)
108 WMSetTableColumnWidth(column
, column
->maxWidth
);
113 WMSetTableColumnEditable(WMTableColumn
*column
, Bool flag
)
115 column
->editable
= ((flag
==0) ? 0 : 1);
120 WMGetTableColumnTableView(WMTableColumn
*column
)
122 return column
->table
;
139 WMPixmap
*viewBuffer
;
144 WMArray
*selectedRows
;
155 Cursor splitterCursor
;
159 WMTableViewDelegate
*delegate
;
169 unsigned headerHeight
;
174 unsigned drawsGrid
:1;
175 unsigned canSelectRow
:1;
176 unsigned canSelectMultiRows
:1;
177 unsigned canDeselectRow
:1;
179 unsigned int hasVScroller
:1;
180 unsigned int hasHScroller
:1;
183 static W_Class tableClass
= 0;
186 static W_ViewDelegate viewDelegate
= {
196 static void reorganizeInterior(WMTableView
*table
);
199 static void handleEvents(XEvent
*event
, void *data
);
200 static void handleTableEvents(XEvent
*event
, void *data
);
201 static void repaintTable(WMTableView
*table
);
204 getTotalSize(WMTableView
*table
)
209 /* get width from columns */
211 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
212 WMTableColumn
*column
;
214 column
= WMGetFromArray(table
->columns
, i
);
216 size
.width
+= column
->width
;
219 /* get height from rows */
220 size
.height
= table
->rows
* table
->rowHeight
;
227 getVisibleRect(WMTableView
*table
)
229 WMSize size
= getTotalSize(table
);
232 if (table
->vscroll
) {
233 rect
.size
.height
= size
.height
* WMGetScrollerKnobProportion(table
->vscroll
);
234 rect
.pos
.y
= (size
.height
- rect
.size
.height
) * WMGetScrollerValue(table
->vscroll
);
236 rect
.size
.height
= size
.height
;
240 if (table
->hscroll
) {
241 rect
.size
.width
= size
.width
* WMGetScrollerKnobProportion(table
->hscroll
);
242 rect
.pos
.x
= (size
.width
- rect
.size
.width
) * WMGetScrollerValue(table
->hscroll
);
244 rect
.size
.width
= size
.width
;
253 scrollToPoint(WMTableView
*table
, int x
, int y
)
255 WMSize size
= getTotalSize(table
);
259 if (table
->hscroll
) {
260 if (size
.width
> W_VIEW_WIDTH(table
->tableView
)) {
261 prop
= (float)W_VIEW_WIDTH(table
->tableView
) / (float)size
.width
;
262 value
= (float)x
/ (float)(size
.width
- W_VIEW_WIDTH(table
->tableView
));
267 WMSetScrollerParameters(table
->hscroll
, value
, prop
);
270 if (table
->vscroll
) {
271 if (size
.height
> W_VIEW_HEIGHT(table
->tableView
)) {
272 prop
= (float)W_VIEW_HEIGHT(table
->tableView
) / (float)size
.height
;
273 value
= (float)y
/ (float)(size
.height
- W_VIEW_HEIGHT(table
->tableView
));
279 WMSetScrollerParameters(table
->vscroll
, value
, prop
);
283 if (table
->editingRow
>= 0) {
284 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
285 WMTableColumn
*column
;
287 column
= WMGetFromArray(table
->columns
, i
);
289 if (column
->delegate
&& column
->delegate
->beginCellEdit
)
290 (*column
->delegate
->beginCellEdit
)(column
->delegate
, column
,
300 adjustScrollers(WMTableView
*table
)
302 WMSize size
= getTotalSize(table
);
303 WMSize vsize
= WMGetViewSize(table
->tableView
);
307 if (table
->hscroll
) {
308 if (size
.width
<= vsize
.width
) {
312 oprop
= WMGetScrollerKnobProportion(table
->hscroll
);
315 ovalue
= WMGetScrollerValue(table
->hscroll
);
317 prop
= (float)vsize
.width
/(float)size
.width
;
318 value
= prop
*ovalue
/ oprop
;
320 WMSetScrollerParameters(table
->hscroll
, value
, prop
);
323 if (table
->vscroll
) {
324 if (size
.height
<= vsize
.height
) {
328 oprop
= WMGetScrollerKnobProportion(table
->vscroll
);
331 ovalue
= WMGetScrollerValue(table
->vscroll
);
333 prop
= (float)vsize
.height
/(float)size
.height
;
334 value
= prop
*ovalue
/ oprop
;
336 WMSetScrollerParameters(table
->vscroll
, value
, prop
);
342 doScroll(WMWidget
*self
, void *data
)
344 WMTableView
*table
= (WMTableView
*)data
;
348 WMSize ts
= getTotalSize(table
);
350 value
= WMGetScrollerValue(self
);
352 if (table
->hscroll
== (WMScroller
*)self
) {
353 vpsize
= W_VIEW_WIDTH(table
->tableView
);
356 vpsize
= W_VIEW_HEIGHT(table
->tableView
);
360 switch (WMGetScrollerHitPart(self
)) {
361 case WSDecrementWheel
:
362 case WSDecrementLine
:
363 value
-= (float)table
->rowHeight
/ size
;
366 WMSetScrollerParameters(self
, value
,
367 WMGetScrollerKnobProportion(self
));
371 case WSIncrementWheel
:
372 case WSIncrementLine
:
373 value
+= (float)table
->rowHeight
/ size
;
376 WMSetScrollerParameters(self
, value
,
377 WMGetScrollerKnobProportion(self
));
385 case WSDecrementPage
:
386 value
-= vpsize
/ size
;
389 WMSetScrollerParameters(self
, value
,
390 WMGetScrollerKnobProportion(self
));
394 case WSIncrementPage
:
395 value
+= vpsize
/ size
;
398 WMSetScrollerParameters(self
, value
,
399 WMGetScrollerKnobProportion(self
));
409 if (table
->editingRow
>= 0) {
411 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
412 WMTableColumn
*column
;
414 column
= WMGetFromArray(table
->columns
, i
);
416 if (column
->delegate
&& column
->delegate
->beginCellEdit
)
417 (*column
->delegate
->beginCellEdit
)(column
->delegate
, column
,
423 if (table
->hscroll
== self
) {
426 WMRect rect
= getVisibleRect(table
);
428 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
429 WMTableColumn
*column
;
432 column
= WMGetFromArray(table
->columns
, i
);
434 WMMoveWidget(column
->titleW
, x
- rect
.pos
.x
, 0);
436 x
+= W_VIEW_WIDTH(WMWidgetView(column
->titleW
)) + 1;
438 splitter
= WMGetFromArray(table
->splitters
, i
);
439 W_MoveView(splitter
, x
- rect
.pos
.x
- 1, 0);
446 splitterHandler(XEvent
*event
, void *data
)
448 WMTableColumn
*column
= (WMTableColumn
*)data
;
449 WMTableView
*table
= column
->table
;
453 WMScreen
*scr
= WMWidgetScreen(table
);
455 Display
*dpy
= WMScreenDisplay(scr
);
456 int h
= WMWidgetHeight(table
) - 22;
457 Window w
= WMViewXID(table
->view
);
459 pos
= WMGetViewPosition(WMWidgetView(column
->titleW
));
461 offsX
= pos
.x
+ column
->width
;
465 XDrawLine(dpy
, w
, gc
, cx
+20, 0, cx
+20, h
);
470 WMMaskEvent(dpy
, ButtonMotionMask
|ButtonReleaseMask
, &ev
);
476 if (column
->width
+ ev
.xmotion
.x
< column
->minWidth
)
477 cx
= pos
.x
+ column
->minWidth
;
478 else if (column
->maxWidth
> 0
479 && column
->width
+ ev
.xmotion
.x
> column
->maxWidth
)
480 cx
= pos
.x
+ column
->maxWidth
;
482 cx
= offsX
+ ev
.xmotion
.x
;
484 XDrawLine(dpy
, w
, gc
, ox
+20, 0, ox
+20, h
);
485 XDrawLine(dpy
, w
, gc
, cx
+20, 0, cx
+20, h
);
489 column
->width
= cx
- pos
.x
;
495 XDrawLine(dpy
, w
, gc
, cx
+20, 0, cx
+20, h
);
496 rearrangeHeader(table
);
502 realizeTable(void *data
, WMNotification
*notif
)
509 WMCreateTableView(WMWidget
*parent
)
511 WMTableView
*table
= wmalloc(sizeof(WMTableView
));
512 WMScreen
*scr
= WMWidgetScreen(parent
);
514 memset(table
, 0, sizeof(WMTableView
));
517 tableClass
= W_RegisterUserWidget();
519 table
->widgetClass
= tableClass
;
521 table
->view
= W_CreateView(W_VIEW(parent
));
524 table
->view
->self
= table
;
526 table
->view
->delegate
= &viewDelegate
;
528 table
->headerHeight
= 20;
530 table
->hscroll
= WMCreateScroller(table
);
531 WMSetScrollerAction(table
->hscroll
, doScroll
, table
);
532 WMMoveWidget(table
->hscroll
, 1, 2+table
->headerHeight
);
533 WMMapWidget(table
->hscroll
);
535 table
->hasHScroller
= 1;
537 table
->vscroll
= WMCreateScroller(table
);
538 WMSetScrollerArrowsPosition(table
->vscroll
, WSAMaxEnd
);
539 WMSetScrollerAction(table
->vscroll
, doScroll
, table
);
540 WMMoveWidget(table
->vscroll
, 1, 2+table
->headerHeight
);
541 WMMapWidget(table
->vscroll
);
543 table
->hasVScroller
= 1;
545 table
->header
= WMCreateFrame(table
);
546 WMMoveWidget(table
->header
, 22, 2);
547 WMMapWidget(table
->header
);
548 WMSetFrameRelief(table
->header
, WRFlat
);
550 table
->corner
= WMCreateLabel(table
);
551 WMResizeWidget(table
->corner
, 20, table
->headerHeight
);
552 WMMoveWidget(table
->corner
, 2, 2);
553 WMMapWidget(table
->corner
);
554 WMSetLabelRelief(table
->corner
, WRRaised
);
555 WMSetWidgetBackgroundColor(table
->corner
, scr
->darkGray
);
558 table
->tableView
= W_CreateView(table
->view
);
559 if (!table
->tableView
)
561 table
->tableView
->self
= table
;
562 W_MapView(table
->tableView
);
564 WMAddNotificationObserver(realizeTable
, table
, WMViewRealizedNotification
,
567 table
->tableView
->flags
.dontCompressExpose
= 1;
569 table
->gridColor
= WMCreateNamedColor(scr
, "#cccccc", False
);
570 /* table->gridColor = WMGrayColor(scr);*/
575 table
->backColor
= WMWhiteColor(scr
);
577 gcv
.foreground
= WMColorPixel(table
->gridColor
);
579 gcv
.line_style
= LineOnOffDash
;
580 table
->gridGC
= XCreateGC(WMScreenDisplay(scr
), W_DRAWABLE(scr
),
584 table
->editingRow
= -1;
585 table
->clickedRow
= -1;
587 table
->drawsGrid
= 1;
588 table
->rowHeight
= 16;
590 table
->tableWidth
= 1;
592 table
->columns
= WMCreateArray(4);
593 table
->splitters
= WMCreateArray(4);
595 table
->selectedRows
= WMCreateArray(16);
597 table
->splitterCursor
= XCreateFontCursor(WMScreenDisplay(scr
),
598 XC_sb_h_double_arrow
);
600 table
->canSelectRow
= 1;
602 WMCreateEventHandler(table
->view
, ExposureMask
|StructureNotifyMask
,
603 handleEvents
, table
);
605 WMCreateEventHandler(table
->tableView
, ExposureMask
|ButtonPressMask
|
606 ButtonReleaseMask
|ButtonMotionMask
,
607 handleTableEvents
, table
);
609 WMResizeWidget(table
, 50, 50);
614 if (table
->tableView
)
615 W_DestroyView(table
->tableView
);
617 W_DestroyView(table
->view
);
624 WMAddTableViewColumn(WMTableView
*table
, WMTableColumn
*column
)
626 WMScreen
*scr
= WMWidgetScreen(table
);
628 column
->table
= table
;
630 WMAddToArray(table
->columns
, column
);
632 if (!column
->titleW
) {
633 column
->titleW
= WMCreateLabel(table
);
634 WMSetLabelRelief(column
->titleW
, WRRaised
);
635 WMSetLabelFont(column
->titleW
, scr
->boldFont
);
636 WMSetLabelTextColor(column
->titleW
, scr
->white
);
637 WMSetWidgetBackgroundColor(column
->titleW
, scr
->darkGray
);
638 WMSetLabelText(column
->titleW
, column
->title
);
639 W_ReparentView(WMWidgetView(column
->titleW
),
640 WMWidgetView(table
->header
), 0, 0);
641 if (W_VIEW_REALIZED(table
->view
))
642 WMRealizeWidget(column
->titleW
);
643 WMMapWidget(column
->titleW
);
647 WMView
*splitter
= W_CreateView(WMWidgetView(table
->header
));
649 W_SetViewBackgroundColor(splitter
, WMWhiteColor(scr
));
651 if (W_VIEW_REALIZED(table
->view
))
652 W_RealizeView(splitter
);
654 W_ResizeView(splitter
, 2, table
->headerHeight
);
657 W_SetViewCursor(splitter
, table
->splitterCursor
);
658 WMCreateEventHandler(splitter
, ButtonPressMask
|ButtonReleaseMask
,
659 splitterHandler
, column
);
661 WMAddToArray(table
->splitters
, splitter
);
664 rearrangeHeader(table
);
669 WMSetTableViewHeaderHeight(WMTableView
*table
, unsigned height
)
671 table
->headerHeight
= height
;
673 handleResize(NULL
, table
->view
);
678 WMSetTableViewDelegate(WMTableView
*table
, WMTableViewDelegate
*delegate
)
680 table
->delegate
= delegate
;
685 WMSetTableViewAction(WMTableView
*table
, WMAction
*action
, void *clientData
)
687 table
->action
= action
;
689 table
->clientData
= clientData
;
694 WMGetTableViewClickedColumn(WMTableView
*table
)
696 return table
->clickedColumn
;
701 WMGetTableViewClickedRow(WMTableView
*table
)
703 return table
->clickedRow
;
708 WMGetTableViewSelectedRows(WMTableView
*table
)
710 return table
->selectedRows
;
715 WMGetTableViewDocumentView(WMTableView
*table
)
717 return table
->tableView
;
722 WMTableViewDataForCell(WMTableView
*table
, WMTableColumn
*column
, int row
)
724 return (*table
->delegate
->valueForCell
)(table
->delegate
, column
, row
);
729 WMSetTableViewDataForCell(WMTableView
*table
, WMTableColumn
*column
, int row
,
732 (*table
->delegate
->setValueForCell
)(table
->delegate
, column
, row
, data
);
737 WMTableViewRectForCell(WMTableView
*table
, WMTableColumn
*column
, int row
)
743 rect
.pos
.y
= row
* table
->rowHeight
;
744 rect
.size
.height
= table
->rowHeight
;
746 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
748 col
= WMGetFromArray(table
->columns
, i
);
751 rect
.size
.width
= col
->width
;
755 rect
.pos
.x
+= col
->width
;
759 WMRect r
= getVisibleRect(table
);
761 rect
.pos
.y
-= r
.pos
.y
;
762 rect
.pos
.x
-= r
.pos
.x
;
770 WMSetTableViewDataSource(WMTableView
*table
, void *source
)
772 table
->dataSource
= source
;
777 WMGetTableViewDataSource(WMTableView
*table
)
779 return table
->dataSource
;
785 WMSetTableViewHasHorizontalScroller(WMTableView
*tPtr
, Bool flag
)
788 if (tPtr
->hasHScroller
)
790 tPtr
->hasHScroller
= 1;
792 tPtr
->hscroll
= WMCreateScroller(tPtr
);
793 WMSetScrollerAction(tPtr
->hscroll
, doScroll
, tPtr
);
794 WMSetScrollerArrowsPosition(tPtr
->hscroll
, WSAMaxEnd
);
795 /* make it a horiz. scroller */
796 WMResizeWidget(tPtr
->hscroll
, 1, 2);
798 if (W_VIEW_REALIZED(tPtr
->view
)) {
799 WMRealizeWidget(tPtr
->hscroll
);
802 reorganizeInterior(tPtr
);
804 WMMapWidget(tPtr
->hscroll
);
806 if (!tPtr
->hasHScroller
)
808 tPtr
->hasHScroller
= 0;
810 WMUnmapWidget(tPtr
->hscroll
);
811 WMDestroyWidget(tPtr
->hscroll
);
812 tPtr
->hscroll
= NULL
;
814 reorganizeInterior(tPtr
);
819 /* not supported by now */
821 WMSetTableViewHasVerticalScroller(WMTableView
*tPtr
, Bool flag
)
824 if (tPtr
->hasVScroller
)
826 tPtr
->hasVScroller
= 1;
828 tPtr
->vscroll
= WMCreateScroller(tPtr
);
829 WMSetScrollerAction(tPtr
->vscroll
, doScroll
, tPtr
);
830 WMSetScrollerArrowsPosition(tPtr
->vscroll
, WSAMaxEnd
);
831 /* make it a vert. scroller */
832 WMResizeWidget(tPtr
->vscroll
, 1, 2);
834 if (W_VIEW_REALIZED(tPtr
->view
)) {
835 WMRealizeWidget(tPtr
->vscroll
);
838 reorganizeInterior(tPtr
);
840 WMMapWidget(tPtr
->vscroll
);
842 if (!tPtr
->hasVScroller
)
844 tPtr
->hasVScroller
= 0;
846 WMUnmapWidget(tPtr
->vscroll
);
847 WMDestroyWidget(tPtr
->vscroll
);
848 tPtr
->vscroll
= NULL
;
850 reorganizeInterior(tPtr
);
856 WMSetTableViewBackgroundColor(WMTableView
*table
, WMColor
*color
)
858 W_SetViewBackgroundColor(table
->tableView
, color
);
860 if (table
->backColor
)
861 WMReleaseColor(table
->backColor
);
863 table
->backColor
= WMRetainColor(color
);
870 WMSetTableViewGridColor(WMTableView
*table
, WMColor
*color
)
872 WMReleaseColor(table
->gridColor
);
873 table
->gridColor
= WMRetainColor(color
);
874 XSetForeground(WMScreenDisplay(WMWidgetScreen(table
)), table
->gridGC
,
875 WMColorPixel(color
));
882 WMSetTableViewRowHeight(WMTableView
*table
, int height
)
884 table
->rowHeight
= height
;
891 WMScrollTableViewRowToVisible(WMTableView
*table
, int row
)
893 WMScroller
*scroller
;
898 rect
= getVisibleRect(table
);
899 range
= rowsInRect(table
, rect
);
901 scroller
= table
->vscroll
;
903 if (row
< range
.position
) {
904 newY
= row
* table
->rowHeight
- rect
.size
.height
/ 2;
905 } else if (row
>= range
.position
+ range
.count
) {
906 newY
= row
* table
->rowHeight
- rect
.size
.height
/ 2;
910 tmp
= table
->rows
*table
->rowHeight
- rect
.size
.height
;
911 newY
= WMAX(0, WMIN(newY
, tmp
));
913 scrollToPoint(table
, rect
.pos
.x
, newY
);
919 drawGrid(WMTableView
*table
, WMRect rect
)
921 WMScreen
*scr
= WMWidgetScreen(table
);
922 Display
*dpy
= WMScreenDisplay(scr
);
927 Drawable d
= WMGetPixmapXID(table
->viewBuffer
);
928 GC gc
= table
->gridGC
;
933 XSetDashes(dpy
, gc
, 0, dashl
, 1);
935 y1
= (rect
.pos
.y
/table
->rowHeight
- 1)*table
->rowHeight
;
936 y2
= y1
+ (rect
.size
.height
/table
->rowHeight
+2)*table
->rowHeight
;
939 y2
= W_VIEW_HEIGHT(table
->tableView
);
942 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
943 WMTableColumn
*column
;
945 XDrawLine(dpy
, d
, gc
, xx
, y1
, xx
, y2
);
947 column
= WMGetFromArray(table
->columns
, i
);
950 XDrawLine(dpy
, d
, gc
, xx
, y1
, xx
, y2
);
953 x2
= rect
.size
.width
;
958 XSetDashes(dpy
, gc
, (rect
.pos
.x
&1), dashl
, 1);
961 y1
= -rect
.pos
.y
%table
->rowHeight
;
962 y2
= y1
+ rect
.size
.height
+ table
->rowHeight
;
964 for (i
= y1
; i
<= y2
; i
+= table
->rowHeight
) {
965 XDrawLine(dpy
, d
, gc
, x1
, i
, x2
, i
);
971 columnsInRect(WMTableView
*table
, WMRect rect
)
973 WMTableColumn
*column
;
976 int totalColumns
= WMGetArrayItemCount(table
->columns
);
981 for (i
= 0; i
< totalColumns
; i
++) {
982 column
= WMGetFromArray(table
->columns
, i
);
984 if (rect
.pos
.x
>= pos
&& rect
.pos
.x
< pos
+ column
->width
) {
990 if (pos
> rect
.pos
.x
+ rect
.size
.width
) {
995 pos
+= column
->width
;
997 range
.count
= WMAX(1, WMIN(range
.count
, totalColumns
- range
.position
));
1003 rowsInRect(WMTableView
*table
, WMRect rect
)
1006 int rh
= table
->rowHeight
;
1009 dif
= rect
.pos
.y
% rh
;
1011 range
.position
= WMAX(0, (rect
.pos
.y
- dif
) / rh
);
1012 range
.count
= WMAX(1, WMIN((rect
.size
.height
+ dif
) / rh
, table
->rows
));
1019 drawRow(WMTableView
*table
, int row
, WMRect clipRect
)
1022 WMRange cols
= columnsInRect(table
, clipRect
);
1023 WMTableColumn
*column
;
1024 Drawable d
= WMGetPixmapXID(table
->viewBuffer
);
1026 for (i
= cols
.position
; i
< cols
.position
+cols
.count
; i
++) {
1027 column
= WMGetFromArray(table
->columns
, i
);
1029 if (!column
->delegate
|| !column
->delegate
->drawCell
)
1032 if (WMFindInArray(table
->selectedRows
, NULL
, (void*)(uintptr_t)row
) != WANotFound
)
1033 (*column
->delegate
->drawSelectedCell
)(column
->delegate
, column
, row
, d
);
1035 (*column
->delegate
->drawCell
)(column
->delegate
, column
, row
, d
);
1042 drawFullRow(WMTableView
*table
, int row
)
1045 WMTableColumn
*column
;
1046 Drawable d
= WMGetPixmapXID(table
->viewBuffer
);
1048 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
1049 column
= WMGetFromArray(table
->columns
, i
);
1051 if (!column
->delegate
|| !column
->delegate
->drawCell
)
1054 if (WMFindInArray(table
->selectedRows
, NULL
, (void*)row
) != WANotFound
)
1055 (*column
->delegate
->drawSelectedCell
)(column
->delegate
, column
, row
, d
);
1057 (*column
->delegate
->drawCell
)(column
->delegate
, column
, row
, d
);
1064 setRowSelected(WMTableView
*table
, unsigned row
, Bool flag
)
1068 if (WMFindInArray(table
->selectedRows
, NULL
, (void*)(uintptr_t)row
) != WANotFound
) {
1070 WMRemoveFromArray(table
->selectedRows
, (void*)(uintptr_t)row
);
1075 WMAddToArray(table
->selectedRows
, (void*)(uintptr_t)row
);
1079 if (repaint
&& row
< table
->rows
) {
1080 /*drawFullRow(table, row);*/
1081 repaintTable(table
);
1087 repaintTable(WMTableView
*table
)
1091 WMScreen
*scr
= WMWidgetScreen(table
);
1094 if (!table
->delegate
|| !W_VIEW_REALIZED(table
->view
))
1097 wassertr(table
->delegate
->numberOfRows
);
1099 if (!table
->viewBuffer
) {
1100 table
->viewBuffer
= WMCreatePixmap(scr
,
1101 W_VIEW_WIDTH(table
->tableView
),
1102 W_VIEW_HEIGHT(table
->tableView
),
1103 WMScreenDepth(scr
), 0);
1106 XFillRectangle(scr
->display
,
1107 WMGetPixmapXID(table
->viewBuffer
),
1108 WMColorGC(table
->backColor
), 0, 0,
1109 W_VIEW_WIDTH(table
->tableView
),
1110 W_VIEW_HEIGHT(table
->tableView
));
1112 rect
= getVisibleRect(table
);
1114 if (table
->drawsGrid
) {
1115 drawGrid(table
, rect
);
1118 rows
= rowsInRect(table
, rect
);
1119 for (i
= rows
.position
;
1120 i
< WMIN(rows
.position
+rows
.count
+ 1, table
->rows
);
1122 drawRow(table
, i
, rect
);
1125 XSetWindowBackgroundPixmap(scr
->display
, table
->tableView
->window
,
1126 WMGetPixmapXID(table
->viewBuffer
));
1127 XClearWindow(scr
->display
, table
->tableView
->window
);
1132 stopRowEdit(WMTableView
*table
, int row
)
1135 WMTableColumn
*column
;
1137 table
->editingRow
= -1;
1138 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
1139 column
= WMGetFromArray(table
->columns
, i
);
1141 if (column
->delegate
&& column
->delegate
->endCellEdit
)
1142 (*column
->delegate
->endCellEdit
)(column
->delegate
, column
, row
);
1149 WMEditTableViewRow(WMTableView
*table
, int row
)
1152 WMTableColumn
*column
;
1154 if (table
->editingRow
>= 0) {
1155 stopRowEdit(table
, table
->editingRow
);
1158 table
->editingRow
= row
;
1163 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
1164 column
= WMGetFromArray(table
->columns
, i
);
1166 if (column
->delegate
&& column
->delegate
->beginCellEdit
)
1167 (*column
->delegate
->beginCellEdit
)(column
->delegate
, column
, row
);
1173 WMSelectTableViewRow(WMTableView
*table
, int row
)
1175 if (table
->clickedRow
>= 0)
1176 setRowSelected(table
, table
->clickedRow
, False
);
1178 if (row
>= table
->rows
) {
1182 setRowSelected(table
, row
, True
);
1183 table
->clickedRow
= row
;
1186 (*table
->action
)(table
, table
->clientData
);
1187 WMPostNotificationName(WMTableViewSelectionDidChangeNotification
,
1193 WMReloadTableView(WMTableView
*table
)
1195 if (table
->editingRow
>= 0)
1196 stopRowEdit(table
, table
->editingRow
);
1198 /* when this is called, nothing in the table can be assumed to be
1199 * like the last time we accessed it (ie, rows might have disappeared) */
1201 WMEmptyArray(table
->selectedRows
);
1203 if (table
->clickedRow
>= 0) {
1205 (*table
->action
)(table
, table
->clientData
);
1206 WMPostNotificationName(WMTableViewSelectionDidChangeNotification
,
1208 table
->clickedRow
= -1;
1211 if (table
->delegate
&& table
->delegate
->numberOfRows
) {
1214 rows
= (*table
->delegate
->numberOfRows
)(table
->delegate
, table
);
1216 if (rows
!= table
->rows
) {
1218 handleResize(table
->view
->delegate
, table
->view
);
1220 repaintTable(table
);
1227 WMNoteTableViewNumberOfRowsChanged(WMTableView
*table
)
1229 WMReloadTableView(table
);
1234 handleTableEvents(XEvent
*event
, void *data
)
1236 WMTableView
*table
= (WMTableView
*)data
;
1239 switch (event
->type
) {
1241 if (event
->xbutton
.button
== Button1
) {
1242 WMRect rect
= getVisibleRect(table
);
1244 row
= (event
->xbutton
.y
+ rect
.pos
.y
)/table
->rowHeight
;
1245 if (row
!= table
->clickedRow
) {
1246 setRowSelected(table
, table
->clickedRow
, False
);
1247 setRowSelected(table
, row
, True
);
1248 table
->clickedRow
= row
;
1249 table
->dragging
= 1;
1251 table
->dragging
= 1;
1257 if (table
->dragging
&& event
->xmotion
.y
>= 0) {
1258 WMRect rect
= getVisibleRect(table
);
1260 row
= (event
->xmotion
.y
+ rect
.pos
.y
)/table
->rowHeight
;
1261 if (table
->clickedRow
!= row
&& row
>= 0 && row
< table
->rows
) {
1262 setRowSelected(table
, table
->clickedRow
, False
);
1263 setRowSelected(table
, row
, True
);
1264 table
->clickedRow
= row
;
1270 if (event
->xbutton
.button
== Button1
) {
1272 (*table
->action
)(table
, table
->clientData
);
1273 WMPostNotificationName(WMTableViewSelectionDidChangeNotification
,
1275 table
->dragging
= 0;
1283 handleEvents(XEvent
*event
, void *data
)
1285 WMTableView
*table
= (WMTableView
*)data
;
1286 WMScreen
*scr
= WMWidgetScreen(table
);
1288 switch (event
->type
) {
1290 W_DrawRelief(scr
, W_VIEW_DRAWABLE(table
->view
), 0, 0,
1291 W_VIEW_WIDTH(table
->view
), W_VIEW_HEIGHT(table
->view
),
1299 handleResize(W_ViewDelegate
*self
, WMView
*view
)
1301 reorganizeInterior(view
->self
);
1306 reorganizeInterior(WMTableView
*table
)
1310 WMSize size
= getTotalSize(table
);
1311 WMView
*view
= table
->view
;
1313 int hsThickness
, vsThickness
;
1316 vsThickness
= WMWidgetWidth(table
->vscroll
);
1318 hsThickness
= WMWidgetHeight(table
->hscroll
);
1320 width
= W_VIEW_WIDTH(view
) - 2;
1321 height
= W_VIEW_HEIGHT(view
) - 3;
1323 height
-= table
->headerHeight
; /* table header */
1326 WMResizeWidget(table
->corner
, 20, table
->headerHeight
);
1328 WMMoveWidget(table
->vscroll
, 1, table
->headerHeight
+ 1);
1329 WMResizeWidget(table
->vscroll
, 20, height
+ 1);
1331 if (table
->hscroll
) {
1332 WMMoveWidget(table
->hscroll
, vsThickness
, W_VIEW_HEIGHT(view
) - hsThickness
- 1);
1333 WMResizeWidget(table
->hscroll
, width
-(vsThickness
+1), hsThickness
);
1337 WMResizeWidget(table
->header
, width
-(vsThickness
+1), table
->headerHeight
);
1339 if (table
->viewBuffer
) {
1340 WMReleasePixmap(table
->viewBuffer
);
1341 table
->viewBuffer
= NULL
;
1344 width
-= vsThickness
;
1345 height
-= hsThickness
;
1348 vw
= WMIN(size
.width
, width
);
1349 vh
= WMIN(size
.height
, height
);
1351 W_MoveView(table
->tableView
, vsThickness
+1, 1+table
->headerHeight
+1);
1352 W_ResizeView(table
->tableView
, WMAX(vw
, 1), WMAX(vh
, 1)+1);
1354 adjustScrollers(table
);
1356 repaintTable(table
);
1361 rearrangeHeader(WMTableView
*table
)
1366 /*WMRect rect = WMGetScrollViewVisibleRect(table->scrollView);*/
1370 count
= WMGetArrayItemCount(table
->columns
);
1371 for (i
= 0; i
< count
; i
++) {
1372 WMTableColumn
*column
= WMGetFromArray(table
->columns
, i
);
1373 WMView
*splitter
= WMGetFromArray(table
->splitters
, i
);
1375 WMMoveWidget(column
->titleW
, width
, 0);
1376 WMResizeWidget(column
->titleW
, column
->width
-1, table
->headerHeight
);
1378 width
+= column
->width
;
1379 W_MoveView(splitter
, width
-1, 0);
1382 wassertr(table
->delegate
&& table
->delegate
->numberOfRows
);
1384 table
->rows
= table
->delegate
->numberOfRows(table
->delegate
, table
);
1386 table
->tableWidth
= width
+ 1;
1388 handleResize(table
->view
->delegate
, table
->view
);