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
;
29 static void handleResize(W_ViewDelegate
*self
, WMView
*view
);
31 static void rearrangeHeader(WMTableView
*table
);
33 static WMRange
rowsInRect(WMTableView
*table
, WMRect rect
);
37 WMCreateTableColumn(char *title
)
39 WMTableColumn
*col
= wmalloc(sizeof(WMTableColumn
));
49 col
->title
= wstrdup(title
);
61 WMSetTableColumnId(WMTableColumn
*column
, void *id
)
68 WMGetTableColumnId(WMTableColumn
*column
)
75 WMSetTableColumnWidth(WMTableColumn
*column
, unsigned width
)
77 if (column
->maxWidth
== 0)
78 column
->width
= WMAX(column
->minWidth
, width
);
80 column
->width
= WMAX(column
->minWidth
, WMIN(column
->maxWidth
, width
));
83 rearrangeHeader(column
->table
);
89 WMSetTableColumnDelegate(WMTableColumn
*column
, WMTableColumnDelegate
*delegate
)
91 column
->delegate
= delegate
;
96 WMSetTableColumnConstraints(WMTableColumn
*column
, unsigned minWidth
,
99 wassertr(maxWidth
== 0 || minWidth
<= maxWidth
);
101 column
->minWidth
= minWidth
;
102 column
->maxWidth
= maxWidth
;
104 if (column
->width
< column
->minWidth
)
105 WMSetTableColumnWidth(column
, column
->minWidth
);
106 else if (column
->width
> column
->maxWidth
&& column
->maxWidth
!= 0)
107 WMSetTableColumnWidth(column
, column
->maxWidth
);
112 WMSetTableColumnEditable(WMTableColumn
*column
, Bool flag
)
114 column
->editable
= ((flag
==0) ? 0 : 1);
119 WMGetTableColumnTableView(WMTableColumn
*column
)
121 return column
->table
;
138 WMPixmap
*viewBuffer
;
143 WMArray
*selectedRows
;
154 Cursor splitterCursor
;
158 WMTableViewDelegate
*delegate
;
168 unsigned headerHeight
;
173 unsigned drawsGrid
:1;
174 unsigned canSelectRow
:1;
175 unsigned canSelectMultiRows
:1;
176 unsigned canDeselectRow
:1;
178 unsigned int hasVScroller
:1;
179 unsigned int hasHScroller
:1;
182 static W_Class tableClass
= 0;
185 static W_ViewDelegate viewDelegate
= {
195 static void reorganizeInterior(WMTableView
*table
);
198 static void handleEvents(XEvent
*event
, void *data
);
199 static void handleTableEvents(XEvent
*event
, void *data
);
200 static void repaintTable(WMTableView
*table
);
203 getTotalSize(WMTableView
*table
)
208 /* get width from columns */
210 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
211 WMTableColumn
*column
;
213 column
= WMGetFromArray(table
->columns
, i
);
215 size
.width
+= column
->width
;
218 /* get height from rows */
219 size
.height
= table
->rows
* table
->rowHeight
;
226 getVisibleRect(WMTableView
*table
)
228 WMSize size
= getTotalSize(table
);
231 if (table
->vscroll
) {
232 rect
.size
.height
= size
.height
* WMGetScrollerKnobProportion(table
->vscroll
);
233 rect
.pos
.y
= (size
.height
- rect
.size
.height
) * WMGetScrollerValue(table
->vscroll
);
235 rect
.size
.height
= size
.height
;
239 if (table
->hscroll
) {
240 rect
.size
.width
= size
.width
* WMGetScrollerKnobProportion(table
->hscroll
);
241 rect
.pos
.x
= (size
.width
- rect
.size
.width
) * WMGetScrollerValue(table
->hscroll
);
243 rect
.size
.width
= size
.width
;
252 scrollToPoint(WMTableView
*table
, int x
, int y
)
254 WMSize size
= getTotalSize(table
);
258 if (table
->hscroll
) {
259 if (size
.width
> W_VIEW_WIDTH(table
->tableView
)) {
260 prop
= (float)W_VIEW_WIDTH(table
->tableView
) / (float)size
.width
;
261 value
= (float)x
/ (float)(size
.width
- W_VIEW_WIDTH(table
->tableView
));
266 WMSetScrollerParameters(table
->hscroll
, value
, prop
);
269 if (table
->vscroll
) {
270 if (size
.height
> W_VIEW_HEIGHT(table
->tableView
)) {
271 prop
= (float)W_VIEW_HEIGHT(table
->tableView
) / (float)size
.height
;
272 value
= (float)y
/ (float)(size
.height
- W_VIEW_HEIGHT(table
->tableView
));
278 WMSetScrollerParameters(table
->vscroll
, value
, prop
);
282 if (table
->editingRow
>= 0) {
283 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
284 WMTableColumn
*column
;
286 column
= WMGetFromArray(table
->columns
, i
);
288 if (column
->delegate
&& column
->delegate
->beginCellEdit
)
289 (*column
->delegate
->beginCellEdit
)(column
->delegate
, column
,
299 adjustScrollers(WMTableView
*table
)
301 WMSize size
= getTotalSize(table
);
302 WMSize vsize
= WMGetViewSize(table
->tableView
);
306 if (table
->hscroll
) {
307 if (size
.width
<= vsize
.width
) {
311 oprop
= WMGetScrollerKnobProportion(table
->hscroll
);
314 ovalue
= WMGetScrollerValue(table
->hscroll
);
316 prop
= (float)vsize
.width
/(float)size
.width
;
317 value
= prop
*ovalue
/ oprop
;
319 WMSetScrollerParameters(table
->hscroll
, value
, prop
);
322 if (table
->vscroll
) {
323 if (size
.height
<= vsize
.height
) {
327 oprop
= WMGetScrollerKnobProportion(table
->vscroll
);
330 ovalue
= WMGetScrollerValue(table
->vscroll
);
332 prop
= (float)vsize
.height
/(float)size
.height
;
333 value
= prop
*ovalue
/ oprop
;
335 WMSetScrollerParameters(table
->vscroll
, value
, prop
);
341 doScroll(WMWidget
*self
, void *data
)
343 WMTableView
*table
= (WMTableView
*)data
;
347 WMSize ts
= getTotalSize(table
);
349 value
= WMGetScrollerValue(self
);
351 if (table
->hscroll
== (WMScroller
*)self
) {
352 vpsize
= W_VIEW_WIDTH(table
->tableView
);
355 vpsize
= W_VIEW_HEIGHT(table
->tableView
);
359 switch (WMGetScrollerHitPart(self
)) {
360 case WSDecrementWheel
:
361 case WSDecrementLine
:
362 value
-= (float)table
->rowHeight
/ size
;
365 WMSetScrollerParameters(self
, value
,
366 WMGetScrollerKnobProportion(self
));
370 case WSIncrementWheel
:
371 case WSIncrementLine
:
372 value
+= (float)table
->rowHeight
/ size
;
375 WMSetScrollerParameters(self
, value
,
376 WMGetScrollerKnobProportion(self
));
384 case WSDecrementPage
:
385 value
-= vpsize
/ size
;
388 WMSetScrollerParameters(self
, value
,
389 WMGetScrollerKnobProportion(self
));
393 case WSIncrementPage
:
394 value
+= vpsize
/ size
;
397 WMSetScrollerParameters(self
, value
,
398 WMGetScrollerKnobProportion(self
));
408 if (table
->editingRow
>= 0) {
410 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
411 WMTableColumn
*column
;
413 column
= WMGetFromArray(table
->columns
, i
);
415 if (column
->delegate
&& column
->delegate
->beginCellEdit
)
416 (*column
->delegate
->beginCellEdit
)(column
->delegate
, column
,
422 if (table
->hscroll
== self
) {
425 WMRect rect
= getVisibleRect(table
);
427 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
428 WMTableColumn
*column
;
431 column
= WMGetFromArray(table
->columns
, i
);
433 WMMoveWidget(column
->titleW
, x
- rect
.pos
.x
, 0);
435 x
+= W_VIEW_WIDTH(WMWidgetView(column
->titleW
)) + 1;
437 splitter
= WMGetFromArray(table
->splitters
, i
);
438 W_MoveView(splitter
, x
- rect
.pos
.x
- 1, 0);
445 splitterHandler(XEvent
*event
, void *data
)
447 WMTableColumn
*column
= (WMTableColumn
*)data
;
448 WMTableView
*table
= column
->table
;
452 WMScreen
*scr
= WMWidgetScreen(table
);
454 Display
*dpy
= WMScreenDisplay(scr
);
455 int h
= WMWidgetHeight(table
) - 22;
456 Window w
= WMViewXID(table
->view
);
458 pos
= WMGetViewPosition(WMWidgetView(column
->titleW
));
460 offsX
= pos
.x
+ column
->width
;
464 XDrawLine(dpy
, w
, gc
, cx
+20, 0, cx
+20, h
);
469 WMMaskEvent(dpy
, ButtonMotionMask
|ButtonReleaseMask
, &ev
);
475 if (column
->width
+ ev
.xmotion
.x
< column
->minWidth
)
476 cx
= pos
.x
+ column
->minWidth
;
477 else if (column
->maxWidth
> 0
478 && column
->width
+ ev
.xmotion
.x
> column
->maxWidth
)
479 cx
= pos
.x
+ column
->maxWidth
;
481 cx
= offsX
+ ev
.xmotion
.x
;
483 XDrawLine(dpy
, w
, gc
, ox
+20, 0, ox
+20, h
);
484 XDrawLine(dpy
, w
, gc
, cx
+20, 0, cx
+20, h
);
488 column
->width
= cx
- pos
.x
;
494 XDrawLine(dpy
, w
, gc
, cx
+20, 0, cx
+20, h
);
495 rearrangeHeader(table
);
501 realizeTable(void *data
, WMNotification
*notif
)
508 WMCreateTableView(WMWidget
*parent
)
510 WMTableView
*table
= wmalloc(sizeof(WMTableView
));
511 WMScreen
*scr
= WMWidgetScreen(parent
);
513 memset(table
, 0, sizeof(WMTableView
));
516 tableClass
= W_RegisterUserWidget();
518 table
->widgetClass
= tableClass
;
520 table
->view
= W_CreateView(W_VIEW(parent
));
523 table
->view
->self
= table
;
525 table
->view
->delegate
= &viewDelegate
;
527 table
->headerHeight
= 20;
529 table
->hscroll
= WMCreateScroller(table
);
530 WMSetScrollerAction(table
->hscroll
, doScroll
, table
);
531 WMMoveWidget(table
->hscroll
, 1, 2+table
->headerHeight
);
532 WMMapWidget(table
->hscroll
);
534 table
->hasHScroller
= 1;
536 table
->vscroll
= WMCreateScroller(table
);
537 WMSetScrollerArrowsPosition(table
->vscroll
, WSAMaxEnd
);
538 WMSetScrollerAction(table
->vscroll
, doScroll
, table
);
539 WMMoveWidget(table
->vscroll
, 1, 2+table
->headerHeight
);
540 WMMapWidget(table
->vscroll
);
542 table
->hasVScroller
= 1;
544 table
->header
= WMCreateFrame(table
);
545 WMMoveWidget(table
->header
, 22, 2);
546 WMMapWidget(table
->header
);
547 WMSetFrameRelief(table
->header
, WRFlat
);
549 table
->corner
= WMCreateLabel(table
);
550 WMResizeWidget(table
->corner
, 20, table
->headerHeight
);
551 WMMoveWidget(table
->corner
, 2, 2);
552 WMMapWidget(table
->corner
);
553 WMSetLabelRelief(table
->corner
, WRRaised
);
554 WMSetWidgetBackgroundColor(table
->corner
, scr
->darkGray
);
557 table
->tableView
= W_CreateView(table
->view
);
558 if (!table
->tableView
)
560 table
->tableView
->self
= table
;
561 W_MapView(table
->tableView
);
563 WMAddNotificationObserver(realizeTable
, table
, WMViewRealizedNotification
,
566 table
->tableView
->flags
.dontCompressExpose
= 1;
568 table
->gridColor
= WMCreateNamedColor(scr
, "#cccccc", False
);
569 /* table->gridColor = WMGrayColor(scr);*/
574 table
->backColor
= WMWhiteColor(scr
);
576 gcv
.foreground
= WMColorPixel(table
->gridColor
);
578 gcv
.line_style
= LineOnOffDash
;
579 table
->gridGC
= XCreateGC(WMScreenDisplay(scr
), W_DRAWABLE(scr
),
583 table
->editingRow
= -1;
584 table
->clickedRow
= -1;
586 table
->drawsGrid
= 1;
587 table
->rowHeight
= 16;
589 table
->tableWidth
= 1;
591 table
->columns
= WMCreateArray(4);
592 table
->splitters
= WMCreateArray(4);
594 table
->selectedRows
= WMCreateArray(16);
596 table
->splitterCursor
= XCreateFontCursor(WMScreenDisplay(scr
),
597 XC_sb_h_double_arrow
);
599 table
->canSelectRow
= 1;
601 WMCreateEventHandler(table
->view
, ExposureMask
|StructureNotifyMask
,
602 handleEvents
, table
);
604 WMCreateEventHandler(table
->tableView
, ExposureMask
|ButtonPressMask
|
605 ButtonReleaseMask
|ButtonMotionMask
,
606 handleTableEvents
, table
);
608 WMResizeWidget(table
, 50, 50);
613 if (table
->tableView
)
614 W_DestroyView(table
->tableView
);
616 W_DestroyView(table
->view
);
623 WMAddTableViewColumn(WMTableView
*table
, WMTableColumn
*column
)
625 WMScreen
*scr
= WMWidgetScreen(table
);
627 column
->table
= table
;
629 WMAddToArray(table
->columns
, column
);
631 if (!column
->titleW
) {
632 column
->titleW
= WMCreateLabel(table
);
633 WMSetLabelRelief(column
->titleW
, WRRaised
);
634 WMSetLabelFont(column
->titleW
, scr
->boldFont
);
635 WMSetLabelTextColor(column
->titleW
, scr
->white
);
636 WMSetWidgetBackgroundColor(column
->titleW
, scr
->darkGray
);
637 WMSetLabelText(column
->titleW
, column
->title
);
638 W_ReparentView(WMWidgetView(column
->titleW
),
639 WMWidgetView(table
->header
), 0, 0);
640 if (W_VIEW_REALIZED(table
->view
))
641 WMRealizeWidget(column
->titleW
);
642 WMMapWidget(column
->titleW
);
646 WMView
*splitter
= W_CreateView(WMWidgetView(table
->header
));
648 W_SetViewBackgroundColor(splitter
, WMWhiteColor(scr
));
650 if (W_VIEW_REALIZED(table
->view
))
651 W_RealizeView(splitter
);
653 W_ResizeView(splitter
, 2, table
->headerHeight
);
656 W_SetViewCursor(splitter
, table
->splitterCursor
);
657 WMCreateEventHandler(splitter
, ButtonPressMask
|ButtonReleaseMask
,
658 splitterHandler
, column
);
660 WMAddToArray(table
->splitters
, splitter
);
663 rearrangeHeader(table
);
668 WMSetTableViewHeaderHeight(WMTableView
*table
, unsigned height
)
670 table
->headerHeight
= height
;
672 handleResize(NULL
, table
->view
);
677 WMSetTableViewDelegate(WMTableView
*table
, WMTableViewDelegate
*delegate
)
679 table
->delegate
= delegate
;
684 WMSetTableViewAction(WMTableView
*table
, WMAction
*action
, void *clientData
)
686 table
->action
= action
;
688 table
->clientData
= clientData
;
693 WMGetTableViewClickedColumn(WMTableView
*table
)
695 return table
->clickedColumn
;
700 WMGetTableViewClickedRow(WMTableView
*table
)
702 return table
->clickedRow
;
707 WMGetTableViewSelectedRows(WMTableView
*table
)
709 return table
->selectedRows
;
714 WMGetTableViewDocumentView(WMTableView
*table
)
716 return table
->tableView
;
721 WMTableViewDataForCell(WMTableView
*table
, WMTableColumn
*column
, int row
)
723 return (*table
->delegate
->valueForCell
)(table
->delegate
, column
, row
);
728 WMSetTableViewDataForCell(WMTableView
*table
, WMTableColumn
*column
, int row
,
731 (*table
->delegate
->setValueForCell
)(table
->delegate
, column
, row
, data
);
736 WMTableViewRectForCell(WMTableView
*table
, WMTableColumn
*column
, int row
)
742 rect
.pos
.y
= row
* table
->rowHeight
;
743 rect
.size
.height
= table
->rowHeight
;
745 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
747 col
= WMGetFromArray(table
->columns
, i
);
750 rect
.size
.width
= col
->width
;
754 rect
.pos
.x
+= col
->width
;
758 WMRect r
= getVisibleRect(table
);
760 rect
.pos
.y
-= r
.pos
.y
;
761 rect
.pos
.x
-= r
.pos
.x
;
769 WMSetTableViewDataSource(WMTableView
*table
, void *source
)
771 table
->dataSource
= source
;
776 WMGetTableViewDataSource(WMTableView
*table
)
778 return table
->dataSource
;
784 WMSetTableViewHasHorizontalScroller(WMTableView
*tPtr
, Bool flag
)
787 if (tPtr
->hasHScroller
)
789 tPtr
->hasHScroller
= 1;
791 tPtr
->hscroll
= WMCreateScroller(tPtr
);
792 WMSetScrollerAction(tPtr
->hscroll
, doScroll
, tPtr
);
793 WMSetScrollerArrowsPosition(tPtr
->hscroll
, WSAMaxEnd
);
794 /* make it a horiz. scroller */
795 WMResizeWidget(tPtr
->hscroll
, 1, 2);
797 if (W_VIEW_REALIZED(tPtr
->view
)) {
798 WMRealizeWidget(tPtr
->hscroll
);
801 reorganizeInterior(tPtr
);
803 WMMapWidget(tPtr
->hscroll
);
805 if (!tPtr
->hasHScroller
)
807 tPtr
->hasHScroller
= 0;
809 WMUnmapWidget(tPtr
->hscroll
);
810 WMDestroyWidget(tPtr
->hscroll
);
811 tPtr
->hscroll
= NULL
;
813 reorganizeInterior(tPtr
);
818 /* not supported by now */
820 WMSetTableViewHasVerticalScroller(WMTableView
*tPtr
, Bool flag
)
823 if (tPtr
->hasVScroller
)
825 tPtr
->hasVScroller
= 1;
827 tPtr
->vscroll
= WMCreateScroller(tPtr
);
828 WMSetScrollerAction(tPtr
->vscroll
, doScroll
, tPtr
);
829 WMSetScrollerArrowsPosition(tPtr
->vscroll
, WSAMaxEnd
);
830 /* make it a vert. scroller */
831 WMResizeWidget(tPtr
->vscroll
, 1, 2);
833 if (W_VIEW_REALIZED(tPtr
->view
)) {
834 WMRealizeWidget(tPtr
->vscroll
);
837 reorganizeInterior(tPtr
);
839 WMMapWidget(tPtr
->vscroll
);
841 if (!tPtr
->hasVScroller
)
843 tPtr
->hasVScroller
= 0;
845 WMUnmapWidget(tPtr
->vscroll
);
846 WMDestroyWidget(tPtr
->vscroll
);
847 tPtr
->vscroll
= NULL
;
849 reorganizeInterior(tPtr
);
855 WMSetTableViewBackgroundColor(WMTableView
*table
, WMColor
*color
)
857 W_SetViewBackgroundColor(table
->tableView
, color
);
859 if (table
->backColor
)
860 WMReleaseColor(table
->backColor
);
862 table
->backColor
= WMRetainColor(color
);
869 WMSetTableViewGridColor(WMTableView
*table
, WMColor
*color
)
871 WMReleaseColor(table
->gridColor
);
872 table
->gridColor
= WMRetainColor(color
);
873 XSetForeground(WMScreenDisplay(WMWidgetScreen(table
)), table
->gridGC
,
874 WMColorPixel(color
));
881 WMSetTableViewRowHeight(WMTableView
*table
, int height
)
883 table
->rowHeight
= height
;
890 WMScrollTableViewRowToVisible(WMTableView
*table
, int row
)
892 WMScroller
*scroller
;
897 rect
= getVisibleRect(table
);
898 range
= rowsInRect(table
, rect
);
900 scroller
= table
->vscroll
;
902 if (row
< range
.position
) {
903 newY
= row
* table
->rowHeight
- rect
.size
.height
/ 2;
904 } else if (row
>= range
.position
+ range
.count
) {
905 newY
= row
* table
->rowHeight
- rect
.size
.height
/ 2;
909 tmp
= table
->rows
*table
->rowHeight
- rect
.size
.height
;
910 newY
= WMAX(0, WMIN(newY
, tmp
));
912 scrollToPoint(table
, rect
.pos
.x
, newY
);
918 drawGrid(WMTableView
*table
, WMRect rect
)
920 WMScreen
*scr
= WMWidgetScreen(table
);
921 Display
*dpy
= WMScreenDisplay(scr
);
926 Drawable d
= WMGetPixmapXID(table
->viewBuffer
);
927 GC gc
= table
->gridGC
;
932 XSetDashes(dpy
, gc
, 0, dashl
, 1);
934 y1
= (rect
.pos
.y
/table
->rowHeight
- 1)*table
->rowHeight
;
935 y2
= y1
+ (rect
.size
.height
/table
->rowHeight
+2)*table
->rowHeight
;
938 y2
= W_VIEW_HEIGHT(table
->tableView
);
941 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
942 WMTableColumn
*column
;
944 XDrawLine(dpy
, d
, gc
, xx
, y1
, xx
, y2
);
946 column
= WMGetFromArray(table
->columns
, i
);
949 XDrawLine(dpy
, d
, gc
, xx
, y1
, xx
, y2
);
952 x2
= rect
.size
.width
;
957 XSetDashes(dpy
, gc
, (rect
.pos
.x
&1), dashl
, 1);
960 y1
= -rect
.pos
.y
%table
->rowHeight
;
961 y2
= y1
+ rect
.size
.height
+ table
->rowHeight
;
963 for (i
= y1
; i
<= y2
; i
+= table
->rowHeight
) {
964 XDrawLine(dpy
, d
, gc
, x1
, i
, x2
, i
);
970 columnsInRect(WMTableView
*table
, WMRect rect
)
972 WMTableColumn
*column
;
975 int totalColumns
= WMGetArrayItemCount(table
->columns
);
980 for (i
= 0; i
< totalColumns
; i
++) {
981 column
= WMGetFromArray(table
->columns
, i
);
983 if (rect
.pos
.x
>= pos
&& rect
.pos
.x
< pos
+ column
->width
) {
989 if (pos
> rect
.pos
.x
+ rect
.size
.width
) {
994 pos
+= column
->width
;
996 range
.count
= WMAX(1, WMIN(range
.count
, totalColumns
- range
.position
));
1002 rowsInRect(WMTableView
*table
, WMRect rect
)
1005 int rh
= table
->rowHeight
;
1008 dif
= rect
.pos
.y
% rh
;
1010 range
.position
= WMAX(0, (rect
.pos
.y
- dif
) / rh
);
1011 range
.count
= WMAX(1, WMIN((rect
.size
.height
+ dif
) / rh
, table
->rows
));
1018 drawRow(WMTableView
*table
, int row
, WMRect clipRect
)
1021 WMRange cols
= columnsInRect(table
, clipRect
);
1022 WMTableColumn
*column
;
1023 Drawable d
= WMGetPixmapXID(table
->viewBuffer
);
1025 for (i
= cols
.position
; i
< cols
.position
+cols
.count
; i
++) {
1026 column
= WMGetFromArray(table
->columns
, i
);
1028 if (!column
->delegate
|| !column
->delegate
->drawCell
)
1031 if (WMFindInArray(table
->selectedRows
, NULL
, (void*)row
) != WANotFound
)
1032 (*column
->delegate
->drawSelectedCell
)(column
->delegate
, column
, row
, d
);
1034 (*column
->delegate
->drawCell
)(column
->delegate
, column
, row
, d
);
1041 drawFullRow(WMTableView
*table
, int row
)
1044 WMTableColumn
*column
;
1045 Drawable d
= WMGetPixmapXID(table
->viewBuffer
);
1047 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
1048 column
= WMGetFromArray(table
->columns
, i
);
1050 if (!column
->delegate
|| !column
->delegate
->drawCell
)
1053 if (WMFindInArray(table
->selectedRows
, NULL
, (void*)row
) != WANotFound
)
1054 (*column
->delegate
->drawSelectedCell
)(column
->delegate
, column
, row
, d
);
1056 (*column
->delegate
->drawCell
)(column
->delegate
, column
, row
, d
);
1063 setRowSelected(WMTableView
*table
, unsigned row
, Bool flag
)
1067 if (WMFindInArray(table
->selectedRows
, NULL
, (void*)row
) != WANotFound
) {
1069 WMRemoveFromArray(table
->selectedRows
, (void*)row
);
1074 WMAddToArray(table
->selectedRows
, (void*)row
);
1078 if (repaint
&& row
< table
->rows
) {
1079 /*drawFullRow(table, row);*/
1080 repaintTable(table
);
1086 repaintTable(WMTableView
*table
)
1090 WMScreen
*scr
= WMWidgetScreen(table
);
1093 if (!table
->delegate
|| !W_VIEW_REALIZED(table
->view
))
1096 wassertr(table
->delegate
->numberOfRows
);
1098 if (!table
->viewBuffer
) {
1099 table
->viewBuffer
= WMCreatePixmap(scr
,
1100 W_VIEW_WIDTH(table
->tableView
),
1101 W_VIEW_HEIGHT(table
->tableView
),
1102 WMScreenDepth(scr
), 0);
1105 XFillRectangle(scr
->display
,
1106 WMGetPixmapXID(table
->viewBuffer
),
1107 WMColorGC(table
->backColor
), 0, 0,
1108 W_VIEW_WIDTH(table
->tableView
),
1109 W_VIEW_HEIGHT(table
->tableView
));
1111 rect
= getVisibleRect(table
);
1113 if (table
->drawsGrid
) {
1114 drawGrid(table
, rect
);
1117 rows
= rowsInRect(table
, rect
);
1118 for (i
= rows
.position
;
1119 i
< WMIN(rows
.position
+rows
.count
+ 1, table
->rows
);
1121 drawRow(table
, i
, rect
);
1124 XSetWindowBackgroundPixmap(scr
->display
, table
->tableView
->window
,
1125 WMGetPixmapXID(table
->viewBuffer
));
1126 XClearWindow(scr
->display
, table
->tableView
->window
);
1131 stopRowEdit(WMTableView
*table
, int row
)
1134 WMTableColumn
*column
;
1136 table
->editingRow
= -1;
1137 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
1138 column
= WMGetFromArray(table
->columns
, i
);
1140 if (column
->delegate
&& column
->delegate
->endCellEdit
)
1141 (*column
->delegate
->endCellEdit
)(column
->delegate
, column
, row
);
1148 WMEditTableViewRow(WMTableView
*table
, int row
)
1151 WMTableColumn
*column
;
1153 if (table
->editingRow
>= 0) {
1154 stopRowEdit(table
, table
->editingRow
);
1157 table
->editingRow
= row
;
1162 for (i
= 0; i
< WMGetArrayItemCount(table
->columns
); i
++) {
1163 column
= WMGetFromArray(table
->columns
, i
);
1165 if (column
->delegate
&& column
->delegate
->beginCellEdit
)
1166 (*column
->delegate
->beginCellEdit
)(column
->delegate
, column
, row
);
1172 WMSelectTableViewRow(WMTableView
*table
, int row
)
1174 if (table
->clickedRow
>= 0)
1175 setRowSelected(table
, table
->clickedRow
, False
);
1177 if (row
>= table
->rows
) {
1181 setRowSelected(table
, row
, True
);
1182 table
->clickedRow
= row
;
1185 (*table
->action
)(table
, table
->clientData
);
1186 WMPostNotificationName(WMTableViewSelectionDidChangeNotification
,
1192 WMReloadTableView(WMTableView
*table
)
1194 if (table
->editingRow
>= 0)
1195 stopRowEdit(table
, table
->editingRow
);
1197 /* when this is called, nothing in the table can be assumed to be
1198 * like the last time we accessed it (ie, rows might have disappeared) */
1200 WMEmptyArray(table
->selectedRows
);
1202 if (table
->clickedRow
>= 0) {
1204 (*table
->action
)(table
, table
->clientData
);
1205 WMPostNotificationName(WMTableViewSelectionDidChangeNotification
,
1207 table
->clickedRow
= -1;
1210 if (table
->delegate
&& table
->delegate
->numberOfRows
) {
1213 rows
= (*table
->delegate
->numberOfRows
)(table
->delegate
, table
);
1215 if (rows
!= table
->rows
) {
1217 handleResize(table
->view
->delegate
, table
->view
);
1219 repaintTable(table
);
1226 WMNoteTableViewNumberOfRowsChanged(WMTableView
*table
)
1228 WMReloadTableView(table
);
1233 handleTableEvents(XEvent
*event
, void *data
)
1235 WMTableView
*table
= (WMTableView
*)data
;
1238 switch (event
->type
) {
1240 if (event
->xbutton
.button
== Button1
) {
1241 WMRect rect
= getVisibleRect(table
);
1243 row
= (event
->xbutton
.y
+ rect
.pos
.y
)/table
->rowHeight
;
1244 if (row
!= table
->clickedRow
) {
1245 setRowSelected(table
, table
->clickedRow
, False
);
1246 setRowSelected(table
, row
, True
);
1247 table
->clickedRow
= row
;
1248 table
->dragging
= 1;
1250 table
->dragging
= 1;
1256 if (table
->dragging
&& event
->xmotion
.y
>= 0) {
1257 WMRect rect
= getVisibleRect(table
);
1259 row
= (event
->xmotion
.y
+ rect
.pos
.y
)/table
->rowHeight
;
1260 if (table
->clickedRow
!= row
&& row
>= 0 && row
< table
->rows
) {
1261 setRowSelected(table
, table
->clickedRow
, False
);
1262 setRowSelected(table
, row
, True
);
1263 table
->clickedRow
= row
;
1269 if (event
->xbutton
.button
== Button1
) {
1271 (*table
->action
)(table
, table
->clientData
);
1272 WMPostNotificationName(WMTableViewSelectionDidChangeNotification
,
1274 table
->dragging
= 0;
1282 handleEvents(XEvent
*event
, void *data
)
1284 WMTableView
*table
= (WMTableView
*)data
;
1285 WMScreen
*scr
= WMWidgetScreen(table
);
1287 switch (event
->type
) {
1289 W_DrawRelief(scr
, W_VIEW_DRAWABLE(table
->view
), 0, 0,
1290 W_VIEW_WIDTH(table
->view
), W_VIEW_HEIGHT(table
->view
),
1298 handleResize(W_ViewDelegate
*self
, WMView
*view
)
1300 reorganizeInterior(view
->self
);
1305 reorganizeInterior(WMTableView
*table
)
1309 WMSize size
= getTotalSize(table
);
1310 WMView
*view
= table
->view
;
1312 int hsThickness
, vsThickness
;
1315 vsThickness
= WMWidgetWidth(table
->vscroll
);
1317 hsThickness
= WMWidgetHeight(table
->hscroll
);
1319 width
= W_VIEW_WIDTH(view
) - 2;
1320 height
= W_VIEW_HEIGHT(view
) - 3;
1322 height
-= table
->headerHeight
; /* table header */
1325 WMResizeWidget(table
->corner
, 20, table
->headerHeight
);
1327 WMMoveWidget(table
->vscroll
, 1, table
->headerHeight
+ 1);
1328 WMResizeWidget(table
->vscroll
, 20, height
+ 1);
1330 if (table
->hscroll
) {
1331 WMMoveWidget(table
->hscroll
, vsThickness
, W_VIEW_HEIGHT(view
) - hsThickness
- 1);
1332 WMResizeWidget(table
->hscroll
, width
-(vsThickness
+1), hsThickness
);
1336 WMResizeWidget(table
->header
, width
-(vsThickness
+1), table
->headerHeight
);
1338 if (table
->viewBuffer
) {
1339 WMReleasePixmap(table
->viewBuffer
);
1340 table
->viewBuffer
= NULL
;
1343 width
-= vsThickness
;
1344 height
-= hsThickness
;
1347 vw
= WMIN(size
.width
, width
);
1348 vh
= WMIN(size
.height
, height
);
1350 W_MoveView(table
->tableView
, vsThickness
+1, 1+table
->headerHeight
+1);
1351 W_ResizeView(table
->tableView
, WMAX(vw
, 1), WMAX(vh
, 1)+1);
1353 adjustScrollers(table
);
1355 repaintTable(table
);
1360 rearrangeHeader(WMTableView
*table
)
1365 /*WMRect rect = WMGetScrollViewVisibleRect(table->scrollView);*/
1369 count
= WMGetArrayItemCount(table
->columns
);
1370 for (i
= 0; i
< count
; i
++) {
1371 WMTableColumn
*column
= WMGetFromArray(table
->columns
, i
);
1372 WMView
*splitter
= WMGetFromArray(table
->splitters
, i
);
1374 WMMoveWidget(column
->titleW
, width
, 0);
1375 WMResizeWidget(column
->titleW
, column
->width
-1, table
->headerHeight
);
1377 width
+= column
->width
;
1378 W_MoveView(splitter
, width
-1, 0);
1381 wassertr(table
->delegate
&& table
->delegate
->numberOfRows
);
1383 table
->rows
= table
->delegate
->numberOfRows(table
->delegate
, table
);
1385 table
->tableWidth
= width
+ 1;
1387 handleResize(table
->view
->delegate
, table
->view
);