Project

General

Profile

Bug #1501 » TestApp.cc

Koen Deforche, 10/30/2012 10:31 AM

 
#include <Wt/WApplication>
#include <Wt/WComboBox>
#include <Wt/WContainerWidget>
#include <Wt/WGridLayout>
#include <Wt/WVBoxLayout>
#include <Wt/WHBoxLayout>
#include <Wt/WGroupBox>
#include <Wt/WLabel>
#include <Wt/WText>
#include <Wt/WPushButton>
#include <Wt/WLineEdit>
#include <Wt/WPopupMenu>
#include <Wt/WCssDecorationStyle>
#include <Wt/WStandardItemModel>
#include <Wt/WAbstractTableModel>
#include <Wt/WStandardItem>
#include <Wt/WTableView>
#include <iostream>

#include <stdio.h>

class AttributeGroup;

using namespace Wt;

//#define USE_CONTAINER_INSTEAD_OF_LAYOUT 1
#define USE_CONTAINER_INSTEAD_OF_LAYOUT 0
#define USE_CONTAINER_INSTEAD_OF_GROUPBOX 0
//#define USE_CONTAINER_INSTEAD_OF_GROUPBOX 1

class VirtualTable : public WAbstractTableModel
{
public:
VirtualTable(WObject *parent)
: colCount_(0),
rowCount_(0)
{ }
virtual int columnCount(const WModelIndex& parent = WModelIndex()) const
{
if (!parent.isValid())
return colCount_;
else
return 0;
}

virtual int rowCount(const WModelIndex& parent = WModelIndex()) const
{
if (!parent.isValid())
return rowCount_;
else
return 0;
}

virtual bool insertColumns(int column, int count,
const WModelIndex& parent = WModelIndex())
{
beginInsertColumns(parent, column, column + count - 1);
colCount_ += count;
endInsertColumns();

return true;
}

virtual bool insertRows(int row, int count,
const WModelIndex& parent = WModelIndex())
{
beginInsertRows(parent, row, row + count - 1);
rowCount_ += count;
endInsertRows();

return true;
}

virtual boost::any headerData(const WModelIndex& index,
int role = DisplayRole) const
{
if (role == DisplayRole) {
return boost::any(std::string("Header"));
} else {
return boost::any();
}
}

virtual boost::any data(const WModelIndex& index,
int role = DisplayRole) const
{
if (role == DisplayRole) {
return boost::any(std::string("Data"));
} else {
return boost::any();
}
}

private:
int colCount_;
int rowCount_;
};


class WtApp : public Wt::WApplication
{
public:
WtApp( const Wt::WEnvironment& env);
~WtApp() {}


void apply()
{
mHideDetails = !mHideDetails;
mDetails->setHidden(mHideDetails);
}

void addRows()
{
fprintf(stderr, "addRows()\n");
mModel->insertRows(mModel->rowCount(), 7185);
}

private:
Wt::WText *createText(const Wt::WString& text);
Wt::WWidget *createSelection();

void choiceChanged(int i);

private:
VirtualTable* mModel;
Wt::WGridLayout* mLayout;
Wt::WContainerWidget* mSelections;
Wt::WVBoxLayout* mSelectionLayout;
Wt::WWidget* mDetails;
Wt::WText* mStretch;
AttributeGroup* mAttrGroup;
bool mHideDetails;
};

