Browse Source

Add authors and tags label. Add author and tag filtering functionality.

tags/v1.0.0
Andrew Belt 6 years ago
parent
commit
5e21dedc0f
1 changed files with 118 additions and 29 deletions
  1. +118
    -29
      src/app/ModuleBrowser.cpp

+ 118
- 29
src/app/ModuleBrowser.cpp View File

@@ -232,6 +232,16 @@ struct ModelBox : widget::OpaqueWidget {
};


struct AuthorItem : ui::MenuItem {
void onAction(const widget::ActionEvent &e) override;
};


struct TagItem : ui::MenuItem {
void onAction(const widget::ActionEvent &e) override;
};


struct BrowserSearchField : ui::TextField {
void step() override {
// Steal focus when step is called
@@ -268,8 +278,10 @@ struct BrowserSearchField : ui::TextField {

struct BrowserSidebar : widget::Widget {
BrowserSearchField *searchField;
ui::List *pluginList;
ui::ScrollWidget *pluginScroll;
ui::Label *authorLabel;
ui::List *authorList;
ui::ScrollWidget *authorScroll;
ui::Label *tagLabel;
ui::List *tagList;
ui::ScrollWidget *tagScroll;

@@ -277,24 +289,34 @@ struct BrowserSidebar : widget::Widget {
searchField = new BrowserSearchField;
addChild(searchField);

authorLabel = new ui::Label;
authorLabel->color = nvgRGB(0x80, 0x80, 0x80);
authorLabel->text = "Authors";
addChild(authorLabel);

// Plugin list
pluginScroll = new ui::ScrollWidget;
addChild(pluginScroll);
authorScroll = new ui::ScrollWidget;
addChild(authorScroll);

pluginList = new ui::List;
pluginScroll->container->addChild(pluginList);
authorList = new ui::List;
authorScroll->container->addChild(authorList);

std::set<std::string, string::CaseInsensitiveCompare> pluginNames;
std::set<std::string, string::CaseInsensitiveCompare> authorNames;
for (plugin::Plugin *plugin : plugin::plugins) {
pluginNames.insert(plugin->name);
authorNames.insert(plugin->author);
}

for (const std::string &pluginName : pluginNames) {
ui::MenuItem *item = new ui::MenuItem;
item->text = pluginName;
pluginList->addChild(item);
for (const std::string &authorName : authorNames) {
AuthorItem *item = new AuthorItem;
item->text = authorName;
authorList->addChild(item);
}

tagLabel = new ui::Label;
tagLabel->color = nvgRGB(0x80, 0x80, 0x80);
tagLabel->text = "Tags";
addChild(tagLabel);

// Tag list
tagScroll = new ui::ScrollWidget;
addChild(tagScroll);
@@ -303,22 +325,32 @@ struct BrowserSidebar : widget::Widget {
tagScroll->container->addChild(tagList);

for (const std::string &tag : plugin::allowedTags) {
ui::MenuItem *item = new ui::MenuItem;
TagItem *item = new TagItem;
item->text = tag;
tagList->addChild(item);
}
}

void step() override {
float listHeight = (box.size.y - searchField->box.size.y) / 2 - authorLabel->box.size.y;
listHeight = std::floor(listHeight);

searchField->box.size.x = box.size.x;
pluginScroll->box.pos = searchField->box.getBottomLeft();
pluginScroll->box.size.y = (box.size.y - searchField->box.size.y) / 2;
pluginScroll->box.size.x = box.size.x;
pluginList->box.size.x = pluginScroll->box.size.x;
tagScroll->box.pos = pluginScroll->box.getBottomLeft().floor();
tagScroll->box.size.y = (box.size.y - searchField->box.size.y) / 2;

authorLabel->box.pos = searchField->box.getBottomLeft();
authorLabel->box.size.x = box.size.x;
authorScroll->box.pos = authorLabel->box.getBottomLeft();
authorScroll->box.size.y = listHeight;
authorScroll->box.size.x = box.size.x;
authorList->box.size.x = authorScroll->box.size.x;

tagLabel->box.pos = authorScroll->box.getBottomLeft();
tagLabel->box.size.x = box.size.x;
tagScroll->box.pos = tagLabel->box.getBottomLeft();
tagScroll->box.size.y = listHeight;
tagScroll->box.size.x = box.size.x;
tagList->box.size.x = tagScroll->box.size.x;

Widget::step();
}
};
@@ -330,6 +362,10 @@ struct ModuleBrowser : widget::OpaqueWidget {
ui::MarginLayout *modelMargin;
ui::SequentialLayout *modelContainer;

std::string search;
std::string author;
std::string tag;

ModuleBrowser() {
sidebar = new BrowserSidebar;
sidebar->box.size.x = 200;
@@ -346,6 +382,7 @@ struct ModuleBrowser : widget::OpaqueWidget {
modelContainer->spacing = math::Vec(10, 10);
modelMargin->addChild(modelContainer);

// Add ModelBoxes for each Model
for (plugin::Plugin *plugin : plugin::plugins) {
for (plugin::Model *model : plugin->models) {
ModelBox *moduleBox = new ModelBox;
@@ -354,11 +391,11 @@ struct ModuleBrowser : widget::OpaqueWidget {
}
}

setSearch("");
refreshModels();
}

void step() override {
box = parent->box.zeroPos().grow(math::Vec(-50, -50));
box = parent->box.zeroPos().grow(math::Vec(-70, -70));

sidebar->box.size.y = box.size.y;

@@ -376,16 +413,16 @@ struct ModuleBrowser : widget::OpaqueWidget {
Widget::draw(args);
}

void setSearch(const std::string &search) {
std::string searchTrimmed = string::trim(search);
void refreshModels() {
// Reset scroll position
modelScroll->offset = math::Vec();

if (searchTrimmed.empty()) {
if (search.empty()) {
// Make all ModelBoxes visible
for (Widget *w : modelContainer->children) {
w->visible = true;
}
// If no search query, sort by plugin name and module name
// Sort by plugin name and then module name
modelContainer->children.sort([&](Widget *w1, Widget *w2) {
ModelBox *m1 = dynamic_cast<ModelBox*>(w1);
ModelBox *m2 = dynamic_cast<ModelBox*>(w2);
@@ -396,11 +433,11 @@ struct ModuleBrowser : widget::OpaqueWidget {
}
else {
std::map<Widget*, float> scores;
// Compute scores and set visibility
// Compute scores and filter visibility
for (Widget *w : modelContainer->children) {
ModelBox *m = dynamic_cast<ModelBox*>(w);
assert(m);
float score = modelScore(m->model, searchTrimmed);
float score = modelScore(m->model, search);
scores[m] = score;
m->visible = (score > 0);
}
@@ -409,6 +446,37 @@ struct ModuleBrowser : widget::OpaqueWidget {
return scores[w1] > scores[w2];
});
}

// Filter authors
if (!author.empty()) {
for (Widget *w : modelContainer->children) {
if (!w->visible)
continue;
ModelBox *m = dynamic_cast<ModelBox*>(w);
assert(m);
if (m->model->plugin->author != author)
m->visible = false;
}
}

// Filter tags
if (!tag.empty()) {
for (Widget *w : modelContainer->children) {
if (!w->visible)
continue;
ModelBox *m = dynamic_cast<ModelBox*>(w);
assert(m);
bool found = false;
for (const std::string &tag : m->model->tags) {
if (tag == this->tag) {
found = true;
break;
}
}
if (!found)
m->visible = false;
}
}
}
};

@@ -442,12 +510,33 @@ inline void ModelBox::onButton(const widget::ButtonEvent &e) {
}
}

inline void BrowserSearchField::onChange(const widget::ChangeEvent &e) {

inline void AuthorItem::onAction(const widget::ActionEvent &e) {
ModuleBrowser *browser = getAncestorOfType<ModuleBrowser>();
browser->setSearch(text);
if (browser->author == text)
browser->author = "";
else
browser->author = text;
browser->refreshModels();
}


inline void TagItem::onAction(const widget::ActionEvent &e) {
ModuleBrowser *browser = getAncestorOfType<ModuleBrowser>();
if (browser->tag == text)
browser->tag = "";
else
browser->tag = text;
browser->refreshModels();
}


inline void BrowserSearchField::onChange(const widget::ChangeEvent &e) {
ModuleBrowser *browser = getAncestorOfType<ModuleBrowser>();
browser->search = string::trim(text);
browser->refreshModels();
}


// Global functions



Loading…
Cancel
Save