From 6973f07f30ff3a8cd2ca25f75b560a58425791b3 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 28 Sep 2000 03:09:57 +0000 Subject: [PATCH] Remake of the WMList code to allow multiple selection. Not complete yet. It will not even compile. I Will finish it later today. --- WINGs/ChangeLog | 8 ++- WINGs/WINGs.h | 23 ++++++- WINGs/WUtil.h | 5 +- WINGs/array.c | 9 ++- WINGs/wbrowser.c | 8 +-- WINGs/wlist.c | 179 +++++++++++++++++++++++++++++++++---------------------- 6 files changed, 147 insertions(+), 85 deletions(-) diff --git a/WINGs/ChangeLog b/WINGs/ChangeLog index 0f9971fe..d5179858 100644 --- a/WINGs/ChangeLog +++ b/WINGs/ChangeLog @@ -17,7 +17,13 @@ changes since wmaker 0.62.1: subdirectories - removed WMArrayBag and reorganized WMTreeBag to be WMBag. - added WMArray class. -- added WMSetWindowUserPosition() +- added WMSetWindowUserPosition(). +- added WMGetListSelectedItems() +- added WMSetListAllowMultipleSelection(), WMListAllowsMultipleSelection(). +- 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). changes since wmaker 0.62.0: diff --git a/WINGs/WINGs.h b/WINGs/WINGs.h index f1ec27c9..737c4044 100644 --- a/WINGs/WINGs.h +++ b/WINGs/WINGs.h @@ -1059,6 +1059,10 @@ void WMSetScrollerArrowsPosition(WMScroller *sPtr, WMList *WMCreateList(WMWidget *parent); +void WMSetListAllowMultipleSelection(WMList *lPtr, Bool flag); + +void WMSetListAllowEmptySelection(WMList *lPtr, Bool flag); + #define WMAddListItem(lPtr, text) WMInsertListItem((lPtr), -1, (text)) WMListItem *WMInsertListItem(WMList *lPtr, int row, char *text); @@ -1073,8 +1077,7 @@ WMListItem *WMGetListItem(WMList *lPtr, int row); WMArray *WMGetListItems(WMList *lPtr); - -void WMRemoveListItem(WMList *lPtr, int row); +int WMRemoveListItem(WMList *lPtr, int row); void WMSelectListItem(WMList *lPtr, int row); @@ -1085,7 +1088,16 @@ void WMSetListUserDrawItemHeight(WMList *lPtr, unsigned short height); int WMGetListItemHeight(WMList *lPtr); /* don't free the returned data */ -WMListItem *WMGetListSelectedItem(WMList *lPtr); +WMArray* WMGetListSelectedItems(WMList *lPtr); + +/* + * For the following 2 functions, in case WMList allows multiple selection, + * the first item in the list of selected items, respective its row number, + * will be returned. + */ + +/* don't free the returned data */ +WMListItem* WMGetListSelectedItem(WMList *lPtr); int WMGetListSelectedItemRow(WMList *lPtr); @@ -1103,6 +1115,11 @@ void WMSetListBottomPosition(WMList *lPtr, int row); int WMGetListPosition(WMList *lPtr); +Bool WMListAllowsMultipleSelection(WMList *lPtr); + +Bool WMListAllowsEmptySelection(WMList *lPtr); + + extern char *WMListDidScrollNotification; extern char *WMListSelectionDidChangeNotification; diff --git a/WINGs/WUtil.h b/WINGs/WUtil.h index 04a33407..8a14ddfb 100644 --- a/WINGs/WUtil.h +++ b/WINGs/WUtil.h @@ -112,8 +112,9 @@ typedef enum { enum { - WBNotFound = INT_MIN, /* element was not found in bag */ - WANotFound = -1 /* element was not found in array */ + WBNotFound = INT_MIN, /* element was not found in WMBag */ + WANotFound = -1, /* element was not found in WMArray */ + WLNotFound = -1 /* element was not found in WMList */ }; diff --git a/WINGs/array.c b/WINGs/array.c index c860b23e..30fa70a7 100644 --- a/WINGs/array.c +++ b/WINGs/array.c @@ -122,7 +122,7 @@ WMAddToArray(WMArray *array, void *item) int WMInsertInArray(WMArray *array, int index, void *item) { - wassertrv(index <= array->itemCount, 0); + wassertrv(index >= 0 && index <= array->itemCount, 0); if (array->itemCount >= array->allocSize) { array->allocSize += RESIZE_INCREMENT; @@ -145,7 +145,7 @@ WMReplaceInArray(WMArray *array, int index, void *item) { void *old; - wassertrv(index > array->itemCount, 0); + wassertrv(index >= 0 && index <= array->itemCount, NULL); if (index == array->itemCount) { WMAddToArray(array, item); @@ -162,8 +162,7 @@ WMReplaceInArray(WMArray *array, int index, void *item) int WMDeleteFromArray(WMArray *array, int index) { - if (index >= array->itemCount) - return 0; + wassertrv(index >= 0 && index < array->itemCount, 0); if (array->destructor) { array->destructor(array->items[index]); @@ -198,7 +197,7 @@ WMRemoveFromArray(WMArray *array, void *item) void* WMGetFromArray(WMArray *array, int index) { - if (index >= array->itemCount) + if (index < 0 || index >= array->itemCount) return NULL; return array->items[index]; diff --git a/WINGs/wbrowser.c b/WINGs/wbrowser.c index c463495d..e615128b 100644 --- a/WINGs/wbrowser.c +++ b/WINGs/wbrowser.c @@ -84,8 +84,8 @@ static void loadColumn(WMBrowser *bPtr, int column); static void removeColumn(WMBrowser *bPtr, int column); -static char* -createTruncatedString(WMFont *font, char *text, int *textLen, int width); +static char* createTruncatedString(WMFont *font, char *text, int *textLen, + int width); static void willResizeBrowser(W_ViewDelegate*, WMView*, unsigned int*, unsigned int*); @@ -1030,7 +1030,7 @@ static void listSelectionObserver(void *observerData, WMNotification *notification) { WMBrowser *bPtr = (WMBrowser*)observerData; - int column, item = (int)WMGetNotificationClientData(notification); + int column; WMList *lPtr = (WMList*)WMGetNotificationObject(notification); for (column = 0; column < bPtr->usedColumnCount; column++) @@ -1043,7 +1043,7 @@ listSelectionObserver(void *observerData, WMNotification *notification) return; } - if (item < 0) + if (WMGetArrayItemCount(WMGetListSelectedItems(lPtr)) == 0) column--; bPtr->selectedColumn = column; diff --git a/WINGs/wlist.c b/WINGs/wlist.c index 551a9c41..ea127c27 100644 --- a/WINGs/wlist.c +++ b/WINGs/wlist.c @@ -14,7 +14,7 @@ typedef struct W_List { WMArray *items; /* list of WMListItem */ WMArray *selectedItems; /* list of selected WMListItems */ - short selectedItem; + //short selectedItem; short itemHeight; @@ -115,6 +115,7 @@ WMCreateList(WMWidget *parent) lPtr->itemHeight = WMFontHeight(scrPtr->normalFont) + 1; lPtr->items = WMCreateArrayWithDestructor(4, releaseItem); + lPtr->selectedItems = WMCreateArray(4); /* create the vertical scroller */ lPtr->vScroller = WMCreateScroller(lPtr); @@ -128,12 +129,27 @@ WMCreateList(WMWidget *parent) W_ResizeView(lPtr->view, DEFAULT_WIDTH, DEFAULT_HEIGHT); - lPtr->selectedItem = -1; + //lPtr->selectedItem = -1; return lPtr; } +void +WMSetListAllowMultipleSelection(WMList *lPtr, Bool flag) +{ + lPtr->flags.allowMultipleSelection = flag ? 1 : 0; + +} + + +void +WMSetListAllowEmptySelection(WMList *lPtr, Bool flag) +{ + lPtr->flags.allowEmptySelection = flag ? 1 : 0; +} + + static int comparator(const void *a, const void *b) { @@ -173,9 +189,9 @@ WMInsertListItem(WMList *lPtr, int row, char *text) item->text = wstrdup(text); - if (lPtr->selectedItem >= row && lPtr->selectedItem >= 0 - && row >= 0) - lPtr->selectedItem++; + //if (lPtr->selectedItem >= row && lPtr->selectedItem >= 0 + // && row >= 0) + // lPtr->selectedItem++; row = WMIN(row, WMGetArrayItemCount(lPtr->items)); @@ -194,24 +210,32 @@ WMInsertListItem(WMList *lPtr, int row, char *text) } -void +int WMRemoveListItem(WMList *lPtr, int row) { + WMLIstItem *item; int topItem = lPtr->topItem; int selNotify = 0; CHECK_CLASS(lPtr, WC_List); if (row < 0 || row >= WMGetArrayItemCount(lPtr->items)) - return; + return 0; - if (lPtr->selectedItem == row) { - lPtr->selectedItem = -1; + item = WMGetFromArray(lPtr->items, row); + if (item->flags.selected) { + WMRemoveFromArray(lPtr->selectedItems, item); + //WMUnselectListItem(lPtr, row); selNotify = 1; - } else if (lPtr->selectedItem > row) { - lPtr->selectedItem--; } + //if (lPtr->selectedItem == row) { + // lPtr->selectedItem = -1; + // selNotify = 1; + //} else if (lPtr->selectedItem > row) { + // lPtr->selectedItem--; + //} + if (row <= lPtr->topItem+lPtr->fullFitLines+lPtr->flags.dontFitAll) lPtr->topItem--; if (lPtr->topItem < 0) @@ -222,13 +246,15 @@ WMRemoveListItem(WMList *lPtr, int row) if (!lPtr->idleID) { lPtr->idleID = WMAddIdleHandler((WMCallback*)updateScroller, lPtr); } - if (lPtr->topItem != topItem) + if (lPtr->topItem != topItem) { WMPostNotificationName(WMListDidScrollNotification, lPtr, NULL); - if (selNotify) - WMPostNotificationName(WMListSelectionDidChangeNotification, lPtr, - (void*)((int)lPtr->selectedItem)); -} + } + if (selNotify) { + WMPostNotificationName(WMListSelectionDidChangeNotification, lPtr, NULL); + } + return 1; +} WMListItem* @@ -245,7 +271,6 @@ WMGetListItems(WMList *lPtr) } - void WMSetListUserDrawProc(WMList *lPtr, WMListDrawProc *proc) { @@ -269,12 +294,13 @@ WMSetListUserDrawItemHeight(WMList *lPtr, unsigned short height) void WMClearList(WMList *lPtr) { - int oldSelected = lPtr->selectedItem; + int selNo = WMGetArrayItemCount(lPtr->selectedItems); + WMEmptyArray(lPtr->selectedItems); WMEmptyArray(lPtr->items); lPtr->topItem = 0; - lPtr->selectedItem = -1; + //lPtr->selectedItem = -1; if (!lPtr->idleID) { WMDeleteIdleHandler(lPtr->idleID); @@ -283,9 +309,9 @@ WMClearList(WMList *lPtr) if (lPtr->view->flags.realized) { updateScroller(lPtr); } - if (oldSelected != -1) - WMPostNotificationName(WMListSelectionDidChangeNotification, lPtr, - (void*)-1); + if (selNo > 0) { + WMPostNotificationName(WMListSelectionDidChangeNotification, lPtr, NULL); + } } @@ -305,20 +331,26 @@ WMSetListDoubleAction(WMList *lPtr, WMAction *action, void *clientData) } +WMArray* +WMGetListSelectedItems(WMList *lPtr) +{ + return lPtr->selectedItems; +} + + WMListItem* WMGetListSelectedItem(WMList *lPtr) { - if (lPtr->selectedItem < 0) - return NULL; - - return WMGetFromArray(lPtr->items, lPtr->selectedItem); + return WMGetFromArray(lPtr->selectedItems, 0); } int WMGetListSelectedItemRow(WMList *lPtr) { - return lPtr->selectedItem; + WMListItem *item = WMGetFromArray(lPtr->selectedItems, 0); + + return (item!=NULL ? WMGetFirstInArray(lPtr->items, item) : WLNotFound); } @@ -363,6 +395,7 @@ WMGetListNumberOfRows(WMList *lPtr) return WMGetArrayItemCount(lPtr->items); } + int WMGetListPosition(WMList *lPtr) { @@ -370,6 +403,20 @@ WMGetListPosition(WMList *lPtr) } +Bool +WMListAllowsMultipleSelection(WMList *lPtr) +{ + return lPtr->flags.allowMultipleSelection; +} + + +Bool +WMListAllowsEmptySelection(WMList *lPtr) +{ + return lPtr->flags.allowEmptySelection; +} + + static void vScrollCallBack(WMWidget *scroller, void *self) { @@ -479,11 +526,12 @@ paintItem(List *lPtr, int index) (*lPtr->draw)(lPtr, index, view->window, itemPtr->text, flags, &rect); } else { - if (itemPtr->selected) + if (itemPtr->selected) { XFillRectangle(scr->display, view->window, WMColorGC(scr->white), x, y, width, height); - else + } else { XClearArea(scr->display, view->window, x, y, width, height, False); + } W_PaintText(view, view->window, scr->normalFont, x+4, y, width, WALeft, WMColorGC(scr->black), False, @@ -596,55 +644,45 @@ WMFindRowOfListItemWithTitle(WMList *lPtr, char *title) void WMSelectListItem(WMList *lPtr, int row) { - WMListItem *itemPtr; - int notify = 0; + WMListItem *item, *oldSelected; 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); + } + return; + } - /* the check below must be changed when the multiple selection is - * implemented. -Dan - */ - if (!lPtr->flags.allowMultipleSelection && row == lPtr->selectedItem) - notify = 0; - else - notify = 1; + item = WMGetFromArray(lPtr->items, row); + if (item->selected) + return; /* Return if already selected */ - assert(lPtr->selectedItem < WMGetArrayItemCount(lPtr->items)); + oldSelected = WMGetFromArray(lPtr->selectedItems, 0); - if (!lPtr->flags.allowMultipleSelection) { - /* unselect previous selected item */ - if (lPtr->selectedItem >= 0) { - itemPtr = WMGetFromArray(lPtr->items, lPtr->selectedItem); + /* unselect previous selected item if case */ + if (!lPtr->flags.allowMultipleSelection && oldSelected) { + int oldSelectedRow = WMGetListSelectedItemRow(lPtr); - if (itemPtr->selected) { - itemPtr->selected = 0; - if (lPtr->view->flags.mapped - && lPtr->selectedItem>=lPtr->topItem - && lPtr->selectedItem<=lPtr->topItem+lPtr->fullFitLines) { - paintItem(lPtr, lPtr->selectedItem); - } - } - } - } + // 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 (row < 0) { - if (!lPtr->flags.allowMultipleSelection) { - lPtr->selectedItem = -1; - if (notify) - WMPostNotificationName(WMListSelectionDidChangeNotification, - lPtr, (void*)((int)lPtr->selectedItem)); + if (lPtr->view->flags.mapped && oldSelectedRow>=lPtr->topItem + && oldSelectedRow<=lPtr->topItem+lPtr->fullFitLines) { + paintItem(lPtr, oldSelectedRow); } - return; } /* select item */ - itemPtr = WMGetFromArray(lPtr->items, row); - - if (lPtr->flags.allowMultipleSelection) - itemPtr->selected = !itemPtr->selected; - else - itemPtr->selected = 1; + item->selected = 1; + WMAddToArray(lPtr->selectedItems, item); if (lPtr->view->flags.mapped) { paintItem(lPtr, row); @@ -655,10 +693,9 @@ WMSelectListItem(WMList *lPtr, int row) lPtr->view->size.width, lPtr->view->size.height, WRSunken); } - lPtr->selectedItem = row; - if (notify) - WMPostNotificationName(WMListSelectionDidChangeNotification, lPtr, - (void*)((int)lPtr->selectedItem)); + //lPtr->selectedItem = row; + + WMPostNotificationName(WMListSelectionDidChangeNotification, lPtr, NULL); } @@ -826,3 +863,5 @@ destroyList(List *lPtr) wfree(lPtr); } + + -- 2.11.4.GIT