@ -1,6 +1,15 @@
@@ -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>();
@@ -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() {
@@ -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() {
@@ -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 {