1
0
mirror of https://github.com/gryf/wmaker.git synced 2026-01-10 15:54:17 +01:00

- the list multiple selection code is working now. it still needs some

minor work and cleanup.
- made some bag and array functions to return void instead of int.
- a few new array functions.
- better handling of mouse wheel.

!!! make clean after this update before you rebuild. some enums changed.
This commit is contained in:
dan
2000-10-01 23:26:03 +00:00
parent 6de1c41865
commit b2478b634f
13 changed files with 467 additions and 157 deletions

View File

@@ -23,15 +23,17 @@ changes since wmaker 0.62.1:
- added WMSetListAllowEmptySelection(), WMListAllowsEmptySelection().
- WMListSelectionDidChangeNotification passes NULL as the notification
client data (previously passed the selected item row).
- WMRemoveListItem() returns an int : 1 success, 0 fail (previously was void).
- added WMUnselectListItem(), WMSelectAllListItems(), WMUnselectAllListItems()
- better behavior of wheel mices in WMList. Simple mouse wheel events
will scroll by 1/3 of the WMList height. Using Control as a modifier will
scroll line by line, while using Shift as a modifier will scroll page
will scroll by 1/3 of the WMList height. Using Shift as a modifier will
scroll line by line, while using Control as a modifier will scroll page
by page.
- better behavior of WMScroller regarding mouse wheel events. Control modifier
will scroll line by line, while Shift modifier will scroll page by page.
- better behavior of WMScroller regarding mouse wheel events. 'Shift' modifier
will scroll line by line, while 'Control' modifier will scroll page by page.
- fixed some buffer overflow allowing bugs.
- added WSDecrementWheel and WSIncrementWheel for handling mouse wheel in
scrollers and scrolled widgets. This should be treated like the WSxxxPage
counterparts, except it should scroll by page_size/3 instead of one full page
changes since wmaker 0.62.0:

View File

@@ -1,4 +1,8 @@
- move paint to idle handlers
- finish the multiple selection code for lists (check for
allowEmptySelection and add handlers for scrolling while drag-selecting).
- check whether WMDestroyWidget() should first call WMUnmapWidget().
- optimize color allocation for repeated colors
- make it work in 8bpp

View File

