Files
wx_wherigo/libs/wxWidgets-3.3.1/tests/controls/auitest.cpp
2026-02-14 09:47:24 +01:00

361 lines
10 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/auitest.cpp
// Purpose: wxAui control tests
// Author: Sebastian Walderich
// Created: 2018-12-19
// Copyright: (c) 2018 Sebastian Walderich
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "testprec.h"
#if wxUSE_AUI
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "wx/panel.h"
#include "wx/aui/auibar.h"
#include "wx/aui/auibook.h"
#include "wx/aui/serializer.h"
#include "asserthelper.h"
#include <memory>
// ----------------------------------------------------------------------------
// test fixtures
// ----------------------------------------------------------------------------
class AuiNotebookTestCase
{
public:
AuiNotebookTestCase()
: nb(new wxAuiNotebook(wxTheApp->GetTopWindow()))
{
}
~AuiNotebookTestCase()
{
delete nb;
}
protected:
wxAuiNotebook* const nb;
};
// ----------------------------------------------------------------------------
// the tests themselves
// ----------------------------------------------------------------------------
TEST_CASE_METHOD(AuiNotebookTestCase, "wxAuiNotebook::DoGetBestSize", "[aui]")
{
wxPanel *p = new wxPanel(nb);
p->SetMinSize(wxSize(100, 100));
REQUIRE( nb->AddPage(p, "Center Pane") );
const int tabHeight = nb->GetTabCtrlHeight();
SECTION( "Single pane with multiple tabs" )
{
p = new wxPanel(nb);
p->SetMinSize(wxSize(300, 100));
nb->AddPage(p, "Center Tab 2");
p = new wxPanel(nb);
p->SetMinSize(wxSize(100, 200));
nb->AddPage(p, "Center Tab 3");
CHECK( nb->GetBestSize() == wxSize(300, 200 + tabHeight) );
}
SECTION( "Horizontal split" )
{
p = new wxPanel(nb);
p->SetMinSize(wxSize(25, 0));
nb->AddPage(p, "Left Pane");
nb->Split(nb->GetPageCount()-1, wxLEFT);
CHECK( nb->GetBestSize() == wxSize(125, 100 + tabHeight) );
p = new wxPanel(nb);
p->SetMinSize(wxSize(50, 0));
nb->AddPage(p, "Right Pane 1");
nb->Split(nb->GetPageCount()-1, wxRIGHT);
CHECK( nb->GetBestSize() == wxSize(175, 100 + tabHeight) );
p = new wxPanel(nb);
p->SetMinSize(wxSize(100, 0));
nb->AddPage(p, "Right Pane 2");
nb->Split(nb->GetPageCount()-1, wxRIGHT);
CHECK( nb->GetBestSize() == wxSize(275, 100 + tabHeight) );
}
SECTION( "Vertical split" )
{
p = new wxPanel(nb);
p->SetMinSize(wxSize(0, 100));
nb->AddPage(p, "Top Pane 1");
nb->Split(nb->GetPageCount()-1, wxTOP);
p = new wxPanel(nb);
p->SetMinSize(wxSize(0, 50));
nb->AddPage(p, "Top Pane 2");
nb->Split(nb->GetPageCount()-1, wxTOP);
CHECK( nb->GetBestSize() == wxSize(100, 250 + 3*tabHeight) );
p = new wxPanel(nb);
p->SetMinSize(wxSize(0, 25));
nb->AddPage(p, "Bottom Pane");
nb->Split(nb->GetPageCount()-1, wxBOTTOM);
CHECK( nb->GetBestSize() == wxSize(100, 275 + 4*tabHeight) );
}
SECTION( "Surrounding panes" )
{
p = new wxPanel(nb);
p->SetMinSize(wxSize(50, 25));
nb->AddPage(p, "Bottom Pane");
nb->Split(nb->GetPageCount()-1, wxBOTTOM);
p = new wxPanel(nb);
p->SetMinSize(wxSize(50, 120));
nb->AddPage(p, "Right Pane");
nb->Split(nb->GetPageCount()-1, wxRIGHT);
p = new wxPanel(nb);
p->SetMinSize(wxSize(225, 50));
nb->AddPage(p, "Top Pane");
nb->Split(nb->GetPageCount()-1, wxTOP);
p = new wxPanel(nb);
p->SetMinSize(wxSize(25, 105));
nb->AddPage(p, "Left Pane");
nb->Split(nb->GetPageCount()-1, wxLEFT);
CHECK( nb->GetBestSize() == wxSize(250, 175 + 3*tabHeight) );
}
}
TEST_CASE_METHOD(AuiNotebookTestCase, "wxAuiNotebook::RTTI", "[aui][rtti]")
{
wxBookCtrlBase* const book = nb;
CHECK( wxDynamicCast(book, wxAuiNotebook) == nb );
CHECK( wxDynamicCast(nb, wxBookCtrlBase) == book );
}
TEST_CASE_METHOD(AuiNotebookTestCase, "wxAuiNotebook::FindPage", "[aui]")
{
wxPanel *p1 = new wxPanel(nb);
wxPanel *p2 = new wxPanel(nb);
wxPanel *p3 = new wxPanel(nb);
REQUIRE( nb->AddPage(p1, "Page 1") );
REQUIRE( nb->AddPage(p2, "Page 2") );
CHECK( nb->FindPage(nullptr) == wxNOT_FOUND );
CHECK( nb->FindPage(p1) == 0 );
CHECK( nb->FindPage(p2) == 1 );
CHECK( nb->FindPage(p3) == wxNOT_FOUND );
}
TEST_CASE_METHOD(AuiNotebookTestCase, "wxAuiNotebook::Layout", "[aui]")
{
const auto addPage = [this](int n)
{
return nb->AddPage(new wxPanel(nb), wxString::Format("Page %d", n + 1));
};
for ( int n = 0; n < 5; n++ )
{
REQUIRE( addPage(n) );
}
using Ints = std::vector<int>;
using Indices = std::vector<size_t>;
// This serializer allows the code below to tweak its data before using it
// as deserializer.
class TestSerializer : public wxAuiBookSerializer,
public wxAuiBookDeserializer
{
public:
virtual void BeforeSaveNotebook(const wxString& name) override
{
m_name = name;
m_afterSaveCalled = false;
m_tabsLayoutInfo.clear();
}
virtual void
SaveNotebookTabControl(const wxAuiTabLayoutInfo& tab) override
{
m_tabsLayoutInfo.push_back(tab);
}
virtual void AfterSaveNotebook() override
{
m_afterSaveCalled = true;
}
virtual std::vector<wxAuiTabLayoutInfo>
LoadNotebookTabs(const wxString& name) override
{
CHECK( name == m_name );
m_orphanedPages.clear();
return m_tabsLayoutInfo;
}
virtual bool
HandleOrphanedPage(wxAuiNotebook& WXUNUSED(book),
int page,
wxAuiTabCtrl** WXUNUSED(tabCtrl),
int* tabIndex) override
{
m_orphanedPages.push_back(page);
*tabIndex = m_orphanedPageReturnIndex;
return m_orphanedPageReturnValue;
}
wxString m_name;
std::vector<wxAuiTabLayoutInfo> m_tabsLayoutInfo;
bool m_afterSaveCalled = false;
Ints m_orphanedPages;
bool m_orphanedPageReturnValue = true;
int m_orphanedPageReturnIndex = wxNOT_FOUND;
} ser;
// Just for convenience.
auto& info = ser.m_tabsLayoutInfo;
// Check the default layout has expected representation.
nb->SaveLayout("layout", ser);
CHECK( ser.m_name == "layout" );
CHECK( ser.m_afterSaveCalled );
REQUIRE( info.size() == 1 );
CHECK( info[0].pages == Ints{} );
CHECK( info[0].pinned == Ints{} );
CHECK( info[0].active == 0 );
// Check that the active page is restored correctly.
info[0].active = 1;
nb->LoadLayout("layout", ser);
CHECK( nb->GetSelection() == 1 );
// Check that page order is serialized as expected.
auto* mainTabCtrl = nb->GetMainTabCtrl();
REQUIRE( mainTabCtrl );
CHECK( mainTabCtrl->MovePage(1, 4) );
nb->SaveLayout("layout", ser);
REQUIRE( info.size() == 1 );
CHECK( info[0].pages == Ints{0, 2, 3, 4, 1} );
// Check that pinned pages are serialized as expected.
REQUIRE( nb->SetPageKind(2, wxAuiTabKind::Pinned) );
nb->SaveLayout("layout", ser);
REQUIRE( info.size() == 1 );
// Note that pinning a page moves it in front of all other pages.
CHECK( info[0].pages == Ints{2, 0, 3, 4, 1} );
CHECK( info[0].pinned == Ints{2} );
// Check a more complicated case with both locked and pinned pages.
REQUIRE( nb->SetPageKind(4, wxAuiTabKind::Locked) );
REQUIRE( nb->SetPageKind(3, wxAuiTabKind::Pinned) );
nb->SaveLayout("layout", ser);
REQUIRE( info.size() == 1 );
// Note that pinning a page moves it in front of all other pages.
CHECK( info[0].pages == Ints{4, 2, 3, 0, 1} );
CHECK( info[0].pinned == Ints{2, 3} );
// Check that restoring existing layout after adding some pages works.
addPage(5);
addPage(6);
nb->LoadLayout("layout", ser);
CHECK( ser.m_orphanedPages == Ints{5, 6} );
// By default, orphaned pages should have been appended.
CHECK( nb->GetPagesInDisplayOrder(mainTabCtrl) ==
Indices{4, 2, 3, 0, 1, 5, 6} );
// But we can change this by telling deserializer to insert them in front.
ser.m_orphanedPageReturnIndex = 0;
nb->LoadLayout("layout", ser);
CHECK( ser.m_orphanedPages == Ints{5, 6} );
CHECK( nb->GetPagesInDisplayOrder(mainTabCtrl) ==
Indices{6, 5, 4, 2, 3, 0, 1} );
// Or drop them entirely.
ser.m_orphanedPageReturnValue = false;
nb->LoadLayout("layout", ser);
CHECK( ser.m_orphanedPages == Ints{5, 6} );
CHECK( nb->GetPagesInDisplayOrder(mainTabCtrl) ==
Indices{4, 2, 3, 0, 1} );
// Finally, check that invalid data is handled gracefully.
info[0].active = 100;
info[0].pages = Ints{10, 0, 1, 2, 3, 4};
info[0].pinned = Ints{2, 99, 0};
nb->LoadLayout("layout", ser);
CHECK( ser.m_orphanedPages == Ints{} );
// Locked tab should have remained first.
CHECK( nb->GetPagesInDisplayOrder(mainTabCtrl) == Indices{4, 0, 1, 2, 3} );
// And selection should have been set to it because the specified value was
// invalid.
CHECK( nb->GetSelection() == 4 );
// And only tabs appearing before the normal ones can be pinned.
CHECK( nb->GetPageKind(0) == wxAuiTabKind::Pinned );
CHECK( nb->GetPageKind(1) == wxAuiTabKind::Normal );
CHECK( nb->GetPageKind(2) == wxAuiTabKind::Normal );
CHECK( nb->GetPageKind(3) == wxAuiTabKind::Normal );
CHECK( nb->GetPageKind(4) == wxAuiTabKind::Locked );
}
TEST_CASE("wxAuiToolBar::Items", "[aui][toolbar]")
{
std::unique_ptr<wxAuiToolBar> tbar{new wxAuiToolBar(wxTheApp->GetTopWindow())};
// Check that adding more toolbar elements doesn't invalidate the existing
// pointers.
auto first = tbar->AddLabel(wxID_ANY, "first");
tbar->AddLabel(wxID_ANY, "second");
CHECK( first->GetLabel() == "first" );
}
#endif