root/headers/os/interface/LayoutBuilder.h
/*
 * Copyright 2009-2015, Haiku, Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 */
#ifndef _LAYOUT_BUILDER_H
#define _LAYOUT_BUILDER_H


#include <new>

#include <CardLayout.h>
#include <CardView.h>
#include <GridLayout.h>
#include <GridView.h>
#include <GroupLayout.h>
#include <GroupView.h>
#include <Menu.h>
#include <MenuField.h>
#include <MenuItem.h>
#include <SpaceLayoutItem.h>
#include <SplitView.h>
#include <TextControl.h>
#include <Window.h>


namespace BLayoutBuilder {

template<typename ParentBuilder> class Base;
template<typename ParentBuilder = void*> class Group;
template<typename ParentBuilder = void*> class Grid;
template<typename ParentBuilder = void*> class Split;
template<typename ParentBuilder = void*> class Cards;
template<typename ParentBuilder = void*> class Menu;
template<typename ParentBuilder = void*> class MenuItem;


template<typename ParentBuilder>
class Base {
protected:
        inline                                          Base();

public:
        inline  void                            SetParent(ParentBuilder* parent);
                // conceptually private
        inline  ParentBuilder&          End();

protected:
                        ParentBuilder*          fParent;
};


template<typename ParentBuilder>
class Group : public Base<ParentBuilder> {
public:
        typedef Group<ParentBuilder>    ThisBuilder;
        typedef Group<ThisBuilder>              GroupBuilder;
        typedef Grid<ThisBuilder>               GridBuilder;
        typedef Split<ThisBuilder>              SplitBuilder;
        typedef Cards<ThisBuilder>              CardBuilder;

public:
        inline                                          Group(orientation orientation = B_HORIZONTAL,
                                                                        float spacing = B_USE_DEFAULT_SPACING);
        inline                                          Group(BWindow* window,
                                                                        orientation orientation = B_HORIZONTAL,
                                                                        float spacing = B_USE_DEFAULT_SPACING);
        inline                                          Group(BView* view,
                                                                        orientation orientation = B_HORIZONTAL,
                                                                        float spacing = B_USE_DEFAULT_SPACING);
        inline                                          Group(BGroupLayout* layout);
        inline                                          Group(BGroupView* view);

        inline  BGroupLayout*           Layout() const;
        inline  BView*                          View() const;
        inline  ThisBuilder&            GetLayout(BGroupLayout** _layout);
        inline  ThisBuilder&            GetView(BView** _view);

        inline  ThisBuilder&            Add(BView* view);
        inline  ThisBuilder&            Add(BView* view, float weight);
        inline  ThisBuilder&            Add(BLayoutItem* item);
        inline  ThisBuilder&            Add(BLayoutItem* item, float weight);

        inline  GroupBuilder            AddGroup(orientation orientation,
                                                                        float spacing = B_USE_DEFAULT_SPACING,
                                                                        float weight = 1.0f);
        inline  GroupBuilder            AddGroup(BGroupView* groupView,
                                                                        float weight = 1.0f);
        inline  GroupBuilder            AddGroup(BGroupLayout* groupLayout,
                                                                        float weight = 1.0f);

        inline  GridBuilder                     AddGrid(float horizontal
                                                                                = B_USE_DEFAULT_SPACING,
                                                                        float vertical = B_USE_DEFAULT_SPACING,
                                                                        float weight = 1.0f);
        inline  GridBuilder                     AddGrid(BGridLayout* gridLayout,
                                                                        float weight = 1.0f);
        inline  GridBuilder                     AddGrid(BGridView* gridView,
                                                                        float weight = 1.0f);

        inline  SplitBuilder            AddSplit(orientation orientation,
                                                                        float spacing = B_USE_DEFAULT_SPACING,
                                                                        float weight = 1.0f);
        inline  SplitBuilder            AddSplit(BSplitView* splitView,
                                                                        float weight = 1.0f);

        inline  CardBuilder                     AddCards(float weight = 1.0f);
        inline  CardBuilder                     AddCards(BCardLayout* cardLayout,
                                                                        float weight = 1.0f);
        inline  CardBuilder                     AddCards(BCardView* cardView,
                                                                        float weight = 1.0f);

        inline  ThisBuilder&            AddGlue(float weight = 1.0f);
        inline  ThisBuilder&            AddStrut(float size);

        inline  ThisBuilder&            SetInsets(float left, float top, float right,
                                                                        float bottom);
        inline  ThisBuilder&            SetInsets(float horizontal, float vertical);
        inline  ThisBuilder&            SetInsets(float insets);

        inline  ThisBuilder&            SetExplicitMinSize(BSize size);
        inline  ThisBuilder&            SetExplicitMaxSize(BSize size);
        inline  ThisBuilder&            SetExplicitPreferredSize(BSize size);
        inline  ThisBuilder&            SetExplicitAlignment(BAlignment alignment);

        inline                                          operator BGroupLayout*();

private:
                        BGroupLayout*           fLayout;
};


template<typename ParentBuilder>
class Grid : public Base<ParentBuilder> {
public:
        typedef Grid<ParentBuilder>             ThisBuilder;
        typedef Group<ThisBuilder>              GroupBuilder;
        typedef Grid<ThisBuilder>               GridBuilder;
        typedef Split<ThisBuilder>              SplitBuilder;
        typedef Cards<ThisBuilder>              CardBuilder;

public:
        inline                                          Grid(float horizontal
                                                                                = B_USE_DEFAULT_SPACING,
                                                                        float vertical = B_USE_DEFAULT_SPACING);
        inline                                          Grid(BWindow* window,
                                                                        float horizontal = B_USE_DEFAULT_SPACING,
                                                                        float vertical = B_USE_DEFAULT_SPACING);
        inline                                          Grid(BView* view,
                                                                        float horizontal = B_USE_DEFAULT_SPACING,
                                                                        float vertical = B_USE_DEFAULT_SPACING);
        inline                                          Grid(BGridLayout* layout);
        inline                                          Grid(BGridView* view);

        inline  BGridLayout*            Layout() const;
        inline  BView*                          View() const;
        inline  ThisBuilder&            GetLayout(BGridLayout** _layout);
        inline  ThisBuilder&            GetView(BView** _view);

        inline  ThisBuilder&            Add(BView* view, int32 column, int32 row,
                                                                        int32 columnCount = 1, int32 rowCount = 1);
        inline  ThisBuilder&            Add(BLayoutItem* item, int32 column, int32 row,
                                                                        int32 columnCount = 1, int32 rowCount = 1);
        inline  ThisBuilder&            AddMenuField(BMenuField* menuField,
                                                                        int32 column, int32 row,
                                                                        alignment labelAlignment
                                                                                = B_ALIGN_HORIZONTAL_UNSET,
                                                                        int32 labelColumnCount = 1,
                                                                        int32 fieldColumnCount = 1,
                                                                        int32 rowCount = 1);
        inline  ThisBuilder&            AddTextControl(BTextControl* textControl,
                                                                        int32 column, int32 row,
                                                                        alignment labelAlignment
                                                                                = B_ALIGN_HORIZONTAL_UNSET,
                                                                        int32 labelColumnCount = 1,
                                                                        int32 textColumnCount = 1,
                                                                        int32 rowCount = 1);

        inline  GroupBuilder            AddGroup(orientation orientation,
                                                                        float spacing, int32 column, int32 row,
                                                                        int32 columnCount = 1, int32 rowCount = 1);
        inline  GroupBuilder            AddGroup(BGroupView* groupView, int32 column,
                                                                        int32 row, int32 columnCount = 1,
                                                                        int32 rowCount = 1);
        inline  GroupBuilder            AddGroup(BGroupLayout* groupLayout,
                                                                        int32 column, int32 row,
                                                                        int32 columnCount = 1, int32 rowCount = 1);

        inline  GridBuilder                     AddGrid(float horizontalSpacing,
                                                                        float verticalSpacing, int32 column,
                                                                        int32 row, int32 columnCount = 1,
                                                                        int32 rowCount = 1);
        inline  GridBuilder                     AddGrid(BGridLayout* gridLayout,
                                                                        int32 column, int32 row,
                                                                        int32 columnCount = 1, int32 rowCount = 1);
        inline  GridBuilder                     AddGrid(BGridView* gridView,
                                                                        int32 column, int32 row,
                                                                        int32 columnCount = 1, int32 rowCount = 1);

        inline  SplitBuilder            AddSplit(orientation orientation,
                                                                        float spacing, int32 column, int32 row,
                                                                        int32 columnCount = 1, int32 rowCount = 1);
        inline  SplitBuilder            AddSplit(BSplitView* splitView, int32 column,
                                                                        int32 row, int32 columnCount = 1,
                                                                        int32 rowCount = 1);

        inline  CardBuilder                     AddCards(int32 column, int32 row,
                                                                        int32 columnCount = 1, int32 rowCount = 1);
        inline  CardBuilder                     AddCards(BCardLayout* cardLayout, int32 column,
                                                                        int32 row, int32 columnCount = 1,
                                                                        int32 rowCount = 1);
        inline  CardBuilder                     AddCards(BCardView* cardView, int32 column,
                                                                        int32 row, int32 columnCount = 1,
                                                                        int32 rowCount = 1);

        inline  ThisBuilder&            AddGlue(int32 column, int32 row,
                                                                        int32 columnCount = 1, int32 rowCount = 1);

        inline  ThisBuilder&            SetHorizontalSpacing(float spacing);
        inline  ThisBuilder&            SetVerticalSpacing(float spacing);
        inline  ThisBuilder&            SetSpacing(float horizontal, float vertical);

        inline  ThisBuilder&            SetColumnWeight(int32 column, float weight);
        inline  ThisBuilder&            SetRowWeight(int32 row, float weight);

        inline  ThisBuilder&            SetInsets(float left, float top, float right,
                                                                        float bottom);
        inline  ThisBuilder&            SetInsets(float horizontal, float vertical);
        inline  ThisBuilder&            SetInsets(float insets);

        inline  ThisBuilder&            SetExplicitMinSize(BSize size);
        inline  ThisBuilder&            SetExplicitMaxSize(BSize size);
        inline  ThisBuilder&            SetExplicitPreferredSize(BSize size);
        inline  ThisBuilder&            SetExplicitAlignment(BAlignment alignment);

        inline                                          operator BGridLayout*();

private:
                        BGridLayout*            fLayout;
};


template<typename ParentBuilder>
class Split : public Base<ParentBuilder> {
public:
        typedef Split<ParentBuilder>    ThisBuilder;
        typedef Group<ThisBuilder>              GroupBuilder;
        typedef Grid<ThisBuilder>               GridBuilder;
        typedef Split<ThisBuilder>              SplitBuilder;
        typedef Cards<ThisBuilder>              CardBuilder;

public:
        inline                                          Split(orientation orientation = B_HORIZONTAL,
                                                                        float spacing = B_USE_DEFAULT_SPACING);
        inline                                          Split(BSplitView* view);

        inline  BSplitView*                     View() const;
        inline  ThisBuilder&            GetView(BView** _view);
        inline  ThisBuilder&            GetSplitView(BSplitView** _view);

        inline  ThisBuilder&            Add(BView* view);
        inline  ThisBuilder&            Add(BView* view, float weight);
        inline  ThisBuilder&            Add(BLayoutItem* item);
        inline  ThisBuilder&            Add(BLayoutItem* item, float weight);

        inline  GroupBuilder            AddGroup(orientation orientation,
                                                                        float spacing = B_USE_DEFAULT_SPACING,
                                                                        float weight = 1.0f);
        inline  GroupBuilder            AddGroup(BGroupView* groupView,
                                                                        float weight = 1.0f);
        inline  GroupBuilder            AddGroup(BGroupLayout* groupLayout,
                                                                        float weight = 1.0f);

        inline  GridBuilder                     AddGrid(float horizontal
                                                                                        = B_USE_DEFAULT_SPACING,
                                                                        float vertical = B_USE_DEFAULT_SPACING,
                                                                        float weight = 1.0f);
        inline  GridBuilder                     AddGrid(BGridView* gridView,
                                                                        float weight = 1.0f);
        inline  GridBuilder                     AddGrid(BGridLayout* gridLayout,
                                                                        float weight = 1.0f);

        inline  SplitBuilder            AddSplit(orientation orientation,
                                                                        float spacing = B_USE_DEFAULT_SPACING,
                                                                        float weight = 1.0f);
        inline  SplitBuilder            AddSplit(BSplitView* splitView,
                                                                        float weight = 1.0f);

        inline  CardBuilder                     AddCards(float weight = 1.0f);
        inline  CardBuilder                     AddCards(BCardLayout* cardLayout,
                                                                        float weight = 1.0f);
        inline  CardBuilder                     AddCards(BCardView* cardView,
                                                                        float weight = 1.0f);

        inline  ThisBuilder&            SetCollapsible(bool collapsible);
        inline  ThisBuilder&            SetCollapsible(int32 index, bool collapsible);
        inline  ThisBuilder&            SetCollapsible(int32 first, int32 last,
                                                                        bool collapsible);

        inline  ThisBuilder&            SetInsets(float left, float top, float right,
                                                                        float bottom);
        inline  ThisBuilder&            SetInsets(float horizontal, float vertical);
        inline  ThisBuilder&            SetInsets(float insets);

        inline                                          operator BSplitView*();

private:
                        BSplitView*                     fView;
};

template<typename ParentBuilder>
class Cards : public Base<ParentBuilder> {
public:
        typedef Cards<ParentBuilder>    ThisBuilder;
        typedef Group<ThisBuilder>              GroupBuilder;
        typedef Grid<ThisBuilder>               GridBuilder;
        typedef Split<ThisBuilder>              SplitBuilder;
        typedef Cards<ThisBuilder>              CardBuilder;

public:
        inline                                          Cards();
        inline                                          Cards(BWindow* window);
        inline                                          Cards(BView* view);
        inline                                          Cards(BCardLayout* layout);
        inline                                          Cards(BCardView* view);

        inline  BCardLayout*            Layout() const;
        inline  BView*                          View() const;
        inline  ThisBuilder&            GetLayout(BCardLayout** _layout);
        inline  ThisBuilder&            GetView(BView** _view);

        inline  ThisBuilder&            Add(BView* view);
        inline  ThisBuilder&            Add(BLayoutItem* item);

        inline  GroupBuilder            AddGroup(orientation orientation,
                                                                        float spacing = B_USE_DEFAULT_SPACING);
        inline  GroupBuilder            AddGroup(BGroupView* groupView);
        inline  GroupBuilder            AddGroup(BGroupLayout* groupLayout);

        inline  GridBuilder                     AddGrid(float horizontal
                                                                                = B_USE_DEFAULT_SPACING,
                                                                        float vertical = B_USE_DEFAULT_SPACING);
        inline  GridBuilder                     AddGrid(BGridLayout* gridLayout);
        inline  GridBuilder                     AddGrid(BGridView* gridView);

        inline  SplitBuilder            AddSplit(orientation orientation,
                                                                        float spacing = B_USE_DEFAULT_SPACING);
        inline  SplitBuilder            AddSplit(BSplitView* splitView);

        inline  CardBuilder                     AddCards();
        inline  CardBuilder                     AddCards(BCardLayout* cardLayout);
        inline  CardBuilder                     AddCards(BCardView* cardView);

        inline  ThisBuilder&            SetExplicitMinSize(BSize size);
        inline  ThisBuilder&            SetExplicitMaxSize(BSize size);
        inline  ThisBuilder&            SetExplicitPreferredSize(BSize size);
        inline  ThisBuilder&            SetExplicitAlignment(BAlignment alignment);

        inline  ThisBuilder&            SetVisibleItem(int32 index);

        inline                                          operator BCardLayout*();

private:
                        BCardLayout*            fLayout;
};


template<typename ParentBuilder>
class Menu : public Base<ParentBuilder> {
public:
        typedef Menu<ParentBuilder>             ThisBuilder;
        typedef MenuItem<ParentBuilder> ItemBuilder;
        typedef Menu<ThisBuilder>               MenuBuilder;

public:
        inline                                          Menu(BMenu* menu);

        inline  ThisBuilder&            GetMenu(BMenu*& _menu);

        inline  ItemBuilder                     AddItem(BMenuItem* item);
        inline  ItemBuilder                     AddItem(BMenu* menu);
        inline  ItemBuilder                     AddItem(const char* label, BMessage* message,
                                                                        char shortcut = 0, uint32 modifiers = 0);
        inline  ItemBuilder                     AddItem(const char* label, uint32 messageWhat,
                                                                        char shortcut = 0, uint32 modifiers = 0);

        inline  MenuBuilder                     AddMenu(BMenu* menu);
        inline  MenuBuilder                     AddMenu(const char* title,
                                                                        menu_layout layout = B_ITEMS_IN_COLUMN);

        inline  ThisBuilder&            AddSeparator();

private:
                        BMenu*                          fMenu;
};


template<typename ParentBuilder>
class MenuItem : public Menu<ParentBuilder> {
public:
        typedef MenuItem<ParentBuilder> ThisBuilder;

public:
        inline                                          MenuItem(ParentBuilder* parentBuilder,
                                                                        BMenu* menu, BMenuItem* item);

        inline  ThisBuilder&            GetItem(BMenuItem*& _item);

