7 char *WMListDidScrollNotification
= "WMListDidScrollNotification";
8 char *WMListSelectionDidChangeNotification
= "WMListSelectionDidChangeNotification";
10 typedef struct W_List
{
14 WMArray
*items
; /* list of WMListItem */
15 WMArray
*selectedItems
; /* list of selected WMListItems */
19 short topItem
; /* index of first visible item */
21 short fullFitLines
; /* no of lines that fit entirely */
25 void *doubleClientData
;
26 WMAction
*doubleAction
;
30 WMHandlerID
*idleID
; /* for updating the scroller after adding elements */
32 WMScroller
*vScroller
;
35 unsigned int allowMultipleSelection
:1;
36 unsigned int allowEmptySelection
:1;
37 unsigned int userDrawn
:1;
38 unsigned int userItemHeight
:1;
39 unsigned int dontFitAll
:1; /* 1 = last item won't be fully visible */
40 unsigned int redrawPending
:1;
41 unsigned int buttonPressed
:1;
42 unsigned int buttonWasPressed
:1;
48 #define DEFAULT_WIDTH 150
49 #define DEFAULT_HEIGHT 150
52 static void destroyList(List
*lPtr
);
53 static void paintList(List
*lPtr
);
56 static void handleEvents(XEvent
*event
, void *data
);
57 static void handleActionEvents(XEvent
*event
, void *data
);
58 static void updateScroller(List
*lPtr
);
60 static void vScrollCallBack(WMWidget
*scroller
, void *self
);
62 static void updateGeometry(WMList
*lPtr
);
63 static void didResizeList();
65 static void unselectAllListItems(WMList
*lPtr
, WMListItem
*exceptThis
);
68 W_ViewDelegate _ListViewDelegate
= {
78 releaseItem(void *data
)
80 WMListItem
*item
= (WMListItem
*)data
;
89 WMCreateList(WMWidget
*parent
)
92 W_Screen
*scrPtr
= W_VIEW(parent
)->screen
;
94 lPtr
= wmalloc(sizeof(List
));
95 memset(lPtr
, 0, sizeof(List
));
97 lPtr
->widgetClass
= WC_List
;
99 lPtr
->view
= W_CreateView(W_VIEW(parent
));
104 lPtr
->view
->self
= lPtr
;
106 lPtr
->view
->delegate
= &_ListViewDelegate
;
108 WMCreateEventHandler(lPtr
->view
, ExposureMask
|StructureNotifyMask
109 |ClientMessageMask
, handleEvents
, lPtr
);
111 WMCreateEventHandler(lPtr
->view
, ButtonPressMask
|ButtonReleaseMask
112 |EnterWindowMask
|LeaveWindowMask
|ButtonMotionMask
,
113 handleActionEvents
, lPtr
);
115 lPtr
->itemHeight
= WMFontHeight(scrPtr
->normalFont
) + 1;
117 lPtr
->items
= WMCreateArrayWithDestructor(4, releaseItem
);
118 lPtr
->selectedItems
= WMCreateArray(4);
120 /* create the vertical scroller */
121 lPtr
->vScroller
= WMCreateScroller(lPtr
);
122 WMMoveWidget(lPtr
->vScroller
, 1, 1);
123 WMSetScrollerArrowsPosition(lPtr
->vScroller
, WSAMaxEnd
);
125 WMSetScrollerAction(lPtr
->vScroller
, vScrollCallBack
, lPtr
);
127 /* make the scroller map itself when it's realized */
128 WMMapWidget(lPtr
->vScroller
);
130 W_ResizeView(lPtr
->view
, DEFAULT_WIDTH
, DEFAULT_HEIGHT
);
137 WMSetListAllowMultipleSelection(WMList
*lPtr
, Bool flag
)
139 lPtr
->flags
.allowMultipleSelection
= flag
? 1 : 0;
144 WMSetListAllowEmptySelection(WMList
*lPtr
, Bool flag
)
146 lPtr
->flags
.allowEmptySelection
= flag
? 1 : 0;
151 comparator(const void *a
, const void *b
)
153 return (strcmp((*(WMListItem
**)a
)->text
, (*(WMListItem
**)b
)->text
));
158 WMSortListItems(WMList
*lPtr
)
160 WMSortArray(lPtr
->items
, comparator
);
168 WMSortListItemsWithComparer(WMList
*lPtr
, WMCompareDataProc
*func
)
170 WMSortArray(lPtr
->items
, func
);
178 WMInsertListItem(WMList
*lPtr
, int row
, char *text
)
182 CHECK_CLASS(lPtr
, WC_List
);
184 item
= wmalloc(sizeof(WMListItem
));
185 memset(item
, 0, sizeof(WMListItem
));
186 item
->text
= wstrdup(text
);
188 row
= WMIN(row
, WMGetArrayItemCount(lPtr
->items
));
191 WMAddToArray(lPtr
->items
, item
);
193 WMInsertInArray(lPtr
->items
, row
, item
);
195 /* update the scroller when idle, so that we don't waste time
196 * updating it when another item is going to be added later */
198 lPtr
->idleID
= WMAddIdleHandler((WMCallback
*)updateScroller
, lPtr
);
206 WMRemoveListItem(WMList
*lPtr
, int row
)
209 int topItem
= lPtr
->topItem
;
212 CHECK_CLASS(lPtr
, WC_List
);
214 /*wassertr(row>=0 && row<WMGetArrayItemCount(lPtr->items));*/
215 if (row
<0 || row
>=WMGetArrayItemCount(lPtr
->items
))
218 item
= WMGetFromArray(lPtr
->items
, row
);
219 if (item
->selected
) {
220 WMRemoveFromArray(lPtr
->selectedItems
, item
);
224 if (row
<= lPtr
->topItem
+lPtr
->fullFitLines
+lPtr
->flags
.dontFitAll
)
226 if (lPtr
->topItem
< 0)
229 WMDeleteFromArray(lPtr
->items
, row
);
232 lPtr
->idleID
= WMAddIdleHandler((WMCallback
*)updateScroller
, lPtr
);
234 if (lPtr
->topItem
!= topItem
) {
235 WMPostNotificationName(WMListDidScrollNotification
, lPtr
, NULL
);
238 WMPostNotificationName(WMListSelectionDidChangeNotification
, lPtr
, NULL
);
244 WMGetListItem(WMList
*lPtr
, int row
)
246 return WMGetFromArray(lPtr
->items
, row
);
251 WMGetListItems(WMList
*lPtr
)
258 WMSetListUserDrawProc(WMList
*lPtr
, WMListDrawProc
*proc
)
260 lPtr
->flags
.userDrawn
= 1;
266 WMSetListUserDrawItemHeight(WMList
*lPtr
, unsigned short height
)
270 lPtr
->flags
.userItemHeight
= 1;
271 lPtr
->itemHeight
= height
;
273 updateGeometry(lPtr
);
278 WMClearList(WMList
*lPtr
)
280 int selNo
= WMGetArrayItemCount(lPtr
->selectedItems
);
282 WMEmptyArray(lPtr
->selectedItems
);
283 WMEmptyArray(lPtr
->items
);
288 WMDeleteIdleHandler(lPtr
->idleID
);
291 if (lPtr
->view
->flags
.realized
) {
292 updateScroller(lPtr
);
295 WMPostNotificationName(WMListSelectionDidChangeNotification
, lPtr
, NULL
);
301 WMSetListAction(WMList
*lPtr
, WMAction
*action
, void *clientData
)
303 lPtr
->action
= action
;
304 lPtr
->clientData
= clientData
;
309 WMSetListDoubleAction(WMList
*lPtr
, WMAction
*action
, void *clientData
)
311 lPtr
->doubleAction
= action
;
312 lPtr
->doubleClientData
= clientData
;
317 WMGetListSelectedItems(WMList
*lPtr
)
319 return lPtr
->selectedItems
;
324 WMGetListSelectedItem(WMList
*lPtr
)
326 return WMGetFromArray(lPtr
->selectedItems
, 0);
331 WMGetListSelectedItemRow(WMList
*lPtr
)
333 WMListItem
*item
= WMGetFromArray(lPtr
->selectedItems
, 0);
335 return (item
!=NULL
? WMGetFirstInArray(lPtr
->items
, item
) : WLNotFound
);
340 WMGetListItemHeight(WMList
*lPtr
)
342 return lPtr
->itemHeight
;
347 WMSetListPosition(WMList
*lPtr
, int row
)
350 if (lPtr
->topItem
+ lPtr
->fullFitLines
> WMGetArrayItemCount(lPtr
->items
))
351 lPtr
->topItem
= WMGetArrayItemCount(lPtr
->items
) - lPtr
->fullFitLines
;
353 if (lPtr
->topItem
< 0)
356 if (lPtr
->view
->flags
.realized
)
357 updateScroller(lPtr
);
362 WMSetListBottomPosition(WMList
*lPtr
, int row
)
364 if (WMGetArrayItemCount(lPtr
->items
) > lPtr
->fullFitLines
) {
365 lPtr
->topItem
= row
- lPtr
->fullFitLines
;
366 if (lPtr
->topItem
< 0)
368 if (lPtr
->view
->flags
.realized
)
369 updateScroller(lPtr
);
375 WMGetListNumberOfRows(WMList
*lPtr
)
377 return WMGetArrayItemCount(lPtr
->items
);
382 WMGetListPosition(WMList
*lPtr
)
384 return lPtr
->topItem
;
389 WMListAllowsMultipleSelection(WMList
*lPtr
)
391 return lPtr
->flags
.allowMultipleSelection
;
396 WMListAllowsEmptySelection(WMList
*lPtr
)
398 return lPtr
->flags
.allowEmptySelection
;
403 scrollByAmount(WMList
*lPtr
, int amount
)
405 int itemCount
= WMGetArrayItemCount(lPtr
->items
);
407 if ((amount
< 0 && lPtr
->topItem
> 0) ||
408 (amount
> 0 && (lPtr
->topItem
+ lPtr
->fullFitLines
< itemCount
))) {
410 lPtr
->topItem
+= amount
;
411 if (lPtr
->topItem
< 0)
413 if (lPtr
->topItem
+ lPtr
->fullFitLines
> itemCount
)
414 lPtr
->topItem
= itemCount
- lPtr
->fullFitLines
;
416 updateScroller(lPtr
);
422 vScrollCallBack(WMWidget
*scroller
, void *self
)
424 WMList
*lPtr
= (WMList
*)self
;
426 int oldTopItem
= lPtr
->topItem
;
427 int itemCount
= WMGetArrayItemCount(lPtr
->items
);
429 height
= lPtr
->view
->size
.height
- 4;
431 switch (WMGetScrollerHitPart((WMScroller
*)scroller
)) {
432 case WSDecrementLine
:
433 scrollByAmount(lPtr
, -1);
436 case WSIncrementLine
:
437 scrollByAmount(lPtr
, 1);
440 case WSDecrementPage
:
441 scrollByAmount(lPtr
, -lPtr
->fullFitLines
+(1-lPtr
->flags
.dontFitAll
)+1);
444 case WSIncrementPage
:
445 scrollByAmount(lPtr
, lPtr
->fullFitLines
-(1-lPtr
->flags
.dontFitAll
)-1);
448 case WSDecrementWheel
:
449 scrollByAmount(lPtr
, -lPtr
->fullFitLines
/ 3);
452 case WSIncrementWheel
:
453 scrollByAmount(lPtr
, lPtr
->fullFitLines
/ 3);
457 lPtr
->topItem
= WMGetScrollerValue(lPtr
->vScroller
) *
458 (float)(itemCount
- lPtr
->fullFitLines
);
460 if (oldTopItem
!= lPtr
->topItem
)
461 paintList(lPtr
); // use updateScroller(lPtr) here?
471 if (lPtr
->topItem
!= oldTopItem
)
472 WMPostNotificationName(WMListDidScrollNotification
, lPtr
, NULL
);
477 paintItem(List
*lPtr
, int index
)
479 WMView
*view
= lPtr
->view
;
480 W_Screen
*scr
= view
->screen
;
481 int width
, height
, x
, y
;
484 itemPtr
= WMGetFromArray(lPtr
->items
, index
);
486 width
= lPtr
->view
->size
.width
- 2 - 19;
487 height
= lPtr
->itemHeight
;
489 y
= 2 + (index
-lPtr
->topItem
) * lPtr
->itemHeight
+ 1;
491 if (lPtr
->flags
.userDrawn
) {
495 rect
.size
.width
= width
;
496 rect
.size
.height
= height
;
500 flags
= itemPtr
->uflags
;
501 if (itemPtr
->disabled
)
502 flags
|= WLDSDisabled
;
503 if (itemPtr
->selected
)
504 flags
|= WLDSSelected
;
505 if (itemPtr
->isBranch
)
506 flags
|= WLDSIsBranch
;
509 (*lPtr
->draw
)(lPtr
, index
, view
->window
, itemPtr
->text
, flags
,
512 if (itemPtr
->selected
) {
513 XFillRectangle(scr
->display
, view
->window
, WMColorGC(scr
->white
),
514 x
, y
, width
, height
);
516 XClearArea(scr
->display
, view
->window
, x
, y
, width
, height
, False
);
519 W_PaintText(view
, view
->window
, scr
->normalFont
, x
+4, y
, width
,
520 WALeft
, WMColorGC(scr
->black
), False
,
521 itemPtr
->text
, strlen(itemPtr
->text
));
524 if ((index
-lPtr
->topItem
+lPtr
->fullFitLines
)*lPtr
->itemHeight
>
525 lPtr
->view
->size
.height
-2) {
526 W_DrawRelief(lPtr
->view
->screen
, lPtr
->view
->window
, 0, 0,
527 lPtr
->view
->size
.width
, lPtr
->view
->size
.height
,
535 paintList(List
*lPtr
)
537 W_Screen
*scrPtr
= lPtr
->view
->screen
;
540 if (!lPtr
->view
->flags
.mapped
)
543 if (WMGetArrayItemCount(lPtr
->items
) > 0) {
544 if (lPtr
->topItem
+lPtr
->fullFitLines
+lPtr
->flags
.dontFitAll
545 > WMGetArrayItemCount(lPtr
->items
)) {
547 lim
= WMGetArrayItemCount(lPtr
->items
) - lPtr
->topItem
;
548 XClearArea(scrPtr
->display
, lPtr
->view
->window
, 19,
549 2+lim
*lPtr
->itemHeight
, lPtr
->view
->size
.width
-21,
550 lPtr
->view
->size
.height
-lim
*lPtr
->itemHeight
-3, False
);
552 lim
= lPtr
->fullFitLines
+ lPtr
->flags
.dontFitAll
;
554 for (i
= lPtr
->topItem
; i
< lPtr
->topItem
+ lim
; i
++) {
558 XClearWindow(scrPtr
->display
, lPtr
->view
->window
);
560 W_DrawRelief(scrPtr
, lPtr
->view
->window
, 0, 0, lPtr
->view
->size
.width
,
561 lPtr
->view
->size
.height
, WRSunken
);
566 scrollTo(List
*lPtr
, int newTop
)
573 updateScroller(List
*lPtr
)
575 float knobProportion
, floatValue
, tmp
;
576 int count
= WMGetArrayItemCount(lPtr
->items
);
579 WMDeleteIdleHandler(lPtr
->idleID
);
584 if (count
== 0 || count
<= lPtr
->fullFitLines
)
585 WMSetScrollerParameters(lPtr
->vScroller
, 0, 1);
587 tmp
= lPtr
->fullFitLines
;
588 knobProportion
= tmp
/(float)count
;
590 floatValue
= (float)lPtr
->topItem
/(float)(count
- lPtr
->fullFitLines
);
592 WMSetScrollerParameters(lPtr
->vScroller
, floatValue
, knobProportion
);
598 handleEvents(XEvent
*event
, void *data
)
600 List
*lPtr
= (List
*)data
;
602 CHECK_CLASS(data
, WC_List
);
605 switch (event
->type
) {
607 if (event
->xexpose
.count
!=0)
621 matchTitle(void *item
, void *title
)
623 return (strcmp(((WMListItem
*)item
)->text
, (char*)title
)==0 ? 1 : 0);
628 WMFindRowOfListItemWithTitle(WMList
*lPtr
, char *title
)
630 return WMFindInArray(lPtr
->items
, matchTitle
, title
);
635 WMSelectListItem(WMList
*lPtr
, int row
)
639 if (row
>= WMGetArrayItemCount(lPtr
->items
))
643 /* row = -1 will deselects all for backward compatibility.
644 * will be removed later. -Dan */
645 WMUnselectAllListItems(lPtr
);
649 item
= WMGetFromArray(lPtr
->items
, row
);
651 return; /* Return if already selected */
653 if (!lPtr
->flags
.allowMultipleSelection
) {
654 /* unselect previous selected items */
655 unselectAllListItems(lPtr
, NULL
);
660 WMAddToArray(lPtr
->selectedItems
, item
);
662 if (lPtr
->view
->flags
.mapped
&& row
>=lPtr
->topItem
663 && row
<=lPtr
->topItem
+lPtr
->fullFitLines
) {
664 paintItem(lPtr
, row
);
667 WMPostNotificationName(WMListSelectionDidChangeNotification
, lPtr
, NULL
);
672 WMUnselectListItem(WMList
*lPtr
, int row
)
674 WMListItem
*item
= WMGetFromArray(lPtr
->items
, row
);
676 if (!item
|| !item
->selected
)
679 if (!lPtr
->flags
.allowEmptySelection
&&
680 WMGetArrayItemCount(lPtr
->selectedItems
) <= 1) {
685 WMRemoveFromArray(lPtr
->selectedItems
, item
);
687 if (lPtr
->view
->flags
.mapped
&& row
>=lPtr
->topItem
688 && row
<=lPtr
->topItem
+lPtr
->fullFitLines
) {
689 paintItem(lPtr
, row
);
692 WMPostNotificationName(WMListSelectionDidChangeNotification
, lPtr
, NULL
);
697 WMSelectListItemsInRange(WMList
*lPtr
, WMRange range
)
700 int position
= range
.position
, k
= 1, notify
= 0;
701 int total
= WMGetArrayItemCount(lPtr
->items
);
703 if (!lPtr
->flags
.allowMultipleSelection
)
706 return; /* Nothing to select */
708 if (range
.count
< 0) {
709 range
.count
= -range
.count
;
713 for (; range
.count
>0 && position
>=0 && position
<total
; range
.count
--) {
714 item
= WMGetFromArray(lPtr
->items
, position
);
715 if (!item
->selected
) {
717 WMAddToArray(lPtr
->selectedItems
, item
);
718 if (lPtr
->view
->flags
.mapped
&& position
>=lPtr
->topItem
719 && position
<=lPtr
->topItem
+lPtr
->fullFitLines
) {
720 paintItem(lPtr
, position
);
728 WMPostNotificationName(WMListSelectionDidChangeNotification
, lPtr
, NULL
);
734 WMSetListSelectionToRange(WMList
*lPtr
, WMRange range
)
737 int mark1
, mark2
, i
, k
;
738 int position
= range
.position
, notify
= 0;
739 int total
= WMGetArrayItemCount(lPtr
->items
);
741 if (!lPtr
->flags
.allowMultipleSelection
)
744 if (range
.count
==0) {
745 WMUnselectAllListItems(lPtr
);
749 if (range
.count
< 0) {
750 mark1
= range
.position
+ range
.count
+ 1;
751 mark2
= range
.position
+ 1;
752 range
.count
= -range
.count
;
755 mark1
= range
.position
;
756 mark2
= range
.position
+ range
.count
;
764 WMEmptyArray(lPtr
->selectedItems
);
766 for (i
=0; i
<mark1
; i
++) {
767 item
= WMGetFromArray(lPtr
->items
, i
);
768 if (item
->selected
) {
770 if (lPtr
->view
->flags
.mapped
&& i
>=lPtr
->topItem
771 && i
<=lPtr
->topItem
+lPtr
->fullFitLines
) {
777 for (; range
.count
>0 && position
>=0 && position
<total
; range
.count
--) {
778 item
= WMGetFromArray(lPtr
->items
, position
);
779 if (!item
->selected
) {
781 if (lPtr
->view
->flags
.mapped
&& position
>=lPtr
->topItem
782 && position
<=lPtr
->topItem
+lPtr
->fullFitLines
) {
783 paintItem(lPtr
, position
);
787 WMAddToArray(lPtr
->selectedItems
, item
);
790 for (i
=mark2
; i
<total
; i
++) {
791 item
= WMGetFromArray(lPtr
->items
, i
);
792 if (item
->selected
) {
794 if (lPtr
->view
->flags
.mapped
&& i
>=lPtr
->topItem
795 && i
<=lPtr
->topItem
+lPtr
->fullFitLines
) {
803 WMPostNotificationName(WMListSelectionDidChangeNotification
, lPtr
, NULL
);
809 WMSelectAllListItems(WMList
*lPtr
)
814 if (!lPtr
->flags
.allowMultipleSelection
)
817 if (WMGetArrayItemCount(lPtr
->items
) ==
818 WMGetArrayItemCount(lPtr
->selectedItems
)) {
819 return; /* All items are selected already */
822 WMFreeArray(lPtr
->selectedItems
);
823 lPtr
->selectedItems
= WMCreateArrayWithArray(lPtr
->items
);
825 for (i
=0; i
<WMGetArrayItemCount(lPtr
->items
); i
++) {
826 item
= WMGetFromArray(lPtr
->items
, i
);
827 if (!item
->selected
) {
829 if (lPtr
->view
->flags
.mapped
&& i
>=lPtr
->topItem
830 && i
<=lPtr
->topItem
+lPtr
->fullFitLines
) {
836 WMPostNotificationName(WMListSelectionDidChangeNotification
, lPtr
, NULL
);
840 * Be careful from where you call this function! It doesn't honor the
841 * allowEmptySelection flag and doesn't send a notification about selection
842 * change! You need to manage these in the functions from where you call it.
844 * This will unselect all items if exceptThis is NULL, else will keep
845 * exceptThis selected.
846 * Make sure that exceptThis is one of the already selected items if not NULL!
850 unselectAllListItems(WMList
*lPtr
, WMListItem
*exceptThis
)
855 for (i
=0; i
<WMGetArrayItemCount(lPtr
->items
); i
++) {
856 item
= WMGetFromArray(lPtr
->items
, i
);
857 if (item
!=exceptThis
&& item
->selected
) {
859 if (lPtr
->view
->flags
.mapped
&& i
>=lPtr
->topItem
860 && i
<=lPtr
->topItem
+lPtr
->fullFitLines
) {
866 WMEmptyArray(lPtr
->selectedItems
);
867 if (exceptThis
!=NULL
) {
868 exceptThis
->selected
= 1;
869 WMAddToArray(lPtr
->selectedItems
, exceptThis
);
875 WMUnselectAllListItems(WMList
*lPtr
)
878 WMListItem
*keepItem
;
880 keep
= lPtr
->flags
.allowEmptySelection
? 0 : 1;
882 if (WMGetArrayItemCount(lPtr
->selectedItems
) == keep
)
885 keepItem
= (keep
==1 ? WMGetFromArray(lPtr
->selectedItems
, 0) : NULL
);
887 unselectAllListItems(lPtr
, keepItem
);
889 WMPostNotificationName(WMListSelectionDidChangeNotification
, lPtr
, NULL
);
894 getItemIndexAt(List
*lPtr
, int clickY
)
898 index
= (clickY
- 2) / lPtr
->itemHeight
+ lPtr
->topItem
;
900 if (index
< 0 || index
>= WMGetArrayItemCount(lPtr
->items
))
908 toggleItemSelection(WMList
*lPtr
, int index
)
910 WMListItem
*item
= WMGetFromArray(lPtr
->items
, index
);
912 if (item
&& item
->selected
) {
913 WMUnselectListItem(lPtr
, index
);
915 WMSelectListItem(lPtr
, index
);
921 handleActionEvents(XEvent
*event
, void *data
)
923 List
*lPtr
= (List
*)data
;
925 int topItem
= lPtr
->topItem
;
926 static int lastClicked
= -1, prevItem
= -1;
928 CHECK_CLASS(data
, WC_List
);
930 switch (event
->type
) {
932 /* Ignore mouse wheel events, they're not "real" button events */
933 if (event
->xbutton
.button
== WINGsConfiguration
.mouseWheelUp
||
934 event
->xbutton
.button
== WINGsConfiguration
.mouseWheelDown
) {
938 lPtr
->flags
.buttonPressed
= 0;
939 tmp
= getItemIndexAt(lPtr
, event
->xbutton
.y
);
943 (*lPtr
->action
)(lPtr
, lPtr
->clientData
);
946 if (!(event
->xbutton
.state
& ShiftMask
))
947 lastClicked
= prevItem
= tmp
;
952 lPtr
->flags
.buttonPressed
= lPtr
->flags
.buttonWasPressed
;
953 lPtr
->flags
.buttonWasPressed
= 0;
957 lPtr
->flags
.buttonWasPressed
= lPtr
->flags
.buttonPressed
;
958 lPtr
->flags
.buttonPressed
= 0;
962 if (event
->xbutton
.x
<= WMWidgetWidth(lPtr
->vScroller
))
964 if (event
->xbutton
.button
== WINGsConfiguration
.mouseWheelDown
||
965 event
->xbutton
.button
== WINGsConfiguration
.mouseWheelUp
) {
968 if (event
->xbutton
.state
& ControlMask
) {
969 amount
= lPtr
->fullFitLines
-(1-lPtr
->flags
.dontFitAll
)-1;
970 } else if (event
->xbutton
.state
& ShiftMask
) {
973 amount
= lPtr
->fullFitLines
/ 3;
977 if (event
->xbutton
.button
== WINGsConfiguration
.mouseWheelUp
)
980 scrollByAmount(lPtr
, amount
);
984 tmp
= getItemIndexAt(lPtr
, event
->xbutton
.y
);
985 lPtr
->flags
.buttonPressed
= 1;
988 if (tmp
== lastClicked
&& WMIsDoubleClick(event
)) {
989 WMSelectListItem(lPtr
, tmp
);
990 if (lPtr
->doubleAction
)
991 (*lPtr
->doubleAction
)(lPtr
, lPtr
->doubleClientData
);
993 if (!lPtr
->flags
.allowMultipleSelection
) {
994 if (event
->xbutton
.state
& ControlMask
) {
995 toggleItemSelection(lPtr
, tmp
);
997 WMSelectListItem(lPtr
, tmp
);
1001 WMListItem
*lastSel
;
1003 if (event
->xbutton
.state
& ControlMask
) {
1004 toggleItemSelection(lPtr
, tmp
);
1005 } else if (event
->xbutton
.state
& ShiftMask
) {
1006 if (WMGetArrayItemCount(lPtr
->selectedItems
) == 0) {
1007 WMSelectListItem(lPtr
, tmp
);
1009 lastSel
= WMGetFromArray(lPtr
->items
, lastClicked
);
1010 range
.position
= WMGetFirstInArray(lPtr
->items
,
1012 if (tmp
>= range
.position
)
1013 range
.count
= tmp
- range
.position
+ 1;
1015 range
.count
= tmp
- range
.position
- 1;
1017 WMSetListSelectionToRange(lPtr
, range
);
1020 range
.position
= tmp
;
1022 WMSetListSelectionToRange(lPtr
, range
);
1028 if (!(event
->xbutton
.state
& ShiftMask
))
1029 lastClicked
= prevItem
= tmp
;
1034 if (lPtr
->flags
.buttonPressed
) {
1035 tmp
= getItemIndexAt(lPtr
, event
->xmotion
.y
);
1036 if (tmp
>=0 && tmp
!=prevItem
) {
1037 if (lPtr
->flags
.allowMultipleSelection
) {
1040 range
.position
= lastClicked
;
1041 if (tmp
>= lastClicked
)
1042 range
.count
= tmp
- lastClicked
+ 1;
1044 range
.count
= tmp
- lastClicked
- 1;
1045 WMSetListSelectionToRange(lPtr
, range
);
1047 WMSelectListItem(lPtr
, tmp
);
1054 if (lPtr
->topItem
!= topItem
)
1055 WMPostNotificationName(WMListDidScrollNotification
, lPtr
, NULL
);
1060 updateGeometry(WMList
*lPtr
)
1062 lPtr
->fullFitLines
= (lPtr
->view
->size
.height
- 4) / lPtr
->itemHeight
;
1063 if (lPtr
->fullFitLines
* lPtr
->itemHeight
< lPtr
->view
->size
.height
- 4) {
1064 lPtr
->flags
.dontFitAll
= 1;
1066 lPtr
->flags
.dontFitAll
= 0;
1069 if (WMGetArrayItemCount(lPtr
->items
) - lPtr
->topItem
<= lPtr
->fullFitLines
) {
1070 lPtr
->topItem
= WMGetArrayItemCount(lPtr
->items
) - lPtr
->fullFitLines
;
1071 if (lPtr
->topItem
< 0)
1075 updateScroller(lPtr
);
1080 didResizeList(W_ViewDelegate
*self
, WMView
*view
)
1082 WMList
*lPtr
= (WMList
*)view
->self
;
1084 WMResizeWidget(lPtr
->vScroller
, 1, view
->size
.height
-2);
1086 updateGeometry(lPtr
);
1091 destroyList(List
*lPtr
)
1094 WMDeleteIdleHandler(lPtr
->idleID
);
1095 lPtr
->idleID
= NULL
;
1097 WMFreeArray(lPtr
->items
);