Listview O0

Dimitrie O. Paun dpaun at rogers.com
Thu Oct 10 23:30:59 CDT 2002


Separate item metrics computation from positioning.

ChangeLog
  Separate item metrics computation from positioning
  Add support for computing state icon metrics.

Index: dlls/comctl32/listview.c
===================================================================
RCS file: /var/cvs/wine/dlls/comctl32/listview.c,v
retrieving revision 1.215
diff -u -r1.215 listview.c
--- dlls/comctl32/listview.c	11 Oct 2002 04:19:20 -0000	1.215
+++ dlls/comctl32/listview.c	11 Oct 2002 04:29:43 -0000
@@ -1378,11 +1378,13 @@
  *
  * PARAMETER(S):
  * [I] infoPtr : valid pointer to the listview structure
- * [I] nItem  : item number
+ * [I] lpLVItem : item to compute the measures for
  * [O] lprcBox : ptr to Box rectangle
  *                The internal LVIR_BOX rectangle
  * [O] lprcBounds : ptr to Bounds rectangle
  *                Same as LVM_GETITEMRECT with LVIR_BOUNDS
+ * [0] lprcState : ptr to State icon rectangle
+ *  		  The internal LVIR_STATE rectangle
  * [O] lprcIcon : ptr to Icon rectangle
  *                Same as LVM_GETITEMRECT with LVIR_ICON
  * [O] lprcLabel : ptr to Label rectangle
@@ -1392,54 +1394,73 @@
  *   TRUE if computations OK
  *   FALSE otherwise
  */
-static BOOL LISTVIEW_GetItemMeasures(LISTVIEW_INFO *infoPtr, INT nItem,
+static BOOL LISTVIEW_GetItemMetrics(LISTVIEW_INFO *infoPtr, LVITEMW *lpLVItem,
 				    LPRECT lprcBox, LPRECT lprcBounds,
-				    LPRECT lprcIcon, LPRECT lprcLabel)
+				    LPRECT lprcState, LPRECT lprcIcon, LPRECT lprcLabel)
 {
     UINT uView = infoPtr->dwStyle & LVS_TYPEMASK;
-    BOOL doIcon = FALSE, doLabel = FALSE, oversizedBox = FALSE;
-    WCHAR szDispText[DISP_TEXT_SIZE] = { '\0' };
-    RECT Box, Icon, Label;
-    POINT Position, Origin;
-    LVITEMW lvItem;
+    BOOL doState = FALSE, doIcon = FALSE, doLabel = FALSE, oversizedBox = FALSE;
+    RECT Box, State, Icon, Label;
 
+    ERR("(lpLVItem=%s)\n", debuglvitem_t(lpLVItem, TRUE));
+	
     /* Be smart and try to figure out the minimum we have to do */
     if (lprcBounds)
     {
 	if (uView == LVS_REPORT) doIcon = TRUE;
         else doLabel = TRUE;
     }
-    if (uView == LVS_ICON && infoPtr->bFocus &&
-	!(infoPtr->dwStyle & LVS_OWNERDRAWFIXED) &&
-	LISTVIEW_GetItemState(infoPtr, nItem, LVIS_FOCUSED))
-	oversizedBox = doLabel = TRUE;
+    if (uView == LVS_ICON && (lprcBox || lprcBounds || lprcLabel))
+    {
+	if (!(lpLVItem->mask & LVIF_STATE) || 
+	    !(lpLVItem->stateMask & LVIS_FOCUSED)) 
+	    return FALSE;
+	if ((lpLVItem->state & LVIS_FOCUSED) &&
+	    !(infoPtr->dwStyle & LVS_OWNERDRAWFIXED))
+	    oversizedBox = doLabel = TRUE;
+    }
     if (lprcLabel) doLabel = TRUE;
     if (doLabel || lprcIcon) doIcon = TRUE;
+    if (doIcon || lprcState) doState = TRUE;
     
-    /* get what we need from the item before hand, so we make
-     * only one request. This can speed up things, if data
-     * is stored on the app side */
-    if (doLabel || (doIcon && uView == LVS_REPORT))
-    {
-	lvItem.mask = 0;
-	if (doIcon) lvItem.mask |= LVIF_INDENT;
-	if (doLabel) lvItem.mask |= LVIF_TEXT;
-	lvItem.iItem = nItem;
-	lvItem.iSubItem = 0;
-    	lvItem.pszText = szDispText;
-    	lvItem.cchTextMax = DISP_TEXT_SIZE;
-	if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) return FALSE;
-    }
-
     /************************************************************/
     /* compute the box rectangle (it should be cheap to do)     */
     /************************************************************/