class SelectionDefinitionTest :
#if USE_CONTAINER_INSTEAD_OF_GROUPBOX
public Wt::WContainerWidget
#else
public Wt::WGroupBox
#endif
{
public:
SelectionDefinitionTest(const Wt::WString& title)
:
#if USE_CONTAINER_INSTEAD_OF_GROUPBOX
Wt::WContainerWidget()
#else
Wt::WGroupBox(title)
#endif
, mVBox(new Wt::WVBoxLayout())
, mFilterLabel(new Wt::WLabel(Wt::WString("Filter")))
, mSelection(new Wt::WComboBox())
, mSelectionEditFilter(new Wt::WLineEdit())
, mMenu(new Wt::WLabel())
{
//mFilterLabel->setBuddy(mSelectionEditFilter);

//mSelection->setMaximumSize(layout::EntityMaxWidth, WLength::Auto);
mSelection->addItem(Wt::WString("{1} ({2})").arg(Wt::WString("Please select")).arg(0));

setStyleClass("selectionarea");

Wt::WHBoxLayout* hbox1 = new Wt::WHBoxLayout();
hbox1->addWidget(mFilterLabel, 0);
hbox1->addWidget(mSelectionEditFilter, 1);
Wt::WHBoxLayout* hbox2 = new Wt::WHBoxLayout();
hbox2->addWidget(mMenu, 0);
hbox2->addWidget(mSelection, 1);

mVBox->addLayout(hbox1, 0, Wt::AlignTop | Wt::AlignJustify);
mVBox->addLayout(hbox2, 0, Wt::AlignTop | Wt::AlignJustify);
//mVBox->addWidget(mSelectionEditFilter, 0, AlignTop | AlignJustify);
//mVBox->addWidget(mSelection, 0, AlignTop | AlignJustify);
mVBox->setContentsMargins(2, 0, 4, 0);
mVBox->setSpacing(4);
setPadding(2);
setLayout(mVBox);

//addWidget(mSelection);
//setContentAlignment(AlignJustify);
}

Wt::WVBoxLayout* mVBox;
Wt::WLabel* mFilterLabel;
Wt::WComboBox *mSelection;
Wt::WStringListModel *mSelectionStrings;
Wt::WLineEdit *mSelectionEditFilter;
Wt::WLabel *mMenu;
Wt::WPopupMenuItem* mShowFilterItem;
};

class Attribute : public Wt::WGroupBox
{
public:
Attribute(const Wt::WString& title,
const Wt::WString& description)
: WGroupBox(title)
, mDesc(description)
, mLabel(new Wt::WLabel(mDesc))
, mVBox(new Wt::WVBoxLayout())
, mHBox(new Wt::WHBoxLayout())
{
mHBox->setContentsMargins(0, 0, 0, 0);
mHBox->addWidget(mLabel, 0);
mVBox->addLayout(mHBox);
mVBox->setContentsMargins(0, 0, 0, 3);
setLayout(mVBox);
setStyleClass("attrbox");
hide();
}

Attribute(const Wt::WString& title)
: WGroupBox(title)
, mDesc()
, mLabel(0)
, mVBox(new Wt::WVBoxLayout())
, mHBox(0)
{
mVBox->setContentsMargins(0, 0, 0, 3);
setLayout(mVBox);
setStyleClass("attrbox");
hide();
}

protected:
Wt::WString mDesc;
Wt::WLabel* mLabel;
Wt::WVBoxLayout* mVBox;
Wt::WHBoxLayout* mHBox;
};

class NameAttribute : public Attribute
{
public:
NameAttribute(const Wt::WString& name)
: Attribute(Wt::WString("Edit ")+name,
Wt::WString())
, mName(new Wt::WLineEdit())
{
mHBox->addWidget(mName, 1);
mLabel->setBuddy(mName);
}

private:
Wt::WLineEdit* mName;
};

class ListAttribute : public Attribute
{
public:
ListAttribute(const Wt::WString& name,
const std::vector<Wt::WString>& list)
: Attribute(Wt::WString("Select ") + name,
Wt::WString())
, mList(new Wt::WComboBox())
{
for(size_t i=0; i<list.size(); ++i)
mList->addItem(list[i]);
mHBox->addWidget(mList, 1);
}

private:
Wt::WComboBox* mList;
};

