Skip to content
Snippets Groups Projects
Commit c21e0917 authored by Nicolas Pope's avatar Nicolas Pope
Browse files

Add a search bar

The configuration window now has a search bar which reacts to user
input on the fly.
parent 65bd3f38
No related branches found
No related tags found
No related merge requests found
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <nanogui/entypo.h> #include <nanogui/entypo.h>
#include <nanogui/formhelper.h> #include <nanogui/formhelper.h>
#include <nanogui/vscrollpanel.h> #include <nanogui/vscrollpanel.h>
#include <nanogui/opengl.h>
#include <vector> #include <vector>
#include <string> #include <string>
...@@ -15,6 +16,67 @@ using std::string; ...@@ -15,6 +16,67 @@ using std::string;
using std::vector; using std::vector;
using ftl::config::json_t; using ftl::config::json_t;
class SearchBox : public nanogui::TextBox {
private:
std::vector<std::string> configurables_;
Widget *buttons_;
std::string previous;
void _setVisible(const std::string &str) {
// Check whether the search string has changed to prevent
// unnecessary searching.
if (str != previous) {
for (int i = configurables_.size()-1; i >= 0; --i) {
if (configurables_[i].find(mValueTemp) != std::string::npos) {
buttons_->childAt(i)->setVisible(true);
} else {
buttons_->childAt(i)->setVisible(false);
}
}
previous = str;
}
}
public:
SearchBox(Widget *parent, std::vector<std::string> &configurables) : nanogui::TextBox(parent, ""), configurables_(configurables) {
setAlignment(TextBox::Alignment::Left);
setEditable(true);
setPlaceholder("Search");
}
~SearchBox() {
}
bool keyboardEvent(int key, int scancode, int action, int modifier) {
TextBox::keyboardEvent(key, scancode, action, modifier);
_setVisible(mValueTemp);
return true;
}
void setButtons(Widget *buttons) {
buttons_ = buttons;
}
};
static std::string titleForURI(const ftl::URI &uri) {
auto *cfg = ftl::config::find(uri.getBaseURI());
if (cfg && cfg->get<std::string>("title")) {
return *cfg->get<std::string>("title");
} else if (uri.getPath().size() > 0) {
return uri.getPathSegment(-1);
} else {
return uri.getHost();
}
}
static std::string genPadding(const std::string &str, size_t count) {
std::string res = "";
for (size_t i=0; i<count; ++i) {
res += str;
}
return res;
}
ConfigWindow::ConfigWindow(nanogui::Widget *parent, ftl::ctrl::Master *ctrl) ConfigWindow::ConfigWindow(nanogui::Widget *parent, ftl::ctrl::Master *ctrl)
: nanogui::Window(parent, "Settings"), ctrl_(ctrl) { : nanogui::Window(parent, "Settings"), ctrl_(ctrl) {
using namespace nanogui; using namespace nanogui;
...@@ -23,17 +85,52 @@ ConfigWindow::ConfigWindow(nanogui::Widget *parent, ftl::ctrl::Master *ctrl) ...@@ -23,17 +85,52 @@ ConfigWindow::ConfigWindow(nanogui::Widget *parent, ftl::ctrl::Master *ctrl)
setPosition(Vector2i(parent->width()/2.0f - 100.0f, parent->height()/2.0f - 100.0f)); setPosition(Vector2i(parent->width()/2.0f - 100.0f, parent->height()/2.0f - 100.0f));
//setModal(true); //setModal(true);
configurables_ = ftl::config::list(); auto configurables = ftl::config::list();
const auto size = configurables.size();
new Label(this, "Select Configurable","sans-bold"); new Label(this, "Select Configurable","sans-bold");
auto searchBox = new SearchBox(this, configurables);
auto vscroll = new VScrollPanel(this); auto vscroll = new VScrollPanel(this);
vscroll->setFixedHeight(300); vscroll->setFixedHeight(300);
Widget *buttons = new Widget(vscroll); auto buttons = new Widget(vscroll);
buttons->setLayout(new BoxLayout(Orientation::Vertical, Alignment::Fill)); buttons->setLayout(new BoxLayout(Orientation::Vertical, Alignment::Fill));
for (auto c : configurables_) { searchBox->setButtons(buttons);
auto itembutton = new Button(buttons, c);
std::vector<std::string> configurable_titles(size);
for (int i = 0; i < size; ++i) {
ftl::URI uri(configurables[i]);
std::string label = uri.getFragment();
size_t pos = label.find_last_of("/");
if (pos != std::string::npos) label = label.substr(pos+1);
std::string parentName = configurables[i];
size_t pos2 = parentName.find_last_of("/");
if (pos2 != std::string::npos) parentName = parentName.substr(0,pos2);
// FIXME: Does not indicated parent indentation ... needs sorting?
if (i > 0 && parentName == configurables[i-1]) {
ftl::URI uri(configurables[i-1]);
configurable_titles[i-1] = std::string("[") + titleForURI(uri) + std::string("] ") + uri.getFragment();
auto *prev = dynamic_cast<Button*>(buttons->childAt(buttons->childCount()-1));
prev->setCaption(configurable_titles[i-1]);
prev->setBackgroundColor(nanogui::Color(0.3f,0.3f,0.3f,1.0f));
prev->setTextColor(nanogui::Color(1.0f,1.0f,1.0f,1.0f));
prev->setIconPosition(Button::IconPosition::Left);
prev->setIcon(ENTYPO_ICON_FOLDER);
}
configurable_titles[i] = label;
auto itembutton = new nanogui::Button(buttons, configurable_titles[i]);
std::string c = configurables[i];
itembutton->setTooltip(c);
itembutton->setBackgroundColor(nanogui::Color(0.9f,0.9f,0.9f,0.9f));
itembutton->setCallback([this,c]() { itembutton->setCallback([this,c]() {
LOG(INFO) << "Change configurable: " << c; LOG(INFO) << "Change configurable: " << c;
_buildForm(c); _buildForm(c);
...@@ -136,3 +233,4 @@ void ConfigWindow::_buildForm(const std::string &suri) { ...@@ -136,3 +233,4 @@ void ConfigWindow::_buildForm(const std::string &suri) {
bool ConfigWindow::exists(const std::string &uri) { bool ConfigWindow::exists(const std::string &uri) {
return ftl::config::find(uri) != nullptr; return ftl::config::find(uri) != nullptr;
} }
...@@ -2,10 +2,10 @@ ...@@ -2,10 +2,10 @@
#define _FTL_GUI_CFGWINDOW_HPP_ #define _FTL_GUI_CFGWINDOW_HPP_
#include <nanogui/window.h> #include <nanogui/window.h>
#include <nanogui/formhelper.h>
#include <ftl/master.hpp> #include <ftl/master.hpp>
#include <ftl/uuid.hpp> #include <ftl/uuid.hpp>
#include <nanogui/formhelper.h>
#include <ftl/net_configurable.hpp> #include <ftl/net_configurable.hpp>
namespace ftl { namespace ftl {
...@@ -21,7 +21,6 @@ class ConfigWindow : public nanogui::Window { ...@@ -21,7 +21,6 @@ class ConfigWindow : public nanogui::Window {
private: private:
ftl::ctrl::Master *ctrl_; ftl::ctrl::Master *ctrl_;
std::vector<std::string> configurables_;
void _buildForm(const std::string &uri); void _buildForm(const std::string &uri);
void _addElements(nanogui::FormHelper *form, const std::string &suri); void _addElements(nanogui::FormHelper *form, const std::string &suri);
......
...@@ -227,6 +227,13 @@ static void run(ftl::Configurable *root) { ...@@ -227,6 +227,13 @@ static void run(ftl::Configurable *root) {
}); });
stream->add(vs); stream->add(vs);
for (auto c : ftl::config::getChildren(root->getID())) {
LOG(INFO) << "Tagging configurable: " << c->getID();
auto tags = c->value<std::vector<std::string>>("tags", nlohmann::json::array({}));
tags.push_back("reconstruction");
c->set("tags", tags);
}
// ---- Recording code ----------------------------------------------------- // ---- Recording code -----------------------------------------------------
std::ofstream fileout; std::ofstream fileout;
ftl::codecs::Writer writer(fileout); ftl::codecs::Writer writer(fileout);
......
...@@ -83,6 +83,13 @@ const std::vector<Configurable *> &findByTag(const std::string &tag); ...@@ -83,6 +83,13 @@ const std::vector<Configurable *> &findByTag(const std::string &tag);
std::vector<std::string> list(); std::vector<std::string> list();
/**
* Recursively get all children of a configurable. The given configurable is
* also included in the vector, unless it is null,
* in which case an empty vector is returned.
*/
const std::vector<Configurable *> getChildren(const std::string &uri);
/** /**
* Adds a Configurable instance to the database of instances so that it can * Adds a Configurable instance to the database of instances so that it can
* then be resolved using find(). * then be resolved using find().
......
...@@ -212,6 +212,17 @@ std::vector<std::string> ftl::config::list() { ...@@ -212,6 +212,17 @@ std::vector<std::string> ftl::config::list() {
return r; return r;
} }
const std::vector<Configurable *> ftl::config::getChildren(const string &uri) {
std::vector<Configurable *> children;
for (const auto &[curi, c] : config_instance) {
auto mismatch = std::mismatch(uri.begin(), uri.end(), curi.begin());
if (mismatch.first == uri.end()) {
children.push_back(c);
}
}
return children;
}
void ftl::config::registerConfigurable(ftl::Configurable *cfg) { void ftl::config::registerConfigurable(ftl::Configurable *cfg) {
auto uri = cfg->get<string>("$id"); auto uri = cfg->get<string>("$id");
if (!uri) { if (!uri) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment