Listview V14
Dimitrie O. Paun
dpaun at rogers.com
Mon Oct 21 00:37:51 CDT 2002
This is soooo nice. I am very happy how it turned out.
In fact, I am almost extatic because:
-- the code turned out very nice, clean, and simple
-- we are now virtually flicker free
Please people, give it the worse lists, long, what
have you: it should now be a pleasure to work with
the thing: fast, light, etc.
There are still sore spots:
-- placing icons in LVS{SMALL,}ICON modes
-- autoarrange in the above modes
-- adding bulk items in LVS_OWNERDATA
But other than that, we should be smocking. If not,
I'd like to hear about it.
ChangeLog
Optimize invalidation on insert
Share the invalidation code between {Delete,Insert}Item.
--- dlls/comctl32/listview.c.V13 Mon Oct 21 00:57:06 2002
+++ dlls/comctl32/listview.c Mon Oct 21 01:29:57 2002
@@ -3969,6 +3970,70 @@
/***
* DESCRIPTION:
+ * Invalidates the listview after an item's insertion or deletion.
+ *
+ * PARAMETER(S):
+ * [I] infoPtr : valid pointer to the listview structure
+ * [I] nItem : item index
+ * [I] dir : -1 if deleting, 1 if inserting
+ *
+ * RETURN:
+ * None
+ */
+static void LISTVIEW_ScrollOnInsert(LISTVIEW_INFO *infoPtr, INT nItem, INT dir)
+{
+ UINT uView = infoPtr->dwStyle & LVS_TYPEMASK;
+ INT nPerCol, nItemCol, nItemRow;
+ RECT rcScroll;
+ POINT Origin;
+
+ assert (abs(dir) == 1);
+
+ /* arrange icons if autoarrange is on */
+ if (infoPtr->dwStyle & LVS_AUTOARRANGE)
+ LISTVIEW_Arrange(infoPtr, LVA_DEFAULT);
+
+ /* scrollbars need updating */
+ LISTVIEW_UpdateScroll(infoPtr);
+
+ /* figure out the item's position */
+ if (uView == LVS_REPORT)
+ nPerCol = infoPtr->nItemCount + 1;
+ else if (uView == LVS_LIST)
+ nPerCol = LISTVIEW_GetCountPerColumn(infoPtr);
+ else /* LVS_ICON, or LVS_SMALLICON */
+ return;
+
+ nItemCol = nItem / nPerCol;
+ nItemRow = nItem % nPerCol;
+ LISTVIEW_GetOrigin(infoPtr, &Origin);
+
+ /* move the items below up a slot */
+ rcScroll.left = nItemCol * infoPtr->nItemWidth;
+ rcScroll.top = nItemRow * infoPtr->nItemHeight;
+ rcScroll.right = rcScroll.left + infoPtr->nItemWidth;
+ rcScroll.bottom = nPerCol * infoPtr->nItemHeight;
+ OffsetRect(&rcScroll, Origin.x, Origin.y);
+ if (IntersectRect(&rcScroll, &rcScroll, &infoPtr->rcList))
+ ScrollWindowEx(infoPtr->hwndSelf, 0, dir * infoPtr->nItemHeight,
+ &rcScroll, &rcScroll, 0, 0, SW_ERASE | SW_INVALIDATE);
+
+ /* report has only that column, so we're done */
+ if (uView == LVS_REPORT) return;
+
+ /* now for LISTs, we have to deal with the columns to the right */
+ rcScroll.left = (nItemCol + 1) * infoPtr->nItemWidth;
+ rcScroll.top = 0;
+ rcScroll.right = (infoPtr->nItemCount / nPerCol + 1) * infoPtr->nItemWidth;
+ rcScroll.bottom = nPerCol * infoPtr->nItemHeight;
+ OffsetRect(&rcScroll, Origin.x, Origin.y);
+ if (IntersectRect(&rcScroll, &rcScroll, &infoPtr->rcList))
+ ScrollWindowEx(infoPtr->hwndSelf, 0, dir * infoPtr->nItemHeight,
+ &rcScroll, &rcScroll, 0, 0, SW_ERASE | SW_INVALIDATE);
+}
+
+/***
+ * DESCRIPTION:
* Removes an item from the listview control.
*
* PARAMETER(S):
@@ -3982,12 +4047,9 @@
static BOOL LISTVIEW_DeleteItem(LISTVIEW_INFO *infoPtr, INT nItem)
{
UINT uView = infoPtr->dwStyle & LVS_TYPEMASK;
- INT nPerCol, nItemCol, nItemRow;
NMLISTVIEW nmlv;
LVITEMW item;
- BOOL is_icon;
- RECT rcScroll;
- POINT Origin;
+ RECT rcBox;
TRACE("(nItem=%d)\n", nItem);
@@ -3998,6 +4060,10 @@
item.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
LISTVIEW_SetItemState(infoPtr, nItem, &item);
+ /* we need to do this here, because we'll be deleting stuff */
+ if (uView == LVS_SMALLICON || uView == LVS_ICON)
+ LISTVIEW_GetItemBox(infoPtr, nItem, &rcBox);
+
/* send LVN_DELETEITEM notification. */
ZeroMemory(&nmlv, sizeof (NMLISTVIEW));
nmlv.iItem = nItem;
@@ -4018,13 +4084,9 @@
}
DPA_Destroy(hdpaSubItems);
}
-
- is_icon = (uView == LVS_SMALLICON || uView == LVS_ICON);
- if (is_icon)
- {
- RECT rcBox;
- LISTVIEW_GetItemBox(infoPtr, nItem, &rcBox);
+ if (uView == LVS_SMALLICON || uView == LVS_ICON)
+ {
DPA_DeletePtr(infoPtr->hdpaPosX, nItem);
DPA_DeletePtr(infoPtr->hdpaPosY, nItem);
LISTVIEW_InvalidateRect(infoPtr, &rcBox);
@@ -4033,48 +4095,8 @@
infoPtr->nItemCount--;
LISTVIEW_ShiftIndices(infoPtr, nItem, -1);
- if (is_icon && (infoPtr->dwStyle & LVS_AUTOARRANGE))
- LISTVIEW_Arrange(infoPtr, LVA_DEFAULT);
-
- LISTVIEW_UpdateScroll(infoPtr);
-
/* now is the invalidation fun */
-
- /* there's nothing else to do in icon mode */
- if (is_icon) return TRUE;
-
- /* figure out the item's position */
- if (uView == LVS_REPORT)
- nPerCol = infoPtr->nItemCount + 1;
- else /* LVS_LIST */
- nPerCol = LISTVIEW_GetCountPerColumn(infoPtr);
- nItemCol = nItem / nPerCol;
- nItemRow = nItem % nPerCol;
- LISTVIEW_GetOrigin(infoPtr, &Origin);
-
- /* move the items below up a slot */
- rcScroll.left = nItemCol * infoPtr->nItemWidth;
- rcScroll.top = nItemRow * infoPtr->nItemHeight;
- rcScroll.right = rcScroll.left + infoPtr->nItemWidth;
- rcScroll.bottom = nPerCol * infoPtr->nItemHeight;
- OffsetRect(&rcScroll, Origin.x, Origin.y);
- if (IntersectRect(&rcScroll, &rcScroll, &infoPtr->rcList))
- ScrollWindowEx(infoPtr->hwndSelf, 0, -infoPtr->nItemHeight,
- &rcScroll, &rcScroll, 0, 0, SW_ERASE | SW_INVALIDATE);
-
- /* report has only that column, so we're done */
- if (uView == LVS_REPORT) return TRUE;
-
- /* now for LISTs, we have to deal with the columns to the right */
- rcScroll.left = (nItemCol + 1) * infoPtr->nItemWidth;
- rcScroll.top = 0;
- rcScroll.right = (infoPtr->nItemCount / nPerCol + 1) * infoPtr->nItemWidth;
- rcScroll.bottom = nPerCol * infoPtr->nItemHeight;
- OffsetRect(&rcScroll, Origin.x, Origin.y);
- if (IntersectRect(&rcScroll, &rcScroll, &infoPtr->rcList))
- ScrollWindowEx(infoPtr->hwndSelf, 0, -infoPtr->nItemHeight,
- &rcScroll, &rcScroll, 0, 0, SW_ERASE | SW_INVALIDATE);
-
+ LISTVIEW_ScrollOnInsert(infoPtr, nItem, -1);
return TRUE;
}
@@ -5674,17 +5696,18 @@
notify_listview(infoPtr, LVN_INSERTITEM, &nmlv);
/* align items (set position of each item) */
- if ((uView == LVS_SMALLICON) || (uView == LVS_ICON))
+ if ((uView == LVS_SMALLICON || uView == LVS_ICON))
{
- if (infoPtr->dwStyle & LVS_ALIGNLEFT) LISTVIEW_AlignLeft(infoPtr);
- else LISTVIEW_AlignTop(infoPtr);
+ RECT rcBox;
+ /* FIXME: compute X, Y here, inline */
+ /*if (is_icon && (infoPtr->dwStyle & LVS_AUTOARRANGE))*/
+ LISTVIEW_Arrange(infoPtr, LVA_DEFAULT);
+ LISTVIEW_GetItemBox(infoPtr, nItem, &rcBox);
+ LISTVIEW_InvalidateRect(infoPtr, &rcBox);
}
- LISTVIEW_UpdateScroll(infoPtr);
-
- LISTVIEW_InvalidateList(infoPtr); /* FIXME: optimize */
-
- TRACE(" <- %d\n", nItem);
+ /* now is the invalidation fun */
+ LISTVIEW_ScrollOnInsert(infoPtr, nItem, 1);
return nItem;
undo:
More information about the wine-patches
mailing list