Browse Source

button UI component/element

master
Odilitime 5 years ago
parent
commit
c452756aa5
  1. 181
      src/graphics/components/ButtonComponent.cpp
  2. 21
      src/graphics/components/ButtonComponent.h
  3. 95
      src/graphics/elements/BUTTONElement.cpp
  4. 14
      src/graphics/elements/BUTTONElement.h

181
src/graphics/components/ButtonComponent.cpp

@ -0,0 +1,181 @@ @@ -0,0 +1,181 @@
#include "ButtonComponent.h"
extern TextRasterizerCache *rasterizerCache;
ButtonComponent::ButtonComponent(const float rawX, const float rawY, const float rawWidth, const float rawHeight, const int passedWindowWidth, const int passedWindowHeight) : BoxComponent(rawX, rawY, rawWidth, rawHeight, 0xA0A0A0FF, passedWindowWidth, passedWindowHeight) {
// BoxComponent should set up everything we need
//std::cout << "ButtonComponent::ButtonComponent - boxShader " << this->useBoxShader << std::endl;
// looks like it is
}
void ButtonComponent::render() {
//std::cout << "ButtonComponent::render" << std::endl;
//std::cout << "ButtonComponent::render at " << (int)x << "," << (int)y << std::endl;
GLenum glErr=glGetError();
if(glErr != GL_NO_ERROR) {
std::cout << "ButtonComponent::render - start not ok: " << glErr << std::endl;
}
if (verticesDirty) {
//std::cout << "ButtonComponent::render - update dirty vertex" << std::endl;
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glErr=glGetError();
if(glErr != GL_NO_ERROR) {
std::cout << "ButtonComponent::render - glBindBuffer not ok: " << glErr << std::endl;
}
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glErr=glGetError();
if(glErr != GL_NO_ERROR) {
std::cout << "ButtonComponent::render - glBufferData not ok: " << glErr << std::endl;
}
verticesDirty = false;
}
glBindVertexArray(vertexArrayObject);
glErr=glGetError();
if(glErr != GL_NO_ERROR) {
std::cout << "ButtonComponent::render - glBindVertexArray not ok: " << glErr << std::endl;
}
glBindTexture(GL_TEXTURE_2D, texture);
glErr=glGetError();
if(glErr != GL_NO_ERROR) {
std::cout << "ButtonComponent::render - glBindTexture not ok: " << glErr << std::endl;
}
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
glErr=glGetError();
if(glErr != GL_NO_ERROR) {
std::cout << "ButtonComponent::render - glDrawElements not ok: " << glErr << std::endl;
}
glBindVertexArray(0);
// can actuall delete vertices here
if (textLabel) {
// make sure we're using win's transformMatrix
//glUseProgram(this->win->fontProgram);
Shader *fontShader = this->win->shaderLoader.getShader(VertexShader("FontShader.vert"),
FragmentShader("FontShader.frag"));
fontShader->bind();
if (!boundToPage) {
GLint transformLocation = fontShader->uniform("transform");
//GLint transformLocation = glGetUniformLocation(this->win->fontProgram, "transform");
glErr=glGetError();
if(glErr != GL_NO_ERROR) {
std::cout << "ButtonComponent::render - glGetUniformLocation not ok: " << glErr << std::endl;
}
glUniformMatrix4fv(transformLocation, 1, GL_FALSE, this->win->transformMatrix);
glErr=glGetError();
if(glErr != GL_NO_ERROR) {
std::cout << "ButtonComponent::render - glUniformMatrix4fv not ok: " << glErr << std::endl;
}
}
//std::cout << "rendering some text" << std::endl;
textLabel->render();
//glUseProgram(this->win->textureProgram);
Shader *textureShader = this->win->shaderLoader.getShader(VertexShader("TextureShader.vert"),
FragmentShader("TextureShader.frag"));
textureShader->bind();
}
}
void ButtonComponent::resize(const int passedWindowWidth, const int passedWindowHeight) {
//std::cout << "ButtonComponent::resize" << std::endl;
//std::cout << "ButtonComponent::resize - rasterizing at " << (int)x << "x" << (int)y << " size: " << (int)width << "x" << (int)height << std::endl;
// maybe already done at component::resize
// set up state
windowWidth = passedWindowWidth;
windowHeight = passedWindowHeight;
//std::cout << "ButtonComponent::resize - placing box at " << (int)x << "," << (int)y << " size: " << (int)width << "x" << (int)height << std::endl;
float vx = x;
float vy = y;
//std::cout << "ButtonComponent::resize - boundToPage " << this->boundToPage << std::endl;
if (this->boundToPage) {
vy = this->windowHeight + y - height;
//std::cout << "InputComponent::resize - Adjust y to " << vy << " from " << y << " h: " << (int)height << std::endl;
}
pointToViewport(vx, vy);
float vWidth = width;
float vHeight = height;
distanceToViewport(vWidth, vHeight);
float vx1 = vx + vWidth;
float vy1 = vy + vHeight;
vertices[(0 * 5) + 0] = vx;
vertices[(0 * 5) + 1] = vy1;
vertices[(1 * 5) + 0] = vx1;
vertices[(1 * 5) + 1] = vy1;
vertices[(2 * 5) + 0] = vx1;
vertices[(2 * 5) + 1] = vy;
vertices[(3 * 5) + 0] = vx;
vertices[(3 * 5) + 1] = vy;
glBindVertexArray(vertexArrayObject);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindVertexArray(0); // protect what we created against any further modification
//updateText();
if (textLabel) {
textLabel->resize(passedWindowWidth, passedWindowHeight);
}
}
// most of this functionality should be inside TextComponent
void ButtonComponent::updateText() {
//std::cout << "ButtonComponent::updateText - input value is now: " << value << std::endl;
// maybe tie the fontsize to height
if (textLabel) {
delete textLabel;
}
textLabel=new TextComponent(value, 0, 0, 12, false, 0x000000FF, windowWidth, windowHeight);
if (!textLabel->win && this->win) {
textLabel->win = this->win;
}
//std::cout << "placing userInputText at " << static_cast<int>(x) << "," << static_cast<int>(y) << std::endl;
textLabel->x = x;
if (y < 0) {
textLabel->y = y;
} else {
textLabel->y = y - windowHeight + 16;
}
//std::cout << "placed userInputText at " << static_cast<int>(x) << "," << static_cast<int>(y - windowHeight) << std::endl;
// 62 pixels width
// but first we need to know how wide the text is
const std::shared_ptr<TextRasterizer> textRasterizer=rasterizerCache->loadFont(12, false); // fontSize, bold
rasterizationRequest request;
request.text = value;
request.startX = x;
request.availableWidth = windowWidth; // have to include x, because width=62, and we need to render that
request.sourceStartX = 0;
request.sourceStartY = 0;
request.noWrap = true;
// FIXME: center this!
std::unique_ptr<std::pair<int, int>> textInfo = textRasterizer->size(request);
if (textInfo.get() == nullptr) {
std::cout << "ButtonComponent::updateText - couldn't estimate value[" << value << "] size" << std::endl;
return;
}
//int textWidth = textInfo->first;
int estWidth = std::get<0>(*textInfo.get());
//int estHeight = std::get<1>(*textInfo.get());
textLabel->rasterStartX = 0;
textLabel->rasterStartY = 0;
//std::cout << "ButtonComponent::updateText - estWidth: " << estWidth << " width: " << static_cast<int>(width) << std::endl;
if (estWidth > width) {
//std::cout << "scrolling text" << std::endl;
textLabel->rasterStartX = estWidth - width;
}
textLabel->noWrap = true;
// why does changing the width mess shit up?
//std::cout << "ButtonComponent::updateText - our width: " << static_cast<int>(width) << " windowWidth: " << windowWidth << std::endl;
textLabel->resize(windowWidth, windowHeight, width + x); // need to make sure there's a texture
this->win->renderDirty = true;
}

