You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

653 lines
30 KiB

#include "Component.h"
#include <iostream>
#include <algorithm>
#include <cmath>
#include "TextComponent.h"
#include "InputComponent.h"
#include "ButtonComponent.h"
#include "ComponentBuilder.h"
// pos, size
std::unique_ptr<std::pair<UImetricV2, UImetricV2>> getUIMetric(UImetricV2 &s1, UImetricV2 &s2, UImetricV2 &size) {
// only 2 of these can be requested
if ((s1.requested && s2.requested && size.requested) || (!s1.requested && !s2.requested && !size.requested)) {
// FIXME: better message
std::cout << "component.getUIMetric - can't resolve" << std::endl;
return nullptr;
}
std::unique_ptr<std::pair<UImetricV2, UImetricV2>> result=std::make_unique<std::pair<UImetricV2, UImetricV2>>();
if (s1.requested && s2.requested) {
// left/right top/bottom
//std::cout << "left/right px " << s1.px << " & " << s2.px << std::endl;
//std::cout << "left/right % " << s1.pct << " & " << s2.pct << std::endl;
result->first = { true, s1.pct, s1.px }; // pos
result->second = { true, (100.0 - s2.pct) - s1.pct, -s2.px - s1.px }; // size
/*
if (s1.pct && s2.pct) {
// right 25% = left 75%
result->second = { true, (100 - s2.pct) - s1.pct, 0 }; // size
} else
if (!s1.pct && !s2.pct) {
result->second = { true, 100.0 - s2.pct, -s2.px };
} else if (s1.pct) {
result->second = { true, 100.0 - s2.pct, -s2.px };
} else if (s2.pct) {
// right 25% = left 75%
result->second = { true, 100.0 - s2.pct, -s2.px };
} else {
// unknown
}
*/
} else
if (s1.requested && size.requested) {
// left + width top+height
result->first = { true, s1.pct, s1.px }; // pos
result->second = { true, size.pct, size.px };
} else
if (s2.requested && size.requested) {
// right - width bottom-height
// right 25% = left 75%
// + width 50% means start at 25%
result->first = { true, (100.0 - s2.pct) - size.pct, -s2.px - size.px }; // pos
result->second = { true, size.pct, size.px };
} else {
std::cout << "component.getUIMetric - Unknown state" << std::endl;
}
return result;
}
Component::~Component() {
}
// translate properties (left/right/width && top/bottom/height) into resizeable layout
// we may not need pwin (we have this->win)
void Component::setUpUI(std::map<std::string, std::string> &properties, Window *pwin) {
UILayoutV2 boxSetup;
boxSetup.width.px = 32;
boxSetup.height.px = 32;
//std::cout << "Component::setUpUI - type: " << typeOfComponent(this) << std::endl;
if (properties.find("width") != properties.end()) {
//std::cout << "Component::setUpUI - has width" << std::endl;
boxSetup.width.requested = true;
if (properties["width"][properties["width"].size() - 1] == '%') {
//std::cout << "Component::setUpUI - found width %" << std::endl;
boxSetup.width.pct = std::stoi(properties["width"]);
} else {
boxSetup.width.px = std::stoi(properties["width"]);
}
}
if (properties.find("height") != properties.end()) {
boxSetup.height.requested = true;
if (properties["height"][properties["height"].size() - 1] == '%') {
//std::cout << "Component::setUpUI - found height %" << std::endl;
boxSetup.height.pct = std::stoi(properties["height"]);
} else {
boxSetup.height.px = std::stoi(properties["height"]);
}
}
if (properties.find("top") != properties.end()) {
boxSetup.top.requested = true;
if (properties["top"][properties["top"].size() - 1] == '%') {
//std::cout << "Component::setUpUI - found top %" << std::endl;
boxSetup.top.pct = std::stoi(properties["top"]);
} else {
boxSetup.top.px = std::stoi(properties["top"]);
}
}
if (properties.find("bottom") != properties.end()) {
boxSetup.bottom.requested = true;
if (properties["bottom"][properties["bottom"].size() - 1] == '%') {
//std::cout << "Component::setUpUI - found bottom %" << std::endl;
boxSetup.bottom.pct = std::stoi(properties["bottom"]);
} else {
boxSetup.bottom.px = std::stoi(properties["bottom"]);
}
}
if (properties.find("left") != properties.end()) {
//std::cout << "Component::setUpUI - has left" << std::endl;
boxSetup.left.requested = true;
if (properties["left"][properties["left"].size() - 1] == '%') {
//std::cout << "Component::setUpUI - found left %" << std::endl;
boxSetup.left.pct = std::stoi(properties["left"]);
} else {
boxSetup.left.px = std::stoi(properties["left"]);
}
}
if (properties.find("right") != properties.end()) {
//std::cout << "Component::setUpUI - has right" << std::endl;
boxSetup.right.requested = true;
if (properties["right"][properties["right"].size() - 1] == '%') {
//std::cout << "Component::setUpUI - found right %" << std::endl;
boxSetup.right.pct = std::stoi(properties["right"]);
} else {
boxSetup.right.px = std::stoi(properties["right"]);
}
}
/*
std::cout << "boxSetup left : " << boxSetup.left.requested << " " << boxSetup.left.pct << "% @" << boxSetup.left.px << std::endl;
std::cout << "boxSetup right: " << boxSetup.right.requested << " " << boxSetup.right.pct << "% @" << boxSetup.right.px << std::endl;
std::cout << "boxSetup width: " << boxSetup.width.requested << " " << boxSetup.width.pct << "% @" << boxSetup.width.px << std::endl;
std::cout << "boxSetup top : " << boxSetup.top.requested << " " << boxSetup.top.pct << "% @" << boxSetup.top.px << std::endl;
std::cout << "boxSetup bottom: " << boxSetup.bottom.requested << " " << boxSetup.bottom.pct << "% @" << boxSetup.bottom.px << std::endl;
std::cout << "boxSetup height: " << boxSetup.height.requested << " " << boxSetup.height.pct << "% @" << boxSetup.height.px << std::endl;
*/
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;
int cW = boxSetup.width.px, cH = boxSetup.height.px;
int xPx = 0, yPx = 0;
double xPct = 0, yPct = 0;
double wPct = 100, hPct = 100;
int wPx = 0, hPx = 0;
//int winWidth = pwin->windowWidth;
int winHeight = pwin->windowHeight;
//std::cout << "Component::setUpUI - laying out a " << typeOfComponent(this) << std::endl;
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;
// QUESTION: I don't think cx should take pct into account
// I think it does because 25% into starting px is important
// no because we could just set uiControl.x correctly...
// and if we did that we could pull out win
// well we still need winHeight tho, because of the coords
//cX = (xUI->first.pct * 0.01 * winWidth) + xUI->first.px;
xPct = xUI->first.pct;
xPx = xUI->first.px;
//cW = (xUI->second.pct * 0.01 * winWidth) + xUI->second.px;
wPct = xUI->second.pct;
wPx = xUI->second.px;
//std::cout << "Component::setUpUI X at " << cX << " for " << cW << std::endl;
//std::cout << "Component::setUpUI W at " << wPct << "% for " << wPx << std::endl;
}
if (yUI) {
//std::cout << "Component::setUpUI pct" << yUI->first.pct << "/100 - " << yUI->first.px << std::endl;
//cY = (yUI->first.pct * 0.01 * winHeight) - yUI->first.px;
// bottom=0 is 0, 0, so we do 100- here
yPct = 100 - yUI->first.pct;
yPx = yUI->first.px;
cH = (yUI->second.pct * 0.01 * winHeight) + yUI->second.px;
hPct = yUI->second.pct;
hPx = yUI->second.px;
//std::cout << "Component::setUpUI Y at " << cY << " for " << cH << std::endl;
//std::cout << "Component::setUpUI Y would be " << (-cH - cY) << " and new is " << yPx << std::endl;
//std::cout << "Component::setUpUI H at " << hPct << "% for " << hPx << std::endl;
}
// set up proper component information for resizing
this->uiControl.x = { xPct, xPx }; //
this->uiControl.y = { yPct, -cH - yPx }; //
this->uiControl.w = { wPct, wPx }; //
this->uiControl.h = { hPct, hPx }; //
// recalculate new vertices
this->layout(); // move from uiContorl to x,y
// we don't need to set to call resize because layout already calls it (always calls wrap->resize)
//this->resize(winWidth, winHeight); // apply x,y state to vertices
}
// resize is where width/height can change within the confines of the window
void Component::resize(const int passedWindowWidth, const int passedWindowHeight) {
//std::cout << "Component::resize - doing nothing" << std::endl;
windowWidth = passedWindowWidth;
windowHeight = passedWindowHeight;
/*
if (boundToPage) {
} else {
*/
// no vertices in component
/*
float vx = x;
float vy = y;
float vWidth = width;
float vHeight = height;
pointToViewport(vx, vy);
distanceToViewport(vWidth, vHeight);
vertices[(0 * 5) + 0] = vx;
vertices[(0 * 5) + 1] = vy + vHeight;
vertices[(1 * 5) + 0] = vx + vWidth;
vertices[(1 * 5) + 1] = vy + vHeight;
vertices[(2 * 5) + 0] = vx + vWidth;
vertices[(2 * 5) + 1] = vy;
vertices[(3 * 5) + 0] = vx;
vertices[(3 * 5) + 1] = vy;
verticesDirty = true;
*/
//}
// do we recurse down through children?
// well if a parent resizes, yea we should tell our children the window size has changed
// btw a layout already does this
// yea let's let layout handle this
/*
for (std::shared_ptr<Component> child : children) {
// update it's size
// maybe we should called wrap
child->resize(windowWidth, windowHeight);
}
*/
}
void Component::setParent(std::shared_ptr<Component> passedParent) {
if (!passedParent) {
std::cout << "Component::setParent is empty" << std::endl;
}
if (parent) {
std::cout << "Component::setParent - triggering component move" << std::endl;
}
// set parent of the newly created component
parent = passedParent;
// update our position
// probably could move this out of here
if (boundToPage) {
x = passedParent->x;
y = passedParent->y - passedParent->height;
}
//std::cout << "Component::setParent - placing at " << static_cast<int>(x) << "," << static_cast<int>(y) << std::endl;
if (passedParent) {
if (passedParent->children.size()) {
this->previous = passedParent->children.back();
}
// need to figure out how to make this work
//passedParent->children.push_back(std::make_shared<Component>(this));
}
// add new component as child to parent
//std::shared_ptr<Component> child=*new std::shared_ptr<Component>(this);
//parent->children.push_back(child);
}
// window size is required because we need to know if our x is placed outside bounds
// our size is not required
// but all previous children sizes and positions are
// this function should be smart enough to read state, figure out what changes are actually needed and execute them
void Component::layout() {
// back up current position
//int lx = x;
//int ly = y;
// if we want to position the root component and layout (because to move things we need to trigger a resize)
// then we need this to not reset because it will affect the position we're trying to relayout them out at
// reset position
//x = 0;
//y = 0;
/*
TextComponent *textComponent = dynamic_cast<TextComponent*>(this);
if (textComponent) {
std::cout << "Component::layout[" << textComponent->text << "]" << std::endl;
}
*/
//std::cout << "Component::layout - name: " << name << " type " << typeOfComponent(this) << " boundToPage: " << boundToPage << std::endl;
// if we're a child, get our parents position
if (parent && boundToPage) {
//std::cout << "Component::layout - copying position from parent: " << (int)parent->x << "x" << (int)parent->y << std::endl;
x = parent->x;
y = parent->y;
// if we have sibilings see if they're inline or block
if (parent->children.size()) {
//std::cout << "Component::layout - parent children: " << parent->children.size() << std::endl;
if (previous) {
//std::cout << "Component::layout - has previous " << std::endl;
/*
TextComponent *prevTextComponent = dynamic_cast<TextComponent*>(previous.get());
if (prevTextComponent) {
std::cout << "Component::layout - previous [" << prevTextComponent->text << "] ending at: " << (int)prevTextComponent->endingX << "x" << (int)prevTextComponent->endingY << "" << std::endl;
}
*/
//std::cout << "Component::layout - previous at: " << (int)previous->x << "x" << (int)previous->y << " size: " << (int)previous->width << "x" << (int)previous->height << " ending at: " << (int)previous->endingX << "x" << (int)previous->endingY << std::endl;
// 2nd or last
if (previous->isInline) {
// last was inline
if (isInline) {
x = previous->x + previous->width;
y = previous->y; // keep on same line
//std::cout << "Component::layout - inLine (" << (int)previous->width << " wide) inLine" << std::endl;
if (x >= windowWidth) {
//std::cout << "Component::layout - inline inline wrapping because x: " << (int)x << " window: " << windowWidth << std::endl;
x = previous->endingX;
//std::cout << "Component::layout - p.y: " << (int)previous->y << " p.ey: " << previous->endingY << " p.h" << (int)previous->height << std::endl;
y = previous->y - previous->height + previous->endingY;
}
} else {
// we're block
y = previous->y - previous->height; // advance down one height
if (!previous->height) {
// ok if last is a nothing burger (0x0 size)
// then we need the parent height
// or we could spool to get the height for the last inline that's been set
// this isn't right
//y -= this->parent->height;
// this is bad because we assume there's only going to be one
std::shared_ptr<Component> pos = this->previous;
bool found = false;
while(pos->previous) {
pos = pos->previous;
if (!pos->isInline) {
std::cout << "Component::layout - found block element at " << pos->y << std::endl;
break;
}
if (pos->height) {
//std::cout << "no size, grabbing height " << static_cast<int>(pos->height) << std::endl;
y -= pos->height;
found = true;
break;
}
}
if (!found) {
std::cout << "Component::layout - couldnt adjust height properly" << std::endl;
}
}
//std::cout << "Component::layout - inLine block" << std::endl;
}
} else {
// last was block
y = previous->y - previous->height;
//std::cout << "Component::layout - block * p.x: " << (int)previous->x << " p.h: " << (int)previous->height << std::endl;
}
// really only inline but can't hurt block AFAICT
if (x >= windowWidth) {
//std::cout << "Component::layout - wrapping because x: " << (int)x << " window: " << windowWidth << std::endl;
x = 0;
y -= previous->height; // how far down do we need to wrap?, the previous height?
}
} else {
// first, there will be no width to add
}
} else {
// first component for this parent
}
}
if (!boundToPage) {
// select new x,y & w/h bassed on UImetric
//std::cout << "!boundToPage " << name << " from: " << (int)x << "," << (int)y << " " << (int)width << "," << (int)height << std::endl;
//std::cout << "uic.x.lenghtPct: " << uiControl.x.lengthPct << " width: " << windowWidth << " uic.x.offset: " << uiControl.x.offset << std::endl;
this->x = (uiControl.x.lengthPct / 100.0) * this->windowWidth + uiControl.x.offset;
//std::cout << "uic.y.lenghtPct: " << uiControl.y.lengthPct << " height: " << windowHeight << " uic.y.offset: " << uiControl.y.offset << std::endl;
this->y = (uiControl.y.lengthPct / 100.0) * this->windowHeight + uiControl.y.offset;
this->width = (uiControl.w.lengthPct / 100.0) * this->windowWidth + uiControl.w.offset;
this->height = (uiControl.h.lengthPct / 100.0) * this->windowHeight + uiControl.h.offset;
//std::cout << "!boundToPage " << name << " to: " << (int)x << "," << (int)y << " " << (int)width << "," << (int)height << std::endl;
}
//std::cout << "Component::layout - adjusted by prev: " << (int)x << "x" << (int)y << std::endl;
//std::cout << "Component::layout - moving component to " << (int)x << "x" << (int)y << std::endl;
// change in X position
//std::cout << "Component::layout - component was at " << lx << " moved(?) to " << (int)x << std::endl;
// also need to update texture if our width (which is calculated from windowWidth) changes
// it's more than width because a change to windowWidth fucks up all coordinates in it
// so it has to be recalculated (??)
//if (x!=lx || !textureSetup) {
// this line may have more or less room
// we'll need to rewrap component
wrap();
//}
// recurse down over my children and update their position
// if parent x or y changes or windowWindow changes, all children need to be adjust
// what about recurse up, if this element changes? well wrap recurses up the parent sizes
//std::cout << "Component::layout - I have " << children.size() << " children affected by my moved" << std::endl;
for (std::shared_ptr<Component> child : children) {
// maybe it should be like this:
// hey new w/h
// update wras
// where do we update layout?
// So no, because this is a relayout, we don't know sf w/h has changes
// most component resize()s already update the w/h
//std::cout << "component::layout - " << name << " Doing relayout of a " << typeOfComponent(child) << "-" << child->name << std::endl;
// update new sizes
child->windowWidth = windowWidth;
child->windowHeight = windowHeight;
// update it's layout
child->layout();
}
// also maybe bump siblings after us (inline if x/y moved, block if y moved)
}
// resize/wordwrap to available width
// our position is required
void Component::wrap() {
//std::cout << "Component::wrap - " << typeOfComponent(this) << std::endl;
float lW = width;
float lH = height;
resize(windowWidth, windowHeight); // this may change our w/h
textureSetup = true;
if (lW != width || lH != height) {
//std::cout << "Component::wrap - component was " << (int)lW << "x" << (int)lH << " now " << (int)width << "x" << (int)height << std::endl;
// size has change, update our parent
updateParentSize();
} else {
//std::cout << "Component::wrap - component same size" << std::endl;
}
}
// measure current, apply changes to parent
// our size is required
void Component::updateParentSize() {
//std::cout << "Component::updateParentSize - " << typeOfComponent(this) << std::endl;
if (!parent) {
//std::cout << "Component::updateParentSize - can't update parent size, no parent" << std::endl;
return;
}
// back up current size
unsigned int lastParentWidth = parent->width;
unsigned int lastParentHeight = parent->height;
parent->endingX = endingX;
parent->endingY = endingY;
// find max width of all siblings
unsigned int maxWidth = width; // float?
unsigned int heightAccum = 0;
unsigned int widthAccum = 0;
unsigned int totalHeight = 0;
// integrity check
if (!parent->children.size()) {
// currently means creation
std::cout << "Component::updateParentSize - parent's has no children, strange since we are one" << std::endl;
totalHeight = height;
}
// look at siblings
bool wasInline = false;
//std::cout << "Component::updateParentSize - assessing " << parent->children.size() << " children" << std::endl;
for (std::shared_ptr<Component> child : parent->children) {
maxWidth = std::max(maxWidth, static_cast<unsigned int>(child->width));
if (child->isInline) {
heightAccum = std::max(heightAccum, static_cast<unsigned int>(child->height));
widthAccum += child->width;
/*
if (wasInline) {
// in in
heightAccum = std::max(heightAccum, static_cast<int>(child->height));
} else {
// bl in
heightAccum = static_cast<int>(child->height);
}
*/
} else {
if (wasInline) {
// in bl
// flush height of previous line + our height
totalHeight += heightAccum + child->height;
heightAccum = 0; // reset
maxWidth = std::max(maxWidth, widthAccum);
widthAccum = 0;
} else {
// bl bl
totalHeight += child->height;
// than a max of all widths of the two is fine
}
}
wasInline = child->isInline;
}
// flush any remaining width/heightAccum
totalHeight += heightAccum;
maxWidth = std::max(maxWidth, widthAccum);
//std::cout << "new size " << maxWidth << "x" << totalHeight << std::endl;
// did our size actually change
if (lastParentWidth != maxWidth || lastParentHeight != totalHeight) {
//std::cout << "Component::updateParentSize - from " << (int)height << " totalHeight: " << totalHeight << std::endl;
parent->width = maxWidth;
parent->height = totalHeight;
parent->updateParentSize(); // our parent size can only be recalculated by looking at it's children
}
}
GLuint elementBufferObject = 0;
void Component::initTheElementBufferObject() const {
glGenBuffers(1, &elementBufferObject);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBufferObject);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
}
GLuint Component::CreateVertexArrayObject() const {
GLuint vertexArrayObject = 0;
glGenVertexArrays(1, &vertexArrayObject);
glBindVertexArray(vertexArrayObject);
// we may need the VBO here...
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBufferObject);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), nullptr);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), reinterpret_cast<void*>(3 * sizeof(float)));
glEnableVertexAttribArray(1);
//glBindVertexArray(0);
return vertexArrayObject;
}
GLuint Component::CreateVertexBufferObject() const {
GLuint vertexBufferObject = 0;
glGenBuffers(1, &vertexBufferObject);
return vertexBufferObject;
}
// this always creates, we probably should just respond to existing state
bool Component::setPosition4(GLuint vertexBufferObject, int x0, int y0, int x1, int y1) const {
float vertices[20] = {
0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f
};
vertices[(0 * 5) + 0] = x0;
vertices[(0 * 5) + 1] = y1;
vertices[(1 * 5) + 0] = x1;
vertices[(1 * 5) + 1] = y1;
vertices[(2 * 5) + 0] = x1;
vertices[(2 * 5) + 1] = y0;
vertices[(3 * 5) + 0] = x0;
vertices[(3 * 5) + 1] = y0;
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject); // selects buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // writes buffer
return true;
}
GLuint Component::CreateTexture() const {
GLuint textureNum = 0;
glGenTextures(1, &textureNum);
return textureNum;
}
bool Component::setTexture(GLuint textureNum, GLsizei w, GLsizei h, const unsigned char *texture) const {
glBindTexture(GL_TEXTURE_2D, textureNum);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
glGenerateMipmap(GL_TEXTURE_2D);
return true;
}
// converts 0-1 to screen
// but centered
void Component::pointToViewport(float &rawX, float &rawY) const {
if (useBoxShader) {
//std::cout << "Component::pointToViewport - notBoundToPage converting from " << static_cast<int>(rawX) << "," << static_cast<int>(rawY) << std::endl;
//std::cout << "BoundToPage using " << screenWidth << "x" << screenHeight << std::endl;
rawX = ((rawX / windowWidth) * 2) - 1;
rawY = ((rawY / windowHeight) * 2) - 1;
//std::cout << "Component::pointToViewport - BoundToPage using " << static_cast<int>(rawX) << "x" << static_cast<int>(rawY) << std::endl;
//std::cout << "Component::pointToViewport - BoundToPage converted to " << rawX << "," << rawY << std::endl;
} else {
//std::cout << "notBoundToPage using " << screenWidth << "x" << screenHeight << std::endl;
//std::cout << "Component::pointToViewport - notBoundToPage converting from " << static_cast<int>(rawX) << "," << static_cast<int>(rawY) << std::endl;
if (rawX < 0) {
rawX += windowWidth;
}
if (rawY < 0) {
rawY += windowHeight;
}
if (rawX > 1) {
rawX /= windowWidth;
}
if (rawY > 1) {
rawY /= windowHeight;
}
rawX = (rawX * 2) - 1;
rawY = (rawY * 2) - 1;
//std::cout << "Component::pointToViewport - notBoundToPage converted to " << rawX << "," << rawY << std::endl;
}
}
// keeps 0-1 (and *2 to convert to screen)
// but also takes pixels (and converts to screen)
// anchors to upperleft
void Component::distanceToViewport(float &rawX, float &rawY) const {
if (std::abs(rawX) > 1) {
rawX /= windowWidth;
}
if (std::abs(rawY) > 1) {
rawY /= windowHeight;
}
rawX *= 2;
rawY *= 2;
}
void Component::printComponentTree(const std::shared_ptr<Component> &component, int depth) {
for (int i = 0; i < depth; i++) {
std::cout << '\t';
}
ButtonComponent *butComponent = dynamic_cast<ButtonComponent*>(component.get());
InputComponent *inputComponent = dynamic_cast<InputComponent*>(component.get());
if (butComponent) {
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->getValue() << std::endl;
} else {
TextComponent *textComponent = dynamic_cast<TextComponent*>(component.get());
if (textComponent) {
std::cout << std::fixed << "X: " << static_cast<int>(textComponent->x) << " Y: " << static_cast<int>(textComponent->y) << " WIDTH: " << static_cast<int>(textComponent->width) << " HEIGHT: " << static_cast<int>(textComponent->height) << " INLINE: " << textComponent->isInline << " TEXT: " << textComponent->text << std::endl;
}
else {
std::cout << std::fixed << "X: " << static_cast<int>(component->x) << " Y: " << static_cast<int>(component->y) << " WIDTH: " << static_cast<int>(component->width) << " HEIGHT: " << static_cast<int>(component->height) << " INLINE: " << component->isInline << " NAME: " << component->name << std::endl;
}
}
for (std::shared_ptr<Component> child : component->children) {
Component::printComponentTree(child, depth + 1);
}
}