Newer
Older
#include "DocumentComponent.h"
#include <cmath>
#include <iostream>
#include "../../Log.h"
#include "InputComponent.h"
void deleteComponent(std::shared_ptr<Component> &component);
void deleteNode(std::shared_ptr<Node> node);
DocumentComponent::DocumentComponent(const float rawX, const float rawY, const float rawWidth, const float rawHeight, const int passedWindowWidth, const int passedWindowHeight) : MultiComponent(rawX, rawY, rawWidth, rawHeight, passedWindowWidth, passedWindowHeight) {
//std::cout << "DocumentComponent::DocumentComponent" << std::endl;
windowWidth = passedWindowWidth;
windowHeight = passedWindowHeight;
//std::cout << "DocumentComponent::DocumentComponent - window size: " << windowWidth << "x" << windowHeight << std::endl;
x = rawX;
y = rawY;
width = rawWidth;
height = rawHeight;
if (height < 0) {
std::cout << "DocumentComponent::DocumentComponent - height was less than zero" << std::endl;
height = 0;
}
//std::cout << "DocumentComponent::DocumentComponent - our size" << static_cast<int>(width) << "x" << static_cast<int>(height) << std::endl;
onMousemove=[this](int passedX, int passedY) {
// set hover component
static int lx = 0;
static int ly = 0;
//std::cout << "DocumentComponent::DocumentComponent:onMousemove - at " << passedX << "," << passedY << std::endl;
//std::cout << "DocumentComponent::DocumentComponent:onMousemove - size " << this->windowWidth << "," << this->windowHeight << std::endl;
this->hoverComponent = this->searchComponentTree(this->rootComponent, passedX, passedY);
if (this->hoverComponent) {
//std::cout << "DocumentComponent::DocumentComponent:onMousemove - hovering over " << typeOfComponent(this->hoverComponent) << " component" << std::endl;
if (this->hoverComponent->onMousemove) {
// this could communicate the cursor to use
this->hoverComponent->onMousemove(passedX, passedY);
}
if (this->hoverComponent->onClick) {
glfwSetCursor(this->win->window, this->win->cursorHand);
} else {
glfwSetCursor(this->win->window, this->win->cursorIbeam);
}
} else {
glfwSetCursor(this->win->window, this->win->cursorArrow);
}
};
//std::cout << "DocumentComponent::DocumentComponent:::onWheel - scroll yDelta: " << y << std::endl;
//Component::printComponentTree(rootComponent, 0);
double pY = passedY / 10;
this->scrollY -= pY;
if (this->scrollY < 0) {
this->scrollY = 0;
} else if (this->scrollY > this->scrollHeight) {
this->scrollY = this->scrollHeight;
}
//std::cout << "scroll pos: " << scrollY << "/" << scrollHeight << std::endl;
//std::cout << "y: " << static_cast<int>(this->y) << " - " << this->scrollY << std::endl;
//std::cout << "root.y: " << static_cast<int>(rootComponent->y) << std::endl;
//std::cout << "windowSize: " << windowWidth << "," << windowHeight << std::endl;
// adjust root position
rootComponent->y = this->y + this->scrollY;
//std::cout << "now root.y: " << static_cast<int>(rootComponent->y) << std::endl;
// reset root size
rootComponent->windowWidth = windowWidth;
rootComponent->windowHeight = windowHeight;
//Component::printComponentTree(rootComponent, 0);
// this takes so long, we may want to delay until the input is adjusted
rootComponent->layout(); // need to update the vertices
//renderDirty = true;
// should we mark win->renderDirty = true?
const std::clock_t end = clock();
std::cout << "Scrolled document in: " << std::fixed << ((static_cast<double>(end - begin)) / CLOCKS_PER_SEC) << std::scientific << " seconds" << std::endl;
//rootComponent->y = this->y - this->scrollY;
//std::cout << "after root.y: " << static_cast<int>(rootComponent->y) << std::endl;
// don't need this - why not?
onMousedown=[this](int passedX, int passedY) {
std::cout << "document left press" << std::endl;
if (this->hoverComponent) {
if (this->focusedComponent != this->hoverComponent) {
// blur old component
if (this->focusedComponent) {
if (this->focusedComponent->onBlur) {
this->focusedComponent->onBlur();
}
}
// focus new component
if (this->hoverComponent->onFocus) {
this->hoverComponent->onFocus();
}
}
this->focusedComponent = this->hoverComponent;
if (this->focusedComponent->onMousedown) {
//std::cout << "click event" << std::endl;
this->focusedComponent->onMousedown(passedX, passedY);
onMouseup=[this](int passedX, int passedY) {
std::cout << "document left release" << std::endl;
if (this->hoverComponent) {
//std::cout << "DocumentComponent::DocumentComponent:onMouseup - hovering over " << typeOfComponent(this->hoverComponent) << " component" << std::endl;
if (this->focusedComponent != this->hoverComponent) {
// blur old component
if (this->focusedComponent) {
if (this->focusedComponent->onBlur) {
this->focusedComponent->onBlur();
}
}
// focus new component
if (this->hoverComponent->onFocus) {
this->hoverComponent->onFocus();
}
}
this->focusedComponent = this->hoverComponent;
if (this->focusedComponent->onMouseup) {
//std::cout << "click event" << std::endl;
this->focusedComponent->onMouseup(passedX, passedY);
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
}
if (this->focusedComponent->onClick) {
//std::cout << "click event" << std::endl;
this->focusedComponent->onClick();
}
}
};
onKeyup=[this](int key, int scancode, int action, int mods) {
//std::cout << "DocumentComponent::DocumentComponent:onKeyup" << std::endl;
InputComponent *inputComponent = dynamic_cast<InputComponent*>(this->focusedComponent.get());
if (inputComponent) {
//std::cout << "inputComponent is focused, 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;
} 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
}
}
}
};
}
void deleteComponent(std::shared_ptr<Component> &component) {
// delete all my child first
for (std::shared_ptr<Component> child : component->children) {
deleteComponent(child);
}
component->parent=nullptr;
component->previous=nullptr;
component->children.clear();
// now delete self
void deleteNode(std::shared_ptr<Node> node) {
for (std::shared_ptr<Node> child : node->children) {
deleteNode(child);
node->parent=nullptr;
node->children.clear();
node->component=nullptr; // disassociate component
}
void DocumentComponent::setDOM(const std::shared_ptr<Node> rootNode) {
// reset rootComponent
if (rootComponent) {
deleteComponent(rootComponent);
if (domRootNode) {
deleteNode(domRootNode);
// reset scroll position ?
// new root component
rootComponent = std::make_shared<Component>();
rootComponent->name = "rootComponent of " + name;
rootComponent->y = y;
domRootNode = rootNode;
domDirty = true;
}
void DocumentComponent::render() {
//std::cout << "DocumentComponent::render" << std::endl;
if (domDirty) {
const std::clock_t begin = clock();
createComponentTree(domRootNode, rootComponent);
const std::clock_t end = clock();
// root component here doesn't have any children...
std::cout << "built & laid out document components in: " << std::fixed << ((static_cast<double>(end - begin)) / CLOCKS_PER_SEC) << std::scientific << " seconds" << std::endl;
//Component::printComponentTree(rootComponent, 0);
domDirty = false;
//std::cout << "root Height: " << static_cast<int>(rootComponent->height) << " window Height: " << windowHeight << " y " << static_cast<int>(this->y) << std::endl;
scrollHeight = std::max(0, static_cast<int>(rootComponent->height - (windowHeight + (this->y * 2))));
}
//std::cout << "DocumentComponent::render - renderDirty" << std::endl;
glUseProgram(win->textureProgram);
renderBoxComponents(rootComponent);
glUseProgram(win->fontProgram);
renderComponents(rootComponent);
}
// create this component and all it's children
void DocumentComponent::createComponentTree(const std::shared_ptr<Node> node, const std::shared_ptr<Component> &parentComponent) {
std::shared_ptr<Component> component = componentBuilder.build(node, parentComponent, windowWidth, windowHeight);
//std::cout << "DocumentComponent::createComponentTree" << std::endl;
if (!component) {
//std::cout << "DocumentComponent::createComponentTree - no component" << std::endl;
return;
}
if (node==domRootNode) {
// if this is the root node
component->reqWidth = windowWidth;
component->reqHeight = windowHeight;
}
// create children elements
for (std::shared_ptr<Node> child : node->children) {
createComponentTree(child, component);
}
}
// used for picking
std::shared_ptr<Component> DocumentComponent::searchComponentTree(const std::shared_ptr<Component> &component, const int passedX, const int passedY) {
if (component->children.empty()) {
//std::cout << "DocumentComponent::searchComponentTree - component at " << static_cast<int>(component->x) << "," << static_cast<int>(component->y) << " size " << static_cast<int>(component->width) << "," << static_cast<int>(component->height) << std::endl;
//std::cout << "DocumentComponent::searchComponentTree - y search: " << static_cast<int>(-component->y) << "<" << static_cast<int>(passedY) << "<" << static_cast<int>(-component->y + component->height) << std::endl;
if (-component->y < passedY && -component->y + component->height > passedY) {
//std::cout << "DocumentComponent::searchComponentTree - x search: " << static_cast<int>(component->x) << "<" << static_cast<int>(passedX) << "<" << static_cast<int>(component->x + component->width) << std::endl;
if (component->x < passedX && component->x + component->width > passedX) {
//std::cout << "hit " << typeOfComponent(component) << std::endl;
return component;
}
}
}
else {
for (std::shared_ptr<Component> child : component->children) {
std::shared_ptr<Component> found = searchComponentTree(child, passedX, passedY);
if (found) {
return found;
}
}
}
return nullptr;
}
// moving naviagtion closer to window, as window is now the owner of currentURL
// preparation for multiple HTML documents
void DocumentComponent::navTo(const std::string url) {
logDebug() << "DocumentComponent::navTo(" << url << ")" << std::endl;
logDebug() << "DocumentComponent::navTo - go to: " << currentURL << std::endl;