21
src/graphics/components/ButtonComponent.h

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
#ifndef BUTTONCOMPONENT_H
#define BUTTONCOMPONENT_H
#include <GL/glew.h>
#include "BoxComponent.h"
#include "TextComponent.h"
#include "../opengl/Window.h"
// we may not need this if textComponent took a background color
// I guess we'll be inline for now
class ButtonComponent : public BoxComponent {
public:
ButtonComponent(const float rawX, const float rawY, const float rawWidth, const float rawHeight, const int passedWindowWidth, const int passedWindowHeight);
void render();
void resize(const int passedWindowWidth, const int passedWindowHeight);
void updateText();
std::string value="";
TextComponent *textLabel = nullptr;
};
#endif

95
src/graphics/elements/BUTTONElement.cpp

@ -0,0 +1,95 @@ @@ -0,0 +1,95 @@
#include "BUTTONElement.h"
#include "INPUTElement.h"
#include "../components/InputComponent.h"
#include "../components/ButtonComponent.h"
#include "../components/DocumentComponent.h"
#include "../../WebResource.h"
#include "../../Log.h"
BUTTONElement::BUTTONElement() {
isInline = true;
}
std::unique_ptr<Component> BUTTONElement::renderer(const ElementRenderRequest &request) {
// const float rawX, const float rawY, const float rawWidth, const float rawHeight, const int windowWidth, const int windowHeight
// what should our default size be?
//std::cout << "INPUTElement::renderer - creating InputComponent at " << x << "x" << y << std::endl;
TagNode *tagNode = dynamic_cast<TagNode*>(request.node.get());
if (tagNode) {
//std::cout << "Creating submit" << std::endl;
std::unique_ptr<ButtonComponent> butComponent = std::make_unique<ButtonComponent>(0, 0, 62.0f, 13.0f, request.parentComponent->win->windowWidth, request.parentComponent->win->windowHeight);
butComponent->value = "Button";
butComponent->name = "button";
butComponent->onClick=[tagNode, request]() {
// recurse up to find oug form tag
std::shared_ptr<Node> formNode = findFormNode(request.node);
if (!formNode) {
std::cout << "BUTTONElement::renderer:butComponent->onClick - Can't find form parent for submit" << std::endl;
return;
}
if (!request.docComponent) {
std::cout << "BUTTONElement::renderer:butComponent->onClick - Can't find documentComponent for submit" << std::endl;
return;
}
TagNode *formTagNode = dynamic_cast<TagNode*>(formNode.get());
auto formNodeActionIter = formTagNode->properties.find("action");
if (formNodeActionIter == formTagNode->properties.end()) {
std::cout << "Form has no action" << std::endl;
return;
}
auto formData = buildFormData(formNode, nullptr);
/*
// add our name/value (because we skip all submit buttons, there can only be one)
auto submitButtonNameValue = getTagNodeNameValue(*tagNode);
if (submitButtonNameValue) {
formData->insert(*submitButtonNameValue);
}
*/
auto formNodeMethodIter = formTagNode->properties.find("method");
std::string method="GET";
if (formNodeMethodIter != formTagNode->properties.end()) {
method=formNodeMethodIter->second;
}
std::cout << "Form method is " << method << std::endl;
if (method=="POST" || method=="post") {
// need documentComponent
URL uAction = request.docComponent->currentURL.merge(URL(formNodeActionIter->second));
std::cout << "Action URL is " << uAction.toString() << std::endl;
// download URL
WebResource res = postWebResource(uAction, std::move(formData));
handleResource(res, uAction.toString(), request.docComponent);
} else {
// need documentComponent
std::string queryString = "";
if (formData) {
// iterator over formData
for (auto &entry : *formData) {
queryString += entry.first + "=" + entry.second + "&";
}
// strip last & off
queryString = queryString.substr(0, queryString.size() - 1);
std::cout << "queryString is " << queryString << std::endl;
// The moral of the story is, if you have binary (non-alphanumeric) data (or a significantly sized payload) to transmit, use multipart/form-data
auto search = queryString.find(" ");
if (search != std::string::npos) {
queryString.replace(search, 1, "+");
}
}
URL uAction = request.docComponent->currentURL.merge(URL(formNodeActionIter->second+"?"+queryString));
std::cout << "Action URL is " << uAction.toString() << std::endl;
// download URL
WebResource res = postWebResource(uAction, nullptr);
handleResource(res, uAction.toString(), request.docComponent);
}
};
return std::move(butComponent);
}
return nullptr;
}

14
src/graphics/elements/BUTTONElement.h

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
#ifndef BUTTONELEMENT_H
#define BUTTONELEMENT_H
#include "Element.h"
#include "../components/Component.h"
#include "../../html/TextNode.h"
class BUTTONElement : public Element {
public:
BUTTONElement();
virtual std::unique_ptr<Component> renderer(const ElementRenderRequest &request);
};
#endif
Loading…
Cancel
Save