mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-20 21:08:08 +01:00
Added select while scrolling the list, when the mouse pointer leaves
the list area, at either top or bottom having the mouse button pressed.
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
- move paint to idle handlers
|
||||
- finish the multiple selection code for lists (check for add handlers for
|
||||
scrolling while drag-selecting).
|
||||
- check whether WMDestroyWidget() should first call WMUnmapWidget().
|
||||
- check if its useful to add some WMBrowserSelectionDidChangeNotification
|
||||
(actually a pass-through for WMListSelectionDidChangeNotification).
|
||||
Or a delegate to be called when the list selection change.
|
||||
- check which behavior is better for list selecting while scrolling
|
||||
(the #define behavior2 in wlist.c)
|
||||
|
||||
|
||||
- optimize color allocation for repeated colors
|
||||
|
||||
150
WINGs/wlist.c
150
WINGs/wlist.c
@@ -29,6 +29,8 @@ typedef struct W_List {
|
||||
|
||||
WMHandlerID *idleID; /* for updating the scroller after adding elements */
|
||||
|
||||
WMHandlerID *selectID; /* for selecting items in list while scrolling */
|
||||
|
||||
WMScroller *vScroller;
|
||||
|
||||
struct {
|
||||
@@ -48,6 +50,8 @@ typedef struct W_List {
|
||||
#define DEFAULT_WIDTH 150
|
||||
#define DEFAULT_HEIGHT 150
|
||||
|
||||
#define SCROLL_DELAY 100
|
||||
|
||||
|
||||
static void destroyList(List *lPtr);
|
||||
static void paintList(List *lPtr);
|
||||
@@ -55,10 +59,15 @@ static void paintList(List *lPtr);
|
||||
|
||||
static void handleEvents(XEvent *event, void *data);
|
||||
static void handleActionEvents(XEvent *event, void *data);
|
||||
static void updateScroller(List *lPtr);
|
||||
|
||||
static void updateScroller(void *data);
|
||||
static void scrollForwardSelecting(void *data);
|
||||
static void scrollBackwardSelecting(void *data);
|
||||
|
||||
static void vScrollCallBack(WMWidget *scroller, void *self);
|
||||
|
||||
static void toggleItemSelection(WMList *lPtr, int index);
|
||||
|
||||
static void updateGeometry(WMList *lPtr);
|
||||
static void didResizeList();
|
||||
|
||||
@@ -288,6 +297,10 @@ WMClearList(WMList *lPtr)
|
||||
WMDeleteIdleHandler(lPtr->idleID);
|
||||
lPtr->idleID = NULL;
|
||||
}
|
||||
if (lPtr->selectID) {
|
||||
WMDeleteTimerHandler(lPtr->selectID);
|
||||
lPtr->selectID = NULL;
|
||||
}
|
||||
if (lPtr->view->flags.realized) {
|
||||
updateScroller(lPtr);
|
||||
}
|
||||
@@ -570,8 +583,10 @@ scrollTo(List *lPtr, int newTop)
|
||||
#endif
|
||||
|
||||
static void
|
||||
updateScroller(List *lPtr)
|
||||
updateScroller(void *data)
|
||||
{
|
||||
List *lPtr = (List*)data;
|
||||
|
||||
float knobProportion, floatValue, tmp;
|
||||
int count = WMGetArrayItemCount(lPtr->items);
|
||||
|
||||
@@ -594,6 +609,77 @@ updateScroller(List *lPtr)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scrollForwardSelecting(void *data)
|
||||
{
|
||||
List *lPtr = (List*)data;
|
||||
int lastSelected;
|
||||
|
||||
lastSelected = lPtr->topItem+lPtr->fullFitLines+lPtr->flags.dontFitAll-1;
|
||||
|
||||
if (lastSelected >= WMGetArrayItemCount(lPtr->items)-1) {
|
||||
lPtr->selectID = NULL;
|
||||
if (lPtr->flags.dontFitAll)
|
||||
scrollByAmount(lPtr, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
/* selecting NEEDS to be done before scrolling to avoid flickering */
|
||||
if (lPtr->flags.allowMultipleSelection) {
|
||||
WMListItem *item;
|
||||
WMRange range;
|
||||
|
||||
item = WMGetFromArray(lPtr->selectedItems, 0);
|
||||
range.position = WMGetFirstInArray(lPtr->items, item);
|
||||
if (lastSelected+1 >= range.position) {
|
||||
range.count = lastSelected - range.position + 2;
|
||||
} else {
|
||||
range.count = lastSelected - range.position;
|
||||
}
|
||||
WMSetListSelectionToRange(lPtr, range);
|
||||
} else {
|
||||
WMSelectListItem(lPtr, lastSelected+1);
|
||||
}
|
||||
scrollByAmount(lPtr, 1);
|
||||
|
||||
lPtr->selectID = WMAddTimerHandler(SCROLL_DELAY, scrollForwardSelecting,
|
||||
lPtr);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scrollBackwardSelecting(void *data)
|
||||
{
|
||||
List *lPtr = (List*)data;
|
||||
|
||||
if (lPtr->topItem < 1) {
|
||||
lPtr->selectID = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* selecting NEEDS to be done before scrolling to avoid flickering */
|
||||
if (lPtr->flags.allowMultipleSelection) {
|
||||
WMListItem *item;
|
||||
WMRange range;
|
||||
|
||||
item = WMGetFromArray(lPtr->selectedItems, 0);
|
||||
range.position = WMGetFirstInArray(lPtr->items, item);
|
||||
if (lPtr->topItem-1 >= range.position) {
|
||||
range.count = lPtr->topItem - range.position;
|
||||
} else {
|
||||
range.count = lPtr->topItem - range.position - 2;
|
||||
}
|
||||
WMSetListSelectionToRange(lPtr, range);
|
||||
} else {
|
||||
WMSelectListItem(lPtr, lPtr->topItem-1);
|
||||
}
|
||||
scrollByAmount(lPtr, -1);
|
||||
|
||||
lPtr->selectID = WMAddTimerHandler(SCROLL_DELAY, scrollBackwardSelecting,
|
||||
lPtr);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handleEvents(XEvent *event, void *data)
|
||||
{
|
||||
@@ -916,12 +1002,13 @@ toggleItemSelection(WMList *lPtr, int index)
|
||||
}
|
||||
}
|
||||
|
||||
#define behavior2
|
||||
|
||||
static void
|
||||
handleActionEvents(XEvent *event, void *data)
|
||||
{
|
||||
List *lPtr = (List*)data;
|
||||
int tmp;
|
||||
int tmp, height;
|
||||
int topItem = lPtr->topItem;
|
||||
static int lastClicked = -1, prevItem = -1;
|
||||
|
||||
@@ -936,6 +1023,10 @@ handleActionEvents(XEvent *event, void *data)
|
||||
}
|
||||
|
||||
lPtr->flags.buttonPressed = 0;
|
||||
if (lPtr->selectID) {
|
||||
WMDeleteTimerHandler(lPtr->selectID);
|
||||
lPtr->selectID = NULL;
|
||||
}
|
||||
tmp = getItemIndexAt(lPtr, event->xbutton.y);
|
||||
|
||||
if (tmp >= 0) {
|
||||
@@ -949,13 +1040,39 @@ handleActionEvents(XEvent *event, void *data)
|
||||
break;
|
||||
|
||||
case EnterNotify:
|
||||
#ifndef behavior2
|
||||
lPtr->flags.buttonPressed = lPtr->flags.buttonWasPressed;
|
||||
lPtr->flags.buttonWasPressed = 0;
|
||||
#endif
|
||||
if (lPtr->selectID) {
|
||||
WMDeleteTimerHandler(lPtr->selectID);
|
||||
lPtr->selectID = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case LeaveNotify:
|
||||
#ifndef behavior2
|
||||
lPtr->flags.buttonWasPressed = lPtr->flags.buttonPressed;
|
||||
lPtr->flags.buttonPressed = 0;
|
||||
#endif
|
||||
|
||||
height = WMWidgetHeight(lPtr);
|
||||
|
||||
#ifdef behavior2
|
||||
if (lPtr->flags.buttonPressed && !lPtr->selectID) {
|
||||
#else
|
||||
if (lPtr->flags.buttonWasPressed && !lPtr->selectID) {
|
||||
#endif
|
||||
if (event->xcrossing.y >= height) {
|
||||
lPtr->selectID = WMAddTimerHandler(SCROLL_DELAY,
|
||||
scrollForwardSelecting,
|
||||
lPtr);
|
||||
} else if (event->xcrossing.y <= 0) {
|
||||
lPtr->selectID = WMAddTimerHandler(SCROLL_DELAY,
|
||||
scrollBackwardSelecting,
|
||||
lPtr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ButtonPress:
|
||||
@@ -1031,7 +1148,28 @@ handleActionEvents(XEvent *event, void *data)
|
||||
break;
|
||||
|
||||
case MotionNotify:
|
||||
if (lPtr->flags.buttonPressed) {
|
||||
#ifdef behavior2
|
||||
height = WMWidgetHeight(lPtr);
|
||||
if (lPtr->selectID && event->xmotion.y>=0 && event->xmotion.y<=height) {
|
||||
WMDeleteTimerHandler(lPtr->selectID);
|
||||
lPtr->selectID = NULL;
|
||||
}
|
||||
#endif
|
||||
if (lPtr->flags.buttonPressed && !lPtr->selectID) {
|
||||
#ifdef behavior2
|
||||
if (event->xmotion.y <= 0) {
|
||||
lPtr->selectID = WMAddTimerHandler(SCROLL_DELAY,
|
||||
scrollBackwardSelecting,
|
||||
lPtr);
|
||||
break;
|
||||
} else if (event->xmotion.y >= height) {
|
||||
lPtr->selectID = WMAddTimerHandler(SCROLL_DELAY,
|
||||
scrollForwardSelecting,
|
||||
lPtr);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
tmp = getItemIndexAt(lPtr, event->xmotion.y);
|
||||
if (tmp>=0 && tmp!=prevItem) {
|
||||
if (lPtr->flags.allowMultipleSelection) {
|
||||
@@ -1094,6 +1232,10 @@ destroyList(List *lPtr)
|
||||
WMDeleteIdleHandler(lPtr->idleID);
|
||||
lPtr->idleID = NULL;
|
||||
|
||||
if (lPtr->selectID)
|
||||
WMDeleteTimerHandler(lPtr->selectID);
|
||||
lPtr->selectID = NULL;
|
||||
|
||||
WMFreeArray(lPtr->items);
|
||||
|
||||
wfree(lPtr);
|
||||
|
||||
Reference in New Issue
Block a user