Project

General

Profile

Bug #5889 » TreeViewExample.C

Daniel Lier, 08/23/2017 12:56 PM

 
/*
* Copyright (C) 2008 Emweb bvba, Kessel-Lo, Belgium.
*
* See the LICENSE file for terms of use.
*/
#include "TreeViewExample.h"

#include <iostream>

#include <Wt/WApplication.h>
#include <Wt/WContainerWidget.h>
#include <Wt/WEnvironment.h>
#include <Wt/WPanel.h>
#include <Wt/WPushButton.h>
#include <Wt/WStandardItem.h>
#include <Wt/WStandardItemModel.h>
#include <Wt/WText.h>
#include <Wt/WTreeView.h>

static const char *weatherIcons[] = {
"sun01.png",
"cloudy01.png",
"w_cloud.png",
"rain.png",
"storm.png",
"snow.png"
};

TreeViewModel::TreeViewModel()
: belgium_(nullptr)
{
update();
}

bool TreeViewModel::update()
{
clear();
belgium_ = nullptr;

bool useInternalPath = true;
insertColumns(0, 4);

setHeaderData(0, Orientation::Horizontal, std::string("Places"));
setHeaderData(1, Orientation::Horizontal, std::string("Weather"));
setHeaderData(2, Orientation::Horizontal, std::string("Drink"));
setHeaderData(3, Orientation::Horizontal, std::string("Visited"));

/*
* ... and data
*/
std::unique_ptr<WStandardItem> continent, country;
WStandardItem *continentPtr, *countryPtr;

continent = continentItem("Europe");
continentPtr = continent.get();
this->appendRow(std::move(continent));

country = countryItem("Belgium", "be");
countryPtr = country.get();
continentPtr->appendRow(std::move(country));
countryPtr->appendRow(cityItems("Brussels", Rain, "Beer", useInternalPath, true));

countryPtr->appendRow(cityItems("Brussels", Rain, "Beer", useInternalPath, true));
countryPtr->appendRow(cityItems("Brussels", Rain, "Beer", useInternalPath, true));
countryPtr->appendRow(cityItems("Brussels", Rain, "Beer", useInternalPath, true));
countryPtr->appendRow(cityItems("Brussels", Rain, "Beer", useInternalPath, true));
countryPtr->appendRow(cityItems("Brussels", Rain, "Beer", useInternalPath, true));
countryPtr->appendRow(cityItems("Brussels", Rain, "Beer", useInternalPath, true));
countryPtr->appendRow(cityItems("Brussels", Rain, "Beer", useInternalPath, true));
countryPtr->appendRow(cityItems("Leuven", Rain, "Beer", useInternalPath, true));

country = countryItem("France", "fr");
countryPtr = country.get();
continentPtr->appendRow(std::move(country));
countryPtr->appendRow(cityItems("Paris", Cloud, "Wine", useInternalPath, true));
countryPtr->appendRow(cityItems("Bordeaux", SunCloud, "Bordeaux wine", useInternalPath, false));

country = countryItem("Spain", "sp");
countryPtr = country.get();
continentPtr->appendRow(std::move(country));
countryPtr->appendRow(cityItems("Barcelona", Sun, "Cava", useInternalPath, true));
countryPtr->appendRow(cityItems("Madrid", Sun, "San Miguel", useInternalPath, false));

continent = continentItem("Africa");
continentPtr = continent.get();
appendRow(std::move(continent));

country = countryItem("Morocco (المغرب)", "ma");
countryPtr = country.get();
continentPtr->appendRow(std::move(country));
countryPtr->appendRow(cityItems("Casablanca", Sun, "Tea", useInternalPath, false));

belgium_ = item(0, 0)->child(0, 0);

return true;
}

std::unique_ptr<WStandardItem> TreeViewModel::continentItem(const std::string& continent)
{
std::unique_ptr<WStandardItem> result
= cpp14::make_unique<WStandardItem>(continent);
result->setColumnCount(4);
return result;
}

std::unique_ptr<WStandardItem> TreeViewModel::countryItem(const std::string& country, const std::string& code)
{
std::unique_ptr<WStandardItem> result
= cpp14::make_unique<WStandardItem>(WString(country));
result->setIcon("icons/flag_" + code + ".png");
return result;
}

