[COMCTL32] Implement a simple version of snap to grid for listview

This commit is contained in:
Charles Ambrye 2020-04-15 09:02:00 -07:00 committed by Giannis Adamopoulos
parent 1bee97358e
commit 963d39bf66

View file

@ -2723,11 +2723,16 @@ static DWORD LISTVIEW_MapIndexToId(const LISTVIEW_INFO *infoPtr, INT iItem)
* PARAMETER(S):
* [I] infoPtr : valid pointer to the listview structure
* [O] lpPos : will get the current icon position
* [I] nItem : item id to get position for
*
* RETURN:
* None
*/
#ifdef __REACTOS__
static void LISTVIEW_NextIconPosTop(LISTVIEW_INFO *infoPtr, LPPOINT lpPos, INT nItem)
#else
static void LISTVIEW_NextIconPosTop(LISTVIEW_INFO *infoPtr, LPPOINT lpPos)
#endif
{
INT nListWidth = infoPtr->rcList.right - infoPtr->rcList.left;
@ -2749,11 +2754,16 @@ static void LISTVIEW_NextIconPosTop(LISTVIEW_INFO *infoPtr, LPPOINT lpPos)
* PARAMETER(S):
* [I] infoPtr : valid pointer to the listview structure
* [O] lpPos : will get the current icon position
* [I] nItem : item id to get position for
*
* RETURN:
* None
*/
#ifdef __REACTOS__
static void LISTVIEW_NextIconPosLeft(LISTVIEW_INFO *infoPtr, LPPOINT lpPos, INT nItem)
#else
static void LISTVIEW_NextIconPosLeft(LISTVIEW_INFO *infoPtr, LPPOINT lpPos)
#endif
{
INT nListHeight = infoPtr->rcList.bottom - infoPtr->rcList.top;
@ -2766,7 +2776,45 @@ static void LISTVIEW_NextIconPosLeft(LISTVIEW_INFO *infoPtr, LPPOINT lpPos)
infoPtr->currIconPos.y = 0;
}
#ifdef __REACTOS__
/***
* DESCRIPTION:
* Returns the grid position closest to the already placed icon.
* The returned position is not offset by Origin.
*
* PARAMETER(S):
* [I] infoPtr : valid pointer to the listview structure
* [O] lpPos : will get the current icon position
* [I] nItem : item id to get position for
*
* RETURN:
* None
*/
static void LISTVIEW_NextIconPosSnap(LISTVIEW_INFO *infoPtr, LPPOINT lpPos, INT nItem)
{
INT nListHeight = infoPtr->rcList.bottom - infoPtr->rcList.top;
INT nListWidth = infoPtr->rcList.right - infoPtr->rcList.left;
INT nMaxColumns = nListWidth / infoPtr->nItemWidth;
INT nMaxRows = nListHeight / infoPtr->nItemHeight;
POINT oldPosition;
// get the existing x and y position and then snap to the closest grid square
oldPosition.x = (LONG_PTR)DPA_GetPtr(infoPtr->hdpaPosX, nItem);
oldPosition.y = (LONG_PTR)DPA_GetPtr(infoPtr->hdpaPosY, nItem);
// FIXME: This could should deal with multiple icons in the same grid square
// equivalent of max(0, round(oldPosition / itemSize) * itemSize), but without need for 'round' function
(*lpPos).x = max(0, oldPosition.x + (infoPtr->nItemWidth >> 1) - (oldPosition.x + (infoPtr->nItemWidth >> 1)) % infoPtr->nItemWidth);
(*lpPos).y = max(0, oldPosition.y + (infoPtr->nItemHeight >> 1) - (oldPosition.y + (infoPtr->nItemHeight >> 1)) % infoPtr->nItemHeight);
// deal with any icons that have gone out of range
if ((*lpPos).x > nListWidth) (*lpPos).x = nMaxColumns * infoPtr->nItemWidth;
if ((*lpPos).y > nListHeight) (*lpPos).y = nMaxRows * infoPtr->nItemHeight;
}
#endif
/***
* DESCRIPTION:
* Moves an icon to the specified position.
@ -2819,7 +2867,11 @@ static BOOL LISTVIEW_MoveIconTo(const LISTVIEW_INFO *infoPtr, INT nItem, const P
*/
static BOOL LISTVIEW_Arrange(LISTVIEW_INFO *infoPtr, INT nAlignCode)
{
#ifdef __REACTOS__
void (*next_pos)(LISTVIEW_INFO *, LPPOINT, INT);
#else
void (*next_pos)(LISTVIEW_INFO *, LPPOINT);
#endif
POINT pos;
INT i;
@ -2837,14 +2889,22 @@ static BOOL LISTVIEW_Arrange(LISTVIEW_INFO *infoPtr, INT nAlignCode)
{
case LVA_ALIGNLEFT: next_pos = LISTVIEW_NextIconPosLeft; break;
case LVA_ALIGNTOP: next_pos = LISTVIEW_NextIconPosTop; break;
#ifdef __REACTOS__
case LVA_SNAPTOGRID: next_pos = LISTVIEW_NextIconPosSnap; break;
#else
case LVA_SNAPTOGRID: next_pos = LISTVIEW_NextIconPosTop; break; /* FIXME */
#endif
default: return FALSE;
}
infoPtr->currIconPos.x = infoPtr->currIconPos.y = 0;
for (i = 0; i < infoPtr->nItemCount; i++)
{
next_pos(infoPtr, &pos);
#ifdef __REACTOS__
next_pos(infoPtr, &pos, i);
#else
next_pos(infoPtr, &pos);
#endif
LISTVIEW_MoveIconTo(infoPtr, i, &pos, FALSE);
}
@ -7978,10 +8038,17 @@ static INT LISTVIEW_InsertItemT(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem,
{
POINT pt;
#ifdef __REACTOS__
if (infoPtr->dwStyle & LVS_ALIGNLEFT)
LISTVIEW_NextIconPosLeft(infoPtr, &pt, nItem);
else
LISTVIEW_NextIconPosTop(infoPtr, &pt, nItem);
#else
if (infoPtr->dwStyle & LVS_ALIGNLEFT)
LISTVIEW_NextIconPosLeft(infoPtr, &pt);
else
LISTVIEW_NextIconPosTop(infoPtr, &pt);
#endif
LISTVIEW_MoveIconTo(infoPtr, nItem, &pt, TRUE);
}