/////////////////////////////////////////////////////////////////////////////
-// Name: m_list.cpp
+// Name: src/html/m_list.cpp
// Purpose: wxHtml module for lists
// Author: Vaclav Slavik
// RCS-ID: $Id$
// Copyright: (c) 1999 Vaclav Slavik
-// Licence: wxWindows Licence
+// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
-#ifdef __GNUG__
-#pragma implementation
-#endif
#include "wx/wxprec.h"
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
-#include "wx/defs.h"
#if wxUSE_HTML && wxUSE_STREAMS
-#ifdef __BORDLANDC__
-#pragma hdrstop
+#ifndef WX_PRECOMP
+ #include "wx/brush.h"
+ #include "wx/dc.h"
#endif
-#ifndef WXPRECOMP
-#include "wx/wx.h"
-#endif
-
-
#include "wx/html/forcelnk.h"
#include "wx/html/m_templ.h"
wxBrush m_Brush;
public:
wxHtmlListmarkCell(wxDC *dc, const wxColour& clr);
- void Draw(wxDC& dc, int x, int y, int view_y1, int view_y2);
+ void Draw(wxDC& dc, int x, int y, int view_y1, int view_y2,
+ wxHtmlRenderingInfo& info);
+
+ wxDECLARE_NO_COPY_CLASS(wxHtmlListmarkCell);
};
-wxHtmlListmarkCell::wxHtmlListmarkCell(wxDC* dc, const wxColour& clr) : wxHtmlCell(), m_Brush(clr, wxSOLID)
+wxHtmlListmarkCell::wxHtmlListmarkCell(wxDC* dc, const wxColour& clr) : wxHtmlCell(), m_Brush(clr, wxBRUSHSTYLE_SOLID)
{
- m_Width = dc->GetCharWidth();
+ m_Width = dc->GetCharHeight();
m_Height = dc->GetCharHeight();
- m_Descent = 0;
+ // bottom of list mark is lined with bottom of letters in next cell
+ m_Descent = m_Height / 3;
}
-void wxHtmlListmarkCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2)
+void wxHtmlListmarkCell::Draw(wxDC& dc, int x, int y,
+ int WXUNUSED(view_y1), int WXUNUSED(view_y2),
+ wxHtmlRenderingInfo& WXUNUSED(info))
{
dc.SetBrush(m_Brush);
- dc.DrawEllipse(x + m_PosX + m_Width / 4, y + m_PosY + m_Height / 4, m_Width / 2, m_Width / 2);
- wxHtmlCell::Draw(dc, x, y, view_y1, view_y2);
+ dc.DrawEllipse(x + m_PosX + m_Width / 3, y + m_PosY + m_Height / 3,
+ (m_Width / 3), (m_Width / 3));
+}
+
+//-----------------------------------------------------------------------------
+// wxHtmlListCell
+//-----------------------------------------------------------------------------
+
+struct wxHtmlListItemStruct
+{
+ wxHtmlContainerCell *mark;
+ wxHtmlContainerCell *cont;
+ int minWidth;
+ int maxWidth;
+};
+
+class wxHtmlListCell : public wxHtmlContainerCell
+{
+ private:
+ wxBrush m_Brush;
+
+ int m_NumRows;
+ wxHtmlListItemStruct *m_RowInfo;
+ void ReallocRows(int rows);
+ void ComputeMinMaxWidths();
+ int ComputeMaxBase(wxHtmlCell *cell);
+ int m_ListmarkWidth;
+
+ public:
+ wxHtmlListCell(wxHtmlContainerCell *parent);
+ virtual ~wxHtmlListCell();
+ void AddRow(wxHtmlContainerCell *mark, wxHtmlContainerCell *cont);
+ virtual void Layout(int w);
+
+ wxDECLARE_NO_COPY_CLASS(wxHtmlListCell);
+};
+
+wxHtmlListCell::wxHtmlListCell(wxHtmlContainerCell *parent) : wxHtmlContainerCell(parent)
+{
+ m_NumRows = 0;
+ m_RowInfo = 0;
+ m_ListmarkWidth = 0;
+}
+
+wxHtmlListCell::~wxHtmlListCell()
+{
+ if (m_RowInfo) free(m_RowInfo);
+}
+
+int wxHtmlListCell::ComputeMaxBase(wxHtmlCell *cell)
+{
+ if(!cell)
+ return 0;
+
+ wxHtmlCell *child = cell->GetFirstChild();
+
+ while(child)
+ {
+ int base = ComputeMaxBase( child );
+ if ( base > 0 ) return base + child->GetPosY();
+ child = child->GetNext();
+ }
+
+ return cell->GetHeight() - cell->GetDescent();
+}
+
+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 wxHtmlListCell::AddRow(wxHtmlContainerCell *mark, wxHtmlContainerCell *cont)
+{
+ ReallocRows(++m_NumRows);
+ m_RowInfo[m_NumRows - 1].mark = mark;
+ m_RowInfo[m_NumRows - 1].cont = cont;
+}
+
+void wxHtmlListCell::ReallocRows(int rows)
+{
+ m_RowInfo = (wxHtmlListItemStruct*) realloc(m_RowInfo, sizeof(wxHtmlListItemStruct) * rows);
+ m_RowInfo[rows - 1].mark = NULL;
+ m_RowInfo[rows - 1].cont = NULL;
+ m_RowInfo[rows - 1].minWidth = 0;
+ m_RowInfo[rows - 1].maxWidth = 0;
+
+ m_NumRows = rows;
+}
+
+void wxHtmlListCell::ComputeMinMaxWidths()
+{
+ if (m_NumRows == 0) return;
+
+ m_MaxTotalWidth = 0;
+ m_Width = 0;
+
+ for (int r = 0; r < m_NumRows; r++)
+ {
+ wxHtmlListItemStruct& row = m_RowInfo[r];
+ row.mark->Layout(1);
+ row.cont->Layout(1);
+ int maxWidth = row.cont->GetMaxTotalWidth();
+ int width = row.cont->GetWidth();
+ if (row.mark->GetWidth() > m_ListmarkWidth)
+ m_ListmarkWidth = row.mark->GetWidth();
+ if (maxWidth > m_MaxTotalWidth)
+ m_MaxTotalWidth = maxWidth;
+ if (width > m_Width)
+ m_Width = width;
+ }
+ m_Width += m_ListmarkWidth + m_IndentLeft;
+ m_MaxTotalWidth += m_ListmarkWidth + m_IndentLeft;
+}
+//-----------------------------------------------------------------------------
+// wxHtmlListcontentCell
+//-----------------------------------------------------------------------------
+class wxHtmlListcontentCell : public wxHtmlContainerCell
+{
+public:
+ wxHtmlListcontentCell(wxHtmlContainerCell *p) : wxHtmlContainerCell(p) {}
+ virtual void Layout(int w) {
+ // Reset top indentation, fixes <li><p>
+ SetIndent(0, wxHTML_INDENT_TOP);
+ wxHtmlContainerCell::Layout(w);
+ }
+};
//-----------------------------------------------------------------------------
// The list handler:
TAG_HANDLER_BEGIN(OLULLI, "OL,UL,LI")
TAG_HANDLER_VARS
+ wxHtmlListCell *m_List;
int m_Numbering;
// this is number of actual item of list or 0 for dots
TAG_HANDLER_CONSTR(OLULLI)
{
+ m_List = NULL;
m_Numbering = 0;
}
wxHtmlContainerCell *c;
// List Item:
- if (tag.GetName() == wxT("LI"))
- {
- if (!tag.IsEnding())
- {
- m_WParser->GetContainer()->SetIndent(0, wxHTML_INDENT_TOP);
- // this is to prevent indetation in <li><p> case
- m_WParser->CloseContainer();
- m_WParser->CloseContainer();
-
- c = m_WParser->OpenContainer();
- c->SetWidthFloat(2 * m_WParser->GetCharWidth(), wxHTML_UNITS_PIXELS);
+ if (m_List && tag.GetName() == wxT("LI"))
+ {
+ c = m_WParser->SetContainer(new wxHtmlContainerCell(m_List));
+ c->SetAlignVer(wxHTML_ALIGN_TOP);
+
+ wxHtmlContainerCell *mark = c;
+ c->SetWidthFloat(2 * m_WParser->GetCharWidth(), wxHTML_UNITS_PIXELS);
+ if (m_Numbering == 0)
+ {
+ // Centering gives more space after the bullet
+ c->SetAlignHor(wxHTML_ALIGN_CENTER);
+ c->InsertCell(new wxHtmlListmarkCell(m_WParser->GetDC(), m_WParser->GetActualColor()));
+ }
+ else
+ {
c->SetAlignHor(wxHTML_ALIGN_RIGHT);
- if (m_Numbering == 0)
- c->InsertCell(new wxHtmlListmarkCell(m_WParser->GetDC(), m_WParser->GetActualColor()));
- else
- {
- wxString mark;
- mark.Printf(wxT("%i."), m_Numbering);
- c->InsertCell(new wxHtmlWordCell(mark, *(m_WParser->GetDC())));
- }
- m_WParser->CloseContainer();
-
- c = m_WParser->OpenContainer();
- c->SetIndent(m_WParser->GetCharWidth() / 4, wxHTML_INDENT_LEFT);
- c->SetWidthFloat(-2 * m_WParser->GetCharWidth(), wxHTML_UNITS_PIXELS);
-
- m_WParser->OpenContainer();
-
- if (m_Numbering != 0) m_Numbering++;
+ wxString markStr;
+ markStr.Printf(wxT("%i. "), m_Numbering);
+ c->InsertCell(new wxHtmlWordCell(markStr, *(m_WParser->GetDC())));
}
- return FALSE;
+ m_WParser->CloseContainer();
+
+ c = m_WParser->OpenContainer();
+
+ m_List->AddRow(mark, c);
+ c = m_WParser->OpenContainer();
+ m_WParser->SetContainer(new wxHtmlListcontentCell(c));
+
+ if (m_Numbering != 0) m_Numbering++;
}
// Begin of List (not-numbered): "UL", "OL"
- else
- {
+ else if (tag.GetName() == wxT("UL") || tag.GetName() == wxT("OL"))
+ {
int oldnum = m_Numbering;
if (tag.GetName() == wxT("UL")) m_Numbering = 0;
else m_Numbering = 1;
- c = m_WParser->GetContainer();
- if (c->GetFirstCell() != NULL)
- {
- m_WParser->CloseContainer();
- m_WParser->OpenContainer();
- c = m_WParser->GetContainer();
- }
- c->SetAlignHor(wxHTML_ALIGN_LEFT);
- c->SetIndent(2 * m_WParser->GetCharWidth(), wxHTML_INDENT_LEFT);
- m_WParser->OpenContainer()->SetAlignVer(wxHTML_ALIGN_TOP);
+ wxHtmlContainerCell *oldcont;
+ oldcont = c = m_WParser->OpenContainer();
- m_WParser->OpenContainer();
- m_WParser->OpenContainer();
- ParseInner(tag);
+ wxHtmlListCell *oldList = m_List;
+ m_List = new wxHtmlListCell(c);
+ m_List->SetIndent(2 * m_WParser->GetCharWidth(), wxHTML_INDENT_LEFT);
- m_WParser->GetContainer()->SetIndent(0, wxHTML_INDENT_TOP);
- // this is to prevent indetation in <li><p> case
- m_WParser->CloseContainer();
+ ParseInner(tag);
+ m_WParser->SetContainer(oldcont);
m_WParser->CloseContainer();
- m_WParser->CloseContainer();
- m_WParser->CloseContainer();
- m_WParser->OpenContainer();
m_Numbering = oldnum;
- return TRUE;
+ m_List = oldList;
+ return true;
}
+ return false;
+
}
TAG_HANDLER_END(OLULLI)