https://git.reactos.org/?p=reactos.git;a=commitdiff;h=963d39bf66a2d915e8a7b6...
commit 963d39bf66a2d915e8a7b619db6a948297e8a48f Author: Charles Ambrye giawa@hotmail.com AuthorDate: Wed Apr 15 09:02:00 2020 -0700 Commit: Giannis Adamopoulos gadamopoulos@reactos.org CommitDate: Fri Apr 17 13:23:29 2020 +0300
[COMCTL32] Implement a simple version of snap to grid for listview --- dll/win32/comctl32/listview.c | 71 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 2 deletions(-)
diff --git a/dll/win32/comctl32/listview.c b/dll/win32/comctl32/listview.c index 3d04f103fb2..7a3eeec5404 100644 --- a/dll/win32/comctl32/listview.c +++ b/dll/win32/comctl32/listview.c @@ -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); }