Browse Source

Merge branch 'master' of https://gitgud.io/odilitime/netrunner

# Conflicts:
#	src/graphics/components/ButtonComponent.cpp
master
despair 5 years ago
parent
commit
8516af49a2
  1. 2
      src/graphics/components/BoxComponent.h
  2. 7
      src/graphics/components/ButtonComponent.cpp
  3. 2
      src/graphics/components/Component.cpp
  4. 210
      src/graphics/components/DocumentComponent.cpp
  5. 3
      src/graphics/components/DocumentComponent.h
  6. 118
      src/graphics/components/InputComponent.cpp
  7. 23
      src/graphics/components/InputComponent.h
  8. 18
      src/graphics/components/TabbedComponent.cpp
  9. 2
      src/graphics/elements/INPUTElement.cpp
  10. 83
      src/graphics/opengl/Window.cpp
  11. 23
      src/html/HTMLParser.cpp
  12. 18
      src/scheduler.cpp
  13. 5
      src/scheduler.h

2
src/graphics/components/BoxComponent.h

@ -17,6 +17,7 @@ protected: @@ -17,6 +17,7 @@ protected:
GLuint vertexBufferObject = 0;
GLuint elementBufferObject = 0;
GLuint texture = 0;
// FIXME: deprecate these
int initialX;
int initialY;
int initialWidth;
@ -30,6 +31,7 @@ public: @@ -30,6 +31,7 @@ public:
void changeColor(const unsigned int hexColor);
virtual void render();
virtual void resize(const int passedWindowWidth, const int passedWindowHeight);
// FIXME: create: createVerices, updateVetices, createTexture, updateTexture
};
#endif

7
src/graphics/components/ButtonComponent.cpp

