📄 listview_setsort.c
字号:
/*
*********************************************************************************************************
* uC/GUI V3.98
* Universal graphic software for embedded applications
*
* (c) Copyright 2002, Micrium Inc., Weston, FL
* (c) Copyright 2002, SEGGER Microcontroller Systeme GmbH
*
* 礐/GUI is protected by international copyright laws. Knowledge of the
* source code may not be used to write a similar product. This file may
* only be used in accordance with a license and should not be redistributed
* in any way. We appreciate your understanding and fairness.
*
----------------------------------------------------------------------
File : LISTVIEW_SetSort.c
Purpose : Implementation of LISTVIEW_SetSort
---------------------------END-OF-HEADER------------------------------
*/
#include <string.h>
#include "LISTVIEW_Private.h"
#if GUI_WINSUPPORT
/*********************************************************************
*
* Types
*
**********************************************************************
*/
typedef struct {
LISTVIEW_Obj * pObj;
LISTVIEW_SORT * pSort;
SORT_TYPE * paSortArray;
} SORT_OBJECT;
/*********************************************************************
*
* Static routines
*
**********************************************************************
*/
/*********************************************************************
*
* _Free
*
* Purpose:
* Frees the memory used by the attached LISTVIEW_SORT object.
*
* Parameter:
* hObj - Handle of LISTVIEW_SORT object
*/
static void _Free(WM_HMEM hObj) {
LISTVIEW_SORT * pSort;
pSort = (LISTVIEW_SORT *)GUI_ALLOC_h2p(hObj);
GUI_ALLOC_Free(pSort->hSortArray);
GUI_ALLOC_Free(hObj);
}
/*********************************************************************
*
* _GetSelUnsorted
*/
static int _GetSelUnsorted(LISTVIEW_Obj * pObj) {
int r;
if ((LISTVIEW__GetSel(pObj) >= 0) && (pObj->hSort)) {
LISTVIEW_SORT * pSort;
pSort = (LISTVIEW_SORT *)GUI_ALLOC_h2p(pObj->hSort);
if (!pSort->SortArrayNumItems) {
r = LISTVIEW__GetSel(pObj);
} else {
SORT_TYPE * paSortArray;
paSortArray = (SORT_TYPE *)GUI_ALLOC_h2p(pSort->hSortArray);
r = *(paSortArray + LISTVIEW__GetSel(pObj));
}
} else {
r = LISTVIEW__GetSel(pObj);
}
return r;
}
/*********************************************************************
*
* _SetSelUnsorted
*/
static void _SetSelUnsorted(LISTVIEW_Handle hObj, LISTVIEW_Obj * pObj, int Sel) {
int i, NumItems;
if (pObj->hSort) {
LISTVIEW_SORT * pSort;
SORT_TYPE * paSortArray;
pSort = (LISTVIEW_SORT *)GUI_ALLOC_h2p(pObj->hSort);
NumItems = pSort->SortArrayNumItems;
paSortArray = (SORT_TYPE *)GUI_ALLOC_h2p(pSort->hSortArray);
for (i = 0; i < NumItems; i++) {
if (*(paSortArray + i) == Sel) {
LISTVIEW__SetSel(hObj, pObj, i);
break;
}
}
} else {
LISTVIEW__SetSel(hObj, pObj, Sel);
}
}
/*********************************************************************
*
* _Compare
*/
static int _Compare(unsigned lb, unsigned ub, SORT_OBJECT * pSortObject) {
char * p0, * p1;
LISTVIEW_ROW * pRow0, * pRow1;
LISTVIEW_COLUMN * pColumn;
SORT_TYPE i0, i1;
int Result;
i0 = *(pSortObject->paSortArray + lb);
i1 = *(pSortObject->paSortArray + ub);
pRow0 = (LISTVIEW_ROW *) GUI_ARRAY_GetpItem(&pSortObject->pObj->RowArray, i0);
pRow1 = (LISTVIEW_ROW *) GUI_ARRAY_GetpItem(&pSortObject->pObj->RowArray, i1);
p0 = ((LISTVIEW_CELL *) GUI_ARRAY_GetpItem(&pRow0->CellArray, pSortObject->pObj->SortIndex))->acText;
p1 = ((LISTVIEW_CELL *) GUI_ARRAY_GetpItem(&pRow1->CellArray, pSortObject->pObj->SortIndex))->acText;
pColumn = (LISTVIEW_COLUMN *)GUI_ARRAY_GetpItem(&pSortObject->pObj->ColumnArray, pSortObject->pObj->SortIndex);
if (!pColumn) {
return 0;
}
Result = pColumn->fpCompare(p0, p1);
if (pSortObject->pSort->Reverse) {
Result *= -1;
}
return Result;
}
/*********************************************************************
*
* _Swap
*/
static void _Swap(unsigned lb, unsigned ub, SORT_OBJECT * pSortObject) {
int Temp;
Temp = *(pSortObject->paSortArray + lb);
*(pSortObject->paSortArray + lb) = *(pSortObject->paSortArray + ub);
*(pSortObject->paSortArray + ub) = Temp;
}
/*********************************************************************
*
* _BubbleSort
*
* Purpose:
* Bubble sort algorithm.
*/
static void _BubbleSort(unsigned lb, unsigned ub, SORT_OBJECT * pSortObject) {
int Swapped;
do {
unsigned i;
Swapped = 0;
for (i = ub; i > lb; i--) {
if (_Compare(i - 1, i, pSortObject) > 0) {
_Swap(i - 1, i, pSortObject);
Swapped = 1;
}
}
} while (Swapped);
}
/*********************************************************************
*
* _Reverse
*
* Purpose:
* Reverse the current sorting order
*/
static void _Reverse(SORT_OBJECT * pSortObject) {
int i, NumItems;
NumItems = pSortObject->pSort->SortArrayNumItems;
for (i = 0; i < NumItems / 2; i++) {
int Temp;
Temp = *(pSortObject->paSortArray + i);
*(pSortObject->paSortArray + i) = *(pSortObject->paSortArray + NumItems - i - 1);
*(pSortObject->paSortArray + NumItems - i - 1) = Temp;
}
}
/*********************************************************************
*
* _Sort
*
* Purpose:
* Sorts the contents of the LISTVIEW by using the qsort algorithm.
* The compare function is called for each compare operation with valid
* pointers to cell data of the specified column.
*/
static int _Sort(LISTVIEW_Handle hObj) {
WM_HMEM hSortArray;
SORT_OBJECT SortObject;
int NumItems, NumItemsReq, i, Sel;
SortObject.pObj = LISTVIEW_H2P(hObj);
if (((SortObject.pObj->IsPresorted) && (SortObject.pObj->IsSorted)) || (SortObject.pObj->hSort == 0)) {
return 0;
}
SortObject.pSort = (LISTVIEW_SORT *)GUI_ALLOC_h2p(SortObject.pObj->hSort);
NumItemsReq = SortObject.pObj->RowArray.NumItems;
NumItems = SortObject.pSort->SortArrayNumItems;
Sel = _GetSelUnsorted(SortObject.pObj);
/* Adjust number of items in sort array */
if (NumItems != NumItemsReq) {
if (!SortObject.pSort->hSortArray) {
hSortArray = GUI_ALLOC_AllocZero(sizeof(SORT_TYPE) * NumItemsReq);
} else {
hSortArray = GUI_ALLOC_Realloc(SortObject.pSort->hSortArray, sizeof(SORT_TYPE) * NumItemsReq);
}
if (!hSortArray) {
return 1;
}
SortObject.pObj = LISTVIEW_H2P(hObj);
SortObject.pSort = (LISTVIEW_SORT *)GUI_ALLOC_h2p(SortObject.pObj->hSort);
SortObject.pSort->hSortArray = hSortArray;
}
SortObject.paSortArray = (SORT_TYPE *)GUI_ALLOC_h2p(SortObject.pSort->hSortArray);
if (SortObject.pObj->IsPresorted) {
/* Add new indices */
if (NumItems < NumItemsReq) {
SortObject.pObj->ReverseSort = 0; /* Reverse sort only allowed if listview is presorted and no rows are added */
for (i = NumItems; i < NumItemsReq; i++) {
*(SortObject.paSortArray + i) = i;
}
}
} else {
SortObject.pObj->ReverseSort = 0; /* Reverse sort only allowed if listview is presorted */
/* Fill with indices if not presorted */
for (i = 0; i < NumItemsReq; i++) {
*(SortObject.paSortArray + i) = i;
}
}
SortObject.pSort->SortArrayNumItems = NumItemsReq;
/* Sort only if more than one item is available */
if (NumItemsReq > 1) {
if (SortObject.pObj->ReverseSort) {
_Reverse(&SortObject);
} else {
_BubbleSort(0, NumItemsReq - 1, &SortObject);
}
_SetSelUnsorted(hObj, SortObject.pObj, Sel);
}
SortObject.pObj->IsPresorted = 1;
SortObject.pObj->IsSorted = 1;
HEADER_SetDirIndicator(SortObject.pObj->hHeader, SortObject.pObj->SortIndex, SortObject.pSort->Reverse);
return 0;
}
/*********************************************************************
*
* _CreateSortObject
*/
static LISTVIEW_SORT * _CreateSortObject(LISTVIEW_Handle hObj, LISTVIEW_Obj * pObj) {
LISTVIEW_SORT * pSort;
if (!pObj->hSort) {
pObj->hSort = GUI_ALLOC_AllocZero(sizeof(LISTVIEW_SORT));
pObj = LISTVIEW_H2P(hObj); /* Restore after allocating memory */
if (!pObj->hSort) {
return NULL;
}
}
pSort = (LISTVIEW_SORT *)GUI_ALLOC_h2p(pObj->hSort);
pObj->SortIndex = -1;
pSort->fpFree = _Free;
pSort->fpSort = _Sort;
return pSort;
}
/*********************************************************************
*
* Public routines
*
**********************************************************************
*/
/*********************************************************************
*
* LISTVIEW_CompareText
*/
int LISTVIEW_CompareText(const void * p0, const void * p1) {
return strcmp((const char *)p1, (const char *)p0);
}
/*********************************************************************
*
* LISTVIEW_CompareDec
*/
int LISTVIEW_CompareDec(const void * p0, const void * p1) {
int v[2] = {0}, i, d;
const char * ps[2];
char c;
ps[0] = (const char *)p0;
ps[1] = (const char *)p1;
for (i = 0; i < 2; i++) {
int Neg = 0;
if (*ps[i] == '-') {
Neg = 1;
ps[i]++;
}
while ((c = *ps[i]++) != 0) {
d = c - '0';
if ((d < 0) || (d > 9)) {
break;
}
v[i] *= 10;
v[i] += d;
}
if (Neg) {
v[i] *= -1;
}
}
if (v[0] > v[1]) {
return -1;
} else if (v[0] < v[1]) {
return 1;
}
return 0;
}
/*********************************************************************
*
* LISTVIEW_GetSelUnsorted
*
* Purpose:
* If sorting is disabled, the behaviour is the same as LISTVIEW_GetSel().
* It returns the 'visible' selection index.
* If sorting is enabled, the function returns the 'unselected' index of
* the selected row.
*/
int LISTVIEW_GetSelUnsorted(LISTVIEW_Handle hObj) {
int r = -1;
if (hObj) {
LISTVIEW_Obj * pObj;
WM_LOCK();
pObj = LISTVIEW_H2P(hObj);
_Sort(hObj);
r = _GetSelUnsorted(pObj);
WM_UNLOCK();
}
return r;
}
/*********************************************************************
*
* LISTVIEW_SetSelUnsorted
*
* Purpose:
* If sorting is disabled, the behaviour is the same as LISTVIEW_SetSel().
* It sets the 'visible' selection index.
* If sorting is enabled, the function sets the 'unselected' index of the selected
* the selected row.
*/
void LISTVIEW_SetSelUnsorted(LISTVIEW_Handle hObj, int Sel) {
if (hObj) {
LISTVIEW_Obj * pObj;
WM_LOCK();
pObj = LISTVIEW_H2P(hObj);
_Sort(hObj);
_SetSelUnsorted(hObj, pObj, Sel);
WM_UNLOCK();
}
}
/*********************************************************************
*
* LISTVIEW_SetCompareFunc
*
* Purpose:
* Sets the compare function for the given column, which is called by
* the sorting algorithm if sorting is enabled.
*/
void LISTVIEW_SetCompareFunc(LISTVIEW_Handle hObj, unsigned Column, int (* fpCompare)(const void * p0, const void * p1)) {
int NumColumns;
LISTVIEW_Obj * pObj;
LISTVIEW_COLUMN * pColumn;
if (hObj) {
WM_LOCK();
pObj = LISTVIEW_H2P(hObj);
NumColumns = LISTVIEW_GetNumColumns(hObj);
if ((int)Column <= NumColumns) {
pColumn = (LISTVIEW_COLUMN *)GUI_ARRAY_GetpItem(&pObj->ColumnArray, Column);
pColumn->fpCompare = fpCompare;
}
WM_UNLOCK();
}
}
/*********************************************************************
*
* LISTVIEW_DisableSort
*
* Purpose:
* Disables sorting for the given listview object.
*/
void LISTVIEW_DisableSort(LISTVIEW_Handle hObj) {
if (hObj) {
LISTVIEW_Obj * pObj;
WM_LOCK();
pObj = LISTVIEW_H2P(hObj);
if (pObj->hSort) {
int Sel = _GetSelUnsorted(pObj);
_Free(pObj->hSort);
pObj->hSort = 0;
pObj->SortIndex = -1;
pObj->IsPresorted = 0;
pObj->IsSorted = 0;
HEADER_SetDirIndicator(pObj->hHeader, -1, 0);
LISTVIEW_SetSel(hObj, Sel);
LISTVIEW__InvalidateInsideArea(hObj, pObj);
}
WM_UNLOCK();
}
}
/*********************************************************************
*
* LISTVIEW_EnableSort
*
* Purpose:
* Enables sorting for the given listview object.
*/
void LISTVIEW_EnableSort(LISTVIEW_Handle hObj) {
if (hObj) {
LISTVIEW_Obj * pObj;
WM_LOCK();
pObj = LISTVIEW_H2P(hObj);
if (!pObj->hSort) {
_CreateSortObject(hObj, pObj);
}
WM_UNLOCK();
}
}
/*********************************************************************
*
* LISTVIEW_SetSort
*
* Purpose:
* Enables sorting for the given listview object. The function returns,
* if the object is 0, the column index is >= number of columns or if
* no compare function has been set for the desired column
*
* Return value:
* 0 if succeed
* 1 if not succeed
*/
unsigned LISTVIEW_SetSort(LISTVIEW_Handle hObj, unsigned Column, unsigned Reverse) {
LISTVIEW_Obj * pObj;
LISTVIEW_SORT * pSort;
LISTVIEW_COLUMN * pColumn;
unsigned NumColumns, Error = 0;
if (!hObj) {
return 1;
}
NumColumns = LISTVIEW_GetNumColumns(hObj);
if (Column >= NumColumns) {
return 1;
}
WM_LOCK();
pObj = LISTVIEW_H2P(hObj);
pColumn = (LISTVIEW_COLUMN *)GUI_ARRAY_GetpItem(&pObj->ColumnArray, Column);
if (pColumn->fpCompare) {
pSort = _CreateSortObject(hObj, pObj);
pObj = LISTVIEW_H2P(hObj); /* Restore after allocating memory */
if (pSort) {
pObj->SortIndex = Column;
pSort->Reverse = Reverse;
LISTVIEW__InvalidateInsideArea(hObj, pObj);
} else {
Error = 1;
}
} else {
Error = 1;
}
WM_UNLOCK();
return Error;
}
#else /* Avoid problems with empty object modules */
void LISTVIEW_SetSort_C(void);
void LISTVIEW_SetSort_C(void) {}
#endif
/*************************** End of file ****************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -