////////////////// // 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! } }