Browse Source

doOnClick(), createComponentTree(), build UI from browser.ntrml (missed earlier commit)

master
Odilitime 2 years ago
parent
commit
ceba964103
1 changed files with 430 additions and 1 deletions
  1. 430
    1
      src/browser.cpp

+ 430
- 1
src/browser.cpp View File

@@ -1,6 +1,15 @@
#include "browser.h"
#include "scheduler.h"
#include "graphics/components/TabbedComponent.h"
#include "parsers/ntrml/NTRMLParser.h"
#include "html/HTMLParser.h"

#include "graphics/components/InputComponent.h"
#include "graphics/components/ImageComponent.h"
#include "graphics/components/TabbedComponent.h"
#include "graphics/components/ButtonComponent.h"

#include <fstream>

// why can't I const this?
std::unique_ptr<Scheduler> scheduler = std::make_unique<Scheduler>();
@@ -11,7 +20,407 @@ std::unique_ptr<Scheduler> scheduler = std::make_unique<Scheduler>();
// 1+ back/fwd/reload/stop components
// 1+ address bar

void doOnClick(std::string type, Component *component, Window *win) {
if (type=="back") {
component->onClick=[win]() {
std::cout << "Browser::doOnClick.navBackButton->onClick - Back" << std::endl;
TabbedComponent *pTabComponent = dynamic_cast<TabbedComponent*>(win->tabComponent.get());
if (pTabComponent) {
if (pTabComponent->selectedTabId) {
pTabComponent->selectedTab->get()->history->print();
pTabComponent->selectedTab->get()->history->back();
} else {
std::cout << "Browser::doOnClick.navBackButton->onClick - no tab selected" << std::endl;
}
} else {
std::cout << "Browser::doOnClick.navBackButton->onClick - no tabbed component" << std::endl;
}
};
} else if (type=="forward") {
component->onClick=[win]() {
//std::cout << "Forward" << std::endl;
TabbedComponent *pTabComponent = dynamic_cast<TabbedComponent*>(win->tabComponent.get());
if (pTabComponent) {
if (pTabComponent->selectedTabId) {
pTabComponent->selectedTab->get()->history->forward();
}
}
};
} else if (type=="refresh") {
component->onClick=[win]() {
std::shared_ptr<DocumentComponent> docComponent = win->getActiveDocumentComponent();
if (docComponent) {
std::cout << "Refreshing " << docComponent->currentURL << std::endl;
// now tell it to navigate somewhere
docComponent->navTo(docComponent->currentURL.toString());
}
};
} else if (type=="go") {
component->onClick=[win]() {
// get address bar value and nav away
std::string value;
InputComponent *p_addressComponent = dynamic_cast<InputComponent*>(win->addressComponent.get());
if (!p_addressComponent) {
std::cout << "Browser:zdoOnClick.navAddressBar->onClick - can't find address bar in windows " << std::endl;
return;
}
//std::cout << "Browser:zdoOnClick.navAddressBar->onClick - got " << value << std::endl;
TabbedComponent *p_tabComponent = dynamic_cast<TabbedComponent*>(win->tabComponent.get());
if (p_tabComponent) {
if (!p_tabComponent->tabs.size()) {
p_tabComponent->addTab("Loading...");
p_tabComponent->selectTab(p_tabComponent->tabs.back());
win->renderDirty = true;
win->render(); // display loading tab before IO
}
}
std::shared_ptr<DocumentComponent> docComponent = win->getActiveDocumentComponent();
if (docComponent) {
//std::cout << "Browser:zdoOnClick.navAddressBar->onClick - Found an active document component" << std::endl;
// now tell it to navigate somewhere
docComponent->navTo(value);
} else {
std::cout << "Browser:zdoOnClick.navAddressBar->onClick - No active document component" << std::endl;
}
};
} else if (type=="nextTab") {
component->onClick=[win]() {
// get tab value and nav away
};
} else if (type=="prevTab") {
component->onClick=[win]() {
// get tab value and nav away
};
}
}

Browser::Browser() {
std::string ntrml, line;
std::ifstream myfile("browser.ntrml");
if (myfile.is_open()) {
while(getline(myfile, line)) {
ntrml += line;
}
myfile.close();
} else {
std::cout << "Couldnt read browser.ntrml" << std::endl;
}
NTRMLParser uiParser;
//std::cout << "Browser read [" << ntrml << "]" << std::endl;
this->uiRootNode = uiParser.parse(ntrml);
printNode(this->uiRootNode, 0);
}

void Browser::createComponentTree(const std::shared_ptr<Node> node, const std::shared_ptr<Component> &parentComponent, const std::shared_ptr<Window> win) {
// FIXME: remove these 2 vars
int winWidth = win->windowWidth;
int winHeight = win->windowHeight;
std::string tag;
if (node == nullptr) {
std::cout << "ComponentBuilder::build - node is null" << std::endl;
return;
}
TagNode *tagNode = nullptr;
if (node->nodeType == NodeType::TAG) {
tagNode = dynamic_cast<TagNode*>(node.get());
if (tagNode) {
tag = tagNode->tag;
}
} else if (node->nodeType == NodeType::TEXT) {
tagNode = dynamic_cast<TagNode*>(node->parent.get());
if (tagNode) {
tag = tagNode->tag;
}
}

std::shared_ptr<Component> component = nullptr;
//std::cout << "Looking at tag[" << tag << "]" << std::endl;
if (tag == "layer") {
// the layering only works for default layout due to the ordering we're doign in window.render
component = std::make_shared<Component>();

this->layers.push_back(component);
//std::cout << "there are now " << this->layers.size() << " layers" << std::endl;
} else if (tag == "body") {
if (tagNode->properties.find("bgcolor") != tagNode->properties.end()) {
std::stringstream ss;
ss << std::hex << tagNode->properties["bgcolor"];
ss >> win->clearColor;
//std::cout << "set clear color " << std::hex << win->clearColor << std::dec << std::endl;
float r = (static_cast<float>((win->clearColor >> 24) & 0xFF)) / 255;
float g = (static_cast<float>((win->clearColor >> 16) & 0xFF)) / 255;
float b = (static_cast<float>((win->clearColor >> 8) & 0xFF)) / 255;
float a = (static_cast<float>((win->clearColor >> 0) & 0xFF)) / 255;
glClearColor(r, g, b, a);
}
} else if (tag == "img") {
/*
UILayoutV2 imgSetup;
imgSetup.width.px = 512;
imgSetup.height.px = 512;
if (tagNode->properties.find("width") != tagNode->properties.end()) {
imgSetup.width.requested = true;
imgSetup.width.px = std::stoi(tagNode->properties["width"]);
}
if (tagNode->properties.find("height") != tagNode->properties.end()) {
imgSetup.height.requested = true;
imgSetup.height.px = std::stoi(tagNode->properties["height"]);
}
if (tagNode->properties.find("left") != tagNode->properties.end()) {
imgSetup.left.requested = true;
imgSetup.left.pct = std::stoi(tagNode->properties["left"]);
}
*/
std::string src = "anime.pnm";
if (tagNode->properties.find("src") != tagNode->properties.end()) {
src = tagNode->properties["src"];
}
//std::shared_ptr<ImageComponent> img = std::make_unique<ImageComponent>(src, winWidth * imgSetup.left.pct * 0.01 + imgSetup.left.px, winHeight * imgSetup.top.pct * 0.01 + imgSetup.top.px, imgSetup.width.px, imgSetup.height.px, winWidth, winHeight);
std::shared_ptr<ImageComponent> img = std::make_unique<ImageComponent>(src, 0, 0, 512, 512, winWidth, winHeight);
img->boundToPage = false; // have to set this before setUpUI
img->setUpUI(tagNode->properties, win.get());
// set up interactivity
if (tagNode->properties.find("onClick") != tagNode->properties.end()) {
img->isPickable = true;
//doOnClick(std::string type, Component &component, Window *win)
doOnClick(tagNode->properties["onClick"], img.get(), win.get());
}
/*
img->uiControl.x = { imgSetup.left.pct , imgSetup.left.px };
img->uiControl.y = { imgSetup.top.pct , imgSetup.top.px };
img->uiControl.w = { imgSetup.width.pct, imgSetup.width.px };
img->uiControl.h = { imgSetup.width.pct, imgSetup.height.px };
img->boundToPage = false;
*/
img->isPickable = false;
img->name = "img";
if (tagNode->properties.find("name") != tagNode->properties.end()) {
img->name = tagNode->properties["name"];
}
component = img;
//std::cout << "Added img component to ui" << std::endl;
} else if (tag == "font") {
// TextComponent(const std::string &rawText, const int rawX, const int rawY, const unsigned int size, const bool bolded, const unsigned int hexColor, const int passedWindowWidth, const int passedWindowHeight);
std::shared_ptr<TextComponent> text = std::make_unique<TextComponent>("NeTRunner", 0, 0, 12, false, 0x000000FF, winWidth, winHeight);
text->boundToPage = false; // have to set this before setUpUI
text->win = win;
// this may not work for the text shader...
text->setUpUI(tagNode->properties, win.get());
text->isPickable = false;
// set up interactivity
if (tagNode->properties.find("onClick") != tagNode->properties.end()) {
text->isPickable = true;
//doOnClick(std::string type, Component &component, Window *win)
doOnClick(tagNode->properties["onClick"], text.get(), win.get());
}
component = text;
} else if (tag == "box") {
/*
UILayoutV2 boxSetup;
boxSetup.width.px = 32;
boxSetup.height.px = 32;
if (tagNode->properties.find("width") != tagNode->properties.end()) {
boxSetup.width.requested = true;
boxSetup.width.px = std::stoi(tagNode->properties["width"]);
}
if (tagNode->properties.find("height") != tagNode->properties.end()) {
boxSetup.height.requested = true;
boxSetup.height.px = std::stoi(tagNode->properties["height"]);
}
if (tagNode->properties.find("top") != tagNode->properties.end()) {
boxSetup.top.requested = true;
boxSetup.top.px = std::stoi(tagNode->properties["top"]);
}
if (tagNode->properties.find("bottom") != tagNode->properties.end()) {
boxSetup.bottom.requested = true;
boxSetup.bottom.px = std::stoi(tagNode->properties["bottom"]);
}
if (tagNode->properties.find("left") != tagNode->properties.end()) {
boxSetup.left.requested = true;
boxSetup.left.px = std::stoi(tagNode->properties["left"]);
}
if (tagNode->properties.find("right") != tagNode->properties.end()) {
boxSetup.right.requested = true;
boxSetup.right.px = std::stoi(tagNode->properties["right"]);
}
std::unique_ptr<std::pair<UImetricV2, UImetricV2>> xUI = getUIMetric(boxSetup.left, boxSetup.right, boxSetup.width);
std::unique_ptr<std::pair<UImetricV2, UImetricV2>> yUI = getUIMetric(boxSetup.top, boxSetup.bottom, boxSetup.height);
int cX = 0, cY = 0, cW = boxSetup.width.px, cH = boxSetup.height.px;
double wPct = 100, hPct = 100;
int wPx = 0, hPx = 0;
if (xUI) {
//std::cout << "box XUI at " << xUI->first.pct << "% +" << xUI->first.px << std::endl;
//std::cout << "box XUI for " << xUI->second.pct << "% +" << xUI->second.px << std::endl;
cX = (xUI->first.pct * 0.01 * winWidth) + xUI->first.px;
cW = (xUI->second.pct * 0.01 * winWidth) + xUI->second.px;
wPct = xUI->second.pct;
wPx = xUI->second.px;
std::cout << "box X at " << cX << " for " << cW << std::endl;
std::cout << "box W at " << wPct << "% for " << wPx << std::endl;
}
if (yUI) {
cY = (yUI->first.pct * 0.01 * winHeight) + yUI->first.px;
cH = (yUI->second.pct * 0.01 * winHeight) + yUI->second.px;
hPct = yUI->second.pct;
hPx = yUI->second.px;
std::cout << "box Y at " << cY << " for " << cH << std::endl;
std::cout << "box H at " << hPct << "% for " << hPx << std::endl;
}
*/
unsigned int color = 0x888888FF;
if (tagNode->properties.find("color") != tagNode->properties.end()) {
std::stringstream ss;
ss << std::hex << tagNode->properties["color"];
ss >> color;
//std::cout << "read color " << tagNode->properties["color"] << " as " << std::hex << color << std::dec << std::endl;
}
// winHeight minus because box coordinates? yes
//std::cout << "placing box at " << cX << "," << cY << " " << cW << "x" << cH << " color: " << std::hex << color << std::dec << std::endl;
//std::shared_ptr<BoxComponent> box = std::make_unique<BoxComponent>(cX, winHeight - cH - cY, cW, cH, color, winWidth, winHeight);
std::shared_ptr<BoxComponent> box = nullptr;
if (node->children.size()) {
box = std::make_unique<ButtonComponent>(0, 0, 1, 1, color, winWidth, winHeight);
} else {
box = std::make_unique<BoxComponent>(0, 0, 1, 1, color, winWidth, winHeight);
}
//navBackground->y = -64;
/*
box->uiControl.x = { 0, cX }; //
box->uiControl.y = { 100, -cH - cY }; //
box->uiControl.w = { wPct, wPx }; //
box->uiControl.h = { hPct, hPx }; //
*/
box->boundToPage = false; // have to set this before setUpUI
box->setUpUI(tagNode->properties, win.get());
box->isPickable = false;
box->name = "box";
if (tagNode->properties.find("name") != tagNode->properties.end()) {
box->name = tagNode->properties["name"];
}
// set up interactivity
if (tagNode->properties.find("hover") != tagNode->properties.end()) {
box->isPickable = true;
unsigned int hoverColor = 0;
std::stringstream ss;
ss << std::hex << tagNode->properties["hover"];
ss >> hoverColor;
//std::cout << "setHover Color " << std::hex << hoverColor << std::dec << std::endl;
box->onMouseover = [box, win, hoverColor]() {
//std::cout << "box->onMouseover" << std::endl;
box->changeColor(hoverColor);
win->renderDirty = true;
};
box->onMouseout = [box, win, color]() {
//std::cout << "box->onMouseout" << std::endl;
box->changeColor(color);
win->renderDirty = true;
};
}
if (tagNode->properties.find("onClick") != tagNode->properties.end()) {
box->isPickable = true;
//doOnClick(std::string type, Component &component, Window *win)
doOnClick(tagNode->properties["onClick"], box.get(), win.get());
}
component = box;
// if this button node has children, extract the text before discarding it
if (node->children.size()) {
TextNode *textNode = dynamic_cast<TextNode*>(node->children.front().get());
if (textNode) {
// so now cast back to a ButtonComponent and set it
std::cout << "Box text: " << textNode->text << std::endl;
/*
ButtonComponent *buttonComponent = dynamic_cast<ButtonComponent*>(component.get());
if (buttonComponent) {
buttonComponent->value = textNode->text;
buttonComponent->resizeToTextSize();
buttonComponent->updateText();
}
*/
}
}
// manual quick add before we bail
component->setParent(parentComponent);
parentComponent->children.push_back(component);
// skip my children
return;
} else if (tag == "input") {
//std::shared_ptr<InputComponent> navAddressBar = std::make_unique<InputComponent>(192.0f, winHeight - 48.0f, winWidth - 384.0f, 24.0f, winWidth, winHeight);
std::shared_ptr<InputComponent> navAddressBar = std::make_unique<InputComponent>(0, 0, 384.0f, 24.0f, winWidth, winHeight);
navAddressBar->boundToPage = false; // have to set this before setUpUI
navAddressBar->setUpUI(tagNode->properties, win.get());
/*
navAddressBar->x = 192.0f;
navAddressBar->y = winHeight - 48.0f;
navAddressBar->uiControl.x = { 0, 192 }; // 192px
navAddressBar->uiControl.y = { 100, -48 }; // top - 48px
navAddressBar->uiControl.w = { 100, -384 }; // w - 384px
navAddressBar->uiControl.h = { 0, 24 }; // 24px
*/
navAddressBar->name = "navAddressBar";

navAddressBar->onEnter=[win](std::string value) {
std::cout << "navAddressBar::onEnter got " << value << std::endl;
TabbedComponent *p_tabComponent = dynamic_cast<TabbedComponent*>(win->tabComponent.get());
if (p_tabComponent) {
if (!p_tabComponent->tabs.size()) {
p_tabComponent->addTab("Loading...");
p_tabComponent->selectTab(p_tabComponent->tabs.back());
win->renderDirty = true;
win->render(); // display loading tab before IO
}
}
std::shared_ptr<DocumentComponent> docComponent = win->getActiveDocumentComponent();
if (docComponent) {
std::cout << "Found an active document component" << std::endl;
// now tell it to navigate somewhere
docComponent->navTo(value);
} else {
std::cout << "No active document component" << std::endl;
}
};
navAddressBar->win = win;
win->addressComponent = navAddressBar;
component = navAddressBar;
} else if (tag == "tabselector") {
std::shared_ptr<TabbedComponent> tabbedComponent = std::make_shared<TabbedComponent>(0, 0, static_cast<float>(winWidth), static_cast<float>(winHeight - 64), winWidth, winHeight);
tabbedComponent->boundToPage = false; // have to set this before setUpUI
tabbedComponent->setUpUI(tagNode->properties, win.get());
tabbedComponent->name = "tabbedComponent";
/*
tabbedComponent->y = -64;
tabbedComponent->uiControl.x = { 0 , 0 }; // 0
tabbedComponent->uiControl.y = { 0 , -64 }; // -64px
tabbedComponent->uiControl.w = { 100, 0 }; // 100%
tabbedComponent->uiControl.h = { 100, -64 }; // 100% - 64px
tabbedComponent->boundToPage = false;
*/
tabbedComponent->win = win;
win->tabComponent = tabbedComponent;
component = tabbedComponent;
} else {
std::cout << "Browser::createComponentTree - unknown tag[" << tag << "]" << std::endl;
}
if (!component) {
component = std::make_shared<Component>();
}
// add it to our parent
component->setParent(parentComponent);
parentComponent->children.push_back(component);
// , children count: " << parentComponent->children.size()

// create children elements
for (std::shared_ptr<Node> child : node->children) {
createComponentTree(child, component, win);
}
}

void Browser::addWindow() {
@@ -21,6 +430,18 @@ void Browser::addWindow() {
newWindow->windowWidth = 1024;
newWindow->windowHeight = 640;
newWindow->init(); // load our UI into it
// we want each window to has it's own component tree, so each address bar can have different values
std::shared_ptr<Component> rootComponent = std::make_shared<Component>();
rootComponent->name = "rootComponent of browser";
this->createComponentTree(this->uiRootNode, rootComponent, newWindow);
rootComponent->resize(newWindow->windowWidth, newWindow->windowHeight);
Component::printComponentTree(rootComponent, 0);
newWindow->rootComponent = rootComponent;
newWindow->renderDirty = true;
this->windows.push_back(std::move(newWindow));
if (!activeWindow) {
//std::cout << "Browser::addWindow - setting active window" << std::endl;
@@ -56,7 +477,15 @@ void Browser::loop() {
this->render();
scheduler->fireTimers(); // render may have taken some time
double next = scheduler->getNext();
//std::cout << "next timer at " << next << std::endl;
//if (!next) std::cout << "timer starvation, refiring" << std::endl;
/*
while(!next) {
std::cout << "timer starvation, refiring" << std::endl;
scheduler->fireTimers(); // render may have taken some time
next = scheduler->getNext();
}
*/
//std::cout << "Browser::loop - next timer at " << next << std::endl;
if (next == LONG_MAX) {
glfwWaitEvents(); // block until something changes
} else {

Loading…
Cancel
Save