@@ -115,6 +115,41 @@ testFrame(WMScreen *scr)
}
static void
singleClick(WMWidget *self, void *data)
{
}
static void
doubleClick(WMWidget *self, void *data)
{
WMLabel *label = (WMLabel*)data;
WMList *lPtr = (WMList*)self;
char buf[255];
WMSelectAllListItems(lPtr);
//sprintf(buf, "Selected items: %d",
// WMGetArrayItemCount(WMGetListSelectedItems(lPtr)));;
//WMSetLabelText(label, buf);
}
static void
listSelectionObserver(void *observer, WMNotification *notification)
{
WMLabel *label = (WMLabel*)observer;
WMList *lPtr = (WMList*)WMGetNotificationObject(notification);
char buf[255];
sprintf(buf, "Selected items: %d",
WMGetArrayItemCount(WMGetListSelectedItems(lPtr)));;
WMSetLabelText(label, buf);
}
void
testList(WMScreen *scr)
{
@@ -123,27 +158,67 @@ testList(WMScreen *scr)
WMList *mlist;
WMLabel *label;
WMLabel *mlabel;
WMLabel *title;
WMLabel *mtitle;
char text[100];
int i;
windowCount++;
win = WMCreateWindow(scr, "testList");
WMResizeWidget(win, 370, 250);
WMSetWindowTitle(win, "List");
WMSetWindowCloseAction(win, closeAction, NULL);
title = WMCreateLabel(win);
WMResizeWidget(title, 150, 20);
WMMoveWidget(title, 10, 10);
WMSetLabelRelief(title, WRRidge);
WMSetLabelText(title, "Single selection list");
mtitle = WMCreateLabel(win);
WMResizeWidget(mtitle, 150, 20);
WMMoveWidget(mtitle, 210, 10);
WMSetLabelRelief(mtitle, WRRidge);
WMSetLabelText(mtitle, "Multiple selection list");
list = WMCreateList(win);
WMMoveWidget(list, 10, 40);
for (i=0; i<50; i++) {
sprintf(text, "Item %i", i);
WMAddListItem(list, text);
}
mlist = WMCreateList(win);
WMSetListAllowMultipleSelection(mlist, True);
WMMoveWidget(mlist, 220, 0);
for (i=0; i<50; i++) {
WMMoveWidget(mlist, 210, 40);
for (i=0; i<135; i++) {
sprintf(text, "Item %i", i);
WMAddListItem(mlist, text);
}
label = WMCreateLabel(win);
WMResizeWidget(label, 150, 40);
WMMoveWidget(label, 10, 200);
WMSetLabelRelief(label, WRRidge);
WMSetLabelText(label, "Selected items: 0");
mlabel = WMCreateLabel(win);
WMResizeWidget(mlabel, 150, 40);
WMMoveWidget(mlabel, 210, 200);
WMSetLabelRelief(mlabel, WRRidge);
WMSetLabelText(mlabel, "Selected items: 0");
WMSetListAction(list, singleClick, label);
WMSetListDoubleAction(list, doubleClick, label);
WMSetListAction(mlist, singleClick, mlabel);
WMSetListDoubleAction(mlist, doubleClick, mlabel);
WMAddNotificationObserver(listSelectionObserver, label,
WMListSelectionDidChangeNotification, list);
WMAddNotificationObserver(listSelectionObserver, mlabel,
WMListSelectionDidChangeNotification, mlist);
WMRealizeWidget(win);
WMMapSubwidgets(win);
WMMapWidget(win);

View File

@@ -145,6 +145,8 @@ typedef enum {
WSIncrementPage,
WSDecrementLine,
WSIncrementLine,
WSDecrementWheel,
WSIncrementWheel,
WSKnob,
WSKnobSlot
} WMScrollerPart;
@@ -1088,12 +1090,18 @@ WMListItem *WMGetListItem(WMList *lPtr, int row);
WMArray *WMGetListItems(WMList *lPtr);
int WMRemoveListItem(WMList *lPtr, int row);
void WMRemoveListItem(WMList *lPtr, int row);
void WMSelectListItem(WMList *lPtr, int row);
void WMUnselectListItem(WMList *lPtr, int row);
/* This will select all items in range, and deselect all the others */
void WMSetListSelectionToRange(WMList *lPtr, WMRange range);
/* This will select all items in range, leaving the others as they are */
void WMSelectListItemsInRange(WMList *lPtr, WMRange range);
void WMSelectAllListItems(WMList *lPtr);
void WMUnselectAllListItems(WMList *lPtr);

View File

@@ -332,6 +332,8 @@ WMArray* WMCreateArray(int initialSize);
WMArray* WMCreateArrayWithDestructor(int initialSize, WMFreeDataProc *destructor);
WMArray* WMCreateArrayWithArray(WMArray *array);
void WMEmptyArray(WMArray *array);
void WMFreeArray(WMArray *array);
@@ -339,15 +341,15 @@ void WMFreeArray(WMArray *array);
int WMGetArrayItemCount(WMArray *array);
/* appends other to array. other remains unchanged */
int WMAppendArray(WMArray *array, WMArray *other);
void WMAppendArray(WMArray *array, WMArray *other);
/* add will place the element at the end of the array */
int WMAddToArray(WMArray *array, void *item);
void WMAddToArray(WMArray *array, void *item);
#define WMPushInArray(array, item) WMAddToArray(array, item)
/* insert will increment the index of elements after it by 1 */
int WMInsertInArray(WMArray *array, int index, void *item);
void WMInsertInArray(WMArray *array, int index, void *item);
/* replace and set will return the old item WITHOUT calling the
* destructor on it even if its available. Free the returned item yourself.
@@ -387,6 +389,7 @@ void WMSortArray(WMArray *array, WMCompareDataProc *comparer);
void WMMapArray(WMArray *array, void (*function)(void*, void*), void *data);
WMArray* WMGetSubarrayWithRange(WMArray* array, WMRange aRange);
/*..........................................................................*/
@@ -414,12 +417,12 @@ WMBag* WMCreateTreeBagWithDestructor(WMFreeDataProc *destructor);
int WMGetBagItemCount(WMBag *bag);
int WMAppendBag(WMBag *bag, WMBag *other);
void WMAppendBag(WMBag *bag, WMBag *other);
int WMPutInBag(WMBag *bag, void *item);
void WMPutInBag(WMBag *bag, void *item);
/* insert will increment the index of elements after it by 1 */
int WMInsertInBag(WMBag *bag, int index, void *item);
void WMInsertInBag(WMBag *bag, int index, void *item);
/* this is slow */
/* erase will remove the element from the bag,

View File

@@ -41,7 +41,7 @@ WMCreateArrayWithDestructor(int initialSize, WMFreeDataProc *destructor)
array = wmalloc(sizeof(WMArray));
if (initialSize == 0) {
if (initialSize <= 0) {
initialSize = INITIAL_SIZE;
}
@@ -55,6 +55,24 @@ WMCreateArrayWithDestructor(int initialSize, WMFreeDataProc *destructor)
}
WMArray*
WMCreateArrayWithArray(WMArray *array)
{
WMArray *newArray;
newArray = wmalloc(sizeof(WMArray));
newArray->items = wmalloc(sizeof(void*) * array->allocSize);
memcpy(newArray->items, array->items, sizeof(void*)*array->itemCount);
newArray->itemCount = array->itemCount;
newArray->allocSize = array->allocSize;
newArray->destructor = NULL;
return newArray;
}
void
WMEmptyArray(WMArray *array)
{
@@ -85,11 +103,11 @@ WMGetArrayItemCount(WMArray *array)
}
int
void
WMAppendArray(WMArray *array, WMArray *other)
{
if (other->itemCount == 0)
return 1;
return;
if (array->itemCount + other->itemCount > array->allocSize) {
array->allocSize += other->allocSize;
@@ -99,12 +117,10 @@ WMAppendArray(WMArray *array, WMArray *other)
memcpy(array->items+array->itemCount, other->items,
sizeof(void*)*other->itemCount);
array->itemCount += other->itemCount;
return 1;
}
int
void
WMAddToArray(WMArray *array, void *item)
{
if (array->itemCount >= array->allocSize) {
@@ -114,15 +130,13 @@ WMAddToArray(WMArray *array, void *item)
array->items[array->itemCount] = item;
array->itemCount++;
return 1;
}
int
void
WMInsertInArray(WMArray *array, int index, void *item)
{
wassertrv(index >= 0 && index <= array->itemCount, 0);
wassertr(index >= 0 && index <= array->itemCount);
if (array->itemCount >= array->allocSize) {
array->allocSize += RESIZE_INCREMENT;
@@ -135,8 +149,6 @@ WMInsertInArray(WMArray *array, int index, void *item)
array->items[index] = item;
array->itemCount++;
return 1;
}
@@ -147,6 +159,7 @@ WMReplaceInArray(WMArray *array, int index, void *item)
wassertrv(index >= 0 && index <= array->itemCount, NULL);
/* is it really useful to perform append if index == array->itemCount ? -Dan */
if (index == array->itemCount) {
WMAddToArray(array, item);
return NULL;
@@ -186,7 +199,8 @@ WMRemoveFromArray(WMArray *array, void *item)
for (i = 0; i < array->itemCount; i++) {
if (array->items[i] == item) {
return WMDeleteFromArray(array, i);
WMDeleteFromArray(array, i);
return 1;
}
}
@@ -266,3 +280,27 @@ WMMapArray(WMArray *array, void (*function)(void*, void*), void *data)
}
WMArray*
WMGetSubarrayWithRange(WMArray* array, WMRange aRange)
{
WMArray *newArray;
if (aRange.count <= 0)
return WMCreateArray(0);
if (aRange.position < 0)
aRange.position = 0;
if (aRange.position >= array->itemCount)
aRange.position = array->itemCount - 1;
if (aRange.position + aRange.count > array->itemCount)
aRange.count = array->itemCount - aRange.position;
newArray = WMCreateArray(aRange.count);
memcpy(newArray->items, array->items+aRange.position,
sizeof(void*)*aRange.count);
newArray->itemCount = aRange.count;
return newArray;
}

View File

@@ -423,22 +423,19 @@ WMGetBagItemCount(WMBag *self)
}
int
void
WMAppendBag(WMBag *self, WMBag *bag)
{
WMBagIterator ptr;
void *data;
for (data = WMBagFirst(bag, &ptr); data != NULL; data = WMBagNext(bag, &ptr)) {
if (!WMPutInBag(self, data))
return 0;
WMPutInBag(self, data);
}
return 1;
}
int
void
WMPutInBag(WMBag *self, void *item)
{
W_Node *ptr;
@@ -454,12 +451,10 @@ WMPutInBag(WMBag *self, void *item)
rbTreeInsert(self, ptr);
self->count++;
return 1;
}
int
void
WMInsertInBag(WMBag *self, int index, void *item)
{
W_Node *ptr;
@@ -480,8 +475,6 @@ WMInsertInBag(WMBag *self, int index, void *item)
self->count++;
return 1;
}
@@ -720,9 +713,7 @@ void
WMFreeBag(WMBag *self)
{
WMEmptyBag(self);
free(self->nil);
free(self);
}
@@ -785,11 +776,9 @@ WMBagFirst(WMBag *self, WMBagIterator *ptr)
if (node == self->nil) {
*ptr = NULL;
return NULL;
} else {
*ptr = node;
return node->data;
}
}
@@ -805,11 +794,9 @@ WMBagLast(WMBag *self, WMBagIterator *ptr)
if (node == self->nil) {
*ptr = NULL;
return NULL;
} else {
*ptr = node;
return node->data;
}
}
@@ -827,11 +814,9 @@ WMBagNext(WMBag *self, WMBagIterator *ptr)
if (node == self->nil) {
*ptr = NULL;
return NULL;
} else {
*ptr = node;
return node->data;
}
}
@@ -849,11 +834,9 @@ WMBagPrevious(WMBag *self, WMBagIterator *ptr)
if (node == self->nil) {
*ptr = NULL;
return NULL;
} else {
*ptr = node;
return node->data;
}
}

