Add wxHtmlContainerCell::Detach()

This allows manipulating the HTML DOM from the outside, e.g. to detach
a header element in order to be able to repeat it on all pages.
This commit is contained in:
Vadim Zeitlin
2018-08-25 21:16:55 +02:00
parent 2895e5c4a1
commit a59f5932df
4 changed files with 116 additions and 0 deletions

View File

@@ -459,6 +459,11 @@ public:
// insert cell at the end of m_Cells list // insert cell at the end of m_Cells list
void InsertCell(wxHtmlCell *cell); void InsertCell(wxHtmlCell *cell);
// Detach a child cell. After calling this method, it's the caller
// responsibility to destroy this cell (possibly by calling InsertCell()
// with it to attach it elsewhere).
void Detach(wxHtmlCell *cell);
// sets horizontal/vertical alignment // sets horizontal/vertical alignment
void SetAlignHor(int al) {m_AlignHor = al; m_LastLayout = -1;} void SetAlignHor(int al) {m_AlignHor = al; m_LastLayout = -1;}
int GetAlignHor() const {return m_AlignHor;} int GetAlignHor() const {return m_AlignHor;}

View File

@@ -473,6 +473,20 @@ public:
*/ */
wxHtmlContainerCell(wxHtmlContainerCell* parent); wxHtmlContainerCell(wxHtmlContainerCell* parent);
/**
Detach a child cell.
Detaching a cell removes it from this container and allows to reattach
it to another one by using InsertCell(). Alternatively, this method can
be used to selectively remove some elements of the HTML document tree
by deleting the cell after calling it.
@param cell Must be non-null and an immediate child of this cell.
@since 3.1.2
*/
void Detach(wxHtmlCell* cell);
/** /**
Returns container's horizontal alignment. Returns container's horizontal alignment.
*/ */

View File

@@ -1159,6 +1159,43 @@ void wxHtmlContainerCell::InsertCell(wxHtmlCell *f)
void wxHtmlContainerCell::Detach(wxHtmlCell *cell)
{
wxHtmlCell* const firstChild = GetFirstChild();
if ( cell == firstChild )
{
m_Cells = cell->GetNext();
if ( m_LastCell == cell )
m_LastCell = NULL;
}
else // Not the first child.
{
for ( wxHtmlCell* prev = firstChild;; )
{
wxHtmlCell* const next = prev->GetNext();
// We can't reach the end of the children list without finding this
// cell, normally.
wxCHECK_RET( next, "Detaching cell which is not our child" );
if ( cell == next )
{
prev->SetNext(cell->GetNext());
if ( m_LastCell == cell )
m_LastCell = prev;
break;
}
prev = next;
}
}
cell->SetParent(NULL);
cell->SetNext(NULL);
}
void wxHtmlContainerCell::SetAlign(const wxHtmlTag& tag) void wxHtmlContainerCell::SetAlign(const wxHtmlTag& tag)
{ {
wxString alg; wxString alg;

View File

@@ -46,4 +46,64 @@ TEST_CASE("wxHtmlParser::ParseInvalid", "[html][parser][error]")
p.Parse("<!---"); p.Parse("<!---");
} }
TEST_CASE("wxHtmlCell::Detach", "[html][cell]")
{
wxMemoryDC dc;
wxHtmlContainerCell* const top = new wxHtmlContainerCell(NULL);
wxHtmlContainerCell* const cont = new wxHtmlContainerCell(NULL);
wxHtmlCell* const cell1 = new wxHtmlWordCell("Hello", dc);
wxHtmlCell* const cell2 = new wxHtmlColourCell(*wxRED);
wxHtmlCell* const cell3 = new wxHtmlWordCell("world", dc);
cont->InsertCell(cell1);
cont->InsertCell(cell2);
cont->InsertCell(cell3);
top->InsertCell(cont);
SECTION("container")
{
top->Detach(cont);
CHECK( top->GetFirstChild() == NULL );
delete cont;
}
SECTION("first-child")
{
cont->Detach(cell1);
CHECK( cont->GetFirstChild() == cell2 );
delete cell1;
}
SECTION("middle-child")
{
cont->Detach(cell2);
CHECK( cont->GetFirstChild() == cell1 );
CHECK( cell1->GetNext() == cell3 );
delete cell2;
}
SECTION("last-child")
{
cont->Detach(cell3);
CHECK( cont->GetFirstChild() == cell1 );
CHECK( cell1->GetNext() == cell2 );
CHECK( cell2->GetNext() == NULL );
delete cell3;
}
SECTION("invalid")
{
WX_ASSERT_FAILS_WITH_ASSERT_MESSAGE
(
"Expected assertion for detaching non-child",
top->Detach(cell1);
);
}
}
#endif //wxUSE_HTML #endif //wxUSE_HTML