wxWidgets/tests/sizers/boxsizer.cpp
Stefan Csomor da48b9e45d
adding an iOS build to travis (#1847)
* fixing compilation of tests that cannot build

bracket code with the corresponding wxUSE… macros

* adding directive for iOS

* adding a switch for skipping the run - not the build of tests

right now I don’t know yet, how to run the test binary in the iOS simulator, but building it is still a good test in itself

* adding skipping of tests

* increasing minimum deployment to get proper c++17 support

* using --disable-sys-libs, restoring other targets

even when the zlib in -isysroot is used, due to deployment on lower iOS versions inflateValidate may not be available and crash. The guards are evaluated using macros from the zlib from the SDK, not from the lowest version supported.
2020-05-08 08:01:56 +02:00

443 lines
14 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// Name: tests/sizers/boxsizer.cpp
// Purpose: Unit tests for wxBoxSizer
// Author: Vadim Zeitlin
// Created: 2010-03-06
// Copyright: (c) 2010 Vadim Zeitlin <vadim@wxwidgets.org>
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "testprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/sizer.h"
#include "wx/listbox.h"
#endif // WX_PRECOMP
#include "asserthelper.h"
// ----------------------------------------------------------------------------
// test fixture
// ----------------------------------------------------------------------------
class BoxSizerTestCase
{
public:
BoxSizerTestCase()
: m_win(new wxWindow(wxTheApp->GetTopWindow(), wxID_ANY)),
m_sizer(new wxBoxSizer(wxHORIZONTAL))
{
m_win->SetClientSize(127, 35);
m_win->SetSizer(m_sizer);
}
~BoxSizerTestCase()
{
delete m_win;
}
protected:
wxWindow* const m_win;
wxSizer* const m_sizer;
};
// ----------------------------------------------------------------------------
// tests themselves
// ----------------------------------------------------------------------------
TEST_CASE_METHOD(BoxSizerTestCase, "BoxSizer::Size1", "[sizer]")
{
const wxSize sizeTotal = m_win->GetClientSize();
const wxSize sizeChild = sizeTotal / 2;
wxWindow * const
child = new wxWindow(m_win, wxID_ANY, wxDefaultPosition, sizeChild);
m_sizer->Add(child);
m_win->Layout();
CHECK(child->GetSize() == sizeChild);
m_sizer->Clear();
m_sizer->Add(child, wxSizerFlags(1));
m_win->Layout();
CHECK( child->GetSize() == wxSize(sizeTotal.x, sizeChild.y) );
m_sizer->Clear();
m_sizer->Add(child, wxSizerFlags(1).Expand());
m_win->Layout();
CHECK(child->GetSize() == sizeTotal);
m_sizer->Clear();
m_sizer->Add(child, wxSizerFlags());
m_sizer->SetItemMinSize(child, sizeTotal*2);
m_win->Layout();
CHECK(child->GetSize() == sizeTotal);
m_sizer->Clear();
m_sizer->Add(child, wxSizerFlags().Expand());
m_sizer->SetItemMinSize(child, sizeTotal*2);
m_win->Layout();
CHECK(child->GetSize() == sizeTotal);
}
TEST_CASE_METHOD(BoxSizerTestCase, "BoxSizer::Size3", "[sizer]")
{
wxGCC_WARNING_SUPPRESS(missing-field-initializers)
// check that various combinations of minimal sizes and proportions work as
// expected for different window sizes
static const struct LayoutTestData
{
// proportions of the elements
int prop[3];
// minimal sizes of the elements in the sizer direction
int minsize[3];
// total size and the expected sizes of the elements
int x,
sizes[3];
// if true, don't try the permutations of our test data
bool dontPermute;
// Add the given window to the sizer with the corresponding parameters
void AddToSizer(wxSizer *sizer, wxWindow *win, int n) const
{
sizer->Add(win, wxSizerFlags(prop[n]));
sizer->SetItemMinSize(win, wxSize(minsize[n], -1));
}
} layoutTestData[] =
{
// some really simple cases (no need to permute those, they're
// symmetrical anyhow)
{ { 1, 1, 1, }, { 50, 50, 50, }, 150, { 50, 50, 50, }, true },
{ { 2, 2, 2, }, { 50, 50, 50, }, 600, { 200, 200, 200, }, true },
// items with different proportions and min sizes when there is enough
// space to lay them out
{ { 1, 2, 3, }, { 0, 0, 0, }, 600, { 100, 200, 300, } },
{ { 1, 2, 3, }, { 100, 100, 100, }, 600, { 100, 200, 300, } },
{ { 1, 2, 3, }, { 100, 50, 50, }, 600, { 100, 200, 300, } },
{ { 0, 1, 1, }, { 200, 100, 100, }, 600, { 200, 200, 200, } },
{ { 0, 1, 2, }, { 300, 100, 100, }, 600, { 300, 100, 200, } },
{ { 0, 1, 1, }, { 100, 50, 50, }, 300, { 100, 100, 100, } },
{ { 0, 1, 2, }, { 100, 50, 50, }, 400, { 100, 100, 200, } },
// cases when there is not enough space to lay out the items correctly
// while still respecting their min sizes
{ { 0, 1, 1, }, { 100, 150, 50, }, 300, { 100, 150, 50, } },
{ { 1, 2, 3, }, { 100, 100, 100, }, 300, { 100, 100, 100, } },
{ { 1, 2, 3, }, { 100, 50, 50, }, 300, { 100, 80, 120, } },
{ { 1, 2, 3, }, { 100, 10, 10, }, 150, { 100, 20, 30, } },
// cases when there is not enough space even for the min sizes (don't
// permute in these cases as the layout does depend on the item order
// because the first ones have priority)
{ { 1, 2, 3, }, { 100, 50, 50, }, 150, { 100, 50, 0, }, true },
{ { 1, 2, 3, }, { 100, 100, 100, }, 200, { 100, 100, 0, }, true },
{ { 1, 2, 3, }, { 100, 100, 100, }, 150, { 100, 50, 0, }, true },
{ { 1, 2, 3, }, { 100, 100, 100, }, 50, { 50, 0, 0, }, true },
{ { 1, 2, 3, }, { 100, 100, 100, }, 0, { 0, 0, 0, }, true },
};
wxGCC_WARNING_RESTORE(missing-field-initializers)
wxWindow *child[3];
child[0] = new wxWindow(m_win, wxID_ANY);
child[1] = new wxWindow(m_win, wxID_ANY);
child[2] = new wxWindow(m_win, wxID_ANY);
for ( unsigned i = 0; i < WXSIZEOF(layoutTestData); i++ )
{
LayoutTestData ltd = layoutTestData[i];
// the results shouldn't depend on the order of items except in the
// case when there is not enough space for even the fixed width items
// (in which case the first ones might get enough of it but not the
// last ones) so test a couple of permutations of test data unless
// specifically disabled for this test case
for ( unsigned p = 0; p < 3; p++)
{
switch ( p )
{
case 0:
// nothing to do, use original data
break;
case 1:
// exchange first and last elements
wxSwap(ltd.prop[0], ltd.prop[2]);
wxSwap(ltd.minsize[0], ltd.minsize[2]);
wxSwap(ltd.sizes[0], ltd.sizes[2]);
break;
case 2:
// exchange the original third and second elements
wxSwap(ltd.prop[0], ltd.prop[1]);
wxSwap(ltd.minsize[0], ltd.minsize[1]);
wxSwap(ltd.sizes[0], ltd.sizes[1]);
break;
}
m_sizer->Clear();
unsigned j;
for ( j = 0; j < WXSIZEOF(child); j++ )
ltd.AddToSizer(m_sizer, child[j], j);
m_win->SetClientSize(ltd.x, -1);
m_win->Layout();
for ( j = 0; j < WXSIZEOF(child); j++ )
{
WX_ASSERT_EQUAL_MESSAGE
(
(
"test %lu, permutation #%lu: wrong size for child #%d "
"for total size %d",
static_cast<unsigned long>(i),
static_cast<unsigned long>(p),
j,
ltd.x
),
ltd.sizes[j], child[j]->GetSize().x
);
}
// don't try other permutations if explicitly disabled
if ( ltd.dontPermute )
break;
}
}
}
TEST_CASE_METHOD(BoxSizerTestCase, "BoxSizer::CalcMin", "[sizer]")
{
static const unsigned NUM_TEST_ITEM = 3;
static const struct CalcMinTestData
{
// proportions of the elements, if one of them is -1 it means to not
// use this window at all in this test
int prop[NUM_TEST_ITEM];
// minimal sizes of the elements in the sizer direction
int minsize[NUM_TEST_ITEM];
// the expected minimal sizer size
int total;
} calcMinTestData[] =
{
{ { 1, 1, -1 }, { 30, 50, 0 }, 100 },
{ { 1, 1, 0 }, { 30, 50, 20 }, 120 },
{ { 10, 10, -1 }, { 30, 50, 0 }, 100 },
{ { 1, 2, 2 }, { 50, 50, 80 }, 250 },
{ { 1, 2, 2 }, { 100, 50, 80 }, 500 },
};
unsigned n;
wxWindow *child[NUM_TEST_ITEM];
for ( n = 0; n < NUM_TEST_ITEM; n++ )
child[n] = new wxWindow(m_win, wxID_ANY);
for ( unsigned i = 0; i < WXSIZEOF(calcMinTestData); i++ )
{
m_sizer->Clear();
const CalcMinTestData& cmtd = calcMinTestData[i];
for ( n = 0; n < NUM_TEST_ITEM; n++ )
{
if ( cmtd.prop[n] != -1 )
{
child[n]->SetInitialSize(wxSize(cmtd.minsize[n], -1));
m_sizer->Add(child[n], wxSizerFlags(cmtd.prop[n]));
}
}
WX_ASSERT_EQUAL_MESSAGE
(
("In test #%u", i),
cmtd.total, m_sizer->CalcMin().x
);
}
}
TEST_CASE_METHOD(BoxSizerTestCase, "BoxSizer::SetMinSize", "[sizer]")
{
wxWindow* const child = new wxWindow(m_win, wxID_ANY);
child->SetInitialSize(wxSize(10, -1));
m_sizer->Add(child);
// Setting minimal size explicitly must make GetMinSize() return at least
// this size even if it needs a much smaller one.
m_sizer->SetMinSize(100, 0);
CHECK(m_sizer->GetMinSize().x == 100);
m_sizer->Layout();
CHECK(m_sizer->GetMinSize().x == 100);
}
#if wxUSE_LISTBOX
TEST_CASE_METHOD(BoxSizerTestCase, "BoxSizer::BestSizeRespectsMaxSize", "[sizer]")
{
m_sizer->Clear();
const int maxWidth = 100;
wxSizer* sizer = new wxBoxSizer(wxVERTICAL);
wxListBox* listbox = new wxListBox(m_win, wxID_ANY);
listbox->Append("some very very very very very very very very very very very long string");
listbox->SetMaxSize(wxSize(maxWidth, -1));
sizer->Add(listbox);
m_sizer->Add(sizer);
m_win->Layout();
CHECK(listbox->GetSize().GetWidth() == maxWidth);
}
TEST_CASE_METHOD(BoxSizerTestCase, "BoxSizer::RecalcSizesRespectsMaxSize1", "[sizer]")
{
m_sizer->Clear();
const int maxWidth = 100;
m_win->SetClientSize(300, 300);
wxSizer* sizer1 = new wxBoxSizer(wxVERTICAL);
m_sizer->Add(sizer1);
wxListBox* listbox1 = new wxListBox(m_win, wxID_ANY);
listbox1->Append("some very very very very very very very very very very very long string");
sizer1->Add(listbox1);
wxSizer* sizer2 = new wxBoxSizer(wxHORIZONTAL);
sizer1->Add(sizer2, wxSizerFlags().Expand());
wxListBox* listbox2 = new wxListBox(m_win, wxID_ANY);
listbox2->Append("some string");
listbox2->SetMaxSize(wxSize(100, -1));
sizer2->Add(listbox2, wxSizerFlags().Proportion(1));
m_win->Layout();
CHECK(listbox2->GetSize().GetWidth() == maxWidth);
}
#endif
TEST_CASE_METHOD(BoxSizerTestCase, "BoxSizer::RecalcSizesRespectsMaxSize2", "[sizer]")
{
m_sizer->Clear();
m_win->SetClientSize(300, 300);
wxSizer* sizer1 = new wxBoxSizer(wxVERTICAL);
m_sizer->Add(sizer1, wxSizerFlags().Expand());
wxWindow* child1 = new wxWindow(m_win, wxID_ANY);
sizer1->Add(child1, wxSizerFlags().Proportion(1));
wxWindow* child2 = new wxWindow(m_win, wxID_ANY);
child2->SetMaxSize(wxSize(-1, 50));
sizer1->Add(child2, wxSizerFlags().Proportion(1));
wxWindow* child3 = new wxWindow(m_win, wxID_ANY);
sizer1->Add(child3, wxSizerFlags().Proportion(1));
m_win->Layout();
CHECK(child1->GetSize().GetHeight() == 125);
CHECK(child2->GetSize().GetHeight() == 50);
CHECK(child3->GetSize().GetHeight() == 125);
}
TEST_CASE_METHOD(BoxSizerTestCase, "BoxSizer::IncompatibleFlags", "[sizer]")
{
// This unhygienic macro relies on having a local variable called "sizer".
#define ASSERT_SIZER_INVALID_FLAGS(f, msg) \
WX_ASSERT_FAILS_WITH_ASSERT_MESSAGE( \
"Expected assertion not generated for " msg, \
sizer->Add(10, 10, 0, f) \
)
#define ASSERT_SIZER_INCOMPATIBLE_FLAGS(f1, f2) \
ASSERT_SIZER_INVALID_FLAGS(f1 | f2, \
"using incompatible flags " #f1 " and " #f2 \
)
// First check with the horizontal sizer, which is what we use by default.
wxSizer* sizer = m_sizer;
// In horizontal sizers alignment is only used in vertical direction.
ASSERT_SIZER_INVALID_FLAGS(
wxALIGN_RIGHT,
"using wxALIGN_RIGHT in a horizontal sizer"
);
ASSERT_SIZER_INVALID_FLAGS(
wxALIGN_CENTRE_HORIZONTAL,
"using wxALIGN_CENTRE_HORIZONTAL in a horizontal sizer"
);
// However using wxALIGN_CENTRE_HORIZONTAL together with
// wxALIGN_CENTRE_VERTICAL as done by wxSizerFlags::Centre() should work.
sizer->Add(10, 10, wxSizerFlags().Centre());
// Combining two vertical alignment flags doesn't make sense.
ASSERT_SIZER_INCOMPATIBLE_FLAGS(wxALIGN_BOTTOM, wxALIGN_CENTRE_VERTICAL);
// Combining wxEXPAND with vertical alignment doesn't make sense neither.
ASSERT_SIZER_INCOMPATIBLE_FLAGS(wxEXPAND, wxALIGN_CENTRE_VERTICAL);
ASSERT_SIZER_INCOMPATIBLE_FLAGS(wxEXPAND, wxALIGN_BOTTOM);
// But combining it with these flags and wxSHAPED does make sense and so
// shouldn't result in an assert.
CHECK_NOTHROW(
sizer->Add(10, 10, 0, wxEXPAND | wxSHAPED | wxALIGN_CENTRE_VERTICAL)
);
CHECK_NOTHROW(
sizer->Add(10, 10, 0, wxEXPAND | wxSHAPED | wxALIGN_TOP)
);
// And now exactly the same thing in the other direction.
sizer = new wxBoxSizer(wxVERTICAL);
m_win->SetSizer(sizer);
ASSERT_SIZER_INVALID_FLAGS(
wxALIGN_BOTTOM,
"using wxALIGN_BOTTOM in a vertical sizer"
);
ASSERT_SIZER_INVALID_FLAGS(
wxALIGN_CENTRE_VERTICAL,
"using wxALIGN_CENTRE_VERTICAL in a vertical sizer"
);
sizer->Add(10, 10, wxSizerFlags().Centre());
ASSERT_SIZER_INCOMPATIBLE_FLAGS(wxALIGN_RIGHT, wxALIGN_CENTRE_HORIZONTAL);
ASSERT_SIZER_INCOMPATIBLE_FLAGS(wxEXPAND, wxALIGN_CENTRE_HORIZONTAL);
ASSERT_SIZER_INCOMPATIBLE_FLAGS(wxEXPAND, wxALIGN_RIGHT);
CHECK_NOTHROW(
sizer->Add(10, 10, 0, wxEXPAND | wxSHAPED | wxALIGN_CENTRE_HORIZONTAL)
);
CHECK_NOTHROW(
sizer->Add(10, 10, 0, wxEXPAND | wxSHAPED | wxALIGN_RIGHT)
);
#undef ASSERT_SIZER_INCOMPATIBLE_FLAGS
#undef ASSERT_SIZER_INVALID_FLAGS
}