-    if (!LISTVIEW_GetItemListOrigin(infoPtr, nItem, &Position)) return FALSE;
-    if (!LISTVIEW_GetOrigin(infoPtr, &Origin)) return FALSE;
-    Box.left = Position.x + Origin.x;
-    Box.top = Position.y + Origin.y;
-    Box.right = Box.left + infoPtr->nItemWidth;
-    Box.bottom = Box.top + infoPtr->nItemHeight;
+    Box.left = 0;
+    Box.top = 0;
+    Box.right = infoPtr->nItemWidth;
+    Box.bottom = infoPtr->nItemHeight;
+
+    /************************************************************/
+    /* compute STATEICON bounding box                           */
+    /************************************************************/
+    if (doState)
+    {
+	if (uView == LVS_ICON)
+	{
+     	    State.left = Box.left - infoPtr->iconStateSize.cx + 10;
+	    if (infoPtr->himlNormal) 
+		State.left += (infoPtr->iconSpacing.cx - infoPtr->iconSize.cx) / 2 - ICON_LR_HALF;
+	    State.top  = Box.top + infoPtr->iconSize.cy - infoPtr->iconStateSize.cy + 4;
+	}
+	else
+	{
+	    /* we need the ident in report mode, if we don't have it, we fail */
+	    if (uView == LVS_REPORT && !(lpLVItem->mask & LVIF_INDENT)) return FALSE;
+	    State.left = Box.left;
+	    if (uView == LVS_REPORT) State.left += infoPtr->iconSize.cx * lpLVItem->iIndent;
+	    State.top  = Box.top;
+	}	
+	State.right    = State.left;
+	State.bottom   = State.top;
+	if (infoPtr->himlState)
+	{
+	    State.right  += infoPtr->iconStateSize.cx;
+	    State.bottom += infoPtr->iconStateSize.cy;
+	}
+	if (lprcState) *lprcState = State;
+	TRACE("    - state=%s\n", debugrect(&State));
+    }
 
     /************************************************************/
     /* compute ICON bounding box (ala LVM_GETITEMRECT)          */
@@ -1462,17 +1483,15 @@
 	}
 	else /* LVS_SMALLICON, LVS_LIST or LVS_REPORT */
 	{
-	    /* do indent */
-	    Icon.left = Box.left;
-	    if (uView == LVS_REPORT) Icon.left += infoPtr->iconSize.cx * lvItem.iIndent;
-	    if (infoPtr->himlState) Icon.left += infoPtr->iconStateSize.cx;
+	    Icon.left = State.right;
+	    if (infoPtr->himlState) Icon.left += IMAGE_PADDING;
 	    Icon.top    = Box.top;
 	    Icon.right  = Icon.left;
 	    if (infoPtr->himlSmall) Icon.right += infoPtr->iconSize.cx;
 	    Icon.bottom = Icon.top + infoPtr->nItemHeight;
 	}
 	if(lprcIcon) *lprcIcon = Icon;
-	TRACE("hwnd=%x, item=%d, icon=%s\n", infoPtr->hwndSelf, nItem, debugrect(&Icon));
+	TRACE("    - icon=%s\n", debugrect(&Icon));
      }
 
     /************************************************************/
@@ -1481,13 +1500,16 @@
     if (doLabel)
     {
 	SIZE labelSize = { 0, 0 };
+
+	/* we need the text in non owner draw mode */
+	if (!(infoPtr->dwStyle & LVS_OWNERDRAWFIXED) && !(lpLVItem->mask & LVIF_TEXT)) return FALSE;
 	
 	if (infoPtr->dwStyle & LVS_OWNERDRAWFIXED)
 	{
 	   labelSize.cx = infoPtr->nItemWidth;
 	   labelSize.cy = infoPtr->nItemHeight;
 	}
-	else if (is_textT(lvItem.pszText, TRUE))
+	else if (is_textT(lpLVItem->pszText, TRUE))
         {
     	    HFONT hFont = infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont;
     	    HDC hdc = GetDC(infoPtr->hwndSelf);
@@ -1508,7 +1530,7 @@
 	    else
 		uFormat = LV_SL_DT_FLAGS;
 	    
-    	    DrawTextW (hdc, lvItem.pszText, -1, &rcText, uFormat | DT_CALCRECT);
+    	    DrawTextW (hdc, lpLVItem->pszText, -1, &rcText, uFormat | DT_CALCRECT);
 
 	    labelSize.cx = min(rcText.right - rcText.left + TRAILING_PADDING, infoPtr->nItemWidth);
 	    labelSize.cy = rcText.bottom - rcText.top;
@@ -1540,15 +1562,15 @@
 	else /* LVS_SMALLICON, LVS_LIST or LVS_REPORT */
 	{
 	    Label.left = Icon.right;
+	    if (infoPtr->himlSmall) Label.left += IMAGE_PADDING;
 	    Label.top = Box.top;
 	    Label.right = Label.left + labelSize.cx;
-	    if (infoPtr->himlSmall) Label.right += IMAGE_PADDING;
 	    if (Label.right > Box.right) Label.right = Box.right;
 	    Label.bottom = Label.top + infoPtr->nItemHeight;
 	}
   
 	if (lprcLabel) *lprcLabel = Label;
-	TRACE("hwnd=%x, item=%d, label=%s\n", infoPtr->hwndSelf, nItem, debugrect(&Label));
+	TRACE("    - label=%s\n", debugrect(&Label));
     }
 
     /***********************************************************/
@@ -1566,12 +1588,87 @@
         }
         else
 	    UnionRect(lprcBounds, &Icon, &Label);
