|
#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>
|
|
|
|
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->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;
|
|
}
|