        inline  ThisBuilder&            SetEnabled(bool enabled);

private:
                        BMenuItem*                      fMenuItem;
};


// #pragma mark - Base


template<typename ParentBuilder>
Base<ParentBuilder>::Base()
        :
        fParent(NULL)
{
}


template<typename ParentBuilder>
void
Base<ParentBuilder>::SetParent(ParentBuilder* parent)
{
        fParent = parent;
}


template<typename ParentBuilder>
ParentBuilder&
Base<ParentBuilder>::End()
{
        return *fParent;
}


// #pragma mark - Group


template<typename ParentBuilder>
Group<ParentBuilder>::Group(orientation orientation, float spacing)
        :
        fLayout((new BGroupView(orientation, spacing))->GroupLayout())
{
}


template<typename ParentBuilder>
Group<ParentBuilder>::Group(BWindow* window, orientation orientation,
                float spacing)
        :
        fLayout(new BGroupLayout(orientation, spacing))
{
        window->SetLayout(fLayout);
        fLayout->Owner()->AdoptSystemColors();
}


template<typename ParentBuilder>
Group<ParentBuilder>::Group(BView* view, orientation orientation,
                float spacing)
        :
        fLayout(new BGroupLayout(orientation, spacing))
{

        if (view->HasDefaultColors())
                view->AdoptSystemColors();

        view->SetLayout(fLayout);
}


template<typename ParentBuilder>
Group<ParentBuilder>::Group(BGroupLayout* layout)
        :
        fLayout(layout)
{
}


template<typename ParentBuilder>
Group<ParentBuilder>::Group(BGroupView* view)
        :
        fLayout(view->GroupLayout())
{
}


template<typename ParentBuilder>
BGroupLayout*
Group<ParentBuilder>::Layout() const
{
        return fLayout;
}


template<typename ParentBuilder>
BView*
Group<ParentBuilder>::View() const
{
        return fLayout->Owner();
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::ThisBuilder&
Group<ParentBuilder>::GetLayout(BGroupLayout** _layout)
{
        *_layout = fLayout;
        return *this;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::ThisBuilder&
Group<ParentBuilder>::GetView(BView** _view)
{
        *_view = fLayout->Owner();
        return *this;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::ThisBuilder&
Group<ParentBuilder>::Add(BView* view)
{
        fLayout->AddView(view);
        return *this;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::ThisBuilder&
Group<ParentBuilder>::Add(BView* view, float weight)
{
        fLayout->AddView(view, weight);
        return *this;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::ThisBuilder&
Group<ParentBuilder>::Add(BLayoutItem* item)
{
        fLayout->AddItem(item);
        return *this;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::ThisBuilder&
Group<ParentBuilder>::Add(BLayoutItem* item, float weight)
{
        fLayout->AddItem(item, weight);
        return *this;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::GroupBuilder
Group<ParentBuilder>::AddGroup(orientation orientation, float spacing,
                float weight)
{
        GroupBuilder builder(new BGroupLayout(orientation, spacing));
        builder.SetParent(this);
        fLayout->AddItem(builder.Layout(), weight);
        return builder;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::GroupBuilder
Group<ParentBuilder>::AddGroup(BGroupView* groupView, float weight)
{
        GroupBuilder builder(groupView);
        builder.SetParent(this);
        fLayout->AddItem(builder.Layout(), weight);
        return builder;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::GroupBuilder
Group<ParentBuilder>::AddGroup(BGroupLayout* groupLayout, float weight)
{
        GroupBuilder builder(groupLayout);
        builder.SetParent(this);
        fLayout->AddItem(builder.Layout(), weight);
        return builder;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::GridBuilder
Group<ParentBuilder>::AddGrid(float horizontalSpacing,
        float verticalSpacing, float weight)
{
        GridBuilder builder(new BGridLayout(horizontalSpacing, verticalSpacing));
        builder.SetParent(this);
        fLayout->AddItem(builder.Layout(), weight);
        return builder;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::GridBuilder
Group<ParentBuilder>::AddGrid(BGridLayout* gridLayout, float weight)
{
        GridBuilder builder(gridLayout);
        builder.SetParent(this);
        fLayout->AddItem(builder.Layout(), weight);
        return builder;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::GridBuilder
Group<ParentBuilder>::AddGrid(BGridView* gridView, float weight)
{
        GridBuilder builder(gridView);
        builder.SetParent(this);
        fLayout->AddItem(builder.Layout(), weight);
        return builder;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::SplitBuilder
Group<ParentBuilder>::AddSplit(orientation orientation, float spacing,
                float weight)
{
        SplitBuilder builder(orientation, spacing);
        builder.SetParent(this);
        fLayout->AddView(builder.View(), weight);
        return builder;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::SplitBuilder
Group<ParentBuilder>::AddSplit(BSplitView* splitView, float weight)
{
        SplitBuilder builder(splitView);
        builder.SetParent(this);
        fLayout->AddView(builder.View(), weight);
        return builder;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::CardBuilder
Group<ParentBuilder>::AddCards(float weight)
{
        CardBuilder builder;
        builder.SetParent(this);
        fLayout->AddView(builder.View(), weight);
        return builder;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::CardBuilder
Group<ParentBuilder>::AddCards(BCardLayout* cardLayout, float weight)
{
        CardBuilder builder(cardLayout);
        builder.SetParent(this);
        fLayout->AddView(builder.View(), weight);
        return builder;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::CardBuilder
Group<ParentBuilder>::AddCards(BCardView* cardView, float weight)
{
        CardBuilder builder(cardView);
        builder.SetParent(this);
        fLayout->AddView(builder.View(), weight);
        return builder;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::ThisBuilder&
Group<ParentBuilder>::AddGlue(float weight)
{
        fLayout->AddItem(BSpaceLayoutItem::CreateGlue(), weight);
        return *this;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::ThisBuilder&
Group<ParentBuilder>::AddStrut(float size)
{
        if (fLayout->Orientation() == B_HORIZONTAL)
                fLayout->AddItem(BSpaceLayoutItem::CreateHorizontalStrut(size));
        else
                fLayout->AddItem(BSpaceLayoutItem::CreateVerticalStrut(size));

        return *this;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::ThisBuilder&
Group<ParentBuilder>::SetInsets(float left, float top, float right,
        float bottom)
{
        fLayout->SetInsets(left, top, right, bottom);
        return *this;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::ThisBuilder&
Group<ParentBuilder>::SetInsets(float horizontal, float vertical)
{
        fLayout->SetInsets(horizontal, vertical);
        return *this;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::ThisBuilder&
Group<ParentBuilder>::SetInsets(float insets)
{
        fLayout->SetInsets(insets);
        return *this;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::ThisBuilder&
Group<ParentBuilder>::SetExplicitMinSize(BSize size)
{
        fLayout->SetExplicitMinSize(size);
        return *this;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::ThisBuilder&
Group<ParentBuilder>::SetExplicitMaxSize(BSize size)
{
        fLayout->SetExplicitMaxSize(size);
        return *this;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::ThisBuilder&
Group<ParentBuilder>::SetExplicitPreferredSize(BSize size)
{
        fLayout->SetExplicitPreferredSize(size);
        return *this;
}


template<typename ParentBuilder>
typename Group<ParentBuilder>::ThisBuilder&
Group<ParentBuilder>::SetExplicitAlignment(BAlignment alignment)
{
        fLayout->SetExplicitAlignment(alignment);
        return *this;
}


template<typename ParentBuilder>
Group<ParentBuilder>::operator BGroupLayout*()
{
        return fLayout;
}


// #pragma mark - Grid


template<typename ParentBuilder>
Grid<ParentBuilder>::Grid(float horizontalSpacing, float verticalSpacing)
        :
        fLayout((new BGridView(horizontalSpacing, verticalSpacing))->GridLayout())
{
}


template<typename ParentBuilder>
Grid<ParentBuilder>::Grid(BWindow* window, float horizontalSpacing,
        float verticalSpacing)
        :
        fLayout(new BGridLayout(horizontalSpacing, verticalSpacing))
{
        window->SetLayout(fLayout);
        fLayout->Owner()->AdoptSystemColors();
}


template<typename ParentBuilder>
Grid<ParentBuilder>::Grid(BView* view, float horizontalSpacing,
        float verticalSpacing)
        :
        fLayout(new BGridLayout(horizontalSpacing, verticalSpacing))
{
        if (view->HasDefaultColors())
                view->AdoptSystemColors();

        view->SetLayout(fLayout);
}


template<typename ParentBuilder>
Grid<ParentBuilder>::Grid(BGridLayout* layout)
        :
        fLayout(layout)
{
}


template<typename ParentBuilder>
Grid<ParentBuilder>::Grid(BGridView* view)
        :
        fLayout(view->GridLayout())
{
}


template<typename ParentBuilder>
BGridLayout*
Grid<ParentBuilder>::Layout() const
{
        return fLayout;
}


template<typename ParentBuilder>
BView*
Grid<ParentBuilder>::View() const
{
        return fLayout->Owner();
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::ThisBuilder&
Grid<ParentBuilder>::GetLayout(BGridLayout** _layout)
{
        *_layout = fLayout;
        return *this;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::ThisBuilder&
Grid<ParentBuilder>::GetView(BView** _view)
{
        *_view = fLayout->Owner();
        return *this;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::ThisBuilder&
Grid<ParentBuilder>::Add(BView* view, int32 column, int32 row,
        int32 columnCount, int32 rowCount)
{
        fLayout->AddView(view, column, row, columnCount, rowCount);
        return *this;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::ThisBuilder&
Grid<ParentBuilder>::Add(BLayoutItem* item, int32 column, int32 row,
        int32 columnCount, int32 rowCount)
{
        fLayout->AddItem(item, column, row, columnCount, rowCount);
        return *this;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::ThisBuilder&
Grid<ParentBuilder>::AddMenuField(BMenuField* menuField, int32 column,
        int32 row, alignment labelAlignment, int32 labelColumnCount,
        int32 fieldColumnCount, int32 rowCount)
{
        BLayoutItem* item = menuField->CreateLabelLayoutItem();
        item->SetExplicitAlignment(
                BAlignment(labelAlignment, B_ALIGN_VERTICAL_UNSET));
        fLayout->AddItem(item, column, row, labelColumnCount, rowCount);
        fLayout->AddItem(menuField->CreateMenuBarLayoutItem(),
                column + labelColumnCount, row, fieldColumnCount, rowCount);
        return *this;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::ThisBuilder&
Grid<ParentBuilder>::AddTextControl(BTextControl* textControl, int32 column,
        int32 row, alignment labelAlignment, int32 labelColumnCount,
        int32 textColumnCount, int32 rowCount)
{
        BLayoutItem* item = textControl->CreateLabelLayoutItem();
        item->SetExplicitAlignment(
                BAlignment(labelAlignment, B_ALIGN_VERTICAL_UNSET));
        fLayout->AddItem(item, column, row, labelColumnCount, rowCount);
        fLayout->AddItem(textControl->CreateTextViewLayoutItem(),
                column + labelColumnCount, row, textColumnCount, rowCount);
        return *this;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::GroupBuilder
Grid<ParentBuilder>::AddGroup(orientation orientation, float spacing,
                int32 column, int32 row, int32 columnCount, int32 rowCount)
{
        GroupBuilder builder(new BGroupLayout(orientation, spacing));
        builder.SetParent(this);
        fLayout->AddItem(builder.Layout(), column, row, columnCount, rowCount);
        return builder;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::GroupBuilder
Grid<ParentBuilder>::AddGroup(BGroupView* groupView, int32 column, int32 row,
        int32 columnCount, int32 rowCount)
{
        GroupBuilder builder(groupView);
        builder.SetParent(this);
        fLayout->AddItem(builder.Layout(), column, row, columnCount, rowCount);
        return builder;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::GroupBuilder
Grid<ParentBuilder>::AddGroup(BGroupLayout* groupLayout, int32 column,
        int32 row, int32 columnCount, int32 rowCount)
{
        GroupBuilder builder(groupLayout);
        builder.SetParent(this);
        fLayout->AddItem(builder.Layout(), column, row, columnCount, rowCount);
        return builder;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::GridBuilder
Grid<ParentBuilder>::AddGrid(float horizontalSpacing, float verticalSpacing,
        int32 column, int32 row, int32 columnCount, int32 rowCount)
{
        GridBuilder builder(new BGridLayout(horizontalSpacing, verticalSpacing));
        builder.SetParent(this);
        fLayout->AddItem(builder.Layout(), column, row, columnCount, rowCount);
        return builder;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::GridBuilder
Grid<ParentBuilder>::AddGrid(BGridView* gridView, int32 column, int32 row,
        int32 columnCount, int32 rowCount)
{
        GridBuilder builder(gridView);
        builder.SetParent(this);
        fLayout->AddView(builder.View(), column, row, columnCount, rowCount);
        return builder;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::SplitBuilder
Grid<ParentBuilder>::AddSplit(orientation orientation, float spacing,
        int32 column, int32 row, int32 columnCount, int32 rowCount)
{
        SplitBuilder builder(orientation, spacing);
        builder.SetParent(this);
        fLayout->AddView(builder.View(), column, row, columnCount, rowCount);
        return builder;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::SplitBuilder
Grid<ParentBuilder>::AddSplit(BSplitView* splitView, int32 column, int32 row,
        int32 columnCount, int32 rowCount)
{
        SplitBuilder builder(splitView);
        builder.SetParent(this);
        fLayout->AddView(builder.View(), column, row, columnCount, rowCount);
        return builder;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::CardBuilder
Grid<ParentBuilder>::AddCards(int32 column, int32 row, int32 columnCount,
        int32 rowCount)
{
        CardBuilder builder;
        builder.SetParent(this);
        fLayout->AddView(builder.View(), column, row, columnCount, rowCount);
        return builder;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::CardBuilder
Grid<ParentBuilder>::AddCards(BCardLayout* cardLayout, int32 column, int32 row,
        int32 columnCount, int32 rowCount)
{
        CardBuilder builder(cardLayout);
        builder.SetParent(this);
        fLayout->AddView(builder.View(), column, row, columnCount, rowCount);
        return builder;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::CardBuilder
Grid<ParentBuilder>::AddCards(BCardView* cardView, int32 column, int32 row,
        int32 columnCount, int32 rowCount)
{
        CardBuilder builder(cardView);
        builder.SetParent(this);
        fLayout->AddView(builder.View(), column, row, columnCount, rowCount);
        return builder;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::ThisBuilder&
Grid<ParentBuilder>::AddGlue(int32 column, int32 row, int32 columnCount,
        int32 rowCount)
{
        fLayout->AddItem(BSpaceLayoutItem::CreateGlue(), column, row, columnCount,
                rowCount);
        return *this;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::ThisBuilder&
Grid<ParentBuilder>::SetHorizontalSpacing(float spacing)
{
        fLayout->SetHorizontalSpacing(spacing);
        return *this;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::ThisBuilder&
Grid<ParentBuilder>::SetVerticalSpacing(float spacing)
{
        fLayout->SetVerticalSpacing(spacing);
        return *this;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::ThisBuilder&
Grid<ParentBuilder>::SetSpacing(float horizontal, float vertical)
{
        fLayout->SetSpacing(horizontal, vertical);
        return *this;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::ThisBuilder&
Grid<ParentBuilder>::SetColumnWeight(int32 column, float weight)
{
        fLayout->SetColumnWeight(column, weight);
        return *this;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::ThisBuilder&
Grid<ParentBuilder>::SetRowWeight(int32 row, float weight)
{
        fLayout->SetRowWeight(row, weight);
        return *this;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::ThisBuilder&
Grid<ParentBuilder>::SetInsets(float left, float top, float right,
        float bottom)
{
        fLayout->SetInsets(left, top, right, bottom);
        return *this;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::ThisBuilder&
Grid<ParentBuilder>::SetInsets(float horizontal, float vertical)
{
        fLayout->SetInsets(horizontal, vertical);
        return *this;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::ThisBuilder&
Grid<ParentBuilder>::SetInsets(float insets)
{
        fLayout->SetInsets(insets);
        return *this;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::ThisBuilder&
Grid<ParentBuilder>::SetExplicitMinSize(BSize size)
{
        fLayout->SetExplicitMinSize(size);
        return *this;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::ThisBuilder&
Grid<ParentBuilder>::SetExplicitMaxSize(BSize size)
{
        fLayout->SetExplicitMaxSize(size);
        return *this;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::ThisBuilder&
Grid<ParentBuilder>::SetExplicitPreferredSize(BSize size)
{
        fLayout->SetExplicitPreferredSize(size);
        return *this;
}


template<typename ParentBuilder>
typename Grid<ParentBuilder>::ThisBuilder&
Grid<ParentBuilder>::SetExplicitAlignment(BAlignment alignment)
{
        fLayout->SetExplicitAlignment(alignment);
        return *this;
}


template<typename ParentBuilder>
Grid<ParentBuilder>::operator BGridLayout*()
{
        return fLayout;
}


// #pragma mark - Split


template<typename ParentBuilder>
Split<ParentBuilder>::Split(orientation orientation, float spacing)
        :
        fView(new BSplitView(orientation, spacing))
{
}


template<typename ParentBuilder>
Split<ParentBuilder>::Split(BSplitView* view)
        :
        fView(view)
{
}


template<typename ParentBuilder>
BSplitView*
Split<ParentBuilder>::View() const
{
        return fView;
}


template<typename ParentBuilder>
typename Split<ParentBuilder>::ThisBuilder&
Split<ParentBuilder>::GetView(BView** _view)
{
        *_view = fView;
        return *this;
}


template<typename ParentBuilder>
typename Split<ParentBuilder>::ThisBuilder&
Split<ParentBuilder>::GetSplitView(BSplitView** _view)
{
        *_view = fView;
        return *this;
}


template<typename ParentBuilder>
typename Split<ParentBuilder>::ThisBuilder&
Split<ParentBuilder>::Add(BView* view)
{
        fView->AddChild(view);
        return *this;
}


template<typename ParentBuilder>
typename Split<ParentBuilder>::ThisBuilder&
Split<ParentBuilder>::Add(BView* view, float weight)
{
        fView->AddChild(view, weight);
        return *this;
}


template<typename ParentBuilder>
typename Split<ParentBuilder>::ThisBuilder&
Split<ParentBuilder>::Add(BLayoutItem* item)
{
        fView->AddChild(item);
        return *this;
}


template<typename ParentBuilder>
typename Split<ParentBuilder>::ThisBuilder&
Split<ParentBuilder>::Add(BLayoutItem* item, float weight)
{
        fView->AddChild(item, weight);
        return *this;
}


template<typename ParentBuilder>
typename Split<ParentBuilder>::GroupBuilder
Split<ParentBuilder>::AddGroup(orientation orientation, float spacing,
                float weight)
{
        GroupBuilder builder(new BGroupLayout(orientation, spacing));
        builder.SetParent(this);
        fView->AddChild(builder.Layout(), weight);
        return builder;
}


template<typename ParentBuilder>
typename Split<ParentBuilder>::GroupBuilder
Split<ParentBuilder>::AddGroup(BGroupView* groupView, float weight)
{
        GroupBuilder builder(groupView);
        builder.SetParent(this);
        fView->AddChild(builder.Layout(), weight);
        return builder;
}


template<typename ParentBuilder>
typename Split<ParentBuilder>::GroupBuilder
Split<ParentBuilder>::AddGroup(BGroupLayout* groupLayout, float weight)
{
        GroupBuilder builder(groupLayout);
        builder.SetParent(this);
        fView->AddChild(builder.Layout(), weight);
        return builder;
}


template<typename ParentBuilder>
typename Split<ParentBuilder>::GridBuilder
Split<ParentBuilder>::AddGrid(float horizontalSpacing, float verticalSpacing,
        float weight)
{
        GridBuilder builder(new BGridLayout(horizontalSpacing, verticalSpacing));
        builder.SetParent(this);
        fView->AddChild(builder.Layout(), weight);
        return builder;
}


template<typename ParentBuilder>
typename Split<ParentBuilder>::GridBuilder
Split<ParentBuilder>::AddGrid(BGridView* gridView, float weight)
{
        GridBuilder builder(gridView);
        builder.SetParent(this);
        fView->AddChild(builder.Layout(), weight);
        return builder;
}


template<typename ParentBuilder>
typename Split<ParentBuilder>::GridBuilder
Split<ParentBuilder>::AddGrid(BGridLayout* layout, float weight)
{
        GridBuilder builder(layout);
        builder.SetParent(this);
        fView->AddChild(builder.Layout(), weight);
        return builder;
}


template<typename ParentBuilder>
typename Split<ParentBuilder>::SplitBuilder
Split<ParentBuilder>::AddSplit(orientation orientation, float spacing,
                float weight)
{
        SplitBuilder builder(orientation, spacing);
        builder.SetParent(this);
        fView->AddChild(builder.View(), weight);
        return builder;
}


template<typename ParentBuilder>
typename Split<ParentBuilder>::CardBuilder
Split<ParentBuilder>::AddCards(float weight)
{
        CardBuilder builder;
        builder.SetParent(this);
        fView->AddChild(builder.View(), weight);
        return builder;
}


template<typename ParentBuilder>
typename Split<ParentBuilder>::CardBuilder
Split<ParentBuilder>::AddCards(BCardLayout* cardLayout, float weight)
{
        CardBuilder builder(cardLayout);
        builder.SetParent(this);
        fView->AddChild(builder.View(), weight);
        return builder;
}


template<typename ParentBuilder>
typename Split<ParentBuilder>::CardBuilder
Split<ParentBuilder>::AddCards(BCardView* cardView, float weight)
{
        CardBuilder builder(cardView);
        builder.SetParent(this);
        fView->AddChild(builder.View(), weight);
        return builder;
}


template<typename ParentBuilder>
typename Split<ParentBuilder>::ThisBuilder&
Split<ParentBuilder>::SetCollapsible(bool collapsible)
{
        fView->SetCollapsible(collapsible);
        return *this;
}


template<typename ParentBuilder>
typename Split<ParentBuilder>::ThisBuilder&
Split<ParentBuilder>::SetCollapsible(int32 index, bool collapsible)
{
        fView->SetCollapsible(index, collapsible);
        return *this;
}


template<typename ParentBuilder>
typename Split<ParentBuilder>::ThisBuilder&
Split<ParentBuilder>::SetCollapsible(int32 first, int32 last, bool collapsible)
{
        fView->SetCollapsible(first, last, collapsible);
        return *this;
}


template<typename ParentBuilder>
typename Split<ParentBuilder>::ThisBuilder&
Split<ParentBuilder>::SetInsets(float left, float top, float right,
        float bottom)
{
        fView->SetInsets(left, top, right, bottom);
        return *this;
}


template<typename ParentBuilder>
typename Split<ParentBuilder>::ThisBuilder&
Split<ParentBuilder>::SetInsets(float horizontal, float vertical)
{
        fView->SetInsets(horizontal, vertical);
        return *this;
}


template<typename ParentBuilder>
typename Split<ParentBuilder>::ThisBuilder&
Split<ParentBuilder>::SetInsets(float insets)
{
        fView->SetInsets(insets);
        return *this;
}


template<typename ParentBuilder>
Split<ParentBuilder>::operator BSplitView*()
{
        return fView;
}


// #pragma mark - Cards


template<typename ParentBuilder>
Cards<ParentBuilder>::Cards()
        :
        fLayout((new BCardView())->CardLayout())
{
}


template<typename ParentBuilder>
Cards<ParentBuilder>::Cards(BWindow* window)
        :
        fLayout(new BCardLayout())
{
        window->SetLayout(fLayout);

        fLayout->Owner()->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
}


template<typename ParentBuilder>
Cards<ParentBuilder>::Cards(BView* view)
        :
        fLayout(new BCardLayout())
{
        view->SetLayout(fLayout);
        view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
}


template<typename ParentBuilder>
Cards<ParentBuilder>::Cards(BCardLayout* layout)
        :
        fLayout(layout)
{
}


template<typename ParentBuilder>
Cards<ParentBuilder>::Cards(BCardView* view)
        :
        fLayout(view->CardLayout())
{
}


template<typename ParentBuilder>
BCardLayout*
Cards<ParentBuilder>::Layout() const
{
        return fLayout;
}


template<typename ParentBuilder>
BView*
Cards<ParentBuilder>::View() const
{
        return fLayout->Owner();
}


template<typename ParentBuilder>
typename Cards<ParentBuilder>::ThisBuilder&
Cards<ParentBuilder>::GetLayout(BCardLayout** _layout)
{
        *_layout = fLayout;
        return *this;
}


template<typename ParentBuilder>
typename Cards<ParentBuilder>::ThisBuilder&
Cards<ParentBuilder>::GetView(BView** _view)
{
        *_view = fLayout->Owner();
        return *this;
}


template<typename ParentBuilder>
typename Cards<ParentBuilder>::ThisBuilder&
Cards<ParentBuilder>::Add(BView* view)
{
        fLayout->AddView(view);
        return *this;
}


template<typename ParentBuilder>
typename Cards<ParentBuilder>::ThisBuilder&
Cards<ParentBuilder>::Add(BLayoutItem* item)
{
        fLayout->AddItem(item);
        return *this;
}


template<typename ParentBuilder>
typename Cards<ParentBuilder>::GroupBuilder
Cards<ParentBuilder>::AddGroup(orientation orientation, float spacing)
{
        GroupBuilder builder(new BGroupLayout(orientation, spacing));
        builder.SetParent(this);
        fLayout->AddItem(builder.Layout());
        return builder;
}


template<typename ParentBuilder>
typename Cards<ParentBuilder>::GroupBuilder
Cards<ParentBuilder>::AddGroup(BGroupView* groupView)
{
        GroupBuilder builder(groupView);
        builder.SetParent(this);
        fLayout->AddItem(builder.Layout());
        return builder;
}


template<typename ParentBuilder>
typename Cards<ParentBuilder>::GroupBuilder
Cards<ParentBuilder>::AddGroup(BGroupLayout* groupLayout)
{
        GroupBuilder builder(groupLayout);
        builder.SetParent(this);
        fLayout->AddItem(builder.Layout());
        return builder;
}


template<typename ParentBuilder>
typename Cards<ParentBuilder>::GridBuilder
Cards<ParentBuilder>::AddGrid(float horizontal, float vertical)
{
        GridBuilder builder(horizontal, vertical);
        builder.SetParent(this);
        fLayout->AddItem(builder.Layout());
        return builder;
}


template<typename ParentBuilder>
typename Cards<ParentBuilder>::GridBuilder
Cards<ParentBuilder>::AddGrid(BGridLayout* gridLayout)
{
        GridBuilder builder(gridLayout);
        builder.SetParent(this);
        fLayout->AddItem(builder.Layout());
        return builder;
}


template<typename ParentBuilder>
typename Cards<ParentBuilder>::GridBuilder
Cards<ParentBuilder>::AddGrid(BGridView* gridView)
{
        GridBuilder builder(gridView);
        builder.SetParent(this);
        fLayout->AddItem(builder.Layout());
        return builder;
}


template<typename ParentBuilder>
typename Cards<ParentBuilder>::SplitBuilder
Cards<ParentBuilder>::AddSplit(orientation orientation, float spacing)
{
        SplitBuilder builder(orientation, spacing);
        builder.SetParent(this);
        fLayout->AddView(builder.View());
        return builder;
}


template<typename ParentBuilder>
typename Cards<ParentBuilder>::SplitBuilder
Cards<ParentBuilder>::AddSplit(BSplitView* splitView)
{
        SplitBuilder builder(splitView);
        builder.SetParent(this);
        fLayout->AddView(builder.View());
        return builder;
}


template<typename ParentBuilder>
typename Cards<ParentBuilder>::CardBuilder
Cards<ParentBuilder>::AddCards()
{
        CardBuilder builder;
        builder.SetParent(this);
        fLayout->AddView(builder.View());
        return builder;
}


template<typename ParentBuilder>
typename Cards<ParentBuilder>::CardBuilder
Cards<ParentBuilder>::AddCards(BCardLayout* cardLayout)
{
        CardBuilder builder(cardLayout);
        builder.SetParent(this);
        fLayout->AddView(builder.View());
        return builder;
}

template<typename ParentBuilder>
typename Cards<ParentBuilder>::CardBuilder
Cards<ParentBuilder>::AddCards(BCardView* cardView)
{
        CardBuilder builder(cardView);
        builder.SetParent(this);
        fLayout->AddView(builder.View());
        return builder;
}


template<typename ParentBuilder>
typename Cards<ParentBuilder>::ThisBuilder&
Cards<ParentBuilder>::SetExplicitMinSize(BSize size)
{
        fLayout->SetExplicitMinSize(size);
        return *this;
}


template<typename ParentBuilder>
typename Cards<ParentBuilder>::ThisBuilder&
Cards<ParentBuilder>::SetExplicitMaxSize(BSize size)
{
        fLayout->SetExplicitMaxSize(size);
        return *this;
}


template<typename ParentBuilder>
typename Cards<ParentBuilder>::ThisBuilder&
Cards<ParentBuilder>::SetExplicitPreferredSize(BSize size)
{
        fLayout->SetExplicitPreferredSize(size);
        return *this;
}


template<typename ParentBuilder>
typename Cards<ParentBuilder>::ThisBuilder&
Cards<ParentBuilder>::SetExplicitAlignment(BAlignment alignment)
{
        fLayout->SetExplicitAlignment(alignment);
        return *this;
}


template<typename ParentBuilder>
typename Cards<ParentBuilder>::ThisBuilder&
Cards<ParentBuilder>::SetVisibleItem(int32 item)
{
        fLayout->SetVisibleItem(item);
        return *this;
}


template<typename ParentBuilder>
Cards<ParentBuilder>::operator BCardLayout*()
{
        return fLayout;
}


// #pragma mark - Menu


template<typename ParentBuilder>
Menu<ParentBuilder>::Menu(BMenu* menu)
        :
        fMenu(menu)
{
}


template<typename ParentBuilder>
typename Menu<ParentBuilder>::ThisBuilder&
Menu<ParentBuilder>::GetMenu(BMenu*& _menu)
{
        _menu = fMenu;
        return *this;
}


template<typename ParentBuilder>
typename Menu<ParentBuilder>::ItemBuilder
Menu<ParentBuilder>::AddItem(BMenuItem* item)
{
        fMenu->AddItem(item);
        return MenuItem<ParentBuilder>(this->fParent, fMenu, item);
}


template<typename ParentBuilder>
typename Menu<ParentBuilder>::ItemBuilder
Menu<ParentBuilder>::AddItem(BMenu* menu)
{
        if (!fMenu->AddItem(menu))
                throw std::bad_alloc();

        return MenuItem<ParentBuilder>(this->fParent, fMenu,
                fMenu->ItemAt(fMenu->CountItems() - 1));
}


template<typename ParentBuilder>
typename Menu<ParentBuilder>::ItemBuilder
Menu<ParentBuilder>::AddItem(const char* label, BMessage* message,
        char shortcut, uint32 modifiers)
{
        BMenuItem* item = new BMenuItem(label, message, shortcut, modifiers);
        if (!fMenu->AddItem(item)) {
                delete item;
                item = NULL;
        }

        return MenuItem<ParentBuilder>(this->fParent, fMenu, item);
}


template<typename ParentBuilder>
typename Menu<ParentBuilder>::ItemBuilder
Menu<ParentBuilder>::AddItem(const char* label, uint32 messageWhat,
        char shortcut, uint32 modifiers)
{
        BMessage* message = new BMessage(messageWhat);
        BMenuItem* item;
        try {
                item = new BMenuItem(label, message, shortcut, modifiers);
        } catch (...) {
                delete message;
                throw;
        }

        if (!fMenu->AddItem(item)) {
                delete item;
                item = NULL;
        }

        return MenuItem<ParentBuilder>(this->fParent, fMenu, item);
}


template<typename ParentBuilder>
typename Menu<ParentBuilder>::ThisBuilder&
Menu<ParentBuilder>::AddSeparator()
{
        fMenu->AddSeparatorItem();
        return *this;
}


template<typename ParentBuilder>
typename Menu<ParentBuilder>::MenuBuilder
Menu<ParentBuilder>::AddMenu(BMenu* menu)
{
        if (!fMenu->AddItem(menu))
                throw std::bad_alloc();

        MenuBuilder builder(menu);
        builder.SetParent(this);
        return builder;
}


template<typename ParentBuilder>
typename Menu<ParentBuilder>::MenuBuilder
Menu<ParentBuilder>::AddMenu(const char* title, menu_layout layout)
{
        BMenu* menu = new BMenu(title, layout);
        if (!fMenu->AddItem(menu)) {
                delete menu;
                throw std::bad_alloc();
        }

        MenuBuilder builder(menu);
        builder.SetParent(this);
        return builder;
}


// #pragma mark - MenuItem


template<typename ParentBuilder>
MenuItem<ParentBuilder>::MenuItem(ParentBuilder* parentBuilder, BMenu* menu,
        BMenuItem* item)
        :
        Menu<ParentBuilder>(menu),
        fMenuItem(item)
{
        this->SetParent(parentBuilder);
}


template<typename ParentBuilder>
typename MenuItem<ParentBuilder>::ThisBuilder&
MenuItem<ParentBuilder>::GetItem(BMenuItem*& _item)
{
        _item = fMenuItem;
        return *this;
}


template<typename ParentBuilder>
typename MenuItem<ParentBuilder>::ThisBuilder&
MenuItem<ParentBuilder>::SetEnabled(bool enabled)
{
        fMenuItem->SetEnabled(enabled);
        return *this;
}


}       // namespace BLayoutBuilder


#endif  // _LAYOUT_BUILDER_H