std::vector<std::unique_ptr<WStandardItem>> TreeViewModel::cityItems(const std::string& city, WeatherIcon weather, const std::string& drink, bool useInternalPath, bool visited)
{
std::vector<std::unique_ptr<WStandardItem>> result;
std::unique_ptr<WStandardItem> item;

// column 0: country
item = cpp14::make_unique<WStandardItem>(WString(city));
result.push_back(std::move(item));

// column 1: weather
item = cpp14::make_unique<WStandardItem>();
item->setIcon(std::string("icons/") + weatherIcons[weather]);
result.push_back(std::move(item));

// column 2: drink
item = cpp14::make_unique<WStandardItem>(drink);
if (useInternalPath)
item->setLink(WLink(LinkType::InternalPath, "/drinks/" + drink));
result.push_back(std::move(item));

// column 3: visited
item = cpp14::make_unique<WStandardItem>();
item->setCheckable(true);
item->setChecked(visited);
result.push_back(std::move(item));

return result;
}

void TreeViewModel::toggleRowHeight(WTreeView *treeView_)
{
if (treeView_->rowHeight() == WLength(31))
treeView_->setRowHeight(25);
else
treeView_->setRowHeight(31);
}

void TreeViewModel::toggleStripes(WTreeView *treeView_)
{
treeView_->setAlternatingRowColors(!treeView_->alternatingRowColors());
}

void TreeViewModel::toggleRoot(WTreeView *treeView_)
{
if (treeView_->rootIndex() == WModelIndex())
treeView_->setRootIndex(this->index(0, 0));
else
treeView_->setRootIndex(WModelIndex());
}

void TreeViewModel::addRows(WTreeView *treeView_)
{
if (nullptr != belgium_)
{
int COUNT = 10;

for (int i = 0; i < COUNT; ++i)
{
std::string cityName = "City " + asString(belgium_->rowCount() + 1).toUTF8();
bool useInternalPath = false;
belgium_->appendRow(cityItems(cityName, Storm, "Juice", useInternalPath, false));
}

treeView_->scrollTo(belgium_->child(belgium_->rowCount() - COUNT)->index(), ScrollHint::PositionAtTop);
}
}



TreeViewExample::TreeViewExample(const WString& titleText)
{
model_ = std::make_unique<TreeViewModel>();
TreeViewModel *pTreeViewModel = dynamic_cast<TreeViewModel*>(model_.get());

this->addWidget(cpp14::make_unique<WText>(titleText));

/*
* Now create the view
*/
WPanel *panel = this->addWidget(cpp14::make_unique<WPanel>());
panel->resize(600, 300);

auto treeView = cpp14::make_unique<WTreeView>();
treeView_ = treeView.get();
panel->setCentralWidget(std::move(treeView));
if (!WApplication::instance()->environment().ajax())
treeView_->resize(WLength::Auto, 290);

treeView_->setAlternatingRowColors(true);
treeView_->setRowHeight(25);
treeView_->setModel(model_);

treeView_->setColumnWidth(1, WLength(100));
treeView_->setColumnAlignment(1, AlignmentFlag::Center);
treeView_->setColumnWidth(3, WLength(100));
treeView_->setColumnAlignment(3, AlignmentFlag::Center);

treeView_->setRowHeaderCount(1);
treeView_->setColumnWidth(0, 300);

/*
* Expand the first (and single) top level node
*/
treeView_->setExpanded(model_->index(0, 0), true);
treeView_->setExpanded(model_->index(0, 0, model_->index(0, 0)), true);

treeView_->setSortingEnabled(false);
treeView_->setSortingEnabled(0, true);
treeView_->setSortingEnabled(2, true);

/*
* Setup some buttons to manipulate the view and the model.
*/
WContainerWidget *wc = this->addWidget(cpp14::make_unique<WContainerWidget>());
WPushButton *b;

b = wc->addWidget(cpp14::make_unique<WPushButton>("Toggle row height"));
b->clicked().connect([=] { pTreeViewModel->toggleRowHeight(treeView_); });
b->setToolTip("Toggles row height between 31px and 25px");
b = wc->addWidget(cpp14::make_unique<WPushButton>("Toggle stripes"));
b->clicked().connect([=] { pTreeViewModel->toggleStripes(treeView_); });
b->setToolTip("Toggle alternating row colors");
b = wc->addWidget(cpp14::make_unique<WPushButton>("Toggle root"));
b->clicked().connect([=] { pTreeViewModel->toggleRoot(treeView_); });
b->setToolTip("Toggles root item between all and the first continent.");

b = wc->addWidget(cpp14::make_unique<WPushButton>("Add rows"));
b->clicked().connect([=]{ pTreeViewModel->addRows(treeView_); });
b->setToolTip("Adds some cities to Belgium");
}

bool TreeViewExample::update()
{
bool bReturn = false;

if (nullptr != treeView_)
{
TreeViewModel *pModel = dynamic_cast<TreeViewModel*>(treeView_->model().get());
if (nullptr != pModel) bReturn = pModel->update();
}

return bReturn;
}

(2-2/3)