Listview L3

Dimitrie O. Paun dpaun at rogers.com
Sun Oct 6 18:06:18 CDT 2002


This one is important -- it implements a bunch of very important
cleanups, and clarifications. And fixes bugs :), in particular
the handling of the large item in ICON mode.

ChangeLog
  Cleanup, and clarify the handling of the various rectangles
  Fix handling of large items in ICON mode
  Fix calculation of LVIR_SELECTBOUNDS
  Various cleanups, and simplifications.

--- dlls/comctl32/listview.c.L2	Sun Oct  6 18:12:45 2002
+++ dlls/comctl32/listview.c	Sun Oct  6 19:01:23 2002
@@ -724,7 +724,6 @@
     InvalidateRect(infoPtr->hwndSelf, rect, TRUE); \
 } while (0)
 
-/* FIXME: what if we show the focus on a large item in ICON mode? */
 #define LISTVIEW_InvalidateItem(infoPtr, nItem) do { \
     RECT rcItem; \
     rcItem.left = LVIR_BOUNDS; \
@@ -1206,37 +1205,26 @@
  * [I] infoPtr : valid pointer to the listview structure
  * [I] nItem  : item number
  * [O] lpptPosition : ptr to Position point
- *                the Position point is relative to infoPtr->rcList
- *                (has *NOT* been adjusted by the origin)
- * [O] lprcBoundary : ptr to Boundary rectangle
- *                the Boundary rectangle is relative to infoPtr->rcList
- *                (has *NOT* been adjusted by the origin)
+ * 		  Same as LVM_GETITEMPOSITION
+ * [O] lprcBounds : ptr to Bounds rectangle
+ *                Same as LVM_GETITEMRECT with LVIR_BOUNDS
  * [O] lprcIcon : ptr to Icon rectangle
- *                the Icon rectangle is relative to infoPtr->rcView
- *                (has already been adjusted by the origin)
+ *                Same as LVM_GETITEMRECT with LVIR_ICON
  * [O] lprcLabel : ptr to Label rectangle
- *              - the Label rectangle is relative to infoPtr->rcView
- *                (has already been adjusted by the origin)
- *              - the Label rectangle encloses the label text only
- * [O] lprcText : ptr to FullText rectangle
- *              - the FullText rectangle is relative to infoPtr->rcView
- *                (has already been adjusted by the origin)
- *              - the FullText rectangle contains the Label rectangle
- *                but may be bigger. Used for filling the background.
+ *                Same as LVM_GETITEMRECT with LVIR_LABEL
  *
  * RETURN:
  *   TRUE if computations OK
  *   FALSE otherwise
  */
 static BOOL LISTVIEW_GetItemMeasures(LISTVIEW_INFO *infoPtr, INT nItem,
-				    LPPOINT lpptPosition,
-				    LPRECT lprcBoundary, LPRECT lprcIcon,
-				    LPRECT lprcLabel, LPRECT lprcText)
+				    LPPOINT lpptPosition, LPRECT lprcBounds,
+				    LPRECT lprcIcon, LPRECT lprcLabel)
 {
     LONG lStyle = infoPtr->dwStyle;
     UINT uView = lStyle & LVS_TYPEMASK;
     POINT Origin, Position, TopLeft;
-    RECT Icon, Boundary, Label, FullText;
+    RECT Icon, Bounds, Label;
     INT nIndent = 0;
 
     if (!LISTVIEW_GetOrigin(infoPtr, &Origin)) return FALSE;
@@ -1399,10 +1387,7 @@
 	      Label.bottom = Label.top + infoPtr->nItemHeight + HEIGHT_PADDING;
 	      LISTVIEW_UpdateLargeItemLabelRect (infoPtr, nItem, &Label);
 	  }
-	  FullText = Label;
-	  InflateRect(&FullText, 2, 0);
 	  if (lprcLabel) *lprcLabel = Label;
-	  if (lprcText) *lprcText = FullText;
       }
       else return FALSE;
   }
@@ -1427,7 +1412,6 @@
       else
 	  Label.right = nLeftPos + infoPtr->nItemWidth;
       if (lprcLabel) *lprcLabel = Label;
-      if (lprcText) *lprcText = Label;
   }
   else /* LVS_LIST or LVS_REPORT */
   {
@@ -1450,34 +1434,32 @@
 	if (Label.right - Position.x > infoPtr->nItemWidth)
 	    Label.right = Position.x + infoPtr->nItemWidth;
         if (lprcLabel) *lprcLabel = Label;
-        if (lprcText) *lprcText = Label;
   }
   
-    TRACE("hwnd=%x, item=%d, label=%s, fulltext=%s\n",
-	  infoPtr->hwndSelf, nItem, debugrect(&Label), debugrect(lprcText));
+    TRACE("hwnd=%x, item=%d, label=%s\n", infoPtr->hwndSelf, nItem, debugrect(&Label));
 
     /***********************************************************/