class AttributeGroup : public Wt::WGroupBox
{
public:
AttributeGroup(WtApp* app)
: WGroupBox(Wt::WString("Attribute Group"))
, mVBox(new Wt::WVBoxLayout())
, mAttrs()
, mItemMap()
, mResetPB(new Wt::WPushButton(Wt::WString("Reset")))
{
Wt::WPopupMenu *popup = new Wt::WPopupMenu();
Wt::WLabel *menu = new Wt::WLabel(Wt::WString("Attributes"));
menu->setStyleClass("label-popupmenu");
menu->clicked().connect(popup, &Wt::WPopupMenu::popup);

addPopupItem(popup, Wt::WString("Name"),
new NameAttribute("Name"));
addPopupItem(popup, Wt::WString("Street"),
new NameAttribute(Wt::WString("Street")));
std::vector<Wt::WString> continents;
continents.push_back(Wt::WString("Africa"));
continents.push_back(Wt::WString("Europe ------------------------------------------------------>"));
continents.push_back(Wt::WString("Asia"));
continents.push_back(Wt::WString("America"));
addPopupItem(popup, Wt::WString("Continents"),
new ListAttribute(Wt::WString("Continent"),
continents));
Wt::WPushButton *apply = new Wt::WPushButton(Wt::WString("Apply"));
mResetPB->clicked().connect(this, &AttributeGroup::reset);
mResetPB->disable();
apply->clicked().connect(app, &WtApp::addRows);

Wt::WHBoxLayout* hbox = new Wt::WHBoxLayout();
hbox->setContentsMargins(0, 0, 0, 0);
hbox->addWidget(menu, 1);
hbox->addWidget(mResetPB, 1);
hbox->addWidget(apply, 1);
mVBox->addLayout(hbox);
mVBox->setContentsMargins(0, 0, 0, 0);
setLayout(mVBox);
setStyleClass("selectionarea");
}

void addPopupItem(Wt::WPopupMenu* popup, const Wt::WString& text, Attribute* attr)
{
Wt::WPopupMenuItem* item = popup->addItem(text);
mAttrs.push_back(attr);
item->setCheckable(true);
item->setChecked(false);
item->setData(attr);
item->triggered().connect(this, &AttributeGroup::attrChanged);
mItemMap[attr] = item;
mVBox->addWidget(attr);
}

void attrChanged(Wt::WPopupMenuItem* item)
{
Attribute *attr = reinterpret_cast<Attribute*>(item->data());
attr->setHidden(!item->isChecked());
mResetPB->setEnabled(true);
}

void reset()
{
for(std::list<Attribute*>::const_iterator it = mAttrs.begin(); it != mAttrs.end(); ++it)
{
Attribute* attr = (*it);
attr->setHidden(true);
mItemMap[attr]->setChecked(false);
}
mResetPB->setEnabled(false);
}

private:
Wt::WVBoxLayout* mVBox;
std::list<Attribute*> mAttrs;
std::map<Attribute*,Wt::WPopupMenuItem*> mItemMap;
Wt::WPushButton* mResetPB;
};


WtApp::WtApp(const Wt::WEnvironment& env)
: Wt::WApplication(env)
, mLayout(0)
, mSelections(0)
, mSelectionLayout(0)
, mDetails(0)
, mStretch(0)
, mAttrGroup(0)
, mHideDetails(false)
{
setCssTheme("polished");

mLayout = new Wt::WGridLayout(root());

root()->setLayout(mLayout);

// row 0
mLayout->addWidget(createText("Title"), 0, 0, 0, 3, Wt::AlignTop|Wt::AlignJustify);


// row 1
mLayout->addWidget(createText("SubTitle"), 1, 0, 1, 3, Wt::AlignMiddle|Wt::AlignJustify);


mModel = new VirtualTable(this);
WTableView *view = new WTableView();
view->setModel(mModel);
view->setAlternatingRowColors(true);

mModel->insertColumns(0, 4);
mModel->insertRows(mModel->rowCount(), 40);

// row 2
mLayout->addWidget(createSelection(), 2, 0, Wt::AlignLeft);
mLayout->addWidget(view /*createText("Main")*/, 2, 1, Wt::AlignJustify);
mLayout->addWidget((mDetails = createText("Details")), 2, 2, Wt::AlignJustify);

// row 3
mLayout->addWidget(createText("More details"), 3, 0, 1, 3);

/*
* Let row 2 and column 1 take the excess space.
*/
mLayout->setRowStretch(2, 1);
mLayout->setRowStretch(3, 1);
mLayout->setColumnStretch(1, 1);
mLayout->setColumnStretch(2, 0);
mLayout->setColumnResizable(1);
mLayout->setRowResizable(2);
mLayout->setHorizontalSpacing(4);
mLayout->setVerticalSpacing(2);
mLayout->setContentsMargins(4, 4, 4, 4);
}