View File

@@ -243,14 +243,14 @@ WMGetSubdataWithRange(WMData *aData, WMRange aRange) /*FOLD00*/
void *buffer;
WMData *newData;
/* return an empty subdata instead if aRange.count is 0 ? */
wassertrv(aRange.count > 0, NULL);
if (aRange.count <= 0)
return WMCreateDataWithCapacity(0);
buffer = wmalloc(aRange.count);
WMGetDataBytesWithRange(aData, buffer, aRange);
newData = WMCreateDataWithBytesNoCopy(buffer, aRange.count, wfree);
newData->format = aData->format;
return newData;
}

View File

@@ -571,14 +571,15 @@ scrollCallback(WMWidget *scroller, void *self)
#define LAST_VISIBLE_COLUMN bPtr->firstVisibleColumn+bPtr->maxVisibleColumns
switch (WMGetScrollerHitPart(sPtr)) {
case WSDecrementLine:
case WSDecrementLine:
if (bPtr->firstVisibleColumn > 0) {
scrollToColumn(bPtr, bPtr->firstVisibleColumn-1, True);
}
break;
case WSDecrementPage:
if (bPtr->firstVisibleColumn > 0) {
case WSDecrementPage:
case WSDecrementWheel:
if (bPtr->firstVisibleColumn > 0) {
newFirst = bPtr->firstVisibleColumn - bPtr->maxVisibleColumns;
scrollToColumn(bPtr, newFirst, True);
@@ -586,13 +587,14 @@ scrollCallback(WMWidget *scroller, void *self)
break;
case WSIncrementLine:
case WSIncrementLine:
if (LAST_VISIBLE_COLUMN < bPtr->usedColumnCount) {
scrollToColumn(bPtr, bPtr->firstVisibleColumn+1, True);
}
break;
case WSIncrementPage:
case WSIncrementPage:
case WSIncrementWheel:
if (LAST_VISIBLE_COLUMN < bPtr->usedColumnCount) {
newFirst = bPtr->firstVisibleColumn + bPtr->maxVisibleColumns;
@@ -603,7 +605,7 @@ scrollCallback(WMWidget *scroller, void *self)
}
break;
case WSKnob:
case WSKnob:
{
double floatValue;
double value = bPtr->columnCount - bPtr->maxVisibleColumns;
@@ -624,8 +626,8 @@ scrollCallback(WMWidget *scroller, void *self)
}
break;
case WSKnobSlot:
case WSNoPart:
case WSKnobSlot:
case WSNoPart:
/* do nothing */
break;
}

View File

@@ -201,7 +201,7 @@ WMInsertListItem(WMList *lPtr, int row, char *text)
}
int
void
WMRemoveListItem(WMList *lPtr, int row)
{
WMListItem *item;
@@ -210,13 +210,13 @@ WMRemoveListItem(WMList *lPtr, int row)
CHECK_CLASS(lPtr, WC_List);
if (row < 0 || row >= WMGetArrayItemCount(lPtr->items))
return 0;
/*wassertr(row>=0 && row<WMGetArrayItemCount(lPtr->items));*/
if (row<0 || row>=WMGetArrayItemCount(lPtr->items))
return;
item = WMGetFromArray(lPtr->items, row);
if (item->selected) {
WMRemoveFromArray(lPtr->selectedItems, item);
//WMUnselectListItem(lPtr, row);
selNotify = 1;
}
@@ -236,8 +236,6 @@ WMRemoveListItem(WMList *lPtr, int row)
if (selNotify) {
WMPostNotificationName(WMListSelectionDidChangeNotification, lPtr, NULL);
}
return 1;
}
@@ -446,6 +444,14 @@ vScrollCallBack(WMWidget *scroller, void *self)
scrollByAmount(lPtr, lPtr->fullFitLines-(1-lPtr->flags.dontFitAll)-1);
break;
case WSDecrementWheel:
scrollByAmount(lPtr, -lPtr->fullFitLines / 3);
break;
case WSIncrementWheel:
scrollByAmount(lPtr, lPtr->fullFitLines / 3);
break;
case WSKnob:
lPtr->topItem = WMGetScrollerValue(lPtr->vScroller) *
(float)(itemCount - lPtr->fullFitLines);
@@ -513,6 +519,13 @@ paintItem(List *lPtr, int index)
WALeft, WMColorGC(scr->black), False,
itemPtr->text, strlen(itemPtr->text));
}
if ((index-lPtr->topItem+lPtr->fullFitLines)*lPtr->itemHeight >
lPtr->view->size.height-2) {
W_DrawRelief(lPtr->view->screen, lPtr->view->window, 0, 0,
lPtr->view->size.width, lPtr->view->size.height,
WRSunken);
}
}
@@ -620,62 +633,40 @@ WMFindRowOfListItemWithTitle(WMList *lPtr, char *title)
void
WMSelectListItem(WMList *lPtr, int row)
{
WMListItem *item, *oldSelected;
WMListItem *item;
if (row >= WMGetArrayItemCount(lPtr->items))
return;
if (row < 0) {
/* Should row = -1 deselect all or just do nothing ?. Check it. -Dan */
if (!lPtr->flags.allowMultipleSelection) {
WMUnselectAllListItems(lPtr);
}
/* row = -1 will deselects all for backward compatibility.
* will be removed later. -Dan */
WMUnselectAllListItems(lPtr);
return;
}
item = WMGetFromArray(lPtr->items, row);
if (item->selected)
return; /* Return if already selected */
return; /* Return if already selected */
oldSelected = WMGetFromArray(lPtr->selectedItems, 0);
/* unselect previous selected item if case */
if (!lPtr->flags.allowMultipleSelection && oldSelected) {
int oldSelectedRow = WMGetListSelectedItemRow(lPtr);
// better call WMUnselectAllListItems() here? -Dan
oldSelected->selected = 0;
WMDeleteFromArray(lPtr->selectedItems, 0);
// This is faster and have the same effect in the single selected case
// but may leave xxx->selected flags set after a multi->single selected
// switch
//WMEmptyArray(lPtr->selectedItems);
if (lPtr->view->flags.mapped && oldSelectedRow>=lPtr->topItem
&& oldSelectedRow<=lPtr->topItem+lPtr->fullFitLines) {
paintItem(lPtr, oldSelectedRow);
}
if (!lPtr->flags.allowMultipleSelection) {
/* unselect previous selected items */
WMUnselectAllListItems(lPtr);
}
/* select item */
item->selected = 1;
WMAddToArray(lPtr->selectedItems, item);
if (lPtr->view->flags.mapped) {
if (lPtr->view->flags.mapped && row>=lPtr->topItem
&& row<=lPtr->topItem+lPtr->fullFitLines) {
paintItem(lPtr, row);
if ((row-lPtr->topItem+lPtr->fullFitLines)*lPtr->itemHeight
> lPtr->view->size.height-2)
W_DrawRelief(lPtr->view->screen, lPtr->view->window, 0, 0,
lPtr->view->size.width, lPtr->view->size.height,
WRSunken);
}
WMPostNotificationName(WMListSelectionDidChangeNotification, lPtr, NULL);
}
// make them return an int
void
WMUnselectListItem(WMList *lPtr, int row)
{
@@ -684,7 +675,10 @@ WMUnselectListItem(WMList *lPtr, int row)
if (!item || !item->selected)
return;
// also add check for allowEmptySelection
if (!lPtr->flags.allowEmptySelection &&
WMGetArrayItemCount(lPtr->selectedItems) <= 1) {
return;
}
item->selected = 0;
WMRemoveFromArray(lPtr->selectedItems, item);
@@ -693,6 +687,120 @@ WMUnselectListItem(WMList *lPtr, int row)
&& row<=lPtr->topItem+lPtr->fullFitLines) {
paintItem(lPtr, row);
}
WMPostNotificationName(WMListSelectionDidChangeNotification, lPtr, NULL);
}
void
WMSelectListItemsInRange(WMList *lPtr, WMRange range)
{
WMListItem *item;
int position = range.position, k = 1, notify = 0;
int total = WMGetArrayItemCount(lPtr->items);
if (!lPtr->flags.allowMultipleSelection)
return;
if (range.count==0)
return; /* Nothing to select */
if (range.count < 0) {
range.count = -range.count;
k = -1;
}
for (; range.count>0 && position>=0 && position<total; range.count--) {
item = WMGetFromArray(lPtr->items, position);
if (!item->selected) {
item->selected = 1;
WMAddToArray(lPtr->selectedItems, item);
if (lPtr->view->flags.mapped && position>=lPtr->topItem
&& position<=lPtr->topItem+lPtr->fullFitLines) {
paintItem(lPtr, position);
}
notify = 1;
}
position += k;
}
if (notify) {
WMPostNotificationName(WMListSelectionDidChangeNotification, lPtr, NULL);
}
}
void
WMSetListSelectionToRange(WMList *lPtr, WMRange range)
{
WMListItem *item;
int mark1, mark2, i, k;
int position = range.position, notify = 0;
int total = WMGetArrayItemCount(lPtr->items);
if (!lPtr->flags.allowMultipleSelection)
return;
if (range.count==0) {
WMUnselectAllListItems(lPtr);
return;
}
if (range.count < 0) {
mark1 = range.position + range.count + 1;
mark2 = range.position + 1;
range.count = -range.count;
k = -1;
} else {
mark1 = range.position;
mark2 = range.position + range.count;
k = 1;
}
if (mark1 > total)
mark1 = total;
if (mark2 < 0)
mark2 = 0;
WMEmptyArray(lPtr->selectedItems);
for (i=0; i<mark1; i++) {
item = WMGetFromArray(lPtr->items, i);
if (item->selected) {
item->selected = 0;
if (lPtr->view->flags.mapped && i>=lPtr->topItem
&& i<=lPtr->topItem+lPtr->fullFitLines) {
paintItem(lPtr, i);
}
notify = 1;
}
}
for (; range.count>0 && position>=0 && position<total; range.count--) {
item = WMGetFromArray(lPtr->items, position);
if (!item->selected) {
item->selected = 1;
if (lPtr->view->flags.mapped && position>=lPtr->topItem
&& position<=lPtr->topItem+lPtr->fullFitLines) {
paintItem(lPtr, position);
}
notify = 1;
}
WMAddToArray(lPtr->selectedItems, item);
position += k;
}
for (i=mark2; i<total; i++) {
item = WMGetFromArray(lPtr->items, i);
if (item->selected) {
item->selected = 0;
if (lPtr->view->flags.mapped && i>=lPtr->topItem
&& i<=lPtr->topItem+lPtr->fullFitLines) {
paintItem(lPtr, i);
}
notify = 1;
}
}
if (notify) {
WMPostNotificationName(WMListSelectionDidChangeNotification, lPtr, NULL);
}
}
@@ -705,28 +813,43 @@ WMSelectAllListItems(WMList *lPtr)
if (!lPtr->flags.allowMultipleSelection)
return;
// implement some WMDuplicateArray() ?
if (WMGetArrayItemCount(lPtr->items) ==
WMGetArrayItemCount(lPtr->selectedItems)) {
return; /* All items are selected already */
}
WMFreeArray(lPtr->selectedItems);
lPtr->selectedItems = WMCreateArrayWithArray(lPtr->items);
for (i=0; i<WMGetArrayItemCount(lPtr->items); i++) {
item = WMGetFromArray(lPtr->items, i);
if (!item->selected) {
item->selected = 1;
WMAddToArray(lPtr->selectedItems, item);
if (lPtr->view->flags.mapped && i>=lPtr->topItem
&& i<=lPtr->topItem+lPtr->fullFitLines) {
paintItem(lPtr, i);
}
}
}
WMPostNotificationName(WMListSelectionDidChangeNotification, lPtr, NULL);
}
void
WMUnselectAllListItems(WMList *lPtr)
{
int i;
WMListItem *item;
int i;//, keep;
WMListItem *item;//, *keepItem;
// check for allowEmptySelection
// FIXME: check for allowEmptySelection
//keep = lPtr->flags.allowEmptySelection ? 0 : 1;
//if (WMGetArrayItemCount(lPtr->selectedItems) == keep)
// return 1; /* Nothing selected so return */
//keepItem = (keep==1 ? WMGetFromArray(lPtr->selectedItems, 0) : NULL);
for (i=0; i<WMGetArrayItemCount(lPtr->items); i++) {
item = WMGetFromArray(lPtr->items, i);
@@ -740,6 +863,7 @@ WMUnselectAllListItems(WMList *lPtr)
}
WMEmptyArray(lPtr->selectedItems);
WMPostNotificationName(WMListSelectionDidChangeNotification, lPtr, NULL);
}
@@ -763,30 +887,29 @@ handleActionEvents(XEvent *event, void *data)
List *lPtr = (List*)data;
int tmp;
int topItem = lPtr->topItem;
static int oldClicked = -1;
static int lastClicked = -1, prevItem = -1;
CHECK_CLASS(data, WC_List);
switch (event->type) {
case ButtonRelease:
#define CHECK_WHEEL_PATCH
#ifdef CHECK_WHEEL_PATCH
/* Ignore mouse wheel events, they're not "real" button events */
if (event->xbutton.button == WINGsConfiguration.mouseWheelUp ||
event->xbutton.button == WINGsConfiguration.mouseWheelDown) {
break;
}
#endif
lPtr->flags.buttonPressed = 0;
tmp = getItemIndexAt(lPtr, event->xbutton.y);
if (/*tmp == lPtr->selectedItem && */tmp >= 0) {
if (tmp >= 0) {
if (lPtr->action)
(*lPtr->action)(lPtr, lPtr->clientData);
}
oldClicked = tmp;
if (!(event->xbutton.state & ShiftMask))
lastClicked = prevItem = tmp;
break;
case EnterNotify:
@@ -800,52 +923,96 @@ handleActionEvents(XEvent *event, void *data)
break;
case ButtonPress:
if (event->xbutton.x > WMWidgetWidth(lPtr->vScroller)) {
#ifdef CHECK_WHEEL_PATCH
if (event->xbutton.button == WINGsConfiguration.mouseWheelDown ||
event->xbutton.button == WINGsConfiguration.mouseWheelUp) {
int amount = 0;
if (event->xbutton.x <= WMWidgetWidth(lPtr->vScroller))
break;
if (event->xbutton.button == WINGsConfiguration.mouseWheelDown ||
event->xbutton.button == WINGsConfiguration.mouseWheelUp) {
int amount = 0;
if (event->xbutton.state & ShiftMask) {
amount = lPtr->fullFitLines-(1-lPtr->flags.dontFitAll)-1;
} else if (event->xbutton.state & ControlMask) {
amount = 1;
} else {
amount = lPtr->fullFitLines / 3;
if (amount == 0)
amount++;
}
if (event->xbutton.button == WINGsConfiguration.mouseWheelUp)
amount = -amount;
scrollByAmount(lPtr, amount);
break;
if (event->xbutton.state & ControlMask) {
amount = lPtr->fullFitLines-(1-lPtr->flags.dontFitAll)-1;
} else if (event->xbutton.state & ShiftMask) {
amount = 1;
} else {
amount = lPtr->fullFitLines / 3;
if (amount == 0)
amount++;
}
#endif
if (event->xbutton.button == WINGsConfiguration.mouseWheelUp)
amount = -amount;
tmp = getItemIndexAt(lPtr, event->xbutton.y);
lPtr->flags.buttonPressed = 1;
if (tmp >= 0) {
if (tmp == oldClicked && WMIsDoubleClick(event)) {
WMSelectListItem(lPtr, tmp);
if (lPtr->doubleAction)
(*lPtr->doubleAction)(lPtr, lPtr->doubleClientData);
} else {
WMSelectListItem(lPtr, tmp);
}
}
oldClicked = tmp;
scrollByAmount(lPtr, amount);
break;
}
tmp = getItemIndexAt(lPtr, event->xbutton.y);
lPtr->flags.buttonPressed = 1;
if (tmp >= 0) {
if (tmp == lastClicked && WMIsDoubleClick(event)) {
WMSelectListItem(lPtr, tmp);
if (lPtr->doubleAction)
(*lPtr->doubleAction)(lPtr, lPtr->doubleClientData);
} else {
if (!lPtr->flags.allowMultipleSelection) {
WMSelectListItem(lPtr, tmp);
} else {
WMRange range;
WMListItem *item, *lastSel;
if (event->xbutton.state & ControlMask) {
item = WMGetFromArray(lPtr->items, tmp);
if (item && item->selected) {
WMUnselectListItem(lPtr, tmp);
} else {
WMSelectListItem(lPtr, tmp);
}
} else if (event->xbutton.state & ShiftMask) {
if (WMGetArrayItemCount(lPtr->selectedItems) == 0) {
WMSelectListItem(lPtr, tmp);
} else {
lastSel = WMGetFromArray(lPtr->items, lastClicked);
range.position = WMGetFirstInArray(lPtr->items,
lastSel);
if (tmp >= range.position)
range.count = tmp - range.position + 1;
else
range.count = tmp - range.position - 1;
WMSetListSelectionToRange(lPtr, range);
}
} else {
range.position = tmp;
range.count = 1;
WMSetListSelectionToRange(lPtr, range);
}
}
}
}
if (!(event->xbutton.state & ShiftMask))
lastClicked = prevItem = tmp;
break;
case MotionNotify:
if (lPtr->flags.buttonPressed) {
tmp = getItemIndexAt(lPtr, event->xmotion.y);
if (tmp>=0 /*&& tmp != lPtr->selectedItem*/) {
WMSelectListItem(lPtr, tmp);
if (tmp>=0 && tmp!=prevItem) {
if (lPtr->flags.allowMultipleSelection) {
WMRange range;
range.position = lastClicked;
if (tmp >= lastClicked)
range.count = tmp - lastClicked + 1;
else
range.count = tmp - lastClicked - 1;
WMSetListSelectionToRange(lPtr, range);
} else {
WMSelectListItem(lPtr, tmp);
}
}
prevItem = tmp;
}
break;
}

View File

@@ -817,9 +817,11 @@ handleActionEvents(XEvent *event, void *data)
/* FIXME: change Mod1Mask with something else */
if (event->xbutton.button==WINGsConfiguration.mouseWheelUp) {
if (event->xbutton.state & ControlMask) {
sPtr->flags.hitPart = WSDecrementPage;
} else if (event->xbutton.state & ShiftMask) {
sPtr->flags.hitPart = WSDecrementLine;
} else {
sPtr->flags.hitPart = WSDecrementPage;
sPtr->flags.hitPart = WSDecrementWheel;
}
if (sPtr->action) {
(*sPtr->action)(sPtr, sPtr->clientData);
@@ -827,9 +829,11 @@ handleActionEvents(XEvent *event, void *data)
}
else if (event->xbutton.button==WINGsConfiguration.mouseWheelDown) {
if (event->xbutton.state & ControlMask) {
sPtr->flags.hitPart = WSIncrementPage;
} else if (event->xbutton.state & ShiftMask) {
sPtr->flags.hitPart = WSIncrementLine;
} else {
sPtr->flags.hitPart = WSIncrementPage;
sPtr->flags.hitPart = WSIncrementWheel;
}
if (sPtr->action) {
(*sPtr->action)(sPtr, sPtr->clientData);

View File

@@ -258,7 +258,7 @@ doScrolling(WMWidget *self, void *data)
vpsize = 1;
switch (WMGetScrollerHitPart(self)) {
case WSDecrementLine:
case WSDecrementLine:
if (pos > 0) {
pos-=sPtr->lineScroll;
if (pos < 0)
@@ -268,7 +268,7 @@ doScrolling(WMWidget *self, void *data)
WMGetScrollerKnobProportion(self));
}
break;
case WSIncrementLine:
case WSIncrementLine:
if (pos < size) {
pos+=sPtr->lineScroll;
if (pos > size)
@@ -278,12 +278,13 @@ doScrolling(WMWidget *self, void *data)
WMGetScrollerKnobProportion(self));
}
break;
case WSKnob:
case WSKnob:
value = WMGetScrollerValue(self);
pos = value*size;
break;
case WSDecrementPage:
case WSDecrementPage:
if (pos > 0) {
pos -= vpsize;
if (pos < 0)
@@ -292,9 +293,20 @@ doScrolling(WMWidget *self, void *data)
WMSetScrollerParameters(self, value,
WMGetScrollerKnobProportion(self));
}
break;
case WSDecrementWheel:
if (pos > 0) {
pos -= vpsize/3;
if (pos < 0)
pos = 0;
value = (float)pos / size;
WMSetScrollerParameters(self, value,
WMGetScrollerKnobProportion(self));
}
break;
case WSIncrementPage:
case WSIncrementPage:
if (pos < size) {
pos += vpsize;
if (pos > size)
@@ -304,7 +316,18 @@ doScrolling(WMWidget *self, void *data)
WMGetScrollerKnobProportion(self));
}
break;
case WSIncrementWheel:
if (pos < size) {
pos += vpsize/3;
if (pos > size)
pos = size;
value = (float)pos / size;
WMSetScrollerParameters(self, value,
WMGetScrollerKnobProportion(self));
}
break;
case WSNoPart:
case WSKnobSlot:
break;

View File

@@ -2557,9 +2557,10 @@ prepareForDragOperation(WMView *self, WMDraggingInfo *info)
char *badbadbad;
static void
receivedData(WMView *view, Atom selection, Atom target, Time timestamp,
void *cdata, WMData *data)
{
{
badbadbad = wstrdup((char *)WMDataBytes(data));
}