-    /* compute boundary box for the item (ala LVM_GETITEMRECT) */
+    /* compute bounds box for the item (ala LVM_GETITEMRECT) */
     /***********************************************************/
 
     if (uView == LVS_REPORT)
     {
-	Boundary.left = TopLeft.x;
-	Boundary.top = TopLeft.y;
-	Boundary.right = Boundary.left + infoPtr->nItemWidth;
-	Boundary.bottom = Boundary.top + infoPtr->nItemHeight;
+	Bounds.left = TopLeft.x;
+	Bounds.top = TopLeft.y;
+	Bounds.right = Bounds.left + infoPtr->nItemWidth;
+	Bounds.bottom = Bounds.top + infoPtr->nItemHeight;
 	if (!(infoPtr->dwLvExStyle & LVS_EX_FULLROWSELECT))
-	    Boundary.left += nIndent;
-	Boundary.right -= REPORT_MARGINX;
-	if (Boundary.right < Boundary.left) Boundary.right = Boundary.left;
+	    Bounds.left += nIndent;
+	Bounds.right -= REPORT_MARGINX;
+	if (Bounds.right < Bounds.left) Bounds.right = Bounds.left;
     }
     else
     {
-	UnionRect(&Boundary, &Icon, &Label);
+	UnionRect(&Bounds, &Icon, &Label);
     }
 
-    TRACE("hwnd=%x, item=%d, boundary=%s\n", infoPtr->hwndSelf, nItem, debugrect(&Boundary));
-    if (lprcBoundary) *lprcBoundary = Boundary;
+    TRACE("hwnd=%x, item=%d, bounds=%s\n", infoPtr->hwndSelf, nItem, debugrect(&Bounds));
+    if (lprcBounds) *lprcBounds = Bounds;
 
     return TRUE;
 }
@@ -3087,7 +3069,7 @@
   WCHAR szDispText[DISP_TEXT_SIZE] = { '\0' };
   LVITEMW lvItem;
   UINT uFormat = LISTVIEW_DTFLAGS;
-  RECT rcIcon, rcFocus, rcFullText, rcLabel, *lprcFocus;
+  RECT rcIcon, rcFocus, rcLabel, *lprcFocus;
   POINT ptOrg;
 
   TRACE("(hdc=%x, nItem=%d, rcItem=%s)\n", hdc, nItem, debugrect(&rcItem));
@@ -3106,7 +3088,7 @@
   /* now check if we need to update the focus rectangle */
   lprcFocus = infoPtr->bFocus && (lvItem.state & LVIS_FOCUSED) ? &infoPtr->rcFocus : 0;
   
-  LISTVIEW_GetItemMeasures(infoPtr, nItem, &ptOrg, NULL, &rcIcon, &rcLabel, &rcFullText);
+  LISTVIEW_GetItemMeasures(infoPtr, nItem, &ptOrg, NULL, &rcIcon, &rcLabel);
 
   /* Set the item to the boundary box for now */
   TRACE("iconSize.cx=%ld, nItemWidth=%d\n", infoPtr->iconSize.cx, infoPtr->nItemWidth);
@@ -3222,18 +3204,8 @@
    * that the background is complete
    */
   rcFocus = rcLabel;  /* save for focus */
-  if ((uFormat & DT_NOCLIP) || (lvItem.state & LVIS_SELECTED))
-  {
-      /* FIXME: why do we need this??? */
-      HBRUSH hBrush = CreateSolidBrush(GetBkColor (hdc));
-
-      FillRect(hdc, &rcFullText, hBrush);
-      rcFocus = rcFullText;
-      DeleteObject(hBrush);
-
-      /* Save size of item drawing for next InvalidateRect */
-      TRACE("focused/selected, rcFocus=%s\n", debugrect(&rcFocus));
-  }
+  if (lvItem.state & LVIS_SELECTED)
+      ExtTextOutW(hdc, rcLabel.left, rcLabel.top, ETO_OPAQUE, &rcLabel, 0, 0, 0);
   /* else ? What if we are losing the focus? will we not get a complete
    * background?
    */
@@ -4982,35 +4954,7 @@
 
     if (!lpptPosition || nItem < 0 || nItem >= infoPtr->nItemCount) return FALSE;
 
-    return LISTVIEW_GetItemMeasures(infoPtr, nItem, lpptPosition, NULL, NULL, NULL, NULL);
-}
-
-/***
- *  Adjust a text rectangle to an integral number of text lines.
- */
-static void LISTVIEW_GetIntegralLines(
-	const LISTVIEW_INFO *infoPtr,
-	RECT *rcText)
-{
-    INT i, j, k, l;
-
-    /*
-     * We need to have the bottom to be an intergal number of
-     * text lines (ntmHeight) below text top that is less than
-     * or equal to the nItemHeight.
-	     */
-    i = infoPtr->nItemHeight - infoPtr->iconSize.cy -
-	ICON_TOP_PADDING - ICON_BOTTOM_PADDING;
-    j = i / infoPtr->ntmHeight;
-    k = j * infoPtr->ntmHeight;
-    l = rcText->top + k;
-    rcText->bottom = min(rcText->bottom, l);
-    rcText->bottom += 1;
-
-    TRACE("integral lines, nitemH=%d, ntmH=%d, icon.cy=%ld, i=%d, j=%d, k=%d, rect=(%d,%d)-(%d,%d)\n",
-	  infoPtr->nItemHeight, infoPtr->ntmHeight, infoPtr->iconSize.cy,
-	  i, j, k,
-	  rcText->left, rcText->top, rcText->right, rcText->bottom);
+    return LISTVIEW_GetItemMeasures(infoPtr, nItem, lpptPosition, NULL, NULL, NULL);
 }
 
 