Wt::WText *WtApp::createText(const Wt::WString& text)
{
Wt::WText *w = new Wt::WText(text);
Wt::WCssDecorationStyle style;
style.setBackgroundColor(Wt::WColor(200,200,200));
w->setDecorationStyle(style);
return w;
}

Wt::WWidget *WtApp::createSelection()
{
mSelections = new Wt::WContainerWidget();
Wt::WGroupBox *gbox1 = new Wt::WGroupBox("Config");
gbox1->addWidget(createText("Config selection"));
Wt::WComboBox *cbox1 = new Wt::WComboBox();
cbox1->addItem("please select");
cbox1->addItem("System");
Wt::WGroupBox *gbox2 = new Wt::WGroupBox("Selection Box");
Wt::WComboBox *cbox2 = new Wt::WComboBox();
cbox2->addItem("please select");
cbox2->addItem("Entity 1");
cbox2->activated().connect(this, &WtApp::choiceChanged);
mAttrGroup = new AttributeGroup(this);

Wt::WVBoxLayout* gvbox2 = new Wt::WVBoxLayout();
gvbox2->addWidget(createText("Test 1"), 0, Wt::AlignTop);
gvbox2->addWidget(cbox2, 0, Wt::AlignTop);
gbox2->setLayout(gvbox2);

mStretch = createText("");
#if USE_CONTAINER_INSTEAD_OF_LAYOUT
Wt::WContainerWidget* container = new Wt::WContainerWidget();
container->addWidget(new SelectionDefinitionTest("Test"));
container->addWidget(gbox1);
container->addWidget(cbox1);
container->addWidget(gbox2);
container->addWidget(mAttrGroup);
container->addWidget(mStretch);
mSelections->addWidget(container);
#else
mSelectionLayout = new Wt::WVBoxLayout();
mSelectionLayout->setContentsMargins(4, 2, 4, 2);
mSelectionLayout->addWidget(new SelectionDefinitionTest("Test"));
mSelectionLayout->addWidget(gbox1, 0, Wt::AlignTop);
mSelectionLayout->addWidget(cbox1, 0, Wt::AlignTop);
mSelectionLayout->addWidget(gbox2, 0, Wt::AlignTop);
mSelectionLayout->addWidget(mAttrGroup, 0, Wt::AlignTop);
mSelectionLayout->addWidget(mStretch, 1);
mSelections->setLayout(mSelectionLayout);
#endif
mSelections->setContentAlignment(Wt::AlignJustify);
mSelections->setOverflow(Wt::WContainerWidget::OverflowAuto, Wt::Horizontal);
mSelections->setStyleClass("inputarea");
mSelections->setMinimumSize(Wt::WLength(150, Wt::WLength::Pixel), Wt::WLength());
/// Selection MAXIMUM which is not respected by the continents ComboBox
mSelections->setMaximumSize(Wt::WLength(250, Wt::WLength::Pixel), Wt::WLength());
return mSelections;
}

void WtApp::choiceChanged(int i)
{
mSelections->removeWidget(mStretch);
mSelections->removeWidget(mAttrGroup);

mSelectionLayout->addWidget(mAttrGroup, 0);
mSelectionLayout->addWidget(mStretch, 1);
}

Wt::WApplication *createApplication(const Wt::WEnvironment& env)
{
Wt::WApplication* myApplication = 0;
myApplication = new WtApp( env );
return myApplication;
}


int main(int argc, char **argv)
{
Wt::WRun(argc, argv, &createApplication);
return 0;
}
(3-3/3)