//////////////////
// Calculate size/positions for a row or column group This is the main
// algorithm. If a window is given, it's used to get the min/max size and
// desired size for TOFIT types.
//
void CWinMgr::CalcGroup(WINRECT* pGroup, CWnd* pWnd) {
	// If this bombs, most likely the first entry in your map is not a group!
	ASSERT(pGroup && pGroup->IsGroup());
	ASSERT(pWnd);

	// adjust total avail by margins
	CRect rcTotal = pGroup->GetRect();
	int w,h;
	if (pGroup->GetMargins(w,h)) {
		w = min(abs(w), rcTotal.Width()/2);
		h = min(abs(h), rcTotal.Height()/2);
		rcTotal.DeflateRect(w,h);
	}
	
	BOOL bRow = pGroup->IsRowGroup();		 // Is this a row group?

	// Running height or width: start with total
	int hwRemaining = bRow ? rcTotal.Height() : rcTotal.Width();

	// First, set all rects to their minimum sizes.
	// This ensures that each rect gets its min size.
	CWinGroupIterator it;
	for (it=pGroup; it; it.Next()) {
		WINRECT* wrc = it;
		SIZEINFO szi;
		OnGetSizeInfo(szi, wrc, pWnd);
		int hwMin = bRow ? szi.szMin.cy : szi.szMin.cx;
		hwMin = min(hwMin, hwRemaining);		// truncate
		wrc->SetHeightOrWidth(hwMin, bRow);	// set
		hwRemaining -= hwMin;					// decrement remaining height/width
		ASSERT(hwRemaining>=0);
	}

	// Now adjust all rects upward to desired size. Save REST rect for last.
	WINRECT* pRestRect = NULL;
	for (it=pGroup; it; it.Next()) {
		WINRECT* wrc = it;
		if (wrc->Type()==WRCT_REST) {
			ASSERT(pRestRect==NULL);		 // can only be one REST rect!
			pRestRect = wrc;					 // remember it
		} else {
			AdjustSize(wrc, bRow, hwRemaining, pWnd);
		}
	}
	ASSERT(hwRemaining>=0);

	// Adjust REST rect if any
	if (pRestRect) {
		AdjustSize(pRestRect, bRow, hwRemaining, pWnd);
		ASSERT(hwRemaining==0);
	}

	// All the sizes of the entries have been calculated, including
	// groups (but not their children). Now move all the rects so they're
	// adjacent to one another, without altering sizes.
	PositionRects(pGroup, rcTotal, bRow);

	// Finally, descend recursively into each subgroup.
	for (it=pGroup; it; it.Next()) {
		WINRECT* wrc = it;
		if (wrc->IsGroup())
			CalcGroup(wrc, pWnd); // recurse!
	}
}