@@ -5085,10 +5029,20 @@
     if (focused)
     {
 	rcText.bottom += 2;
+	InflateRect(&rcText, 2, 0);
     }
     else /* not focused, may or may not be selected */
     {
-	LISTVIEW_GetIntegralLines(infoPtr, &rcText);
+        /*
+         * We need to have the bottom to be an intergal number of
+         * text lines (ntmHeight) below text top that is less than
+         * or equal to the nItemHeight.
+         */
+        INT lh = infoPtr->nItemHeight - infoPtr->iconSize.cy - 
+		 ICON_TOP_PADDING - ICON_BOTTOM_PADDING;
+        INT ih = (lh / infoPtr->ntmHeight) * infoPtr->ntmHeight;
+        rcText.bottom = min(rcText.bottom, rcText.top + ih);
+        rcText.bottom += 1;
     }
     *rect = rcText;
 
@@ -5166,7 +5120,7 @@
  */
 static BOOL LISTVIEW_GetItemRect(LISTVIEW_INFO *infoPtr, INT nItem, LPRECT lprc)
 {
-    RECT label_rect, icon_rect;
+    RECT label_rect;
 
     TRACE("(hwnd=%x, nItem=%d, lprc=%p)\n", infoPtr->hwndSelf, nItem, lprc);
 
@@ -5175,20 +5129,22 @@
     switch(lprc->left)
     {
     case LVIR_ICON:
-	if (!LISTVIEW_GetItemMeasures(infoPtr, nItem, NULL, NULL, lprc, NULL, NULL)) return FALSE;
+	if (!LISTVIEW_GetItemMeasures(infoPtr, nItem, NULL, NULL, lprc, NULL)) return FALSE;
         break;
 
     case LVIR_LABEL:
-	if (!LISTVIEW_GetItemMeasures(infoPtr, nItem, NULL, NULL, NULL, lprc, NULL)) return FALSE;
+	if (!LISTVIEW_GetItemMeasures(infoPtr, nItem, NULL, NULL, NULL, lprc)) return FALSE;
         break;
 
     case LVIR_BOUNDS:
-	if (!LISTVIEW_GetItemMeasures(infoPtr, nItem, NULL, lprc, NULL, NULL, NULL)) return FALSE;
+	if (!LISTVIEW_GetItemMeasures(infoPtr, nItem, NULL, lprc, NULL, NULL)) return FALSE;
         break;
 
     case LVIR_SELECTBOUNDS:
-	if (!LISTVIEW_GetItemMeasures(infoPtr, nItem, NULL, NULL, &icon_rect, &label_rect, NULL)) return FALSE;
-	UnionRect (lprc, &icon_rect, &label_rect);
+	if (!LISTVIEW_GetItemMeasures(infoPtr, nItem, NULL, lprc, NULL, &label_rect)) return FALSE;
+	if ( (infoPtr->dwStyle & LVS_TYPEMASK) == LVS_REPORT && 
+	     (infoPtr->dwLvExStyle & LVS_EX_FULLROWSELECT) )
+	    lprc->right = label_rect.right;
         break;
 
     default:
@@ -7629,12 +7585,12 @@
     /* if we have a focus rectagle, get rid of it */
     LISTVIEW_ShowFocusRect(infoPtr, infoPtr->nFocusedItem, FALSE);
     
-    /* invalidate the selected items before reseting focus flag */
-    LISTVIEW_InvalidateSelectedItems(infoPtr);
-    
     /* set window focus flag */
     infoPtr->bFocus = FALSE;
 
+    /* invalidate the selected items before reseting focus flag */
+    LISTVIEW_InvalidateSelectedItems(infoPtr);
+    
     return 0;
 }
 
@@ -8155,12 +8111,12 @@
     /* send NM_SETFOCUS notification */
     notify_setfocus(infoPtr);
 
-    /* put the focus rect back on */
-    LISTVIEW_ShowFocusRect(infoPtr, infoPtr->nFocusedItem, TRUE);
-
     /* set window focus flag */
     infoPtr->bFocus = TRUE;
 
+    /* put the focus rect back on */
+    LISTVIEW_ShowFocusRect(infoPtr, infoPtr->nFocusedItem, TRUE);
+
     /* redraw all visible selected items */
     LISTVIEW_InvalidateSelectedItems(infoPtr);
 




More information about the wine-patches mailing list