#include <stdio.h>
#include <stdlib.h>
#include <typeinfo>
#include <Application.h>
#include <Button.h>
#include <CardLayout.h>
#include <LayoutBuilder.h>
#include <LayoutUtils.h>
#include <ListView.h>
#include <MenuField.h>
#include <RadioButton.h>
#include <ScrollView.h>
#include <String.h>
#include <StringView.h>
#include <TextControl.h>
#include <View.h>
#include <Window.h>
static const rgb_color kBlack = {0, 0, 0, 255};
static const rgb_color kRed = {255, 0, 0, 255};
enum {
MSG_TEST_SELECTED = 'tsts',
MSG_TOGGLE_1 = 'tgl1',
MSG_TOGGLE_2 = 'tgl2',
MSG_FIXED_ASPECT_RATIO = 'hwas',
MSG_FIXED_SUM = 'hwfs',
MSG_FIXED_PRODUCT = 'hwfp',
};
enum {
FIXED_SUM,
FIXED_PRODUCT,
FIXED_ASPECT_RATIO,
};
class TestView : public BView {
public:
TestView(const rgb_color& color = kBlack)
: BView("test view", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
fColor(color)
{
}
void SetColor(const rgb_color& color)
{
fColor = color;
Invalidate();
}
virtual void Draw(BRect updateRect)
{
SetHighColor(fColor);
BRect bounds(Bounds());
StrokeRect(bounds);
BPoint rightBottom = bounds.RightBottom();
StrokeLine(B_ORIGIN, rightBottom);
StrokeLine(BPoint(rightBottom.x, 0), BPoint(0, rightBottom.y));
}
virtual BSize MinSize()
{
return BLayoutUtils::ComposeSize(ExplicitMinSize(), BSize(10, 10));
}
virtual BSize PreferredSize()
{
return BLayoutUtils::ComposeSize(ExplicitPreferredSize(),
BSize(50, 50));
}
private:
rgb_color fColor;
};
class HeightForWidthTestView : public TestView {
public:
HeightForWidthTestView(uint32 type, float value)
: fType(NULL)
{
SetType(type, value);
}
HeightForWidthTestView(const rgb_color& color, uint32 type, float value)
: TestView(color),
fType(NULL)
{
SetType(type, value);
}
~HeightForWidthTestView()
{
delete fType;
}
void SetType(uint32 type, float value)
{
delete fType;
switch (type) {
case FIXED_SUM:
fType = new FixedSumType((int)value);
break;
case FIXED_PRODUCT:
fType = new FixedProductType((int)value);
break;
case FIXED_ASPECT_RATIO:
default:
fType = new FixedAspectRatioType(value);
break;
}
InvalidateLayout();
}
BSize MinSize() {
return BLayoutUtils::ComposeSize(ExplicitMinSize(), fType->MinSize());
}
BSize MaxSize() {
return BLayoutUtils::ComposeSize(ExplicitMaxSize(), fType->MaxSize());
}
BSize PreferredSize() {
return BLayoutUtils::ComposeSize(ExplicitPreferredSize(),
fType->PreferredSize());
}
bool HasHeightForWidth() {
return true;
}
void GetHeightForWidth(float width, float* minHeight, float* maxHeight,
float* preferredHeight) {
float dummy;
fType->GetHeightForWidth(width,
minHeight ? minHeight : &dummy,
maxHeight ? maxHeight : &dummy,
preferredHeight ? preferredHeight : &dummy);
}
private:
class HeightForWidthType {
public:
virtual ~HeightForWidthType()
{
}
virtual BSize MinSize() = 0;
virtual BSize MaxSize() = 0;
virtual BSize PreferredSize() = 0;
virtual void GetHeightForWidth(float width, float* minHeight,
float* maxHeight, float* preferredHeight) = 0;
};
class FixedAspectRatioType : public HeightForWidthType {
public:
FixedAspectRatioType(float ratio)
: fAspectRatio(ratio)
{
}
virtual BSize MinSize()
{
return BSize(-1, -1);
}
virtual BSize MaxSize()
{
return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED);
}
virtual BSize PreferredSize()
{
float preferredWidth = 49;
float dummy, preferredHeight;
GetHeightForWidth(preferredWidth, &dummy, &dummy, &preferredHeight);
return BSize(preferredWidth, preferredHeight);
}
virtual void GetHeightForWidth(float width, float* minHeight,
float* maxHeight, float* preferredHeight)
{
float height = floor((width + 1) * fAspectRatio) - 1;
*minHeight = height;
*maxHeight = height;
*preferredHeight = height;
}
private:
float fAspectRatio;
};
class FixedSumType : public HeightForWidthType {
public:
FixedSumType(float sum)
: fSum(sum)
{
}
virtual BSize MinSize()
{
return BSize(0, 0);
}
virtual BSize MaxSize()
{
return BSize(fSum - 2, fSum - 2);
}
virtual BSize PreferredSize()
{
float preferredWidth = floor(fSum / 2) - 1;
float dummy, preferredHeight;
GetHeightForWidth(preferredWidth, &dummy, &dummy, &preferredHeight);
return BSize(preferredWidth, preferredHeight);
}
virtual void GetHeightForWidth(float width, float* minHeight,
float* maxHeight, float* preferredHeight)
{
float height = fSum - (width + 1) - 1;
*minHeight = height;
*maxHeight = height;
*preferredHeight = height;
}
private:
float fSum;
};
class FixedProductType : public HeightForWidthType {
public:
FixedProductType(float product)
: fProduct(product)
{
}
virtual BSize MinSize()
{
return BSize(0, 0);
}
virtual BSize MaxSize()
{
return BSize(fProduct - 1, fProduct - 1);
}
virtual BSize PreferredSize()
{
float preferredWidth = floor(sqrt(fProduct));
float dummy, preferredHeight;
GetHeightForWidth(preferredWidth, &dummy, &dummy, &preferredHeight);
return BSize(preferredWidth, preferredHeight);
}
virtual void GetHeightForWidth(float width, float* minHeight,
float* maxHeight, float* preferredHeight)
{
float height = floor(fProduct / (width + 1)) - 1;
*minHeight = height;
*maxHeight = height;
*preferredHeight = height;
}
private:
float fProduct;
};
private:
HeightForWidthType* fType;
};
struct Test : BHandler {
BString name;
BView* rootView;
BString description;
Test(const char* name, const char* description)
: BHandler(name),
name(name),
rootView(new BView(name, 0)),
description(description)
{
}
virtual ~Test()
{
}
virtual void RegisterListeners()
{
}
};
struct GroupLayoutTest1 : public Test {
GroupLayoutTest1()
:
Test("Group", "Simple BGroupLayout.")
{
BLayoutBuilder::Group<>(rootView, B_HORIZONTAL)
.AddGroup(B_VERTICAL)
.Add(toggleRowButton = new BButton("Toggle Row",
new BMessage(MSG_TOGGLE_1)))
.Add(toggleViewButton = new BButton("Toggle View",
new BMessage(MSG_TOGGLE_2)))
.AddGlue()
.End()
.AddGroup(B_VERTICAL)
.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 1)
.Add(new TestView(), 1)
.Add(toggledView = new TestView(), 2)
.Add(new TestView(), 3)
.End()
.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 2)
.GetLayout(&toggledRow)
.Add(new TestView())
.Add(new TestView())
.Add(new TestView())
.End()
.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 3)
.Add(new TestView(), 3)
.Add(new TestView(), 2)
.Add(new TestView(), 1);
}
virtual void RegisterListeners()
{
toggleRowButton->SetTarget(this);
toggleViewButton->SetTarget(this);
}
virtual void MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_TOGGLE_1:
{
toggledRow->SetVisible(!toggledRow->IsVisible());
break;
}
case MSG_TOGGLE_2:
{
if (toggledView->IsHidden(toggledView))
toggledView->Show();
else
toggledView->Hide();
break;
}
default:
BHandler::MessageReceived(message);
break;
}
}
private:
BButton* toggleRowButton;
BButton* toggleViewButton;
BGroupLayout* toggledRow;
TestView* toggledView;
};
struct GroupAlignedLayoutTest1 : public Test {
GroupAlignedLayoutTest1()
: Test("Group aligned", "Simple BGroupLayout, rows 1 and 3 aligned.")
{
BGroupView* rootView = new BGroupView(B_HORIZONTAL, 10);
this->rootView = rootView;
BGroupView* controls = new BGroupView(B_VERTICAL, 10);
rootView->AddChild(controls);
toggleRowButton = new BButton("Toggle Row", new BMessage(MSG_TOGGLE_1));
controls->AddChild(toggleRowButton);
toggleViewButton = new BButton("Toggle View",
new BMessage(MSG_TOGGLE_2));
controls->AddChild(toggleViewButton);
controls->AddChild(BSpaceLayoutItem::CreateGlue());
BGroupView* testViews = new BGroupView(B_VERTICAL, 10);
rootView->AddChild(testViews);
BGroupView* row = new BGroupView(B_HORIZONTAL, 10);
BGroupView* row1 = row;
testViews->GroupLayout()->AddView(row, 1);
row->GroupLayout()->AddView(new TestView(), 1);
toggledView = new TestView();
row->GroupLayout()->AddView(toggledView, 2);
row->GroupLayout()->AddView(new TestView(), 3);
row = new BGroupView(B_HORIZONTAL, 10);
toggledRow = row;
testViews->GroupLayout()->AddView(row, 2);
row->GroupLayout()->AddView(new TestView());
row->GroupLayout()->AddView(new TestView());
row->GroupLayout()->AddView(new TestView());
row = new BGroupView(B_HORIZONTAL, 10);
BGroupView* row3 = row;
testViews->GroupLayout()->AddView(row, 3);
row->GroupLayout()->AddView(new TestView(), 3);
row->GroupLayout()->AddView(new TestView(), 2);
row->GroupLayout()->AddView(new TestView(), 1);
row1->GroupLayout()->AlignLayoutWith(row3->GroupLayout(), B_HORIZONTAL);
}
virtual void RegisterListeners()
{
toggleRowButton->SetTarget(this);
toggleViewButton->SetTarget(this);
}
virtual void MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_TOGGLE_1:
{
if (toggledRow->IsHidden(toggledRow))
toggledRow->Show();
else
toggledRow->Hide();
break;
}
case MSG_TOGGLE_2:
{
if (toggledView->IsHidden(toggledView))
toggledView->Show();
else
toggledView->Hide();
break;
}
default:
BHandler::MessageReceived(message);
break;
}
}
private:
BButton* toggleRowButton;
BButton* toggleViewButton;
BGroupView* toggledRow;
TestView* toggledView;
};
struct GridLayoutTest1 : public Test {
GridLayoutTest1()
: Test("Grid", "Simple BGridLayout.")
{
BLayoutBuilder::Group<>(rootView, B_HORIZONTAL)
.AddGroup(B_VERTICAL)
.Add(toggleView1Button = new BButton("Toggle View 1",
new BMessage(MSG_TOGGLE_1)))
.Add(toggleView2Button = new BButton("Toggle View 2",
new BMessage(MSG_TOGGLE_2)))
.AddGlue()
.End()
.AddGrid()
.Add(toggledView1 = new TestView(), 0, 0, 3, 1)
.Add(new TestView(), 3, 0)
.Add(new TestView(), 4, 0)
.Add(new TestView(), 0, 1)
.Add(new TestView(), 1, 1)
.Add(new TestView(), 2, 1)
.Add(new TestView(), 3, 1)
.Add(new TestView(), 4, 1)
.Add(new TestView(), 0, 2)
.Add(toggledView2 = new TestView(), 1, 2, 2, 2)
.Add(new TestView(), 3, 2)
.Add(new TestView(), 4, 2)
.Add(new TestView(), 0, 3)
.Add(new TestView(), 3, 3)
.Add(new TestView(), 4, 3)
.SetColumnWeight(0, 1)
.SetColumnWeight(1, 2)
.SetColumnWeight(2, 3)
.SetColumnWeight(3, 4)
.SetColumnWeight(4, 5)
.SetRowWeight(0, 1)
.SetRowWeight(1, 2)
.SetRowWeight(2, 3)
.SetRowWeight(3, 4);
}
virtual void RegisterListeners()
{
toggleView1Button->SetTarget(this);
toggleView2Button->SetTarget(this);
}
virtual void MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_TOGGLE_1:
{
if (toggledView1->IsHidden(toggledView1))
toggledView1->Show();
else
toggledView1->Hide();
break;
}
case MSG_TOGGLE_2:
{
if (toggledView2->IsHidden(toggledView2))
toggledView2->Show();
else
toggledView2->Hide();
break;
}
default:
BHandler::MessageReceived(message);
break;
}
}
private:
BButton* toggleView1Button;
BButton* toggleView2Button;
TestView* toggledView1;
TestView* toggledView2;
};
struct SplitterGroupLayoutTest1 : public Test {
SplitterGroupLayoutTest1()
: Test("Group, splitters 1", "BGroupLayout with BSplitters.")
{
BLayoutBuilder::Group<>(rootView, B_HORIZONTAL)
.AddGroup(B_VERTICAL)
.Add(toggleRowButton = new BButton("Toggle Row",
new BMessage(MSG_TOGGLE_1)))
.Add(toggleViewButton = new BButton("Toggle View",
new BMessage(MSG_TOGGLE_2)))
.AddGlue()
.End()
.AddSplit(B_VERTICAL)
.AddSplit(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 1)
.Add(new TestView(), 1)
.Add(toggledView = new TestView(), 2)
.Add(new TestView(), 3)
.End()
.SetCollapsible(false)
.AddSplit(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 2)
.GetView(&toggledRow)
.Add(new TestView())
.Add(new TestView())
.Add(new TestView())
.End()
.AddSplit(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 3)
.Add(new TestView(), 3)
.Add(new TestView(), 2)
.Add(new TestView(), 1)
.End()
.SetCollapsible(false);
}
virtual void RegisterListeners()
{
toggleRowButton->SetTarget(this);
toggleViewButton->SetTarget(this);
}
virtual void MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_TOGGLE_1:
{
if (toggledRow->IsHidden(toggledRow))
toggledRow->Show();
else
toggledRow->Hide();
break;
}
case MSG_TOGGLE_2:
{
if (toggledView->IsHidden(toggledView))
toggledView->Show();
else
toggledView->Hide();
break;
}
default:
BHandler::MessageReceived(message);
break;
}
}
private:
BButton* toggleRowButton;
BButton* toggleViewButton;
BView* toggledRow;
TestView* toggledView;
};
struct SplitterGroupLayoutTest2 : public Test {
SplitterGroupLayoutTest2()
: Test("Group, splitters 2",
"BGroupLayout with BSplitters. Restricted maximum widths.")
{
TestView* testView1 = new TestView();
TestView* testView2 = new TestView();
TestView* testView3 = new TestView();
BLayoutBuilder::Group<>(rootView, B_HORIZONTAL)
.AddGroup(B_VERTICAL)
.AddSplit(B_HORIZONTAL)
.Add(testView1, 0)
.Add(testView2, 1)
.Add(testView3, 2);
testView1->SetExplicitMaxSize(BSize(100, B_SIZE_UNSET));
testView2->SetExplicitMaxSize(BSize(100, B_SIZE_UNSET));
testView3->SetExplicitMaxSize(BSize(100, B_SIZE_UNSET));
}
};
struct SplitterGridLayoutTest1 : public Test {
SplitterGridLayoutTest1()
: Test("Grid, h splitters", "BGridLayout with horizontal BSplitters.")
{
BGridLayout* layouts[3];
BLayoutBuilder::Group<>(rootView, B_HORIZONTAL)
.AddGroup(B_VERTICAL)
.Add(toggleView1Button = new BButton("Toggle View 1",
new BMessage(MSG_TOGGLE_1)))
.Add(toggleView2Button = new BButton("Toggle View 2",
new BMessage(MSG_TOGGLE_2)))
.AddGlue()
.End()
.AddSplit(B_HORIZONTAL)
.AddGrid(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, 6)
.GetLayout(&layouts[0])
.Add(toggledView1 = new TestView(), 0, 0, 3, 1)
.Add(new TestView(), 0, 1)
.Add(new TestView(), 1, 1)
.Add(new TestView(), 2, 1)
.Add(new TestView(), 0, 2)
.Add(toggledView2 = new TestView(), 1, 2, 2, 2)
.Add(new TestView(), 0, 3)
.SetColumnWeight(0, 1)
.SetColumnWeight(1, 2)
.SetColumnWeight(2, 3)
.End()
.AddGrid(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, 4)
.GetLayout(&layouts[1])
.Add(new TestView(), 0, 0)
.Add(new TestView(), 0, 1)
.Add(new TestView(), 0, 2)
.Add(new TestView(), 0, 3)
.End()
.AddGrid(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, 5)
.GetLayout(&layouts[2])
.Add(new TestView(), 0, 0)
.Add(new TestView(), 0, 1)
.Add(new TestView(), 0, 2)
.Add(new TestView(), 0, 3);
for (int i = 0; i < 3; i++) {
layouts[i]->SetRowWeight(0, 1);
layouts[i]->SetRowWeight(1, 2);
layouts[i]->SetRowWeight(2, 3);
layouts[i]->SetRowWeight(3, 4);
}
toggledView1->SetExplicitMinSize(BSize(B_SIZE_UNSET, 100));
toggledView2->SetExplicitMaxSize(BSize(B_SIZE_UNSET, 200));
layouts[0]->AlignLayoutWith(layouts[1], B_VERTICAL);
layouts[0]->AlignLayoutWith(layouts[2], B_VERTICAL);
}
virtual void RegisterListeners()
{
toggleView1Button->SetTarget(this);
toggleView2Button->SetTarget(this);
}
virtual void MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_TOGGLE_1:
{
if (toggledView1->IsHidden(toggledView1))
toggledView1->Show();
else
toggledView1->Hide();
break;
}
case MSG_TOGGLE_2:
{
if (toggledView2->IsHidden(toggledView2))
toggledView2->Show();
else
toggledView2->Hide();
break;
}
default:
BHandler::MessageReceived(message);
break;
}
}
private:
BButton* toggleView1Button;
BButton* toggleView2Button;
TestView* toggledView1;
TestView* toggledView2;
};
struct SplitterGridLayoutTest2 : public Test {
SplitterGridLayoutTest2()
: Test("Grid, v splitters", "BGridLayout with vertical BSplitters.")
{
BGridLayout* layouts[3];
BLayoutBuilder::Group<>(rootView, B_HORIZONTAL)
.AddGroup(B_VERTICAL)
.Add(toggleView1Button = new BButton("Toggle View 1",
new BMessage(MSG_TOGGLE_1)))
.Add(toggleView2Button = new BButton("Toggle View 2",
new BMessage(MSG_TOGGLE_2)))
.AddGlue()
.End()
.AddSplit(B_VERTICAL)
.AddGrid(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, 1)
.GetLayout(&layouts[0])
.Add(toggledView1 = new TestView(), 0, 0, 3, 1)
.Add(new TestView(), 3, 0)
.Add(new TestView(), 4, 0)
.End()
.AddGrid(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, 2)
.GetLayout(&layouts[1])
.Add(new TestView(), 0, 0)
.Add(new TestView(), 1, 0)
.Add(new TestView(), 2, 0)
.Add(new TestView(), 3, 0)
.Add(new TestView(), 4, 0)
.End()
.AddGrid(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, 7)
.GetLayout(&layouts[2])
.Add(new TestView(), 0, 0)
.Add(toggledView2 = new TestView(), 1, 0, 2, 2)
.Add(new TestView(), 3, 0)
.Add(new TestView(), 4, 0)
.Add(new TestView(), 0, 1)
.Add(new TestView(), 3, 1)
.Add(new TestView(), 4, 1)
.SetRowWeight(0, 3)
.SetRowWeight(1, 4);
for (int i = 0; i < 3; i++) {
layouts[i]->SetColumnWeight(0, 1);
layouts[i]->SetColumnWeight(1, 2);
layouts[i]->SetColumnWeight(2, 3);
layouts[i]->SetColumnWeight(3, 4);
layouts[i]->SetColumnWeight(4, 5);
}
layouts[0]->AlignLayoutWith(layouts[1], B_HORIZONTAL);
layouts[0]->AlignLayoutWith(layouts[2], B_HORIZONTAL);
}
virtual void RegisterListeners()
{
toggleView1Button->SetTarget(this);
toggleView2Button->SetTarget(this);
}
virtual void MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_TOGGLE_1:
{
if (toggledView1->IsHidden(toggledView1))
toggledView1->Show();
else
toggledView1->Hide();
break;
}
case MSG_TOGGLE_2:
{
if (toggledView2->IsHidden(toggledView2))
toggledView2->Show();
else
toggledView2->Hide();
break;
}
default:
BHandler::MessageReceived(message);
break;
}
}
private:
BButton* toggleView1Button;
BButton* toggleView2Button;
TestView* toggledView1;
TestView* toggledView2;
};
struct GroupLayoutHeightForWidthTestHorizontal1 : public Test {
GroupLayoutHeightForWidthTestHorizontal1()
: Test("Group, height for width, h",
"Horizontal BGroupLayout with height for width view.")
{
BLayoutBuilder::Group<>(rootView, B_HORIZONTAL)
.AddGroup(B_VERTICAL, 10, 0)
.Add(aspectRatioButton = new BRadioButton("fixed aspect ratio",
new BMessage(MSG_FIXED_ASPECT_RATIO)))
.Add(sumButton = new BRadioButton("fixed sum",
new BMessage(MSG_FIXED_SUM)))
.Add(productButton = new BRadioButton("fixed product",
new BMessage(MSG_FIXED_PRODUCT)))
.AddGlue()
.End()
.AddGroup(B_VERTICAL, 10)
.AddGroup(B_HORIZONTAL, 10)
.Add(new TestView())
.Add(new TestView())
.Add(new TestView())
.End()
.AddGroup(B_HORIZONTAL, 10)
.Add(new TestView())
.Add(heightForWidthView = new HeightForWidthTestView(kRed,
FIXED_ASPECT_RATIO, 0.5f))
.Add(new TestView())
.End()
.AddGroup(B_HORIZONTAL, 10)
.Add(new TestView())
.Add(new TestView())
.Add(new TestView())
.End()
.End()
;
aspectRatioButton->SetValue(1);
}
virtual void RegisterListeners()
{
aspectRatioButton->SetTarget(this);
sumButton->SetTarget(this);
productButton->SetTarget(this);
}
virtual void MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_FIXED_ASPECT_RATIO:
{
heightForWidthView->SetType(FIXED_ASPECT_RATIO, 0.5f);
break;
}
case MSG_FIXED_SUM:
{
heightForWidthView->SetType(FIXED_SUM, 200);
break;
}
case MSG_FIXED_PRODUCT:
{
heightForWidthView->SetType(FIXED_PRODUCT, 40000);
break;
}
default:
BHandler::MessageReceived(message);
break;
}
}
private:
BRadioButton* aspectRatioButton;
BRadioButton* sumButton;
BRadioButton* productButton;
HeightForWidthTestView* heightForWidthView;
};
struct GroupLayoutHeightForWidthTestVertical1 : public Test {
GroupLayoutHeightForWidthTestVertical1()
: Test("Group, height for width, v",
"Vertical BGroupLayout with height for width view.")
{
BLayoutBuilder::Group<>(rootView, B_HORIZONTAL)
.AddGroup(B_VERTICAL, 10, 0)
.Add(aspectRatioButton = new BRadioButton("fixed aspect ratio",
new BMessage(MSG_FIXED_ASPECT_RATIO)))
.Add(sumButton = new BRadioButton("fixed sum",
new BMessage(MSG_FIXED_SUM)))
.Add(productButton = new BRadioButton("fixed product",
new BMessage(MSG_FIXED_PRODUCT)))
.AddGlue()
.End()
.AddGroup(B_HORIZONTAL, 10)
.AddGroup(B_VERTICAL, 10)
.Add(new TestView())
.Add(new TestView())
.Add(new TestView())
.End()
.AddGroup(B_VERTICAL, 10)
.Add(new TestView())
.Add(heightForWidthView = new HeightForWidthTestView(kRed,
FIXED_ASPECT_RATIO, 0.5f))
.Add(new TestView())
.End()
.AddGroup(B_VERTICAL, 10)
.Add(new TestView())
.Add(new TestView())
.Add(new TestView())
.End()
.End()
;
aspectRatioButton->SetValue(1);
}
virtual void RegisterListeners()
{
aspectRatioButton->SetTarget(this);
sumButton->SetTarget(this);
productButton->SetTarget(this);
}
virtual void MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_FIXED_ASPECT_RATIO:
{
heightForWidthView->SetType(FIXED_ASPECT_RATIO, 0.5f);
break;
}
case MSG_FIXED_SUM:
{
heightForWidthView->SetType(FIXED_SUM, 200);
break;
}
case MSG_FIXED_PRODUCT:
{
heightForWidthView->SetType(FIXED_PRODUCT, 40000);
break;
}
default:
BHandler::MessageReceived(message);
break;
}
}
private:
BRadioButton* aspectRatioButton;
BRadioButton* sumButton;
BRadioButton* productButton;
HeightForWidthTestView* heightForWidthView;
};
struct GridLayoutHeightForWidthTest1 : public Test {
GridLayoutHeightForWidthTest1()
: Test("Grid, height for width",
"BGridLayout with height for width view.")
{
BLayoutBuilder::Group<>(rootView, B_HORIZONTAL)
.AddGroup(B_VERTICAL, B_USE_DEFAULT_SPACING, 0)
.Add(aspectRatioButton = new BRadioButton("fixed aspect ratio",
new BMessage(MSG_FIXED_ASPECT_RATIO)))
.Add(sumButton = new BRadioButton("fixed sum",
new BMessage(MSG_FIXED_SUM)))
.Add(productButton = new BRadioButton("fixed product",
new BMessage(MSG_FIXED_PRODUCT)))
.AddGlue()
.End()
.AddGrid()
.Add(new TestView(), 0, 0, 3, 1)
.Add(new TestView(), 3, 0)
.Add(new TestView(), 4, 0)
.Add(new TestView(), 0, 1)
.Add(new TestView(), 1, 1)
.Add(new TestView(), 2, 1)
.Add(new TestView(), 3, 1)
.Add(new TestView(), 4, 1)
.Add(new TestView(), 0, 2)
.Add(heightForWidthView = new HeightForWidthTestView(kRed,
FIXED_ASPECT_RATIO, 0.5f), 1, 2, 2, 2)
.Add(new TestView(), 3, 2)
.Add(new TestView(), 4, 2)
.Add(new TestView(), 0, 3)
.Add(new TestView(), 3, 3)
.Add(new TestView(), 4, 3)
.SetColumnWeight(0, 1)
.SetColumnWeight(1, 2)
.SetColumnWeight(2, 3)
.SetColumnWeight(3, 4)
.SetColumnWeight(4, 5)
.SetRowWeight(0, 1)
.SetRowWeight(1, 2)
.SetRowWeight(2, 3)
.SetRowWeight(3, 4);
aspectRatioButton->SetValue(1);
}
virtual void RegisterListeners()
{
aspectRatioButton->SetTarget(this);
sumButton->SetTarget(this);
productButton->SetTarget(this);
}
virtual void MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_FIXED_ASPECT_RATIO:
{
heightForWidthView->SetType(FIXED_ASPECT_RATIO, 0.5f);
break;
}
case MSG_FIXED_SUM:
{
heightForWidthView->SetType(FIXED_SUM, 200);
break;
}
case MSG_FIXED_PRODUCT:
{
heightForWidthView->SetType(FIXED_PRODUCT, 40000);
break;
}
default:
BHandler::MessageReceived(message);
break;
}
}
private:
BRadioButton* aspectRatioButton;
BRadioButton* sumButton;
BRadioButton* productButton;
HeightForWidthTestView* heightForWidthView;
};
struct SplitterGroupLayoutHeightForWidthTest1 : public Test {
SplitterGroupLayoutHeightForWidthTest1()
: Test("Group, splitters, height for width",
"Horizontal BGroupLayout with height for width view and "
"BSplitters.")
{
BLayoutBuilder::Group<>(rootView, B_HORIZONTAL)
.AddGroup(B_VERTICAL, B_USE_DEFAULT_SPACING, 0)
.Add(aspectRatioButton = new BRadioButton("fixed aspect ratio",
new BMessage(MSG_FIXED_ASPECT_RATIO)))
.Add(sumButton = new BRadioButton("fixed sum",
new BMessage(MSG_FIXED_SUM)))
.Add(productButton = new BRadioButton("fixed product",
new BMessage(MSG_FIXED_PRODUCT)))
.AddGlue()
.End()
.AddSplit(B_VERTICAL, B_USE_DEFAULT_SPACING, 1)
.AddSplit(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 1)
.Add(new TestView(), 1)
.Add(new TestView(), 2)
.Add(new TestView(), 3)
.End()
.SetCollapsible(false)
.AddSplit(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 2)
.Add(new TestView())
.Add(heightForWidthView = new HeightForWidthTestView(kRed,
FIXED_ASPECT_RATIO, 0.5f))
.Add(new TestView())
.End()
.AddSplit(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 3)
.Add(new TestView(), 3)
.Add(new TestView(), 2)
.Add(new TestView(), 1)
.End()
.SetCollapsible(false);
aspectRatioButton->SetValue(1);
}
virtual void RegisterListeners()
{
aspectRatioButton->SetTarget(this);
sumButton->SetTarget(this);
productButton->SetTarget(this);
}
virtual void MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_FIXED_ASPECT_RATIO:
{
heightForWidthView->SetType(FIXED_ASPECT_RATIO, 0.5f);
break;
}
case MSG_FIXED_SUM:
{
heightForWidthView->SetType(FIXED_SUM, 200);
break;
}
case MSG_FIXED_PRODUCT:
{
heightForWidthView->SetType(FIXED_PRODUCT, 40000);
break;
}
default:
BHandler::MessageReceived(message);
break;
}
}
private:
BRadioButton* aspectRatioButton;
BRadioButton* sumButton;
BRadioButton* productButton;
HeightForWidthTestView* heightForWidthView;
};
struct SplitterGridLayoutHeightForWidthTest1 : public Test {
SplitterGridLayoutHeightForWidthTest1()
: Test("Grid, splitters, height for width",
"BGridLayout with height for width view and horizontal BSplitters.")
{
BGridLayout* layouts[3];
BLayoutBuilder::Group<>(rootView, B_HORIZONTAL, B_USE_DEFAULT_SPACING)
.AddGroup(B_VERTICAL, B_USE_DEFAULT_SPACING, 0)
.Add(aspectRatioButton = new BRadioButton("fixed aspect ratio",
new BMessage(MSG_FIXED_ASPECT_RATIO)))
.Add(sumButton = new BRadioButton("fixed sum",
new BMessage(MSG_FIXED_SUM)))
.Add(productButton = new BRadioButton("fixed product",
new BMessage(MSG_FIXED_PRODUCT)))
.AddGlue()
.End()
.AddSplit(B_HORIZONTAL)
.AddGrid(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, 6)
.GetLayout(&layouts[0])
.Add(new TestView(), 0, 0, 3, 1)
.Add(new TestView(), 0, 1)
.Add(new TestView(), 1, 1)
.Add(new TestView(), 2, 1)
.Add(new TestView(), 0, 2)
.Add(heightForWidthView = new HeightForWidthTestView(kRed,
FIXED_ASPECT_RATIO, 0.5f), 1, 2, 2, 2)
.Add(new TestView(), 0, 3)
.SetColumnWeight(0, 1)
.SetColumnWeight(1, 2)
.SetColumnWeight(2, 3)
.End()
.AddGrid(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, 4)
.GetLayout(&layouts[1])
.Add(new TestView(), 0, 0)
.Add(new TestView(), 0, 1)
.Add(new TestView(), 0, 2)
.Add(new TestView(), 0, 3)
.End()
.AddGrid(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, 5)
.GetLayout(&layouts[2])
.Add(new TestView(), 0, 0)
.Add(new TestView(), 0, 1)
.Add(new TestView(), 0, 2)
.Add(new TestView(), 0, 3);
for (int i = 0; i < 3; i++) {
layouts[i]->SetRowWeight(0, 1);
layouts[i]->SetRowWeight(1, 2);
layouts[i]->SetRowWeight(2, 3);
layouts[i]->SetRowWeight(3, 4);
}
layouts[0]->AlignLayoutWith(layouts[1], B_VERTICAL);
layouts[0]->AlignLayoutWith(layouts[2], B_VERTICAL);
aspectRatioButton->SetValue(1);
}
virtual void RegisterListeners()
{
aspectRatioButton->SetTarget(this);
sumButton->SetTarget(this);
productButton->SetTarget(this);
}
virtual void MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_FIXED_ASPECT_RATIO:
{
heightForWidthView->SetType(FIXED_ASPECT_RATIO, 0.5f);
break;
}
case MSG_FIXED_SUM:
{
heightForWidthView->SetType(FIXED_SUM, 200);
break;
}
case MSG_FIXED_PRODUCT:
{
heightForWidthView->SetType(FIXED_PRODUCT, 40000);
break;
}
default:
BHandler::MessageReceived(message);
break;
}
}
private:
BRadioButton* aspectRatioButton;
BRadioButton* sumButton;
BRadioButton* productButton;
HeightForWidthTestView* heightForWidthView;
};
struct LabelTest1 : public Test {
LabelTest1()
: Test("BTextControl, BMenuField, grid",
"Aligning BTextControl/BMenuField labels using a 2 column "
"BGridLayout.")
{
textControl1 = new BTextControl("Label", NULL, NULL);
textControl2 = new BTextControl("Long Label", NULL, NULL);
textControl3 = new BTextControl("Very Long Label", NULL, NULL);
menuField1 = new BMenuField("Label", new BMenu("Options"));
menuField2 = new BMenuField("Long Label",
new BMenu("More Options"));
menuField3 = new BMenuField("Very Long Label",
new BMenu("Obscure Options"));
BLayoutBuilder::Group<>(rootView, B_VERTICAL)
.AddGroup(B_HORIZONTAL)
.Add(changeLabelsButton = new BButton("Random Labels",
new BMessage(MSG_TOGGLE_1)))
.AddGlue()
.End()
.AddGlue()
.AddGrid()
.Add(BSpaceLayoutItem::CreateGlue(), 0, 0)
.Add(BSpaceLayoutItem::CreateGlue(), 1, 0)
.Add(textControl1->CreateLabelLayoutItem(), 0, 1)
.Add(textControl1->CreateTextViewLayoutItem(), 1, 1)
.Add(textControl2->CreateLabelLayoutItem(), 0, 2)
.Add(textControl2->CreateTextViewLayoutItem(), 1, 2)
.Add(textControl3->CreateLabelLayoutItem(), 0, 3)
.Add(textControl3->CreateTextViewLayoutItem(), 1, 3)
.Add(menuField1->CreateLabelLayoutItem(), 0, 4)
.Add(menuField1->CreateMenuBarLayoutItem(), 1, 4)
.Add(menuField2->CreateLabelLayoutItem(), 0, 5)
.Add(menuField2->CreateMenuBarLayoutItem(), 1, 5)
.Add(menuField3->CreateLabelLayoutItem(), 0, 6)
.Add(menuField3->CreateMenuBarLayoutItem(), 1, 6)
.Add(BSpaceLayoutItem::CreateGlue(), 0, 7)
.Add(BSpaceLayoutItem::CreateGlue(), 1, 7)
.End()
.AddGlue();
}
virtual void RegisterListeners()
{
changeLabelsButton->SetTarget(this);
}
virtual void MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_TOGGLE_1:
{
BTextControl* textControls[] = {
textControl1, textControl2, textControl3
};
BMenuField* menuFields[] = {
menuField1, menuField2, menuField3
};
for (int i = 0; i < 3; i++) {
BTextControl* textControl = textControls[i];
BMenuField* menuField = menuFields[i];
textControl->SetLabel(_RandomLabel().String());
menuField->SetLabel(_RandomLabel().String());
}
}
default:
BHandler::MessageReceived(message);
break;
}
}
BString _RandomLabel() const
{
const char* digits = "0123456789";
int length = rand() % 20;
BString label("Random ");
for (int k = 0; k < length; k++)
label.Append(digits[k % 10], 1);
return label;
}
private:
BButton* changeLabelsButton;
BTextControl* textControl1;
BTextControl* textControl2;
BTextControl* textControl3;
BMenuField* menuField1;
BMenuField* menuField2;
BMenuField* menuField3;
};
class TestWindow : public BWindow {
public:
TestWindow()
: BWindow(BRect(100, 100, 700, 500), "LayoutTest1",
B_TITLED_WINDOW,
B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE
| B_AUTO_UPDATE_SIZE_LIMITS)
{
fTestList = new BListView(BRect(0, 0, 10, 10), "test list",
B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL);
BView* scrollView = new BScrollView("test scroll view", fTestList);
scrollView->SetExplicitMaxSize(BSize(190, B_SIZE_UNLIMITED));
fTestCardLayout = new BCardLayout();
BView* cardView = new BView("card view", 0, fTestCardLayout);
BLayoutBuilder::Group<>(this, B_HORIZONTAL)
.SetInsets(B_USE_WINDOW_INSETS)
.Add(scrollView)
.Add(cardView);
_AddTest(new GroupLayoutTest1());
_AddTest(new GroupAlignedLayoutTest1());
_AddTest(new GridLayoutTest1());
_AddTest(new SplitterGroupLayoutTest1());
_AddTest(new SplitterGroupLayoutTest2());
_AddTest(new SplitterGridLayoutTest1());
_AddTest(new SplitterGridLayoutTest2());
_AddTest(new GroupLayoutHeightForWidthTestHorizontal1());
_AddTest(new GroupLayoutHeightForWidthTestVertical1());
_AddTest(new GridLayoutHeightForWidthTest1());
_AddTest(new SplitterGroupLayoutHeightForWidthTest1());
_AddTest(new SplitterGridLayoutHeightForWidthTest1());
_AddTest(new LabelTest1());
fTestList->SetSelectionMessage(new BMessage(MSG_TEST_SELECTED));
_DumpViewHierarchy(GetLayout()->Owner());
}
virtual void MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_TEST_SELECTED:
fTestCardLayout->SetVisibleItem(fTestList->CurrentSelection());
break;
default:
BWindow::MessageReceived(message);
break;
}
}
private:
void _AddTest(Test* test) {
fTestList->AddItem(new BStringItem(test->name.String()));
BGroupView* containerView = new BGroupView(B_VERTICAL, 0);
BStringView* descriptionView = new BStringView("test description",
test->description.String());
descriptionView->SetExplicitMinSize(BSize(0, B_SIZE_UNSET));
containerView->AddChild(descriptionView);
containerView->GroupLayout()->AddItem(
BSpaceLayoutItem::CreateVerticalStrut(10));
containerView->GroupLayout()->AddItem(
BSpaceLayoutItem::CreateGlue(), 0);
BGroupView* wrapperView = new BGroupView(B_HORIZONTAL, 0);
containerView->AddChild(wrapperView);
wrapperView->AddChild(test->rootView);
containerView->GroupLayout()->AddItem(
BSpaceLayoutItem::CreateGlue(), 0);
wrapperView->SetExplicitMaxSize(
BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED));
containerView->SetExplicitMaxSize(
BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED));
fTestCardLayout->AddView(containerView);
AddHandler(test);
test->RegisterListeners();
}
void _DumpViewHierarchy(BView* view, int32 indent = 0)
{
for (int32 i = 0; i < indent; i++)
printf(" ");
printf("view: %p", view);
for (int32 i = 0; i < 15 - indent; i++)
printf(" ");
printf("(%s)\n", typeid(*view).name());
int32 count = view->CountChildren();
for (int32 i = 0; i < count; i++)
_DumpViewHierarchy(view->ChildAt(i), indent + 1);
}
private:
BListView* fTestList;
BCardLayout* fTestCardLayout;
};
int
main()
{
BApplication app("application/x-vnd.haiku.layout-test1");
BWindow* window = new TestWindow;
window->Show();
app.Run();
return 0;
}