1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-28 17:32:29 +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(). - added WMSetListAllowEmptySelection(), WMListAllowsEmptySelection().
- WMListSelectionDidChangeNotification passes NULL as the notification - WMListSelectionDidChangeNotification passes NULL as the notification
client data (previously passed the selected item row). client data (previously passed the selected item row).
- WMRemoveListItem() returns an int : 1 success, 0 fail (previously was void).
- added WMUnselectListItem(), WMSelectAllListItems(), WMUnselectAllListItems() - added WMUnselectListItem(), WMSelectAllListItems(), WMUnselectAllListItems()
- better behavior of wheel mices in WMList. Simple mouse wheel events - 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 will scroll by 1/3 of the WMList height. Using Shift as a modifier will
scroll line by line, while using Shift as a modifier will scroll page scroll line by line, while using Control as a modifier will scroll page
by page. by page.
- better behavior of WMScroller regarding mouse wheel events. Control modifier - better behavior of WMScroller regarding mouse wheel events. 'Shift' modifier
will scroll line by line, while Shift modifier will scroll page by page. will scroll line by line, while 'Control' modifier will scroll page by page.
- fixed some buffer overflow allowing bugs. - 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: changes since wmaker 0.62.0:

View File

@@ -1,4 +1,8 @@
- move paint to idle handlers - 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 - optimize color allocation for repeated colors
- make it work in 8bpp - 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 void
testList(WMScreen *scr) testList(WMScreen *scr)
{ {
@@ -123,27 +158,67 @@ testList(WMScreen *scr)
WMList *mlist; WMList *mlist;
WMLabel *label; WMLabel *label;
WMLabel *mlabel; WMLabel *mlabel;
WMLabel *title;
WMLabel *mtitle;
char text[100]; char text[100];
int i; int i;
windowCount++; windowCount++;
win = WMCreateWindow(scr, "testList"); win = WMCreateWindow(scr, "testList");
WMResizeWidget(win, 370, 250);
WMSetWindowTitle(win, "List"); WMSetWindowTitle(win, "List");
WMSetWindowCloseAction(win, closeAction, NULL); 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); list = WMCreateList(win);
WMMoveWidget(list, 10, 40);
for (i=0; i<50; i++) { for (i=0; i<50; i++) {
sprintf(text, "Item %i", i); sprintf(text, "Item %i", i);
WMAddListItem(list, text); WMAddListItem(list, text);
} }
mlist = WMCreateList(win); mlist = WMCreateList(win);
WMSetListAllowMultipleSelection(mlist, True); WMSetListAllowMultipleSelection(mlist, True);
WMMoveWidget(mlist, 220, 0); WMMoveWidget(mlist, 210, 40);
for (i=0; i<50; i++) { for (i=0; i<135; i++) {
sprintf(text, "Item %i", i); sprintf(text, "Item %i", i);
WMAddListItem(mlist, text); 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); WMRealizeWidget(win);
WMMapSubwidgets(win); WMMapSubwidgets(win);
WMMapWidget(win); WMMapWidget(win);

View File

@@ -145,6 +145,8 @@ typedef enum {
WSIncrementPage, WSIncrementPage,
WSDecrementLine, WSDecrementLine,
WSIncrementLine, WSIncrementLine,
WSDecrementWheel,
WSIncrementWheel,
WSKnob, WSKnob,
WSKnobSlot WSKnobSlot
} WMScrollerPart; } WMScrollerPart;
@@ -1088,12 +1090,18 @@ WMListItem *WMGetListItem(WMList *lPtr, int row);
WMArray *WMGetListItems(WMList *lPtr); WMArray *WMGetListItems(WMList *lPtr);
int WMRemoveListItem(WMList *lPtr, int row); void WMRemoveListItem(WMList *lPtr, int row);
void WMSelectListItem(WMList *lPtr, int row); void WMSelectListItem(WMList *lPtr, int row);
void WMUnselectListItem(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 WMSelectAllListItems(WMList *lPtr);
void WMUnselectAllListItems(WMList *lPtr); void WMUnselectAllListItems(WMList *lPtr);

View File

@@ -332,6 +332,8 @@ WMArray* WMCreateArray(int initialSize);
WMArray* WMCreateArrayWithDestructor(int initialSize, WMFreeDataProc *destructor); WMArray* WMCreateArrayWithDestructor(int initialSize, WMFreeDataProc *destructor);
WMArray* WMCreateArrayWithArray(WMArray *array);
void WMEmptyArray(WMArray *array); void WMEmptyArray(WMArray *array);
void WMFreeArray(WMArray *array); void WMFreeArray(WMArray *array);
@@ -339,15 +341,15 @@ void WMFreeArray(WMArray *array);
int WMGetArrayItemCount(WMArray *array); int WMGetArrayItemCount(WMArray *array);
/* appends other to array. other remains unchanged */ /* 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 */ /* 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) #define WMPushInArray(array, item) WMAddToArray(array, item)
/* insert will increment the index of elements after it by 1 */ /* 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 /* replace and set will return the old item WITHOUT calling the
* destructor on it even if its available. Free the returned item yourself. * 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); 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 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 */ /* 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 */ /* this is slow */
/* erase will remove the element from the bag, /* erase will remove the element from the bag,

View File

@@ -41,7 +41,7 @@ WMCreateArrayWithDestructor(int initialSize, WMFreeDataProc *destructor)
array = wmalloc(sizeof(WMArray)); array = wmalloc(sizeof(WMArray));
if (initialSize == 0) { if (initialSize <= 0) {
initialSize = INITIAL_SIZE; 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 void
WMEmptyArray(WMArray *array) WMEmptyArray(WMArray *array)
{ {
@@ -85,11 +103,11 @@ WMGetArrayItemCount(WMArray *array)
} }
int void
WMAppendArray(WMArray *array, WMArray *other) WMAppendArray(WMArray *array, WMArray *other)
{ {
if (other->itemCount == 0) if (other->itemCount == 0)
return 1; return;
if (array->itemCount + other->itemCount > array->allocSize) { if (array->itemCount + other->itemCount > array->allocSize) {
array->allocSize += other->allocSize; array->allocSize += other->allocSize;
@@ -99,12 +117,10 @@ WMAppendArray(WMArray *array, WMArray *other)
memcpy(array->items+array->itemCount, other->items, memcpy(array->items+array->itemCount, other->items,
sizeof(void*)*other->itemCount); sizeof(void*)*other->itemCount);
array->itemCount += other->itemCount; array->itemCount += other->itemCount;
return 1;
} }
int void
WMAddToArray(WMArray *array, void *item) WMAddToArray(WMArray *array, void *item)
{ {
if (array->itemCount >= array->allocSize) { if (array->itemCount >= array->allocSize) {
@@ -114,15 +130,13 @@ WMAddToArray(WMArray *array, void *item)
array->items[array->itemCount] = item; array->items[array->itemCount] = item;
array->itemCount++; array->itemCount++;
return 1;
} }
int void
WMInsertInArray(WMArray *array, int index, void *item) 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) { if (array->itemCount >= array->allocSize) {
array->allocSize += RESIZE_INCREMENT; array->allocSize += RESIZE_INCREMENT;
@@ -135,8 +149,6 @@ WMInsertInArray(WMArray *array, int index, void *item)
array->items[index] = item; array->items[index] = item;
array->itemCount++; array->itemCount++;
return 1;
} }
@@ -147,6 +159,7 @@ WMReplaceInArray(WMArray *array, int index, void *item)
wassertrv(index >= 0 && index <= array->itemCount, NULL); wassertrv(index >= 0 && index <= array->itemCount, NULL);
/* is it really useful to perform append if index == array->itemCount ? -Dan */
if (index == array->itemCount) { if (index == array->itemCount) {
WMAddToArray(array, item); WMAddToArray(array, item);
return NULL; return NULL;
@@ -186,7 +199,8 @@ WMRemoveFromArray(WMArray *array, void *item)
for (i = 0; i < array->itemCount; i++) { for (i = 0; i < array->itemCount; i++) {
if (array->items[i] == item) { 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) WMAppendBag(WMBag *self, WMBag *bag)
{ {
WMBagIterator ptr; WMBagIterator ptr;
void *data; void *data;
for (data = WMBagFirst(bag, &ptr); data != NULL; data = WMBagNext(bag, &ptr)) { for (data = WMBagFirst(bag, &ptr); data != NULL; data = WMBagNext(bag, &ptr)) {
if (!WMPutInBag(self, data)) WMPutInBag(self, data);
return 0;
} }
return 1;
} }
int void
WMPutInBag(WMBag *self, void *item) WMPutInBag(WMBag *self, void *item)
{ {
W_Node *ptr; W_Node *ptr;
@@ -454,12 +451,10 @@ WMPutInBag(WMBag *self, void *item)
rbTreeInsert(self, ptr); rbTreeInsert(self, ptr);
self->count++; self->count++;
return 1;
} }
int void
WMInsertInBag(WMBag *self, int index, void *item) WMInsertInBag(WMBag *self, int index, void *item)
{ {
W_Node *ptr; W_Node *ptr;
@@ -480,8 +475,6 @@ WMInsertInBag(WMBag *self, int index, void *item)
self->count++; self->count++;
return 1;
} }
@@ -720,9 +713,7 @@ void
WMFreeBag(WMBag *self) WMFreeBag(WMBag *self)
{ {
WMEmptyBag(self); WMEmptyBag(self);
free(self->nil); free(self->nil);
free(self); free(self);
} }
@@ -785,11 +776,9 @@ WMBagFirst(WMBag *self, WMBagIterator *ptr)
if (node == self->nil) { if (node == self->nil) {
*ptr = NULL; *ptr = NULL;
return NULL; return NULL;
} else { } else {
*ptr = node; *ptr = node;
return node->data; return node->data;
} }
} }
@@ -805,11 +794,9 @@ WMBagLast(WMBag *self, WMBagIterator *ptr)
if (node == self->nil) { if (node == self->nil) {
*ptr = NULL; *ptr = NULL;
return NULL; return NULL;
} else { } else {
*ptr = node; *ptr = node;
return node->data; return node->data;
} }
} }
@@ -827,11 +814,9 @@ WMBagNext(WMBag *self, WMBagIterator *ptr)
if (node == self->nil) { if (node == self->nil) {
*ptr = NULL; *ptr = NULL;
return NULL; return NULL;
} else { } else {
*ptr = node; *ptr = node;
return node->data; return node->data;
} }
} }
@@ -849,11 +834,9 @@ WMBagPrevious(WMBag *self, WMBagIterator *ptr)
if (node == self->nil) { if (node == self->nil) {
*ptr = NULL; *ptr = NULL;
return NULL; return NULL;
} else { } else {
*ptr = node; *ptr = node;
return node->data; return node->data;
} }
} }

