void wxHtmlListCell::Layout(int w) { wxHtmlCell::Layout(w); ComputeMinMaxWidths(); m_Width = wxMax(m_Width, wxMin(w, GetMaxTotalWidth())); int s_width = m_Width - m_IndentLeft; int vpos = 0; for (int r = 0; r < m_NumRows; r++) { // do layout first time to layout contents and adjust pos m_RowInfo[r].mark->Layout(m_ListmarkWidth); m_RowInfo[r].cont->Layout(s_width - m_ListmarkWidth); const int base_mark = ComputeMaxBase( m_RowInfo[r].mark ); const int base_cont = ComputeMaxBase( m_RowInfo[r].cont ); const int adjust_mark = vpos + wxMax(base_cont-base_mark,0); const int adjust_cont = vpos + wxMax(base_mark-base_cont,0); m_RowInfo[r].mark->SetPos(m_IndentLeft, adjust_mark); m_RowInfo[r].cont->SetPos(m_IndentLeft + m_ListmarkWidth, adjust_cont); vpos = wxMax(adjust_mark + m_RowInfo[r].mark->GetHeight(), adjust_cont + m_RowInfo[r].cont->GetHeight()); } m_Height = vpos; }
void wxHtmlTableCell::Layout(int w) { ComputeMinMaxWidths(); wxHtmlCell::Layout(w); /* WIDTH ADJUSTING : */ if (m_WidthFloatUnits == wxHTML_UNITS_PERCENT) { if (m_WidthFloat < 0) { if (m_WidthFloat < -100) m_WidthFloat = -100; m_Width = (100 + m_WidthFloat) * w / 100; } else { if (m_WidthFloat > 100) m_WidthFloat = 100; m_Width = m_WidthFloat * w / 100; } } else { if (m_WidthFloat < 0) m_Width = w + m_WidthFloat; else m_Width = m_WidthFloat; } /* LAYOUT : */ /* 1. setup columns widths: The algorithm tries to keep the table size less than w if possible. */ { int wpix = m_Width - (m_NumCols + 1) * m_Spacing - 2 * m_Border; // Available space for cell content int i, j; // 1a. setup fixed-width columns: for (i = 0; i < m_NumCols; i++) if (m_ColsInfo[i].units == wxHTML_UNITS_PIXELS) { m_ColsInfo[i].pixwidth = wxMax(m_ColsInfo[i].width, m_ColsInfo[i].minWidth); wpix -= m_ColsInfo[i].pixwidth; } // 1b. Calculate maximum possible width if line wrapping would be disabled // Recalculate total width if m_WidthFloat is zero to keep tables as small // as possible. int maxWidth = 0; for (i = 0; i < m_NumCols; i++) if (m_ColsInfo[i].width == 0) { maxWidth += m_ColsInfo[i].maxWidth; } if (!m_WidthFloat) { // Recalculate table width since no table width was initially given int newWidth = m_Width - wpix + maxWidth; // Make sure that floating-width columns will have the right size. // Calculate sum of all floating-width columns int percentage = 0; for (i = 0; i < m_NumCols; i++) if ((m_ColsInfo[i].units == wxHTML_UNITS_PERCENT) && (m_ColsInfo[i].width != 0)) percentage += m_ColsInfo[i].width; if (percentage >= 100) newWidth = w; else newWidth = newWidth * 100 / (100 - percentage); newWidth = wxMin(newWidth, w - (m_NumCols + 1) * m_Spacing - 2 * m_Border); wpix -= m_Width - newWidth; m_Width = newWidth; } // 1c. setup floating-width columns: int wtemp = wpix; for (i = 0; i < m_NumCols; i++) if ((m_ColsInfo[i].units == wxHTML_UNITS_PERCENT) && (m_ColsInfo[i].width != 0)) { m_ColsInfo[i].pixwidth = wxMin(m_ColsInfo[i].width, 100) * wpix / 100; // Make sure to leave enough space for the other columns int minRequired = m_Border; for (j = 0; j < m_NumCols; j++) { if ((m_ColsInfo[j].units == wxHTML_UNITS_PERCENT && j > i) || !m_ColsInfo[j].width) minRequired += m_ColsInfo[j].minWidth; } m_ColsInfo[i].pixwidth = wxMax(wxMin(wtemp - minRequired, m_ColsInfo[i].pixwidth), m_ColsInfo[i].minWidth); wtemp -= m_ColsInfo[i].pixwidth; } wpix = wtemp; // minimum cells width // 1d. setup default columns (no width specification supplied): // The algorithm assigns calculates the maximum possible width if line // wrapping would be disabled and assigns column width as a fraction // based upon the maximum width of a column // FIXME: I'm not sure if this algorithm is conform to HTML standard, // though it seems to be much better than the old one for (i = j = 0; i < m_NumCols; i++) if (m_ColsInfo[i].width == 0) j++; if (wpix < m_Border) wpix = m_Border; // Assign widths for (i = 0; i < m_NumCols; i++) if (m_ColsInfo[i].width == 0) { // Assign with, make sure not to drop below minWidth if (maxWidth) m_ColsInfo[i].pixwidth = (int)(wpix * (m_ColsInfo[i].maxWidth / (float)maxWidth) + 0.5); else m_ColsInfo[i].pixwidth = wpix / j; // Make sure to leave enough space for the other columns int minRequired = 0; int r; for (r = i + 1; r < m_NumCols; r++) { if (!m_ColsInfo[r].width) minRequired += m_ColsInfo[r].minWidth; } m_ColsInfo[i].pixwidth = wxMax(wxMin(wpix - minRequired, m_ColsInfo[i].pixwidth), m_ColsInfo[i].minWidth); if (maxWidth) { if (m_ColsInfo[i].pixwidth > (wpix * (m_ColsInfo[i].maxWidth / (float)maxWidth) + 0.5)) { int diff = (int)(m_ColsInfo[i].pixwidth - (wpix * m_ColsInfo[i].maxWidth / (float)maxWidth + 0.5)); maxWidth += diff - m_ColsInfo[i].maxWidth; } else maxWidth -= m_ColsInfo[i].maxWidth; } wpix -= m_ColsInfo[i].pixwidth; } } /* 2. compute positions of columns: */ { int wpos = m_Spacing + m_Border; for (int i = 0; i < m_NumCols; i++) { m_ColsInfo[i].leftpos = wpos; wpos += m_ColsInfo[i].pixwidth + m_Spacing; } // add the remaining space to the last column if (m_NumCols > 0 && wpos < m_Width - m_Border) m_ColsInfo[m_NumCols-1].pixwidth += m_Width - wpos - m_Border; } /* 3. sub-layout all cells: */ { int *ypos = new int[m_NumRows + 1]; int actcol, actrow; int fullwid; wxHtmlContainerCell *actcell; ypos[0] = m_Spacing + m_Border; for (actrow = 1; actrow <= m_NumRows; actrow++) ypos[actrow] = -1; for (actrow = 0; actrow < m_NumRows; actrow++) { if (ypos[actrow] == -1) ypos[actrow] = ypos[actrow-1]; // 3a. sub-layout and detect max height: for (actcol = 0; actcol < m_NumCols; actcol++) { if (m_CellInfo[actrow][actcol].flag != cellUsed) continue; actcell = m_CellInfo[actrow][actcol].cont; fullwid = 0; for (int i = actcol; i < m_CellInfo[actrow][actcol].colspan + actcol; i++) fullwid += m_ColsInfo[i].pixwidth; fullwid += (m_CellInfo[actrow][actcol].colspan - 1) * m_Spacing; actcell->SetMinHeight(m_CellInfo[actrow][actcol].minheight, m_CellInfo[actrow][actcol].valign); actcell->Layout(fullwid); if (ypos[actrow] + actcell->GetHeight() + m_CellInfo[actrow][actcol].rowspan * m_Spacing > ypos[actrow + m_CellInfo[actrow][actcol].rowspan]) ypos[actrow + m_CellInfo[actrow][actcol].rowspan] = ypos[actrow] + actcell->GetHeight() + m_CellInfo[actrow][actcol].rowspan * m_Spacing; } } for (actrow = 0; actrow < m_NumRows; actrow++) { // 3b. place cells in row & let'em all have same height: for (actcol = 0; actcol < m_NumCols; actcol++) { if (m_CellInfo[actrow][actcol].flag != cellUsed) continue; actcell = m_CellInfo[actrow][actcol].cont; actcell->SetMinHeight( ypos[actrow + m_CellInfo[actrow][actcol].rowspan] - ypos[actrow] - m_Spacing, m_CellInfo[actrow][actcol].valign); fullwid = 0; for (int i = actcol; i < m_CellInfo[actrow][actcol].colspan + actcol; i++) fullwid += m_ColsInfo[i].pixwidth; fullwid += (m_CellInfo[actrow][actcol].colspan - 1) * m_Spacing; actcell->Layout(fullwid); actcell->SetPos(m_ColsInfo[actcol].leftpos, ypos[actrow]); } } m_Height = ypos[m_NumRows] + m_Border; delete[] ypos; } /* 4. adjust table's width if it was too small: */ if (m_NumCols > 0) { int twidth = m_ColsInfo[m_NumCols-1].leftpos + m_ColsInfo[m_NumCols-1].pixwidth + m_Spacing + m_Border; if (twidth > m_Width) m_Width = twidth; } }