📄 listview.c
字号:
Notification = WM_NOTIFICATION_RELEASED;
}
}
else
{
Notification = WM_NOTIFICATION_MOVED_OUT;
}
_NotifyOwner(hObj, Notification);
}
/*********************************************************************
*
* _GetXSize
*
* Purpose:
* Returns the width of the inside listview area.
*/
static int _GetXSize(LISTVIEW_Handle hObj)
{
GUI_RECT Rect;
WM_GetInsideRectExScrollbar(hObj, &Rect);
return Rect.x1 + 1;
}
/*********************************************************************
*
* _GetHeaderWidth
*
* Purpose:
* Returns the width of all items in header.
*
* Return value:
* NumItems > 0: width of all items.
* NumItems = 0: 1 (to avoid problem with horizontal scrollbar)
*/
static int _GetHeaderWidth(LISTVIEW_Obj *pObj, HEADER_Handle hHeader)
{
int NumItems, i, r = 1;
NumItems = HEADER_GetNumItems(hHeader);
if (NumItems)
{
for (i = 0, r = 0; i < NumItems; i++)
{
r += HEADER_GetItemWidth(hHeader, i);
}
}
if (pObj->ScrollStateH.v > (r - pObj->ScrollStateH.PageSize))
{
r += pObj->ScrollStateH.PageSize - (r - pObj->ScrollStateH.v);
}
return r;
}
/*********************************************************************
*
* LISTVIEW__UpdateScrollPos
*
* Purpose:
* Checks whether if we must scroll up or scroll down to ensure
* that selection is in the visible area. This function also
* makes sure that scroll positions are in valid ranges.
*
* Return value:
* Difference between old and new vertical scroll pos.
*/
int LISTVIEW__UpdateScrollPos(LISTVIEW_Handle hObj, LISTVIEW_Obj *pObj)
{
int PrevScrollStateV;
PrevScrollStateV = pObj->ScrollStateV.v;
if (pObj->Sel >= 0)
{
WM_CheckScrollPos(&pObj->ScrollStateV, pObj->Sel, 0, 0);
}
else
{
WM_CheckScrollBounds(&pObj->ScrollStateV);
}
WM_CheckScrollBounds(&pObj->ScrollStateH);
WIDGET__SetScrollState(hObj, &pObj->ScrollStateV, &pObj->ScrollStateH);
return pObj->ScrollStateV.v - PrevScrollStateV;
}
/*********************************************************************
*
* LISTVIEW__UpdateScrollParas
*
* Purpose:
* Calculates number of items and page size of both vertical
* and horizontal scrollbar. After this LISTVIEW__UpdateScrollPos will
* be called to ensure scroll positions are in valid ranges.
*/
int LISTVIEW__UpdateScrollParas(LISTVIEW_Handle hObj, LISTVIEW_Obj *pObj)
{
int NumRows;
NumRows = GUI_ARRAY_GetNumItems(&pObj->RowArray);
/* update vertical scrollbar */
pObj->ScrollStateV.PageSize = _GetNumVisibleRows(hObj, pObj);
pObj->ScrollStateV.NumItems = (NumRows) ? NumRows : 1;
/* update horizontal scrollbar */
pObj->ScrollStateH.PageSize = _GetXSize(hObj);
pObj->ScrollStateH.NumItems = _GetHeaderWidth(pObj, pObj->hHeader);
return LISTVIEW__UpdateScrollPos(hObj, pObj);
}
/*********************************************************************
*
* _FreeAttached
*
* Purpose:
* Delete attached objects (if any).
*/
static void _FreeAttached(LISTVIEW_Obj *pObj)
{
int i, j, NumRows, NumColumns;
NumRows = GUI_ARRAY_GetNumItems(&pObj->RowArray);
NumColumns = GUI_ARRAY_GetNumItems(&pObj->AlignArray);
for (i = 0; i < NumRows; i++)
{
GUI_ARRAY * pRow;
pRow = (GUI_ARRAY *) GUI_ARRAY_GetpItem(&pObj->RowArray, i);
/* Delete attached info items */
for (j = 0; j < NumColumns; j++)
{
LISTVIEW_ITEM * pItem;
pItem = (LISTVIEW_ITEM *) GUI_ARRAY_GetpItem(pRow, j);
if (pItem->hItemInfo)
{
GUI_ALLOC_Free(pItem->hItemInfo);
}
}
/* Delete row */
GUI_ARRAY_Delete(pRow);
}
GUI_ARRAY_Delete(&pObj->AlignArray);
GUI_ARRAY_Delete(&pObj->RowArray);
}
/*********************************************************************
*
* _AddKey
*
* Returns: 1 if Key has been consumed
* 0 else
*/
static int _AddKey(LISTVIEW_Handle hObj, int Key)
{
switch (Key)
{
case GUI_KEY_DOWN:
LISTVIEW_IncSel(hObj);
return 1; /* Key has been consumed */
case GUI_KEY_UP:
LISTVIEW_DecSel(hObj);
return 1; /* Key has been consumed */
}
return 0; /* Key has NOT been consumed */
}
/*********************************************************************
*
* _LISTVIEW_Callback
*/
static void _LISTVIEW_Callback(WM_MESSAGE *pMsg)
{
LISTVIEW_Handle hObj;
LISTVIEW_Obj* pObj;
WM_SCROLL_STATE ScrollState;
hObj = pMsg->hWin;
/* Let widget handle the standard messages */
if (WIDGET_HandleActive(hObj, pMsg) == 0)
{
return;
}
pObj = LISTVIEW_H2P(hObj);
switch (pMsg->MsgId)
{
case WM_NOTIFY_CLIENTCHANGE:
case WM_SIZE:
LISTVIEW__UpdateScrollParas(hObj, pObj);
return;
case WM_NOTIFY_PARENT:
switch (pMsg->Data.v)
{
case WM_NOTIFICATION_CHILD_DELETED:
/* make sure we do not send any messages to the header child once it has been deleted */
if (pMsg->hWinSrc == pObj->hHeader)
{
pObj->hHeader = 0;
}
break;
case WM_NOTIFICATION_VALUE_CHANGED:
if (pMsg->hWinSrc == WM_GetScrollbarV(hObj))
{
WM_GetScrollState(pMsg->hWinSrc, &ScrollState);
pObj->ScrollStateV.v = ScrollState.v;
LISTVIEW__InvalidateInsideArea(hObj, pObj);
_NotifyOwner(hObj, WM_NOTIFICATION_SCROLL_CHANGED);
}
else if (pMsg->hWinSrc == WM_GetScrollbarH(hObj))
{
WM_GetScrollState(pMsg->hWinSrc, &ScrollState);
pObj->ScrollStateH.v = ScrollState.v;
LISTVIEW__UpdateScrollParas(hObj, pObj);
HEADER_SetScrollPos(pObj->hHeader, pObj->ScrollStateH.v);
_NotifyOwner(hObj, WM_NOTIFICATION_SCROLL_CHANGED);
}
break;
case WM_NOTIFICATION_SCROLLBAR_ADDED:
LISTVIEW__UpdateScrollParas(hObj, pObj);
break;
}
return;
case WM_PAINT:
_Paint(hObj, pObj, pMsg);
return;
case WM_TOUCH:
_OnTouch(hObj, pObj, pMsg);
return; /* Important: message handled ! */
case WM_KEY:
if (((const WM_KEY_INFO *) (pMsg->Data.p))->PressedCnt > 0)
{
int Key;
Key = ((const WM_KEY_INFO *) (pMsg->Data.p))->Key;
if (_AddKey(hObj, Key))
{
return;
}
}
break; /* No return here ... WM_DefaultProc needs to be called */
case WM_DELETE:
_FreeAttached(pObj);
break; /* No return here ... WM_DefaultProc needs to be called */
}
WM_DefaultProc(pMsg);
}
/*********************************************************************
*
* Exported routines: Create
*
**********************************************************************
*/
/* Note: the parameters to a create function may vary.
Some widgets may have multiple create functions */
/*********************************************************************
*
* LISTVIEW_CreateEx
*/
LISTVIEW_Handle LISTVIEW_CreateEx(int x0, int y0, int xsize, int ysize, WM_HWIN hParent, int WinFlags, int ExFlags, int Id)
{
LISTVIEW_Handle hObj;
GUI_USE_PARA(ExFlags);
/* Create the window */
if ((xsize == 0) && (ysize == 0) && (x0 == 0) && (y0 == 0))
{
GUI_RECT Rect;
WM_GetClientRectEx(hParent, &Rect);
xsize = Rect.x1 - Rect.x0 + 1;
ysize = Rect.y1 - Rect.y0 + 1;
}
hObj = WM_CreateWindowAsChild(x0, y0, xsize, ysize, hParent, WinFlags, &_LISTVIEW_Callback, sizeof(LISTVIEW_Obj) - sizeof(WM_Obj));
if (hObj)
{
LISTVIEW_Obj* pObj;
WM_LOCK();
pObj = LISTVIEW_H2P(hObj);
/* Init sub-classes */
GUI_ARRAY_CREATE(&pObj->RowArray);
GUI_ARRAY_CREATE(&pObj->AlignArray);
/* Init widget specific variables */
WIDGET__Init(&pObj->Widget, Id, WIDGET_STATE_FOCUSSABLE);
/* Init member variables */
LISTVIEW_INIT_ID(pObj);
pObj->Props = LISTVIEW_DefaultProps;
pObj->ShowGrid = 0;
pObj->RowDistY = 0;
pObj->Sel = -1;
pObj->LBorder = 1;
pObj->RBorder = 1;
pObj->hHeader = HEADER_CreateEx(0, 0, 0, 0, hObj, WM_CF_SHOW, 0, 0);
LISTVIEW__UpdateScrollParas(hObj, pObj);
WM_UNLOCK();
}
else
{
GUI_DEBUG_ERROROUT_IF(hObj == 0, "LISTVIEW_Create failed")
}
return hObj;
}
/*********************************************************************
*
* Exported routines: Member functions
*
**********************************************************************
*/
/*********************************************************************
*
* LISTVIEW_IncSel
*/
void LISTVIEW_IncSel(LISTVIEW_Handle hObj)
{
int Sel = LISTVIEW_GetSel(hObj);
LISTVIEW_SetSel(hObj, Sel + 1);
}
/*********************************************************************
*
* LISTVIEW_DecSel
*/
void LISTVIEW_DecSel(LISTVIEW_Handle hObj)
{
int Sel = LISTVIEW_GetSel(hObj);
if (Sel)
{
LISTVIEW_SetSel(hObj, Sel - 1);
}
}
/*********************************************************************
*
* LISTVIEW_AddColumn
*/
void LISTVIEW_AddColumn(LISTVIEW_Handle hObj, int Width, const char *s, int Align)
{
if (hObj)
{
LISTVIEW_Obj* pObj;
unsigned NumRows;
WM_LOCK();
pObj = LISTVIEW_H2P(hObj);
HEADER_AddItem(pObj->hHeader, Width, s, Align); /* Modify header */
GUI_ARRAY_AddItem(&pObj->AlignArray, &Align, sizeof(int));
NumRows = LISTVIEW_GetNumRows(hObj);
if (NumRows)
{
GUI_ARRAY* pRow;
unsigned i;
for (i = 0; i < NumRows; i++)
{
pRow = (GUI_ARRAY *) GUI_ARRAY_GetpItem(&pObj->RowArray, i);
GUI_ARRAY_AddItem(pRow, NULL, sizeof(LISTVIEW_ITEM) + 1);
}
}
LISTVIEW__UpdateScrollParas(hObj, pObj);
LISTVIEW__InvalidateInsideArea(hObj, pObj);
WM_UNLOCK();
}
}
/*********************************************************************
*
* LISTVIEW_AddRow
*/
void LISTVIEW_AddRow(LISTVIEW_Handle hObj, const GUI_ConstString *ppText)
{
if (hObj)
{
LISTVIEW_Obj* pObj;
int NumRows;
WM_LOCK();
pObj = LISTVIEW_H2P(hObj);
NumRows = GUI_ARRAY_GetNumItems(&pObj->RowArray);
/* Create GUI_ARRAY for the new row */
if (GUI_ARRAY_AddItem(&pObj->RowArray, NULL, sizeof(GUI_ARRAY)) == 0)
{
int i, NumColumns, NumBytes;
GUI_ARRAY* pRow;
const char* s;
GUI_ARRAY_CREATE((GUI_ARRAY *) GUI_ARRAY_GetpItem(&pObj->RowArray, NumRows)); /* For higher debug levels only */
/* Add columns for the new row */
NumColumns = HEADER_GetNumItems(pObj->hHeader);
for (i = 0; i < NumColumns; i++)
{
LISTVIEW_ITEM * pItem;
pRow = (GUI_ARRAY *) GUI_ARRAY_GetpItem(&pObj->RowArray, NumRows);
s = (ppText) ? *ppText++ : 0;
if (s == 0)
{
ppText = 0;
}
NumBytes = GUI__strlen(s) + 1; /* 0 if no string is specified (s == NULL) */
GUI_ARRAY_AddItem(pRow, NULL, sizeof(LISTVIEW_ITEM) + NumBytes);
pItem = (LISTVIEW_ITEM *) GUI_ARRAY_GetpItem(pRow, i);
if (NumBytes > 1)
{
strcpy(pItem->acText, s);
}
}
LISTVIEW__UpdateScrollParas(hObj, pObj);
LISTVIEW__InvalidateRow(hObj, pObj, NumRows);
}
WM_UNLOCK();
}
}
#else
void LISTVIEW_C(void);
void LISTVIEW_C(void)
{
}
#endif /* #if GUI_WINSUPPORT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -