# include "../../URL.h"
# include "Window.h"
# include "../../html/TagNode.h"
# include "../../html/TextNode.h"
# include "../../networking/HTTPRequest.h"
# include "../../html/HTMLParser.h"
# include "../../StringUtils.h"
# include "../../URL.h"
# include "../../Log.h"
# include "../components/BoxComponent.h"
# include "../components/AnimeComponent.h"
# include "../components/DocumentComponent.h"
# include "../components/TabbedComponent.h"
# include "../components/TextComponent.h"
# include "../components/TabbedComponent.h"
# include "../components/InputComponent.h"
# include "../opengl/Shader.h"
# include "../../browser.h"
# include <cmath>
# include <ctime>
# include <iostream>
extern std : : unique_ptr < Browser > browser ;
Window : : ~ Window ( ) {
glfwTerminate ( ) ;
}
bool Window : : init ( ) {
if ( ! initGLFW ( ) ) {
return false ;
}
if ( ! initGLEW ( ) ) {
return false ;
}
initGL ( ) ;
GLenum glErr = glGetError ( ) ;
if ( glErr ! = GL_NO_ERROR ) {
std : : cout < < " window::init - post initGL - not ok: " < < glErr < < std : : endl ;
}
// set proper scroll position
transformMatrix [ 13 ] = 2 ;
transformMatrixDirty = true ;
// configure root component
//rootComponent = std::make_shared<Component>();
rootComponent - > name = " rootComponent " ;
//rootComponent->y = 0;
// set up our UI with a new window
// (re)build UI (top to bottom)
//std::cout << "Window::setDOM window size: " << windowWidth << "x" << windowHeight << std::endl;
// layout back to front
// 4 multigroups
// 1 -> mascot
// 2 -> tabbed
// 3 -> box
// 4 -> input
//Mascot
std : : shared_ptr < AnimeComponent > mascot = std : : make_unique < AnimeComponent > ( windowWidth * 0.75f , 0.0f , 512.0f , 512.0f , windowWidth , windowHeight ) ;
mascot - > uiControl . x = { 75 , 0 } ; // 75% width
mascot - > uiControl . y = { 0 , 0 } ; // 0px
mascot - > uiControl . w = { 0 , 512 } ; // 512px
mascot - > uiControl . h = { 0 , 512 } ; // 512px
mascot - > boundToPage = false ;
mascot - > isPickable = false ;
mascot - > name = " mascot " ;
// add it to our components
mascot - > setParent ( rootComponent ) ;
rootComponent - > children . push_back ( mascot ) ;
// create tabbed component
// doc text is still showing up ontop of buttons
std : : shared_ptr < TabbedComponent > tabbedComponent = std : : make_shared < TabbedComponent > ( 0 , 0 , static_cast < float > ( windowWidth ) , static_cast < float > ( windowHeight - 64 ) , windowWidth , windowHeight ) ;
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 = shared_from_this ( ) ;
// add it to our components
tabbedComponent - > setParent ( rootComponent ) ;
rootComponent - > children . push_back ( tabbedComponent ) ;
// Nav background
std : : shared_ptr < BoxComponent > navBackground = std : : make_unique < BoxComponent > ( 0.0f , windowHeight - 64.0f , windowWidth , 64.0f , 0x888888FF , windowWidth , windowHeight ) ;
//navBackground->y = -64;
navBackground - > uiControl . y = { 100 , - 64 } ; // -64px
navBackground - > uiControl . w = { 100 , 0 } ; // 100%
navBackground - > uiControl . h = { 0 , 64 } ; // 64px
navBackground - > isPickable = false ;
navBackground - > name = " navBackground " ;
navBackground - > boundToPage = false ;
// add it to our components
navBackground - > setParent ( rootComponent ) ;
rootComponent - > children . push_back ( navBackground ) ;
std : : shared_ptr < BoxComponent > navBackButton = std : : make_unique < BoxComponent > ( 32.0f , windowHeight - 48.0f , 32.0f , 32.0f , 0x000000FF , windowWidth , windowHeight ) ;
navBackButton - > uiControl . x = { 0 , 32 } ; // 32px
navBackButton - > uiControl . y = { 100 , - 48 } ; // top - 48px
navBackButton - > uiControl . w = { 0 , 32 } ; // 32px
navBackButton - > uiControl . h = { 0 , 32 } ; // 32px
navBackButton - > onClick = [ this ] ( ) {
//std::cout << "Back" << std::endl;
TabbedComponent * pTabComponent = dynamic_cast < TabbedComponent * > ( this - > tabComponent . get ( ) ) ;
if ( pTabComponent ) {
if ( pTabComponent - > selectedTabId ) {
pTabComponent - > selectedTab - > get ( ) - > history - > back ( ) ;
}
}
} ;
navBackButton - > onMouseover = [ navBackButton , this ] ( ) {
//std::cout << "navBackButton->onMouseover" << std::endl;
navBackButton - > changeColor ( 0x880000FF ) ;
this - > renderDirty = true ;
} ;
navBackButton - > onMouseout = [ navBackButton , this ] ( ) {
//std::cout << "navBackButton->onMouseout" << std::endl;
navBackButton - > changeColor ( 0x000000FF ) ;
this - > renderDirty = true ;
} ;
navBackButton - > name = " navBackButton " ;
navBackButton - > boundToPage = false ;
// add it to our components
navBackButton - > setParent ( rootComponent ) ;
rootComponent - > children . push_back ( navBackButton ) ;
std : : shared_ptr < BoxComponent > navForwardButton = std : : make_unique < BoxComponent > ( 74.0f , windowHeight - 48.0f , 32.0f , 32.0f , 0x000000FF , windowWidth , windowHeight ) ;
navForwardButton - > uiControl . x = { 0 , 74 } ; // 74px
navForwardButton - > uiControl . y = { 100 , - 48 } ; // top - 48px
navForwardButton - > uiControl . w = { 0 , 32 } ; // 32px
navForwardButton - > uiControl . h = { 0 , 32 } ; // 32px
navForwardButton - > onClick = [ this ] ( ) {
//std::cout << "Forward" << std::endl;
TabbedComponent * pTabComponent = dynamic_cast < TabbedComponent * > ( this - > tabComponent . get ( ) ) ;
if ( pTabComponent ) {
if ( pTabComponent - > selectedTabId ) {
pTabComponent - > selectedTab - > get ( ) - > history - > forward ( ) ;
}
}
} ;
navForwardButton - > onMouseover = [ navForwardButton , this ] ( ) {
//std::cout << "navForwardButton->onMouseover" << std::endl;
navForwardButton - > changeColor ( 0x008800FF ) ;
this - > renderDirty = true ;
} ;
navForwardButton - > onMouseout = [ navForwardButton , this ] ( ) {
//std::cout << "navForwardButton->onMouseout" << std::endl;
navForwardButton - > changeColor ( 0x000000FF ) ;
this - > renderDirty = true ;
} ;
navForwardButton - > name = " navForwardButton " ;
navForwardButton - > boundToPage = false ;
// add it to our components
//navForwardButton->parent = rootComponent;
navForwardButton - > setParent ( rootComponent ) ;
rootComponent - > children . push_back ( navForwardButton ) ;
std : : shared_ptr < BoxComponent > navRefreshButton = std : : make_unique < BoxComponent > ( 116.0f , windowHeight - 48.0f , 32.0f , 32.0f , 0x000000FF , windowWidth , windowHeight ) ;
navRefreshButton - > uiControl . x = { 0 , 116 } ; // 116px
navRefreshButton - > uiControl . y = { 100 , - 48 } ; // top - 48px
navRefreshButton - > uiControl . w = { 0 , 32 } ; // 32px
navRefreshButton - > uiControl . h = { 0 , 32 } ; // 32px
navRefreshButton - > name = " navRefreshButton " ;
navRefreshButton - > boundToPage = false ;
navRefreshButton - > onClick = [ this ] ( ) {
std : : shared_ptr < DocumentComponent > docComponent = this - > getActiveDocumentComponent ( ) ;
if ( docComponent ) {
std : : cout < < " Refreshing " < < docComponent - > currentURL < < std : : endl ;
// now tell it to navigate somewhere
docComponent - > navTo ( docComponent - > currentURL . toString ( ) ) ;
}
} ;
navRefreshButton - > onMouseover = [ navRefreshButton , this ] ( ) {
//std::cout << "navRefreshButton->onMouseover" << std::endl;
navRefreshButton - > changeColor ( 0x000088FF ) ;
this - > renderDirty = true ;
} ;
navRefreshButton - > onMouseout = [ navRefreshButton , this ] ( ) {
//std::cout << "navRefreshButton->onMouseout" << std::endl;
navRefreshButton - > changeColor ( 0x000000FF ) ;
this - > renderDirty = true ;
} ; // add it to our components
navRefreshButton - > setParent ( rootComponent ) ;
rootComponent - > children . push_back ( navRefreshButton ) ;
// Address Bar
std : : shared_ptr < InputComponent > navAddressBar = std : : make_unique < InputComponent > ( 192.0f , windowHeight - 48.0f , windowWidth - 384.0f , 24.0f , windowWidth , windowHeight ) ;
// add it to our components
navAddressBar - > x = 192.0f ;
navAddressBar - > y = windowHeight - 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 - > boundToPage = false ;
navAddressBar - > win = shared_from_this ( ) ;
//navAddressBar->y = -48; // this works but breaks picking
//navAddressBar->value = currentURL.toString();
//navAddressBar->updateText();
navAddressBar - > onEnter = [ this ] ( std : : string value ) {
std : : cout < < " navAddressBar::onEnter got " < < value < < std : : endl ;
TabbedComponent * tabComponent = dynamic_cast < TabbedComponent * > ( this - > tabComponent . get ( ) ) ;
if ( tabComponent ) {
if ( ! tabComponent - > tabs . size ( ) ) {
tabComponent - > addTab ( " Loading... " ) ;
tabComponent - > selectTab ( tabComponent - > tabs . back ( ) ) ;
this - > renderDirty = true ;
this - > render ( ) ; // display loading tab before IO
}
}
std : : shared_ptr < DocumentComponent > docComponent = this - > 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 ;
}
} ;
this - > addressComponent = navAddressBar ;
// we do this to prevent flashing
render ( ) ;
renderDirty = true ;
//std::cout << "placing inputComponent at " << static_cast<int>(navAddressBar->x) << "," << static_cast<int>(navAddressBar->y) << std::endl;
navAddressBar - > setParent ( rootComponent ) ;
rootComponent - > children . push_back ( navAddressBar ) ;
/*
// textTest
// 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 > textTest = std : : make_unique < TextComponent > ( " Test " , - 99 , - 99 , 12 , false , 0x000000ff , windowWidth , windowHeight ) ;
textTest - > x = 192.0f ;
textTest - > y = - 64.0f ;
textTest - > isPickable = false ;
// add it to our components
textTest - > parent = rootComponent ;
rootComponent - > children . push_back ( textTest ) ;
// we really don't want to layout because that's moves us relative to parent
// and this is static layout we want, not a free flow
//textTest->layout(); // to rasterize
textTest - > resize ( windowWidth , windowHeight ) ;
*/
// set tab component
this - > tabComponent = tabbedComponent ;
return true ;
}
bool Window : : initGLFW ( ) {
if ( ! glfwInit ( ) ) {
std : : cout < < " Could not initialize GLFW " < < std : : endl ;
return false ;
}
glfwWindowHint ( GLFW_CONTEXT_VERSION_MAJOR , 3 ) ;
glfwWindowHint ( GLFW_CONTEXT_VERSION_MINOR , 2 ) ;
glfwWindowHint ( GLFW_OPENGL_FORWARD_COMPAT , GL_TRUE ) ;
glfwWindowHint ( GLFW_OPENGL_PROFILE , GLFW_OPENGL_CORE_PROFILE ) ;
//glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
glfwSetErrorCallback ( [ ] ( int error , const char * description ) {
std : : cout < < " glfw error [ " < < error < < " ]: " < < description < < std : : endl ;
} ) ;
GLFWwindow * context = nullptr ;
if ( browser - > windows . size ( ) ) {
context = browser - > windows . front ( ) . get ( ) - > window ;
}
// after title, it's monitor
window = glfwCreateWindow ( windowWidth , windowHeight , " NetRunner " , nullptr , context ) ;
if ( ! window ) {
glfwTerminate ( ) ;
std : : cout < < " Could not create window " < < std : : endl ;
return false ;
}
// replace first parameter of all these callbacks with our window object instead of a GLFWwindow
glfwSetWindowUserPointer ( window , this ) ;
// set window w/h
//glfwGetFramebufferSize(window, &windowWidth, &windowHeight); // in pixels
glfwGetWindowSize ( window , & windowWidth , & windowHeight ) ; // use screen coordinates (not pixels) more retina friendly
// set up event callbacks
glfwSetFramebufferSizeCallback ( window , [ ] ( GLFWwindow * win , int width , int height ) {
glViewport ( 0 , 0 , width , height ) ;
} ) ;
glfwSetWindowSizeCallback ( window , [ ] ( GLFWwindow * win , int width , int height ) {
Window * thiz = reinterpret_cast < Window * > ( glfwGetWindowUserPointer ( win ) ) ;
thiz - > onResize ( width , height ) ;
} ) ;
cursorHand = glfwCreateStandardCursor ( GLFW_HAND_CURSOR ) ;
cursorArrow = glfwCreateStandardCursor ( GLFW_ARROW_CURSOR ) ;
cursorIbeam = glfwCreateStandardCursor ( GLFW_IBEAM_CURSOR ) ;
glfwSetCursorPosCallback ( window , [ ] ( GLFWwindow * win , double xPos , double yPos ) {
Window * thiz = reinterpret_cast < Window * > ( glfwGetWindowUserPointer ( win ) ) ;
thiz - > cursorX = xPos ;
thiz - > cursorY = yPos ;
//std::cout << "Window::Window:onMousemove - at " << static_cast<int>(xPos) << "," << static_cast<int>(yPos) << std::endl;
if ( xPos < 0 | | yPos < 0 ) return ;
if ( xPos > thiz - > windowWidth | | yPos > thiz - > windowHeight ) return ;
// p. much worthless on double
/*
static double lx = 0 ;
static double ly = 0 ;
if ( lx = = xPos & & ly = = yPos ) {
return ;
}
lx = xPos ;
ly = yPos ;
std : : cout < < " Window::Window:onMousemove - noCache " < < std : : endl ;
*/
//std::cout << "Window::Window:onMousemove - begin search" << std::endl;
//std::cout << "Window::Window:onMousemove - windowHeight: " << thiz->windowHeight << " cursorY: " << thiz->cursorY << " scrollY: " << thiz->transformMatrix[13] << std::endl;
std : : shared_ptr < Component > newHover = thiz - > searchComponentTree ( thiz - > rootComponent , thiz - > cursorX , ( thiz - > windowHeight - thiz - > cursorY ) + ( ( - thiz - > transformMatrix [ 13 ] / 2 ) * thiz - > windowHeight ) ) ;
if ( newHover ! = thiz - > hoverComponent ) {
if ( thiz - > hoverComponent & & thiz - > hoverComponent - > onMouseout ) {
thiz - > hoverComponent - > onMouseout ( ) ;
}
if ( newHover & & newHover - > onMouseover ) {
newHover - > onMouseover ( ) ;
}
thiz - > hoverComponent = newHover ;
}
if ( thiz - > hoverComponent ) {
//std::cout << "Window::Window:onMousemove - hover " << typeOfComponent(thiz->hoverComponent) << std::endl;
if ( thiz - > hoverComponent - > onClick ) {
glfwSetCursor ( thiz - > window , thiz - > cursorHand ) ;
} else {
TextComponent * textComponent = dynamic_cast < TextComponent * > ( thiz - > hoverComponent . get ( ) ) ;
InputComponent * inputComponent = dynamic_cast < InputComponent * > ( thiz - > hoverComponent . get ( ) ) ;
if ( textComponent | | inputComponent ) {
glfwSetCursor ( thiz - > window , thiz - > cursorIbeam ) ;
}
// otherwise we could be an Box/Anime or Document Component
}
if ( thiz - > hoverComponent - > onMousemove ) {
// this could communicate the cursor to use
thiz - > hoverComponent - > onMousemove ( thiz - > cursorX , thiz - > cursorY ) ;
}
} else {
glfwSetCursor ( thiz - > window , thiz - > cursorArrow ) ;
}
} ) ;
glfwSetScrollCallback ( window , [ ] ( GLFWwindow * win , double xOffset , double yOffset ) {
Window * thiz = reinterpret_cast < Window * > ( glfwGetWindowUserPointer ( win ) ) ;
// yOffset is a delta vector
thiz - > transformMatrix [ 13 ] + = - yOffset * 0.1 ;
if ( thiz - > hoverComponent ) {
//std::cout << "scroll - hovering over a component" << std::endl;
if ( thiz - > hoverComponent - > onWheel ) {
//std::cout << "scroll - hovering over a scrollabel component" << std::endl;
thiz - > hoverComponent - > onWheel ( xOffset * 100 , yOffset * 100 ) ;
}
}
// 2.0 is one screen height
// we draw from 0 downwards (y+), so can't scroll past our starting draw point
if ( thiz - > transformMatrix [ 13 ] < 2 ) {
thiz - > transformMatrix [ 13 ] = 2 ;
}
// calculate scroll max by calculating how many screens are in the rootComponent's Height
if ( thiz - > transformMatrix [ 13 ] > std : : max ( thiz - > rootComponent - > height / thiz - > windowHeight * 2.0f , 2.0f ) ) {
thiz - > transformMatrix [ 13 ] = std : : max ( thiz - > rootComponent - > height / thiz - > windowHeight * 2.0f , 2.0f ) ;
}
//std::cout << "scroll y is at " << thiz->transformMatrix[13] << "/" << static_cast<int>((thiz->transformMatrix[13]*10000) << std::endl;
thiz - > transformMatrixDirty = true ;
} ) ;
glfwSetMouseButtonCallback ( window , [ ] ( GLFWwindow * win , int button , int action , int mods ) {
Window * thiz = reinterpret_cast < Window * > ( glfwGetWindowUserPointer ( win ) ) ;
if ( button = = GLFW_MOUSE_BUTTON_LEFT & & action = = GLFW_PRESS ) {
//std::cout << "left press" << std::endl;
if ( thiz - > hoverComponent ) {
//std::cout << "focus event" << std::endl;
if ( thiz - > focusedComponent ! = thiz - > hoverComponent ) {
// blur old component
if ( thiz - > focusedComponent ) {
if ( thiz - > focusedComponent - > onBlur ) {
thiz - > focusedComponent - > onBlur ( ) ;
}
}
// focus new component
if ( thiz - > hoverComponent - > onFocus ) {
thiz - > hoverComponent - > onFocus ( ) ;
}
}
thiz - > focusedComponent = thiz - > hoverComponent ;
if ( thiz - > focusedComponent - > onMousedown ) {
//std::cout << "click event" << std::endl;
thiz - > focusedComponent - > onMousedown ( thiz - > cursorX , thiz - > cursorY ) ;
}
}
}
if ( button = = GLFW_MOUSE_BUTTON_LEFT & & action = = GLFW_RELEASE ) {
//std::cout << "left release" << std::endl;
if ( thiz - > hoverComponent ) {
//std::cout << "focus event" << std::endl;
if ( thiz - > focusedComponent ! = thiz - > hoverComponent ) {
// blur old component
if ( thiz - > focusedComponent ) {
if ( thiz - > focusedComponent - > onBlur ) {
thiz - > focusedComponent - > onBlur ( ) ;
}
}
// focus new component
if ( thiz - > hoverComponent - > onFocus ) {
thiz - > hoverComponent - > onFocus ( ) ;
}
}
thiz - > focusedComponent = thiz - > hoverComponent ;
/*
InputComponent * inputComponent = dynamic_cast < InputComponent * > ( thiz - > focusedComponent . get ( ) ) ;
if ( inputComponent ) {
std : : cout < < " inputComponent focus " < < std : : endl ;
}
*/
if ( thiz - > focusedComponent & & thiz - > focusedComponent - > onMouseup ) {
//std::cout << "click event" << std::endl;
thiz - > focusedComponent - > onMouseup ( thiz - > cursorX , thiz - > cursorY ) ;
}
if ( thiz - > focusedComponent & & thiz - > focusedComponent - > onClick ) {
//std::cout << "click event" << std::endl;
thiz - > focusedComponent - > onClick ( ) ;
}
}
}
} ) ;
// works with utf-32 but we'll lkeep the low level for now
/*
glfwSetCharCallback ( window , [ ] ( GLFWwindow * win , unsigned int codepoint ) {
Window * thiz = reinterpret_cast < Window * > ( glfwGetWindowUserPointer ( win ) ) ;
std : : cout < < " Window::glfwSetCharCallback - codepoint: " < < codepoint < < std : : endl ;
} ) ;
*/
glfwSetKeyCallback ( window , [ ] ( GLFWwindow * win , int key , int scancode , int action , int mods ) {
Window * thiz = reinterpret_cast < Window * > ( glfwGetWindowUserPointer ( win ) ) ;
//std::cout << "Key " << key << " action: " << action << "mods: " << mods << std::endl;
if ( key = = GLFW_KEY_N & & action = = GLFW_RELEASE & & mods = = GLFW_MOD_CONTROL ) {
browser - > addWindow ( ) ;
return ;
}
// we're focused on something
//std::cout << "glfwSetKeyCallback" << std::endl;
if ( thiz - > focusedComponent ) {
//std::cout << "glfwSetKeyCallback - focused on " << typeOfComponent(thiz->focusedComponent) << std::endl;
TabbedComponent * p_tabComponent = dynamic_cast < TabbedComponent * > ( thiz - > focusedComponent . get ( ) ) ;
if ( p_tabComponent ) {
// repeat or key up
if ( action = = 2 | | action = = 0 ) {
if ( p_tabComponent - > onKeyPress ) {
p_tabComponent - > onKeyPress ( key , scancode , action , mods ) ;
}
if ( action = = 0 ) {
if ( p_tabComponent - > onKeyup ) {
p_tabComponent - > onKeyup ( key , scancode , action , mods ) ;
}
}
}
return ;
}
DocumentComponent * docComponent = dynamic_cast < DocumentComponent * > ( thiz - > focusedComponent . get ( ) ) ;
if ( docComponent ) {
if ( action = = 0 ) {
if ( docComponent - > onKeyup ) {
docComponent - > onKeyup ( key , scancode , action , mods ) ;
}
}
return ;
}
InputComponent * inputComponent = dynamic_cast < InputComponent * > ( thiz - > focusedComponent . get ( ) ) ;
if ( inputComponent ) {
//std::cout << "inputComponent is focsued, key pressed " << key << " action: " <<action << std::endl;
// action 1 is down, 0 is up, 2 is a repeat
if ( action = = 0 | | action = = 2 ) {
// key up
// it's always uppercase...
if ( key = = 259 ) {
inputComponent - > backSpace ( ) ;
} else if ( key = = 257 ) {
std : : cout < < " enter! " < < std : : endl ;
if ( inputComponent - > onEnter ) {
inputComponent - > onEnter ( inputComponent - > value ) ;
}
} else {
if ( key < 256 ) {
if ( mods & GLFW_MOD_SHIFT ) {
// SHIFT
if ( key = = GLFW_KEY_SLASH ) key = ' ? ' ;
if ( key = = GLFW_KEY_APOSTROPHE ) key = ' " ' ;
if ( key = = GLFW_KEY_COMMA ) key = ' < ' ;
if ( key = = GLFW_KEY_MINUS ) key = ' _ ' ;
if ( key = = GLFW_KEY_PERIOD ) key = ' > ' ;
if ( key = = GLFW_KEY_SEMICOLON ) key = ' : ' ;
if ( key = = GLFW_KEY_EQUAL ) key = ' + ' ;
if ( key = = GLFW_KEY_LEFT_BRACKET ) key = ' { ' ;
if ( key = = GLFW_KEY_BACKSLASH ) key = ' | ' ;
if ( key = = GLFW_KEY_RIGHT_BRACKET ) key = ' } ' ;
if ( key = = GLFW_KEY_GRAVE_ACCENT ) key = ' ~ ' ;
} else {
// no shift or caplocks
// basically: when SHIFT isn't pressed but key is in A-Z range, add ascii offset to make it lower case
if ( key > = ' A ' & & key < = ' Z ' ) {
key + = ' a ' - ' A ' ;
}
}
inputComponent - > addChar ( key ) ;
} // otherwise I think it's some weird control char
}
}
return ;
}
}
switch ( key ) {
case GLFW_KEY_1 :
case GLFW_KEY_2 :
case GLFW_KEY_3 :
case GLFW_KEY_4 :
case GLFW_KEY_5 :
case GLFW_KEY_6 :
case GLFW_KEY_7 :
case GLFW_KEY_8 :
case GLFW_KEY_9 :
case GLFW_KEY_0 :
std : : cout < < " Key was pressed: " < < key < < std : : endl ;
//thiz->transformMatrixIndex = key - GLFW_KEY_0;
//std::cout << thiz->transformMatrixIndex << std::endl;
break ;
default :
break ;
}
if ( key = = GLFW_KEY_Q & & action = = GLFW_PRESS ) {
std : : cout < < " Q was pressed. Exiting. " < < std : : endl ;
exit ( 0 ) ;
}
if ( key = = GLFW_KEY_E & & action = = GLFW_RELEASE ) {
printf ( " Printing NodeTree \n \n " ) ;
TabbedComponent * p_TabComponent = dynamic_cast < TabbedComponent * > ( thiz - > tabComponent . get ( ) ) ;
if ( p_TabComponent ) {
DocumentComponent * p_DocComponent = dynamic_cast < DocumentComponent * > ( p_TabComponent - > documentComponent . get ( ) ) ;
if ( p_DocComponent ) {
printNode ( p_DocComponent - > domRootNode , 1 ) ;
}
}
printf ( " \n \n " ) ;
}
if ( key = = GLFW_KEY_D & & action = = GLFW_RELEASE ) {
printf ( " Printing ComponentTree \n \n " ) ;
TabbedComponent * p_TabComponent = dynamic_cast < TabbedComponent * > ( thiz - > tabComponent . get ( ) ) ;
if ( p_TabComponent ) {
DocumentComponent * p_DocComponent = dynamic_cast < DocumentComponent * > ( p_TabComponent - > documentComponent . get ( ) ) ;
if ( p_DocComponent ) {
Component : : printComponentTree ( p_DocComponent - > rootComponent , 0 ) ;
}
}
printf ( " \n \n " ) ;
}
if ( key = = GLFW_KEY_F & & action = = GLFW_RELEASE ) {
printf ( " Printing UI ComponentTree \n \n " ) ;
Component : : printComponentTree ( thiz - > rootComponent , 0 ) ;
printf ( " \n \n " ) ;
}
int yOffsetScroll = 1 ;
if ( key = = GLFW_KEY_PAGE_UP & & ( action = = GLFW_PRESS | | action = = GLFW_REPEAT ) ) {
TabbedComponent * p_TabComponent = dynamic_cast < TabbedComponent * > ( thiz - > tabComponent . get ( ) ) ;
if ( p_TabComponent ) {
DocumentComponent * p_DocComponent = dynamic_cast < DocumentComponent * > ( p_TabComponent - > documentComponent . get ( ) ) ;
if ( p_DocComponent ) {
p_DocComponent - > transformMatrix [ 13 ] + = - yOffsetScroll * 0.1 ;
p_DocComponent - > transformMatrixDirty = true ;
thiz - > renderDirty = true ;
}
}
}
if ( key = = GLFW_KEY_PAGE_DOWN & & ( action = = GLFW_PRESS | | action = = GLFW_REPEAT ) ) {
TabbedComponent * p_TabComponent = dynamic_cast < TabbedComponent * > ( thiz - > tabComponent . get ( ) ) ;
if ( p_TabComponent ) {
DocumentComponent * p_DocComponent = dynamic_cast < DocumentComponent * > ( p_TabComponent - > documentComponent . get ( ) ) ;
if ( p_DocComponent ) {
p_DocComponent - > transformMatrix [ 13 ] + = yOffsetScroll * 0.1 ;
p_DocComponent - > transformMatrixDirty = true ;
thiz - > renderDirty = true ;
}
}
}
// FIXME Scrolling with this can scroll past boundary whereas the same doesn't happen with
// scrolling wheel
if ( key = = GLFW_KEY_J & & ( action = = GLFW_PRESS | | action = = GLFW_REPEAT ) ) {
std : : cout < < " J is/was pressed. Scrolling down. " < < std : : endl ;
TabbedComponent * p_TabComponent = dynamic_cast < TabbedComponent * > ( thiz - > tabComponent . get ( ) ) ;
if ( p_TabComponent ) {
DocumentComponent * p_DocComponent = dynamic_cast < DocumentComponent * > ( p_TabComponent - > documentComponent . get ( ) ) ;
if ( p_DocComponent ) {
p_DocComponent - > transformMatrix [ 13 ] + = yOffsetScroll * 0.1 ;
p_DocComponent - > transformMatrixDirty = true ;
thiz - > renderDirty = true ;
}
}
}
// FIXME Scrolling with this can scroll past boundary whereas the same doesn't happen with
// scrolling wheel
if ( key = = GLFW_KEY_K & & ( action = = GLFW_PRESS | | action = = GLFW_REPEAT ) ) {
std : : cout < < " K is/was pressed. Scrolling up. " < < std : : endl ;
TabbedComponent * p_TabComponent = dynamic_cast < TabbedComponent * > ( thiz - > tabComponent . get ( ) ) ;
if ( p_TabComponent ) {
DocumentComponent * p_DocComponent = dynamic_cast < DocumentComponent * > ( p_TabComponent - > documentComponent . get ( ) ) ;
if ( p_DocComponent ) {
p_DocComponent - > transformMatrix [ 13 ] + = - yOffsetScroll * 0.1 ;
p_DocComponent - > transformMatrixDirty = true ;
thiz - > renderDirty = true ;
}
}
}
} ) ;
glfwMakeContextCurrent ( window ) ;
return true ;
}
bool Window : : initGLEW ( ) const {
glewExperimental = GL_TRUE ;
const GLenum err = glewInit ( ) ;
if ( err ! = GLEW_OK ) {
std : : cout < < " Could not initialize GLEW: " < < glewGetErrorString ( err ) < < std : : endl ;
return false ;
}
return true ;
}
bool Window : : initGL ( ) {
const GLubyte * renderer = glGetString ( GL_RENDERER ) ;
const GLubyte * version = glGetString ( GL_VERSION ) ;
std : : cout < < " Renderer: " < < renderer < < std : : endl ;
std : : cout < < " Version: " < < version < < std : : endl ;
glEnable ( GL_BLEND ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
glClearColor ( 0.8f , 0.8f , 0.8f , 0.8f ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
GLenum glErr = glGetError ( ) ;
if ( glErr ! = GL_NO_ERROR ) {
std : : cout < < " window::initGL - blend, clear, texParam - not ok: " < < glErr < < std : : endl ;
}
//std::cout << "OpenGL is set up" << std::endl;
glGetIntegerv ( GL_MAX_TEXTURE_SIZE , & maxTextureSize ) ;
return true ;
}
void Window : : onResize ( int passedWidth , int passedHeight ) {
this - > windowWidth = passedWidth ;
this - > windowHeight = passedHeight ;
this - > delayResize = 1 ;
}
void Window : : resize ( ) {
//std::cout << "Window::resize" << std::endl;
//this->printComponentTree(rootComponent, 0);
const std : : clock_t begin = clock ( ) ;
rootComponent - > windowWidth = windowWidth ;
rootComponent - > windowHeight = windowHeight ;
rootComponent - > layout ( ) ;
const std : : clock_t end = clock ( ) ;
std : : cout < < " Window::resize - resized components in: " < < std : : fixed < < ( ( static_cast < double > ( end - begin ) ) / CLOCKS_PER_SEC ) < < std : : scientific < < " seconds " < < std : : endl ;
//this->printComponentTree(rootComponent, 0);
// recalculate scroll max by calculating how many screens are in the rootComponent's Height
if ( transformMatrix [ 13 ] > std : : max ( ( rootComponent - > height ) / ( windowHeight ) * 2.0f , 2.0f ) ) {
transformMatrix [ 13 ] = std : : max ( ( rootComponent - > height ) / ( windowHeight ) * 2.0f , 2.0f ) ;
transformMatrixDirty = true ;
}
renderDirty = true ;
}
void Window : : render ( ) {
if ( delayResize ) {
delayResize - - ;
if ( delayResize ) {
return ;
}
//std::cout << "Window::render - restarting drawing" << std::endl;
this - > resize ( ) ;
}
/*
if ( domDirty ) {
const std : : clock_t begin = clock ( ) ;
createComponentTree ( domRootNode , rootComponent ) ;
const std : : clock_t end = clock ( ) ;
std : : cout < < " built & laid out window components in: " < < std : : fixed < < ( ( static_cast < double > ( end - begin ) ) / CLOCKS_PER_SEC ) < < std : : scientific < < " seconds " < < std : : endl ;
//printComponentTree(rootComponent, 0);
//std::cout << "Window printComponentTree end" << std::endl;
domDirty = false ;
renderDirty = true ;
}
*/
if ( renderDirty | | transformMatrixDirty ) {
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
GLenum glErr = glGetError ( ) ;
if ( glErr ! = GL_NO_ERROR ) {
std : : cout < < " window::render - box render start - not ok: " < < glErr < < std : : endl ;
}
Shader * textureShader = shaderLoader . getShader ( VertexShader ( " TextureShader.vert " ) ,
FragmentShader ( " TextureShader.frag " ) ) ;
if ( ! textureShader ) {
std : : cout < < " Cant load shader " < < std : : endl ;
return ;
}
textureShader - > bind ( ) ;
glErr = glGetError ( ) ;
if ( glErr ! = GL_NO_ERROR ) {
std : : cout < < " window::render - glUseProgram - not ok: " < < glErr < < std : : endl ;
}
// draw anime 1st, tabbed components 2nd
// then box shit
// text last
renderComponentType ( " anime " , rootComponent ) ;
renderComponentType ( " tab " , rootComponent ) ;
textureShader - > bind ( ) ;
//GLint transformLocation = glGetUniformLocation(textureProgram, "transform");
//glUniformMatrix4fv(transformLocation, 1, GL_FALSE, transformMatrix);
renderComponentType ( " box " , rootComponent ) ;
renderComponentType ( " input " , rootComponent ) ;
// it's quick but done on scroll
Shader * fontShader = shaderLoader . getShader ( VertexShader ( " FontShader.vert " ) ,
FragmentShader ( " FontShader.frag " ) ) ;
fontShader - > bind ( ) ;
// reset both, since components can change this
// god we may have to reset this after each component render...
// maybe we don't need too
if ( transformMatrixDirty ) {
//const std::clock_t begin = clock();
GLint transformLocation = fontShader - > uniform ( " transform " ) ;
glErr = glGetError ( ) ;
if ( glErr ! = GL_NO_ERROR ) {
std : : cout < < " window::render - glGetUniformLocation - not ok: " < < glErr < < std : : endl ;
}
glUniformMatrix4fv ( transformLocation , 1 , GL_FALSE , transformMatrix ) ;
glErr = glGetError ( ) ;
if ( glErr ! = GL_NO_ERROR ) {
std : : cout < < " window::render - glUniformMatrix4fv - not ok: " < < glErr < < std : : endl ;
}
// didn't change much (could be we didnt' select the textureProgram first)
//GLint transformLocation2 = glGetUniformLocation(textureProgram, "transform");
//glUniformMatrix4fv(transformLocation2, 1, GL_FALSE, transformMatrix);
//const std::clock_t end = clock();
//std::cout << "Updated font matrix in: " << std::fixed << ((static_cast<double>(end - begin)) / CLOCKS_PER_SEC) << std::scientific << " seconds" << std::endl;
transformMatrixDirty = false ;
}