m_tables.cpp

来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 764 行 · 第 1/2 页

CPP
764
字号
        else if ((m_ColsInfo[c].units == wxHTML_UNITS_PERCENT) && (m_ColsInfo[c].width != 0))
            percentage += m_ColsInfo[c].width;
        else
            m_MaxTotalWidth += m_ColsInfo[c].maxWidth;
    }

    if (percentage >= 100)
    {
        // Table would have infinite length
        // Make it ridiculous large
        m_MaxTotalWidth = 0xFFFFFF;
    }
    else
        m_MaxTotalWidth = m_MaxTotalWidth * 100 / (100 - percentage);

    m_MaxTotalWidth += (m_NumCols + 1) * m_Spacing;
}

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;
    }


    /*

    LAYOUTING :

    */

    /* 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;
        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);
            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 = 0;
                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;

        // 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 < 0)
            wpix = 0;

        // 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;
        for (int i = 0; i < m_NumCols; i++)
        {
            m_ColsInfo[i].leftpos = wpos;
            wpos += m_ColsInfo[i].pixwidth + m_Spacing;
        }
    }

    /* 3.  sub-layout all cells: */
    {
        int *ypos = new int[m_NumRows + 1];

        int actcol, actrow;
        int fullwid;
        wxHtmlContainerCell *actcell;

        ypos[0] = m_Spacing;
        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];
        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;
        if (twidth > m_Width)
            m_Width = twidth;
    }
}






//-----------------------------------------------------------------------------
// The tables handler:
//-----------------------------------------------------------------------------


TAG_HANDLER_BEGIN(TABLE, "TABLE,TR,TD,TH")

    TAG_HANDLER_VARS
        wxHtmlTableCell* m_Table;
        wxString m_tAlign, m_rAlign;

    TAG_HANDLER_CONSTR(TABLE)
    {
        m_Table = NULL;
        m_tAlign = m_rAlign = wxEmptyString;
    }


    TAG_HANDLER_PROC(tag)
    {
        wxHtmlContainerCell *c;

        // new table started, backup upper-level table (if any) and create new:
        if (tag.GetName() == wxT("TABLE"))
        {
            wxHtmlTableCell *oldt = m_Table;
            wxHtmlContainerCell *oldcont;

            oldcont = c = m_WParser->OpenContainer();

            m_Table = new wxHtmlTableCell(c, tag);

            // width:
            {
                if (tag.HasParam(wxT("WIDTH")))
                {
                    wxString wd = tag.GetParam(wxT("WIDTH"));

                    if (wd[wd.Length()-1] == wxT('%'))
                    {
                        int width = 0;
                        wxSscanf(wd.c_str(), wxT("%i%%"), &width);
                        m_Table->SetWidthFloat(width, wxHTML_UNITS_PERCENT);
                    }
                    else
                    {
                        int width = 0;
                        wxSscanf(wd.c_str(), wxT("%i"), &width);
                        m_Table->SetWidthFloat((int)(m_WParser->GetPixelScale() * width), wxHTML_UNITS_PIXELS);
                    }
                }
                else
                    m_Table->SetWidthFloat(0, wxHTML_UNITS_PIXELS);
            }
            int oldAlign = m_WParser->GetAlign();
            m_tAlign = wxEmptyString;
            if (tag.HasParam(wxT("ALIGN")))
                m_tAlign = tag.GetParam(wxT("ALIGN"));

            ParseInner(tag);

            m_WParser->SetAlign(oldAlign);
            m_WParser->SetContainer(oldcont);
            m_WParser->CloseContainer();

            m_Table = oldt;
            return true;
        }


        else if (m_Table)
        {
            // new row in table
            if (tag.GetName() == wxT("TR"))
            {
                m_Table->AddRow(tag);
                m_rAlign = m_tAlign;
                if (tag.HasParam(wxT("ALIGN")))
                    m_rAlign = tag.GetParam(wxT("ALIGN"));
            }

            // new cell
            else
            {
                c = m_WParser->SetContainer(new wxHtmlContainerCell(m_Table));
                m_Table->AddCell(c, tag);

                m_WParser->OpenContainer();

                if (tag.GetName() == wxT("TH")) /*header style*/
                    m_WParser->SetAlign(wxHTML_ALIGN_CENTER);
                else
                    m_WParser->SetAlign(wxHTML_ALIGN_LEFT);

                wxString als;

                als = m_rAlign;
                if (tag.HasParam(wxT("ALIGN")))
                    als = tag.GetParam(wxT("ALIGN"));
                als.MakeUpper();
                if (als == wxT("RIGHT"))
                    m_WParser->SetAlign(wxHTML_ALIGN_RIGHT);
                else if (als == wxT("LEFT"))
                    m_WParser->SetAlign(wxHTML_ALIGN_LEFT);
                else if (als == wxT("CENTER"))
                    m_WParser->SetAlign(wxHTML_ALIGN_CENTER);

                m_WParser->OpenContainer();
            }
        }
        return false;
    }

TAG_HANDLER_END(TABLE)





TAGS_MODULE_BEGIN(Tables)

    TAGS_MODULE_ADD(TABLE)

TAGS_MODULE_END(Tables)


#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?