https://git.reactos.org/?p=reactos.git;a=commitdiff;h=963d39bf66a2d915e8a7b…
commit 963d39bf66a2d915e8a7b619db6a948297e8a48f
Author: Charles Ambrye <giawa(a)hotmail.com>
AuthorDate: Wed Apr 15 09:02:00 2020 -0700
Commit: Giannis Adamopoulos <gadamopoulos(a)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);
}