@ -128,7 +128,11 @@ void ButtonComponent::resize(const int passedWindowWidth, const int passedWindow @@ -128,7 +128,11 @@ void ButtonComponent::resize(const int passedWindowWidth, const int passedWindow
}
void ButtonComponent::resizeToTextSize() {
if (textLabel && !textLabel->win && this->win) {
if (!textLabel) {
std::cout << "ButtonComponent::resizeToTextSize - no textLabel to resize" << std::endl;
return;
}
if (!textLabel->win && this->win) {
textLabel->win = this->win;
}
textLabel->x = x;
@ -178,6 +182,7 @@ void ButtonComponent::resizeToTextSize() { @@ -178,6 +182,7 @@ void ButtonComponent::resizeToTextSize() {
}
}
// most of this functionality should be inside TextComponent
void ButtonComponent::updateText() {
//std::cout << "ButtonComponent::updateText - input value is now: " << value << std::endl;

2
src/graphics/components/Component.cpp

@ -428,7 +428,7 @@ void Component::printComponentTree(const std::shared_ptr<Component> &component, @@ -428,7 +428,7 @@ void Component::printComponentTree(const std::shared_ptr<Component> &component,
std::cout << std::fixed << "X: " << static_cast<int>(butComponent->x) << " Y: " << static_cast<int>(butComponent->y) << " WIDTH: " << static_cast<int>(butComponent->width) << " HEIGHT: " << static_cast<int>(butComponent->height) << " INLINE: " << butComponent->isInline << " Bound: " << butComponent->boundToPage << " BUTTON: " << butComponent->value << std::endl;
} else
if (inputComponent) {
std::cout << std::fixed << "X: " << static_cast<int>(inputComponent->x) << " Y: " << static_cast<int>(inputComponent->y) << " WIDTH: " << static_cast<int>(inputComponent->width) << " HEIGHT: " << static_cast<int>(inputComponent->height) << " INLINE: " << inputComponent->isInline << " Bound: " << inputComponent->boundToPage << " INPUT: " << inputComponent->value << std::endl;
std::cout << std::fixed << "X: " << static_cast<int>(inputComponent->x) << " Y: " << static_cast<int>(inputComponent->y) << " WIDTH: " << static_cast<int>(inputComponent->width) << " HEIGHT: " << static_cast<int>(inputComponent->height) << " INLINE: " << inputComponent->isInline << " Bound: " << inputComponent->boundToPage << " INPUT: " << inputComponent->getValue() << std::endl;
} else {
TextComponent *textComponent = dynamic_cast<TextComponent*>(component.get());
if (textComponent) {

210
src/graphics/components/DocumentComponent.cpp

@ -14,6 +14,42 @@ @@ -14,6 +14,42 @@
void deleteComponent(std::shared_ptr<Component> &component);
void deleteNode(std::shared_ptr<Node> node);
#include <utility>
// well we need to know how many chars in a lines
// we also need to know where a line starts (pos)
// lines start at 0 for first line
std::pair<size_t, size_t> getLine(std::string text, int findLine) {
//std::cout << "DocumentComponent.getLine [" << text << "] findLine: " << findLine << std::endl;
size_t pos = 0;
size_t lPos = 0;
pos = text.find("\r");
size_t line = 0;
while(pos != std::string::npos) {
lPos = pos;
pos = text.find("\r", lPos + 1);
if (line == static_cast<unsigned int>(findLine)) {
//std::cout << "lPos: " << lPos << " pos: " << pos << " line: " << line << std::endl;
//std::cout << "DocumentComponent.getLine start " << (lPos + line + 1) << " end " << (pos == std::string::npos ? text.length() : (lPos + pos)) << std::endl;
return std::make_pair(lPos + line + 1, pos == std::string::npos ? text.length() : (lPos + pos));
}
line++;
}
//std::cout << "end lPos: " << lPos << " pos: " << pos << " line: " << line << std::endl;
//std::cout << "DocumentComponent.getLine result end of text" << findLine << std::endl;
return std::make_pair(lPos + line, text.size());
}
size_t getNumberOfLines(std::string text) {
size_t pos = text.find("\r");
size_t lines = 0;
while(pos != std::string::npos) {
lines++;
pos = text.find("\r", pos + 1);
}
return lines;
}
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;
@ -62,68 +98,12 @@ DocumentComponent::DocumentComponent(const float rawX, const float rawY, const f @@ -62,68 +98,12 @@ DocumentComponent::DocumentComponent(const float rawX, const float rawY, const f
};
onWheel=[this](int passedX, int passedY) {
//std::cout << "DocumentComponent::DocumentComponent:::onWheel - scroll yDelta: " << passedY << std::endl;
//Component::printComponentTree(rootComponent, 0);
//double pY = passedY * 0.1;
/*
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;
// new system
//std::cout << "DocumentComponent::DocumentComponent:::onWheel - old position: " << this->transformMatrix[13] << " adjustment:" << (-pY*0.1) << std::endl;
//this->transformMatrix[13] += -pY * 0.01;
this->scrollY(passedY * 0.1);
/*
// 2.0 is one screen height
// we draw from 0 downwards (y+), so can't scroll past our starting draw point
if (this->transformMatrix[13] < 2) {
this->transformMatrix[13] = 2;
}
// calculate scroll max by calculating how many screens are in the rootComponent's Height
if (this->transformMatrix[13] > std::max( (this->rootComponent->height - this->rootComponent->y) / this->windowHeight * 2.0f, 2.0f)) {
this->transformMatrix[13] = std::max( (this->rootComponent->height - this->rootComponent->y) / this->windowHeight * 2.0f, 2.0f);
}
this->transformMatrixDirty = true;
*/
/*
// 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
const std::clock_t begin = clock();
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?
//this->renderDirty = true;
this->scrollY(passedY);
};
onMousedown=[this](int passedX, int passedY) {
//std::cout << "document left press" << std::endl;
if (this->hoverComponent) {
// if we're hovering over a component that's not focused
if (this->focusedComponent != this->hoverComponent) {
// blur old component
if (this->focusedComponent) {
@ -136,6 +116,7 @@ DocumentComponent::DocumentComponent(const float rawX, const float rawY, const f @@ -136,6 +116,7 @@ DocumentComponent::DocumentComponent(const float rawX, const float rawY, const f
this->hoverComponent->onFocus();
}
}
// set hover component as focused
this->focusedComponent = this->hoverComponent;
if (this->focusedComponent->onMousedown) {
//std::cout << "click event" << std::endl;
@ -181,14 +162,77 @@ DocumentComponent::DocumentComponent(const float rawX, const float rawY, const f @@ -181,14 +162,77 @@ DocumentComponent::DocumentComponent(const float rawX, const float rawY, const f
if (action == 0 || action == 2) {
// key up
// it's always uppercase...
if (key == 259) {
if (key == GLFW_KEY_BACKSPACE) {
focusedInputComponent->backSpace();
} else if (key == 257) {
} else if (key == GLFW_KEY_UP) {
/*
std::pair<int, int> lineData = getLine(focusedInputComponent->value, 0);
std::cout << "line 0 is " << focusedInputComponent->value.substr(lineData.first, lineData.second) << " start: " << lineData.first << " end: " << lineData.second << std::endl;
lineData = getLine(focusedInputComponent->value, 1);
std::cout << "line 1 is " << focusedInputComponent->value.substr(lineData.first, lineData.second) << " start: " << lineData.first << " end: " << lineData.second << std::endl;
*/
if (focusedInputComponent->multiLine) {
//std::pair<int, int> lineData = getLine(focusedInputComponent->value, 0);
focusedInputComponent->cursorCharY--;
if (focusedInputComponent->cursorCharY < 0) {
focusedInputComponent->cursorCharY = 0;
focusedInputComponent->cursorCharX = 0;
}
} else {
focusedInputComponent->cursorCharX = 0;
}
focusedInputComponent->updateCursor();
} else if (key == GLFW_KEY_DOWN) {
if (focusedInputComponent->multiLine) {
//std::pair<int, int> lineData = getLine(focusedInputComponent->value, 0);
focusedInputComponent->cursorCharY++;
size_t lines = getNumberOfLines(focusedInputComponent->getValue());
if (focusedInputComponent->cursorCharY > static_cast<int>(lines)) {
focusedInputComponent->cursorCharY = lines;
focusedInputComponent->cursorCharX = focusedInputComponent->getValue().length();
}
} else {
focusedInputComponent->cursorCharX = focusedInputComponent->getValue().size();
}
focusedInputComponent->updateCursor();
} else if (key == GLFW_KEY_LEFT) {
focusedInputComponent->cursorCharX--;
if (focusedInputComponent->cursorCharX < 0) {
if (focusedInputComponent->multiLine) {
focusedInputComponent->cursorCharY--;
if (focusedInputComponent->cursorCharY < 0) {
focusedInputComponent->cursorCharY = 0;
// if was already at first line, no need to adjust x
} else {
std::pair<int, int> lineData = getLine(focusedInputComponent->getValue(), focusedInputComponent->cursorCharY);
// adjust Y
focusedInputComponent->cursorCharX = lineData.second; // end of this line
}
}
focusedInputComponent->cursorCharX = 0;
}
focusedInputComponent->updateCursor();
} else if (key == GLFW_KEY_RIGHT) {
focusedInputComponent->cursorCharX++;
if (focusedInputComponent->cursorCharX > static_cast<int>(focusedInputComponent->getValue().size())) {
if (focusedInputComponent->multiLine) {
focusedInputComponent->cursorCharY++;
size_t lines = getNumberOfLines(focusedInputComponent->getValue());
if (focusedInputComponent->cursorCharY > static_cast<int>(lines)) {
focusedInputComponent->cursorCharY = lines;
} else {;
focusedInputComponent->cursorCharX = 0;
}
} else {
focusedInputComponent->cursorCharX = focusedInputComponent->getValue().size();
}
}
focusedInputComponent->updateCursor();
} else if (key == GLFW_KEY_ENTER) {
//std::cout << "DocumentComponent::onKeyUp - enter!" << std::endl;
if (focusedInputComponent->multiLine) {
// harfbuzz or freetype2 (something?) doesn't like \n
focusedInputComponent->value += "\r";
focusedInputComponent->updateText();
// harfbuzz or freetype2 (something?) doesn't like \n //focusedInputComponent->value += "\r";
focusedInputComponent->addChar('\r');
} else {
std::cout << "should submit form!" << std::endl;
}
@ -255,10 +299,12 @@ DocumentComponent::DocumentComponent(const float rawX, const float rawY, const f @@ -255,10 +299,12 @@ DocumentComponent::DocumentComponent(const float rawX, const float rawY, const f
}
void DocumentComponent::scrollY(int py) {
this->transformMatrix[13] -= py;
this->textureTransformMatrix[13] -= py;
// we're going to reduce here, so we can get the full signal all the way here
this->transformMatrix[13] -= py * 0.01;
this->textureTransformMatrix[13] -= py * 0.01;
//std::cout << "transformMatrix : " << this->transformMatrix[13] << std::endl;
//std::cout << "textureTransformMatrix: " << this->textureTransformMatrix[13] << std::endl;
// check bounds
if (this->transformMatrix[13] < 2) {
this->transformMatrix[13] = 2;
@ -317,7 +363,7 @@ void DocumentComponent::setDOM(const std::shared_ptr<Node> rootNode) { @@ -317,7 +363,7 @@ void DocumentComponent::setDOM(const std::shared_ptr<Node> rootNode) {
rootComponent->y = y;
domRootNode = rootNode;
printNode(domRootNode, 0);
//std::cout << "DocumentComponent::setDOM - printing nodes" << endl; printNode(domRootNode, 0);
domDirty = true;
}
@ -340,6 +386,9 @@ void DocumentComponent::render() { @@ -340,6 +386,9 @@ void DocumentComponent::render() {
transformMatrix[13]=std::max((rootComponent->height)/(windowHeight)*2.0f, 2.0f);
transformMatrixDirty = true;
}
// after we load in the document, allow scroll to work
this->updateMouse();
}
// we have to do this each time because window resets it
@ -461,7 +510,25 @@ void DocumentComponent::navTo(const std::string url) { @@ -461,7 +510,25 @@ void DocumentComponent::navTo(const std::string url) {
void DocumentComponent::handleResource(WebResource &res, std::string url) {
if (res.resourceType == ResourceType::INVALID) {
logError() << "DocumentComponent::handleResource - Invalid resource type: " << res.raw << std::endl;
return;
std::shared_ptr<Node> rootNode = std::make_shared<Node>(NodeType::ROOT);
std::shared_ptr<TagNode> tagNode = std::make_shared<TagNode>();
tagNode->tag="p";
// bind tag to root
tagNode->parent = rootNode;
rootNode->children.push_back(tagNode);
std::shared_ptr<TextNode> textNode = std::make_shared<TextNode>();
textNode->text = "Invalid Resource Type, HTTP Result Status: " + res.raw;
// bind text to tag
textNode->parent = tagNode;
tagNode->children.push_back(textNode);
// send NodeTree to window
//this->win->setDOM(rootNode);
this->setDOM(rootNode);
}
//std::cout << "body: " << res.raw << std::endl;
@ -473,7 +540,7 @@ void DocumentComponent::handleResource(WebResource &res, std::string url) { @@ -473,7 +540,7 @@ void DocumentComponent::handleResource(WebResource &res, std::string url) {
const std::clock_t begin = clock();
std::shared_ptr<Node> rootNode = parser.parse(res.raw);
const std::clock_t end = clock();
logDebug() << "INPUTElement.handleResource - Parsed document in: " << std::fixed << ((static_cast<double>(end - begin)) / CLOCKS_PER_SEC) << std::scientific << " seconds" << std::endl;
logDebug() << "DocumentComponent::handleResource - Parsed document in: " << std::fixed << ((static_cast<double>(end - begin)) / CLOCKS_PER_SEC) << std::scientific << " seconds" << std::endl;
// send NodeTree to window
//this->win->setDOM(rootNode);
@ -486,7 +553,7 @@ void DocumentComponent::handleResource(WebResource &res, std::string url) { @@ -486,7 +553,7 @@ void DocumentComponent::handleResource(WebResource &res, std::string url) {
}
this->setDOM(rootNode);
} else if (res.resourceType == ResourceType::TXT) {
std::cout << "INPUTElement.handleResource - Rendering text document" << std::endl;
std::cout << "DocumentComponent::handleResource - Rendering text document" << std::endl;
std::shared_ptr<Node> rootNode = std::make_shared<Node>(NodeType::ROOT);
std::shared_ptr<TagNode> tagNode = std::make_shared<TagNode>();
tagNode->tag="p";
@ -506,6 +573,9 @@ void DocumentComponent::handleResource(WebResource &res, std::string url) { @@ -506,6 +573,9 @@ void DocumentComponent::handleResource(WebResource &res, std::string url) {
//this->win->setDOM(rootNode);
this->setDOM(rootNode);
} else {
std::cout << "INPUTElement.handleResource - I don't know how to render non-html files" << std::endl;
std::cout << "DocumentComponent::handleResource - I don't know how to render non-html files" << std::endl;
}
if (this->win) {
this->win->renderDirty = true;
}
}

3
src/graphics/components/DocumentComponent.h

@ -10,6 +10,9 @@ @@ -10,6 +10,9 @@
#include "../../networking/HTTPResponse.h"
#include "../../WebResource.h"
std::pair<size_t, size_t> getLine(std::string text, int findLine);
size_t getNumberOfLines(std::string text);
// document is scrollable until multicomponent
class DocumentComponent : public MultiComponent {
public:

118
src/graphics/components/InputComponent.cpp

@ -1,10 +1,40 @@ @@ -1,10 +1,40 @@
#include "InputComponent.h"
#include "DocumentComponent.h"
#include <iostream>
#include "../text/TextRasterizerCache.h"
#include "../../scheduler.h"
#include "../opengl/Shader.h"
void TextBlock::addChar(char chr) {
if (chr==10 || chr==13) {
this->lineChars.push_back(this->currentLineChars);
this->currentLineChars = 0;
lines++;
}
this->text += std::string(&chr);
this->currentLineChars++;
}
void TextBlock::delLastChar() {
// get last char
char lastChar = this->text.at(this->text.size() - 1);
this->text = this->text.substr(0, this->text.size() - 2);
this->currentLineChars--;
if (lastChar == 10 || lastChar == 13) {
this->lineChars.pop_back();
this->currentLineChars = 0;
}
}
void TextBlock::insertCharAt(char chr, size_t pos) {
}
void TextBlock::delCharAt(size_t pos) {
}
extern TextRasterizerCache *rasterizerCache;
extern std::unique_ptr<Scheduler> scheduler;
@ -44,6 +74,7 @@ InputComponent::InputComponent(const float rawX, const float rawY, const float r @@ -44,6 +74,7 @@ InputComponent::InputComponent(const float rawX, const float rawY, const float r
onFocus=[this]() {
this->focused = true;
//std::cout << "focus input" << std::endl;
// blink cursor
this->cursorTimer = scheduler->setInterval([this]() {
this->showCursor = !this->showCursor;
@ -56,6 +87,7 @@ InputComponent::InputComponent(const float rawX, const float rawY, const float r @@ -56,6 +87,7 @@ InputComponent::InputComponent(const float rawX, const float rawY, const float r
this->win->renderDirty = true;
};
onBlur=[this]() {
//std::cout << "blur input" << std::endl;
if (this->cursorTimer != nullptr) {
scheduler->clearInterval(this->cursorTimer);
}
@ -277,29 +309,105 @@ void InputComponent::resize(const int passedWindowWidth, const int passedWindowH @@ -277,29 +309,105 @@ void InputComponent::resize(const int passedWindowWidth, const int passedWindowH
}
}
std::string InputComponent::getValue() {
return this->value;
}
void InputComponent::setValue(std::string newValue) {
this->value = newValue;
if (!this->multiLine) {
this->cursorCharX = static_cast<int>(this->value.size() & INT_MAX);
}
// if we pasted in a middle of block
}
void InputComponent::addChar(char c) {
value+=c;
value += c;
//std::cout << "InputComponent::addChar - was cursor at " << this->cursorCharX << "," << this->cursorCharY << std::endl;
if (c == '\r') {
if (this->multiLine) {
this->cursorCharY++;
this->cursorCharX = 0;
}
} else {
this->cursorCharX++;
}
//std::cout << "InputComponent::addChar - at " << (int)x << "," << (int)y << std::endl;
updateText();
}
void InputComponent::backSpace() {
value=value.substr(0, value.length() - 1);
char last = '\0';
if (value.length()) {
last = value.at(value.length() - 1);
}
value = value.substr(0, value.length() - 1);
//std::cout << "InputComponent::backSpace - was cursor at " << this->cursorCharX << "," << this->cursorCharY << std::endl;
if (last == '\r') {
if (this->multiLine) {
this->cursorCharY--;
if (this->cursorCharY < 0) this->cursorCharY = 0;
std::pair<int, int> lineData = getLine(this->value, this->cursorCharY);
this->cursorCharX = lineData.second - lineData.first;
}
} else {
this->cursorCharX--;
if (this->cursorCharX < 0) this->cursorCharX = 0;
}
//std::cout << "InputComponent::backSpace - at " << (int)x << "," << (int)y << std::endl;
updateText();
}
void InputComponent::updateCursor() {
std::cout << "InputComponent::updateCursor - cursor at " << this->cursorCharX << "," << this->cursorCharY << std::endl;
//std::cout << "InputComponent::updateCursor - text[" << this->value << "]" << std::endl;
std::pair<int, int> lineData = getLine(this->value, this->cursorCharY);
std::cout << "InputComponent::updateCursor - line " << this->cursorCharY << " starts at " << lineData.first << std::endl;
size_t pos = static_cast<size_t>(lineData.first + this->cursorCharX);
//std::cout << "InputComponent::updateCursor - cx " << this->cursorCharX << " starts at value pos " << pos << std::endl;
if (pos < this->value.size()) {
//std::cout << "InputComponent::updateCursor - Cursor at " << this->cursorCharX << "," << this->cursorCharY << " " << this->value.at(pos) << std::endl;
}
const std::shared_ptr<TextRasterizer> textRasterizer = rasterizerCache->loadFont(12, false); // fontSize, bold
rasterizationRequest request;
request.text = value.substr(0, pos);
std::cout << "InputComponent::updateCursor - sizeText[" << request.text << "]" << std::endl;
request.startX = x;
request.availableWidth = windowWidth;
request.sourceStartX = 0;
request.sourceStartY = 0;
if (this->multiLine) {
request.noWrap = false;
} else {
request.noWrap = true;
}
std::unique_ptr<sizeResponse> textInfo = textRasterizer->size(request);
std::cout << "InputComponent::updateCursor - response at [" << textInfo->endingX << "," << textInfo->endingY << "]" << std::endl;
this->cursorStartAtX = textInfo->endingX;
this->cursorStartAtY = textInfo->endingY;
if (textInfo->height > this->height) {
this->cursorStartAtY += textInfo->height - this->height;
}
// this is texture shader coordinates now (not text shader coords)
//
cursorBox->x = x + this->cursorStartAtX;
if (boundToPage) {
cursorBox->y = windowHeight + y + this->cursorStartAtY;
cursorBox->y = this->windowHeight + y + this->cursorStartAtY;
} else {
// + this->cursorStartAtY
cursorBox->y = y + 5;
cursorBox->y = this->y + 5;
}
//std::cout << "placing cursor at " << (int)cursorBox->x << "," << (int)cursorBox->y << std::endl;
cursorBox->resize(windowWidth, windowHeight);
cursorBox->resize(this->windowWidth, this->windowHeight);
// if we move the cursor, redraw immediately
this->showCursor = true;
if (this->win) {
this->win->renderDirty = true;
}
}
void InputComponent::updateText() {

23
src/graphics/components/InputComponent.h

@ -9,6 +9,22 @@ @@ -9,6 +9,22 @@
class Window;
class TextBlock {
public:
// methods
void addChar(char chr);
void delLastChar();
void insertCharAt(char chr, size_t pos);
void delCharAt(size_t pos);
std::pair<size_t, size_t> getXYPos(size_t pos);
size_t getPosXY(size_t x, size_t y);
// properties
size_t lines;
std::vector<size_t> lineChars;
size_t currentLineChars = 0;
std::string text;
};
class InputComponent : public BoxComponent {
public:
//: BoxComponent(rawX, rawY, rawWidth, rawHeight, passedWindowWidth, passedWindowHeight) { }
@ -17,11 +33,12 @@ public: @@ -17,11 +33,12 @@ public:
//using BoxComponent::BoxComponent;
void resize(const int passedWindowWidth, const int passedWindowHeight);
void render();
std::string getValue();
void setValue(std::string newValue);
void addChar(char c);
void backSpace();
void updateCursor();
void updateText();
std::string value="";
TextComponent *userInputText = nullptr;
BoxComponent *cursorBox = nullptr;
std::function<void(std::string value)> onEnter = nullptr;
@ -33,8 +50,12 @@ public: @@ -33,8 +50,12 @@ public:
// store for cursor
int cursorStartAtX;
int cursorStartAtY;
int cursorCharX = 0;
int cursorCharY = 0;
TagNode *node = nullptr;
bool multiLine = false; // textarea control
protected:
std::string value="";
};
#endif

18
src/graphics/components/TabbedComponent.cpp

@ -195,7 +195,7 @@ void TabbedComponent::addTab(std::string passedTitle) { @@ -195,7 +195,7 @@ void TabbedComponent::addTab(std::string passedTitle) {
// set address bar
InputComponent *ab = dynamic_cast<InputComponent*>(this->win->addressComponent.get());
if (ab) {
ab->value = url;
ab->setValue(url);
ab->updateText();
} else {
std::cout << "No address component" << std::endl;
@ -248,7 +248,7 @@ void TabbedComponent::updateWindowState(std::string newTitle) { @@ -248,7 +248,7 @@ void TabbedComponent::updateWindowState(std::string newTitle) {
//std::cout << "TabbedComponent::updateWindowState - newTitle: " << newTitle << std::endl;
InputComponent *inputComponent = dynamic_cast<InputComponent*>(this->win->addressComponent.get());
if (inputComponent) {
inputComponent->value = newTitle;
inputComponent->setValue(newTitle);
inputComponent->updateText();
} else {
std::cout << "TabbedComponent::updateWindowState - Window addressComponent isn't an inputComponent" << std::endl;
@ -326,15 +326,21 @@ void TabbedComponent::selectTab(std::shared_ptr<Tab> tab) { @@ -326,15 +326,21 @@ void TabbedComponent::selectTab(std::shared_ptr<Tab> tab) {
// select new document
this->rootComponent->children.push_back(tab->contents);
tab->contents->setParent(this->rootComponent);
// resize this content incase the window was resized since last selection
if (tab->contents->windowWidth != this->windowWidth || tab->contents->windowHeight != this->windowHeight) {
std::cout << "detected resize, resizing tab's doc component" << std::endl;
tab->contents->resize(this->windowWidth, this->windowHeight);
}
this->documentComponent = tab->contents;
InputComponent *ab = dynamic_cast<InputComponent*>(this->win->addressComponent.get());
if (ab) {
ab->value = tab->titleBox->text;
ab->setValue(tab->titleBox->text);
//std::cout << "tab->titleBox->text: " << tab->titleBox->text << std::endl;
if (ab->value == "New Tab") {
ab->value = "http://"; // should be "" but we don't have an awesome-bar yet
if (ab->getValue() == "New Tab") {
ab->setValue("http://"); // should be "" but we don't have an awesome-bar yet
}
ab->updateText();
} else {
@ -402,7 +408,7 @@ void TabbedComponent::selectTab(std::shared_ptr<Tab> tab) { @@ -402,7 +408,7 @@ void TabbedComponent::selectTab(std::shared_ptr<Tab> tab) {
// doesn't move, will this double free?
this->mpSelectedTab = tab; // pointer
this->updateWindowState(ab->value);
this->updateWindowState(ab->getValue());
}
// we expect the tab to be set up (all components allocated)

2
src/graphics/elements/INPUTElement.cpp

@ -30,7 +30,7 @@ std::unique_ptr<Component> INPUTElement::renderer(const ElementRenderRequest &re @@ -30,7 +30,7 @@ std::unique_ptr<Component> INPUTElement::renderer(const ElementRenderRequest &re
inputComponent->name = "textInput";
auto propIter2 = tagNode->properties.find("value");
if (propIter2 != tagNode->properties.end()) {
inputComponent->value = propIter2->second;
inputComponent->setValue(propIter2->second);
}
return std::move(inputComponent);
} else if (type == "submit") {

83
src/graphics/opengl/Window.cpp

@ -366,6 +366,7 @@ bool Window::initGLFW() { @@ -366,6 +366,7 @@ bool Window::initGLFW() {
});
glfwSetScrollCallback(window, [](GLFWwindow *win, double xOffset, double yOffset) {
Window *thiz = reinterpret_cast<Window*>(glfwGetWindowUserPointer(win));
//std::cout << "glfwSetScrollCallback " << yOffset << " int" << (int)(yOffset * 10) << std::endl;
// yOffset is a delta vector
thiz->transformMatrix[13] += -yOffset * 0.1;
if (thiz->hoverComponent) {
@ -448,13 +449,13 @@ bool Window::initGLFW() { @@ -448,13 +449,13 @@ bool Window::initGLFW() {
}
});
// works with utf-32 but we'll lkeep the low level for now
/*
// works with utf-32 and os keyboard layout 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;
//std::cout << "Window::glfwSetCharCallback - codepoint: " << codepoint << std::endl;
// should be used for inputComponent
});
*/
glfwSetKeyCallback(window, [](GLFWwindow *win, int key, int scancode, int action, int mods) {
Window *thiz = reinterpret_cast<Window*>(glfwGetWindowUserPointer(win));
@ -503,42 +504,62 @@ bool Window::initGLFW() { @@ -503,42 +504,62 @@ bool Window::initGLFW() {
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) {
if (action == GLFW_RELEASE || action == GLFW_REPEAT) {
if (key == GLFW_KEY_V && action == GLFW_RELEASE && mods == attentionMod) {
const char* clipBoard = glfwGetClipboardString(thiz->window);
for(unsigned int i=0; i < strlen(clipBoard); i++) {
inputComponent->addChar(clipBoard[i]);
}
//inputComponent->setValue(std::string(clipBoard));
return;
}
// key up
// it's always uppercase...
if (key == 259) {
inputComponent->backSpace();
} else if (key == 257) {
return;
}
if (key == 257) {
std::cout << "enter!" << std::endl;
if (inputComponent->onEnter) {
inputComponent->onEnter(inputComponent->value);
inputComponent->onEnter(inputComponent->getValue());
}
} 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';
}
return;
}
if (key < 256) {
if (mods & GLFW_MOD_SHIFT) {
// SHIFT
if (key >= '1' && key <= '9') {
key -= 16;
}
switch(key) {
case GLFW_KEY_SLASH: key='?'; break;
case GLFW_KEY_APOSTROPHE: key='"'; break;
case GLFW_KEY_COMMA: key='<'; break;
case GLFW_KEY_MINUS: key='_'; break;
case GLFW_KEY_PERIOD: key='>'; break;
case GLFW_KEY_SEMICOLON: key=':'; break;
case GLFW_KEY_EQUAL: key='+'; break;
case GLFW_KEY_LEFT_BRACKET: key='{'; break;
case GLFW_KEY_BACKSLASH: key='|'; break;
case GLFW_KEY_RIGHT_BRACKET: key='}'; break;
case GLFW_KEY_GRAVE_ACCENT: key='~'; break;
case GLFW_KEY_0: key=')'; break;
default:
// a key we don't care about atm
break;
}
inputComponent->addChar(key);
} // otherwise I think it's some weird control char
} 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);
return;
}
// otherwise I think it's some weird control char
}
return;
}

23
src/html/HTMLParser.cpp

@ -249,23 +249,27 @@ void HTMLParser::parseTag(const std::string &element, TagNode &tagNode) const { @@ -249,23 +249,27 @@ void HTMLParser::parseTag(const std::string &element, TagNode &tagNode) const {
std::string propertyKey;
for (cursor = 0; cursor < element.length(); cursor++) {
if (state == 0) {
// space or end
if (element[cursor] == ' ' || element[cursor] == '>') {
// set our tag (type / name, i.e. h1)
tagNode.tag = element.substr(start, cursor - start);
// make sure our tag is lowercase
std::transform(tagNode.tag.begin(), tagNode.tag.end(), tagNode.tag.begin(), tolower);
start = cursor + 1;
state = 1;
}
}
else if (state == 1) {
else if (state == 1) { // attribute search
if (element[cursor] == ' ') {
start = cursor + 1;
}
else if (element[cursor] == '=') {
propertyKey = element.substr(start, cursor - start);
start = cursor + 1; // start for non quotes
state = 2;
}
}
else if (state == 2) {
else if (state == 2) { // after = of attribute
if (element[cursor] == '"') {
start = cursor + 1;
state = 3;
@ -273,6 +277,11 @@ void HTMLParser::parseTag(const std::string &element, TagNode &tagNode) const { @@ -273,6 +277,11 @@ void HTMLParser::parseTag(const std::string &element, TagNode &tagNode) const {
else if (element[cursor] == '\'') {
start = cursor + 1;
state = 4;
} else if (element[cursor] == ' ') {
// we just probably found an end of attribute without quotes
tagNode.properties.insert(std::pair<std::string, std::string>(propertyKey, element.substr(start, cursor - start)));
start = cursor + 1;
state = 1;
}
}
else if (state == 3) {
@ -292,5 +301,15 @@ void HTMLParser::parseTag(const std::string &element, TagNode &tagNode) const { @@ -292,5 +301,15 @@ void HTMLParser::parseTag(const std::string &element, TagNode &tagNode) const {
}
}
}
// 2 is attribute without quotes, 3/4 is unclosed quote
if (state == 2 || state == 3 || state ==4) {
// we were in an atrr=
tagNode.properties.insert(std::pair<std::string, std::string>(propertyKey, element.substr(start, cursor - start - 1)));
} else {
if (state != 1) {
// so what's ending on state 0 about (somethin about no atttributes and maybe no tag name/type)
std::cout << "HTMLParser::parseTag ending on state " << state << std::endl;
}
}
}

18
src/scheduler.cpp

@ -8,7 +8,8 @@ std::shared_ptr<timer_handle> Scheduler::setTimeout(std::function<void()> callba @@ -8,7 +8,8 @@ std::shared_ptr<timer_handle> Scheduler::setTimeout(std::function<void()> callba
std::shared_ptr<timer_handle> handle = std::make_shared<timer_handle>();
handle->callback = callback;
handle->nextAt = now + delay;
handle->timeout = true;
handle->interval = 0;
//handle->timeout = true;
this->timers.push_back(handle);
return handle;
}
@ -19,7 +20,8 @@ std::shared_ptr<timer_handle> Scheduler::setInterval(std::function<void()> callb @@ -19,7 +20,8 @@ std::shared_ptr<timer_handle> Scheduler::setInterval(std::function<void()> callb
std::shared_ptr<timer_handle> handle = std::make_shared<timer_handle>();
handle->callback = callback;
handle->nextAt = now + delay;
handle->timeout = false;
handle->interval = delay;
//handle->timeout = false;
this->timers.push_back(handle);
//std::cout << "scheduled at " << (int)handle->nextAt << std::endl;
return handle;
@ -31,8 +33,8 @@ unsigned long Scheduler::getNext() { @@ -31,8 +33,8 @@ unsigned long Scheduler::getNext() {
//std::cout << "there are " << this->timers.size() << std::endl;
for(std::vector<std::shared_ptr<timer_handle>>::iterator it=this->timers.begin(); it!=this->timers.end(); ++it) {
//std::cout << "nextAt " << (int)it->get()->nextAt << " long " << (int)(now - it->get()->nextAt) << std::endl;
//std::cout << "now " << (int)now << " nextAt: " << (int)it->get()->nextAt << std::endl;
int diff = now - it->get()->nextAt;
//std::cout << "now " << (int)now << " - nextAt: " << (int)it->get()->nextAt << std::endl;
int diff = it->get()->nextAt - now;
if (diff < 0) diff = 0;
//std::cout << "timer fires in " << diff << std::endl;
lowest = std::min(lowest, static_cast<unsigned long>(diff));
@ -43,19 +45,23 @@ unsigned long Scheduler::getNext() { @@ -43,19 +45,23 @@ unsigned long Scheduler::getNext() {
bool Scheduler::fireTimer(std::shared_ptr<timer_handle> timer, double now) {
timer->callback();
if (timer->timeout) {
if (!timer->interval) {
return true;
}
// schedule the next one
timer->nextAt = now + timer->nextAt;
//std::cout << "Scheduling next timer in " << timer->interval << "+" << now << "=" << (now + timer->interval) << std::endl;
timer->nextAt = now + timer->interval;
return false;
}
void Scheduler::fireTimers() {
double now = glfwGetTime() * 1000;
for(std::vector<std::shared_ptr<timer_handle>>::iterator it=this->timers.begin(); it!=this->timers.end(); ++it) {
// if it's the timer time to fire
if (it->get()->nextAt < now) {
// fire it, do we need to clean it up
if (this->fireTimer(*it, now)) {
// clena up
it = this->timers.erase(it);
if (it == this->timers.end()) break;
}

5
src/scheduler.h

@ -8,8 +8,9 @@ @@ -8,8 +8,9 @@
class timer_handle {
public:
double nextAt; // in milliseconds
bool timeout;
unsigned long interval; // in milliseconds
double nextAt; // timestamp in milliseconds
//bool timeout; // replaced by interval
std::function<void()> callback;
};

Loading…
Cancel
Save