-        TRACE("hwnd=%x, item=%d, bounds=%s\n", infoPtr->hwndSelf, nItem, debugrect(lprcBounds));
+        TRACE("    - bounds=%s\n", debugrect(lprcBounds));
     }
     
     if (oversizedBox) UnionRect(lprcBox, &Box, &Label);
     else if (lprcBox) *lprcBox = Box; 
-    TRACE("hwnd=%x, item=%d, box=%s\n", infoPtr->hwndSelf, nItem, debugrect(&Box));
+    TRACE("    - box=%s\n", debugrect(&Box));
+
+    return TRUE;
+}
+
+/***
+ * DESCRIPTION:            [INTERNAL]
+ *
+ * PARAMETER(S):
+ * [I] infoPtr : valid pointer to the listview structure
+ * [I] nItem : item number
+ * [O] lprcBox : ptr to Box rectangle
+ *                The internal LVIR_BOX rectangle
+ * [O] lprcBounds : ptr to Bounds rectangle
+ *                Same as LVM_GETITEMRECT with LVIR_BOUNDS
+ * [O] lprcIcon : ptr to Icon rectangle
+ *                Same as LVM_GETITEMRECT with LVIR_ICON
+ * [O] lprcLabel : ptr to Label rectangle
+ *                Same as LVM_GETITEMRECT with LVIR_LABEL
+ *
+ * RETURN:
+ *   TRUE if computations OK
+ *   FALSE otherwise
+ */
+static BOOL LISTVIEW_GetItemMeasures(LISTVIEW_INFO *infoPtr, INT nItem,
+				    LPRECT lprcBox, LPRECT lprcBounds,
+				    LPRECT lprcIcon, LPRECT lprcLabel)
+{
+    UINT uView = infoPtr->dwStyle & LVS_TYPEMASK;
+    WCHAR szDispText[DISP_TEXT_SIZE] = { '\0' };
+    BOOL doIcon = FALSE, doLabel = FALSE, oversizedBox = FALSE;
+    POINT Position, Origin;
+    LVITEMW lvItem;
+
+    if (!LISTVIEW_GetItemListOrigin(infoPtr, nItem, &Position)) return FALSE;
+    if (!LISTVIEW_GetOrigin(infoPtr, &Origin)) return FALSE;
+
+    /* Be smart and try to figure out the minimum we have to do */
+    if (lprcBounds)
+    {
+	if (uView == LVS_REPORT) doIcon = TRUE;
+        else doLabel = TRUE;
+    }
+    if (uView == LVS_ICON && (lprcBox || lprcBounds || lprcLabel) &&
+	infoPtr->bFocus && !(infoPtr->dwStyle & LVS_OWNERDRAWFIXED) &&
+	LISTVIEW_GetItemState(infoPtr, nItem, LVIS_FOCUSED))
+	oversizedBox = doLabel = TRUE;
+    if (lprcLabel) doLabel = TRUE;
+    if (doLabel || lprcIcon) doIcon = TRUE;
+
+    /* get what we need from the item before hand, so we make
+     * only one request. This can speed up things, if data
+     * is stored on the app side */
+    lvItem.mask = 0;
+    if (doIcon && uView == LVS_REPORT) lvItem.mask |= LVIF_INDENT;
+    if (doLabel) lvItem.mask |= LVIF_TEXT;
+    lvItem.iItem = nItem;
+    lvItem.iSubItem = 0;
+    lvItem.pszText = szDispText;
+    lvItem.cchTextMax = DISP_TEXT_SIZE;
+    if (lvItem.mask && !LISTVIEW_GetItemW(infoPtr, &lvItem)) return FALSE;
+    if (uView == LVS_ICON && (lprcBox || lprcBounds || lprcLabel))
+    {
+	lvItem.mask |= LVIF_STATE;
+	lvItem.stateMask = LVIS_FOCUSED;
+	lvItem.state = (oversizedBox ? LVIS_FOCUSED : 0);
+    }
+    if (!LISTVIEW_GetItemMetrics(infoPtr, &lvItem, lprcBox, lprcBounds, 0, lprcIcon, lprcLabel)) return FALSE;
+
+    Position.x += Origin.x;
+    Position.y += Origin.y;
+
+    if (lprcBox) OffsetRect(lprcBox, Position.x, Position.y);
+    if (lprcBounds) OffsetRect(lprcBounds, Position.x, Position.y);
+    if (lprcIcon) OffsetRect(lprcIcon, Position.x, Position.y);
+    if (lprcLabel) OffsetRect(lprcLabel, Position.x, Position.y);
 
     return TRUE;
 }
@@ -2131,6 +2228,7 @@
 
     return TRUE;
 }
+
 /***
  * Helper function for LISTVIEW_AddSelectionRange, and LISTVIEW_SetItem.
  */






More information about the wine-patches mailing list