View File

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

View File

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

View File

@@ -201,7 +201,7 @@ WMInsertListItem(WMList *lPtr, int row, char *text)
} }
int void
WMRemoveListItem(WMList *lPtr, int row) WMRemoveListItem(WMList *lPtr, int row)
{ {
WMListItem *item; WMListItem *item;
@@ -210,13 +210,13 @@ WMRemoveListItem(WMList *lPtr, int row)
CHECK_CLASS(lPtr, WC_List); CHECK_CLASS(lPtr, WC_List);
if (row < 0 || row >= WMGetArrayItemCount(lPtr->items)) /*wassertr(row>=0 && row<WMGetArrayItemCount(lPtr->items));*/
return 0; if (row<0 || row>=WMGetArrayItemCount(lPtr->items))
return;
item = WMGetFromArray(lPtr->items, row); item = WMGetFromArray(lPtr->items, row);
if (item->selected) { if (item->selected) {
WMRemoveFromArray(lPtr->selectedItems, item); WMRemoveFromArray(lPtr->selectedItems, item);
//WMUnselectListItem(lPtr, row);
selNotify = 1; selNotify = 1;
} }
@@ -236,8 +236,6 @@ WMRemoveListItem(WMList *lPtr, int row)
if (selNotify) { if (selNotify) {
WMPostNotificationName(WMListSelectionDidChangeNotification, lPtr, NULL); WMPostNotificationName(WMListSelectionDidChangeNotification, lPtr, NULL);
} }
return 1;
} }
@@ -446,6 +444,14 @@ vScrollCallBack(WMWidget *scroller, void *self)
scrollByAmount(lPtr, lPtr->fullFitLines-(1-lPtr->flags.dontFitAll)-1); scrollByAmount(lPtr, lPtr->fullFitLines-(1-lPtr->flags.dontFitAll)-1);
break; break;
case WSDecrementWheel:
scrollByAmount(lPtr, -lPtr->fullFitLines / 3);
break;
case WSIncrementWheel:
scrollByAmount(lPtr, lPtr->fullFitLines / 3);
break;
case WSKnob: case WSKnob:
lPtr->topItem = WMGetScrollerValue(lPtr->vScroller) * lPtr->topItem = WMGetScrollerValue(lPtr->vScroller) *
(float)(itemCount - lPtr->fullFitLines); (float)(itemCount - lPtr->fullFitLines);
@@ -513,6 +519,13 @@ paintItem(List *lPtr, int index)
WALeft, WMColorGC(scr->black), False, WALeft, WMColorGC(scr->black), False,
itemPtr->text, strlen(itemPtr->text)); 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 void
WMSelectListItem(WMList *lPtr, int row) WMSelectListItem(WMList *lPtr, int row)
{ {
WMListItem *item, *oldSelected; WMListItem *item;
if (row >= WMGetArrayItemCount(lPtr->items)) if (row >= WMGetArrayItemCount(lPtr->items))
return; return;
if (row < 0) { if (row < 0) {
/* Should row = -1 deselect all or just do nothing ?. Check it. -Dan */ /* row = -1 will deselects all for backward compatibility.
if (!lPtr->flags.allowMultipleSelection) { * will be removed later. -Dan */
WMUnselectAllListItems(lPtr); WMUnselectAllListItems(lPtr);
}
return; return;
} }
item = WMGetFromArray(lPtr->items, row); item = WMGetFromArray(lPtr->items, row);
if (item->selected) if (item->selected)
return; /* Return if already selected */ return; /* Return if already selected */
oldSelected = WMGetFromArray(lPtr->selectedItems, 0); if (!lPtr->flags.allowMultipleSelection) {
/* unselect previous selected items */
/* unselect previous selected item if case */ WMUnselectAllListItems(lPtr);
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);
}
} }
/* select item */ /* select item */
item->selected = 1; item->selected = 1;
WMAddToArray(lPtr->selectedItems, item); 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); 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); WMPostNotificationName(WMListSelectionDidChangeNotification, lPtr, NULL);
} }
// make them return an int
void void
WMUnselectListItem(WMList *lPtr, int row) WMUnselectListItem(WMList *lPtr, int row)
{ {
@@ -684,7 +675,10 @@ WMUnselectListItem(WMList *lPtr, int row)
if (!item || !item->selected) if (!item || !item->selected)
return; return;
// also add check for allowEmptySelection if (!lPtr->flags.allowEmptySelection &&
WMGetArrayItemCount(lPtr->selectedItems) <= 1) {
return;
}
item->selected = 0; item->selected = 0;
WMRemoveFromArray(lPtr->selectedItems, item); WMRemoveFromArray(lPtr->selectedItems, item);
@@ -693,6 +687,120 @@ WMUnselectListItem(WMList *lPtr, int row)
&& row<=lPtr->topItem+lPtr->fullFitLines) { && row<=lPtr->topItem+lPtr->fullFitLines) {
paintItem(lPtr, row); 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) if (!lPtr->flags.allowMultipleSelection)
return; 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++) { for (i=0; i<WMGetArrayItemCount(lPtr->items); i++) {
item = WMGetFromArray(lPtr->items, i); item = WMGetFromArray(lPtr->items, i);
if (!item->selected) { if (!item->selected) {
item->selected = 1; item->selected = 1;
WMAddToArray(lPtr->selectedItems, item);
if (lPtr->view->flags.mapped && i>=lPtr->topItem if (lPtr->view->flags.mapped && i>=lPtr->topItem
&& i<=lPtr->topItem+lPtr->fullFitLines) { && i<=lPtr->topItem+lPtr->fullFitLines) {
paintItem(lPtr, i); paintItem(lPtr, i);
} }
} }
} }
WMPostNotificationName(WMListSelectionDidChangeNotification, lPtr, NULL);
} }
void void
WMUnselectAllListItems(WMList *lPtr) WMUnselectAllListItems(WMList *lPtr)
{ {
int i; int i;//, keep;
WMListItem *item; 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++) { for (i=0; i<WMGetArrayItemCount(lPtr->items); i++) {
item = WMGetFromArray(lPtr->items, i); item = WMGetFromArray(lPtr->items, i);
@@ -740,6 +863,7 @@ WMUnselectAllListItems(WMList *lPtr)
} }
WMEmptyArray(lPtr->selectedItems); WMEmptyArray(lPtr->selectedItems);
WMPostNotificationName(WMListSelectionDidChangeNotification, lPtr, NULL);
} }
@@ -763,30 +887,29 @@ handleActionEvents(XEvent *event, void *data)
List *lPtr = (List*)data; List *lPtr = (List*)data;
int tmp; int tmp;
int topItem = lPtr->topItem; int topItem = lPtr->topItem;
static int oldClicked = -1; static int lastClicked = -1, prevItem = -1;
CHECK_CLASS(data, WC_List); CHECK_CLASS(data, WC_List);
switch (event->type) { switch (event->type) {
case ButtonRelease: case ButtonRelease:
#define CHECK_WHEEL_PATCH
#ifdef CHECK_WHEEL_PATCH
/* Ignore mouse wheel events, they're not "real" button events */ /* Ignore mouse wheel events, they're not "real" button events */
if (event->xbutton.button == WINGsConfiguration.mouseWheelUp || if (event->xbutton.button == WINGsConfiguration.mouseWheelUp ||
event->xbutton.button == WINGsConfiguration.mouseWheelDown) { event->xbutton.button == WINGsConfiguration.mouseWheelDown) {
break; break;
} }
#endif
lPtr->flags.buttonPressed = 0; lPtr->flags.buttonPressed = 0;
tmp = getItemIndexAt(lPtr, event->xbutton.y); tmp = getItemIndexAt(lPtr, event->xbutton.y);
if (/*tmp == lPtr->selectedItem && */tmp >= 0) { if (tmp >= 0) {
if (lPtr->action) if (lPtr->action)
(*lPtr->action)(lPtr, lPtr->clientData); (*lPtr->action)(lPtr, lPtr->clientData);
} }
oldClicked = tmp; if (!(event->xbutton.state & ShiftMask))
lastClicked = prevItem = tmp;
break; break;
case EnterNotify: case EnterNotify:
@@ -800,52 +923,96 @@ handleActionEvents(XEvent *event, void *data)
break; break;
case ButtonPress: case ButtonPress:
if (event->xbutton.x > WMWidgetWidth(lPtr->vScroller)) { if (event->xbutton.x <= WMWidgetWidth(lPtr->vScroller))
#ifdef CHECK_WHEEL_PATCH break;
if (event->xbutton.button == WINGsConfiguration.mouseWheelDown || if (event->xbutton.button == WINGsConfiguration.mouseWheelDown ||
event->xbutton.button == WINGsConfiguration.mouseWheelUp) { event->xbutton.button == WINGsConfiguration.mouseWheelUp) {
int amount = 0; int amount = 0;
if (event->xbutton.state & ShiftMask) { if (event->xbutton.state & ControlMask) {
amount = lPtr->fullFitLines-(1-lPtr->flags.dontFitAll)-1; amount = lPtr->fullFitLines-(1-lPtr->flags.dontFitAll)-1;
} else if (event->xbutton.state & ControlMask) { } else if (event->xbutton.state & ShiftMask) {
amount = 1; amount = 1;
} else { } else {
amount = lPtr->fullFitLines / 3; amount = lPtr->fullFitLines / 3;
if (amount == 0) if (amount == 0)
amount++; amount++;
}
if (event->xbutton.button == WINGsConfiguration.mouseWheelUp)
amount = -amount;
scrollByAmount(lPtr, amount);
break;
} }
#endif if (event->xbutton.button == WINGsConfiguration.mouseWheelUp)
amount = -amount;
tmp = getItemIndexAt(lPtr, event->xbutton.y); scrollByAmount(lPtr, amount);
lPtr->flags.buttonPressed = 1; break;
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;
} }
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; break;
case MotionNotify: case MotionNotify:
if (lPtr->flags.buttonPressed) { if (lPtr->flags.buttonPressed) {
tmp = getItemIndexAt(lPtr, event->xmotion.y); tmp = getItemIndexAt(lPtr, event->xmotion.y);
if (tmp>=0 /*&& tmp != lPtr->selectedItem*/) { if (tmp>=0 && tmp!=prevItem) {
WMSelectListItem(lPtr, tmp); 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; break;
} }

View File

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

View File

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

View File

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