Browse Source

move out textblock, updateCursor prototype for movement, convert value to textblock, addChar/backSpace manage cursor and use block, textScroll/crop

Odilitime 5 years ago
parent
commit
d2fd8727ad
  1. 251
      src/graphics/components/InputComponent.cpp
  2. 33
      src/graphics/components/InputComponent.h

251
src/graphics/components/InputComponent.cpp

@ -6,35 +6,6 @@ @@ -6,35 +6,6 @@
#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 insertCharAt(char chr, size_t pos) {
}
void delCharAt(size_t pos) {
}
extern TextRasterizerCache *rasterizerCache;
extern std::unique_ptr<Scheduler> scheduler;
@ -83,7 +54,7 @@ InputComponent::InputComponent(const float rawX, const float rawY, const float r @@ -83,7 +54,7 @@ InputComponent::InputComponent(const float rawX, const float rawY, const float r
this->win->renderDirty = true;
}
}, 500);
this->updateCursor();
this->updateCursor(0, 0);
this->win->renderDirty = true;
};
onBlur=[this]() {
@ -310,19 +281,22 @@ void InputComponent::resize(const int passedWindowWidth, const int passedWindowH @@ -310,19 +281,22 @@ void InputComponent::resize(const int passedWindowWidth, const int passedWindowH
}
std::string InputComponent::getValue() {
return this->value;
//return this->value;
return this->text.getValue();
}
void InputComponent::setValue(std::string newValue) {
this->value = newValue;
//this->value = newValue;
this->text.setValue(newValue);
if (!this->multiLine) {
this->cursorCharX = static_cast<int>(this->value.size() & INT_MAX);
this->cursorCharX = static_cast<int>(newValue.size() & INT_MAX);
}
// if we pasted in a middle of block
}
void InputComponent::addChar(char c) {
value += c;
this->text.insertAt(std::string(1, c), this->cursorCharX, this->cursorCharY);
//this->value += c;
//std::cout << "InputComponent::addChar - was cursor at " << this->cursorCharX << "," << this->cursorCharY << std::endl;
if (c == '\r') {
if (this->multiLine) {
@ -333,47 +307,123 @@ void InputComponent::addChar(char c) { @@ -333,47 +307,123 @@ void InputComponent::addChar(char c) {
this->cursorCharX++;
}
//std::cout << "InputComponent::addChar - at " << (int)x << "," << (int)y << std::endl;
updateText();
this->updateCursor(0, 0);
this->updateText();
}
void InputComponent::backSpace() {
char last = '\0';
if (value.length()) {
last = value.at(value.length() - 1);
if (this->text.getValue().length()) {
last = this->text.getValue().at(this->text.getValue().length() - 1);
}
value = value.substr(0, value.length() - 1);
//std::cout << "InputComponent::backSpace - was cursor at " << this->cursorCharX << "," << this->cursorCharY << std::endl;
//value = value.substr(0, value.length() - 1);
if (this->cursorCharX) {
// since this backSpace, we want to remove the character before this cursor
// 0,A,1,S,2,D,3,F,4
// ^ means remove char 2 (starting at 0)
//
this->text.deleteAt(this->cursorCharX - 1, this->cursorCharY, 1);
} else {
// maybe delete line
this->text.deleteAt(this->cursorCharX, this->cursorCharY, 1);
}
//std::cout << "InputComponent::backSpace - removed [" << last << "]" << 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;
if (this->cursorCharY < 0) {
this->cursorCharY = 0;
this->cursorCharX = 0;
} else {
this->cursorCharX = this->text.lineLength(this->cursorCharY);
}
//std::pair<int, int> lineData = getLine(this->text.getValue(), this->cursorCharY);
//this->cursorCharX = lineData.second - lineData.first + 1;
}
} else {
this->cursorCharX--;
if (this->cursorCharX < 0) this->cursorCharX = 0;
}
//std::cout << "InputComponent::backSpace - at " << (int)x << "," << (int)y << std::endl;
updateText();
this->updateCursor(0, 0);
this->updateText();
}
void InputComponent::updateCursor() {
std::cout << "InputComponent::updateCursor - cursor at " << this->cursorCharX << "," << this->cursorCharY << std::endl;
void InputComponent::updateCursor(int mX, int mY) {
//std::cout << "InputComponent::updateCursor - at " << this->cursorCharX << "," << this->cursorCharY << " move: " << mX << "," << mY << std::endl;
bool moved = false;
if (mX || mY) {
if (this->multiLine) {
if (mY < 0) {
// up
this->cursorCharY--;
if (this->cursorCharY < 0) {
this->cursorCharX = 0;
this->cursorCharY = 0;
}
} else if (mY > 0) {
// down
this->cursorCharY++;
if (this->cursorCharY >= this->text.lines.size()) {
this->cursorCharY = this->text.lines.size() - 1;
this->cursorCharX = this->text.lineLength(this->cursorCharY);
}
}
} else {
if (mY < 0) {
// up
this->cursorCharX = 0;
} else if (mY > 0) {
// down
this->cursorCharX = this->text.lineLength(0);
}
}
if (mX < 0) {
// left
this->cursorCharX--;
if (this->cursorCharX < 0) {
this->cursorCharX = 0;
this->cursorCharY--;
if (this->cursorCharY < 0) {
this->cursorCharY = 0;
} else {
this->cursorCharX = this->text.lineLength(this->cursorCharY);
}
}
} else if (mX > 0) {
// right
this->cursorCharX++;
if (this->cursorCharX > this->text.lineLength(this->cursorCharY)) {
this->cursorCharY++;
if (this->cursorCharY >= this->text.lines.size()) {
this->cursorCharY = this->text.lines.size() - 1;
this->cursorCharX = this->text.lineLength(this->cursorCharY);
} else {
this->cursorCharX = 0;
}
}
}
//std::cout << "InputComponent::updateCursor - cursor now at " << this->cursorCharX << "," << this-> cursorCharY << std::endl;
}
if (this->cursorLastX != this->cursorCharX || this->cursorLastY != this->cursorCharY) {
moved = true;
}
//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 = lineData.first + this->cursorCharX;
//std::pair<int, int> lineData = getLine(this->text.getValue(), this->cursorCharY);
//std::cout << "InputComponent::updateCursor - line " << this->cursorCharY << " starts at " << lineData.first << std::endl;
//size_t pos = lineData.first + this->cursorCharX;
//std::cout << "InputComponent::updateCursor - cx " << this->cursorCharX << " starts at value pos " << pos << std::endl;
if (pos < this->value.size()) {
//if (pos < this->text.getValue().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.text = text.getValue().substr(0, pos);
request.text = this->text.getValueUpTo(this->cursorCharX, this->cursorCharY);
//std::cout << "InputComponent::updateCursor - sizeText[" << request.text << "]" << std::endl;
request.startX = x;
request.availableWidth = windowWidth;
request.sourceStartX = 0;
@ -384,18 +434,29 @@ void InputComponent::updateCursor() { @@ -384,18 +434,29 @@ void InputComponent::updateCursor() {
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;
//std::cout << "InputComponent::updateCursor - response at [" << textInfo->endingX << "," << textInfo->endingY << "]" << std::endl;
int endingX = textInfo->endingX;
int endingY = textInfo->endingY;
// adjust text crop
//std::cout << "c.endingY: " << textInfo->endingY << " c.y:" << endingY << "" << std::endl;
this->textCropX = std::max(textInfo->endingX, static_cast<int>(this->width));
this->textCropY = std::max(-textInfo->endingY, static_cast<int>(this->height));
this->textScrollY = 0; // reset scroll
//this->cursorStartAtX = textInfo->endingX;
//this->cursorStartAtY = textInfo->endingY;
// adjust our scroll
//std::cout << "cursor height" << (int)textInfo->height << " > " << (int)this->height << " (" << this->textScrollY << ")" << std::endl;
if (textInfo->height > this->height) {
this->cursorStartAtY += textInfo->height - this->height;
endingY += textInfo->height - this->height;
this->textScrollY = textInfo->height - this->height;
}
// this is texture shader coordinates now (not text shader coords)
//
cursorBox->x = x + this->cursorStartAtX;
cursorBox->x = x + endingX;
if (boundToPage) {
cursorBox->y = this->windowHeight + y + this->cursorStartAtY;
cursorBox->y = this->windowHeight + this->y + endingY;
} else {
// + this->cursorStartAtY
cursorBox->y = this->y + 5;
@ -403,6 +464,25 @@ void InputComponent::updateCursor() { @@ -403,6 +464,25 @@ void InputComponent::updateCursor() {
//std::cout << "placing cursor at " << (int)cursorBox->x << "," << (int)cursorBox->y << std::endl;
cursorBox->resize(this->windowWidth, this->windowHeight);
// ok placement of the cursor may trigger the text to scroll and need to be re-rasterized
if (moved) {
/*
if (userInputText) {
std::cout << "cursor at " << (int)textInfo->endingY << " to " << textInfo->endingY << " textScrollY: " << this->textScrollY << " inputHeight: " << (int)this->height << " textHeight: " << (int)this->userInputText->height << " adjHeight: " << (int)(this->height - this->textScrollY) << std::endl;
// if we're at the top of input comp moving up
// or at the bottom of the input comp going down
if (-endingY > this->height - this->textScrollY) {
//this->textScrollY = this->height + endingY;
std::cout << "set textScrollY: " << this->textScrollY << std::endl;
}
}
*/
this->updateText();
// we're updated
this->cursorLastX = this->cursorCharX;
this->cursorLastY = this->cursorCharY;
}
// if we move the cursor, redraw immediately
this->showCursor = true;
if (this->win) {
@ -416,9 +496,9 @@ void InputComponent::updateText() { @@ -416,9 +496,9 @@ void InputComponent::updateText() {
if (this->node) {
std::map<std::string, std::string>::iterator it = this->node->properties.find("value");
if (it == this->node->properties.end()) {
this->node->properties.insert(std::make_pair("value", this->value));
this->node->properties.insert(std::make_pair("value", this->text.getValue()));
} else {
it->second = this->value;
it->second = this->text.getValue();
}
}
@ -427,11 +507,12 @@ void InputComponent::updateText() { @@ -427,11 +507,12 @@ void InputComponent::updateText() {
// 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.text = text.getValue();
request.startX = x;
request.availableWidth = windowWidth;
request.sourceStartX = 0;
request.sourceStartY = 0;
// don't wrap if ML, otherwise do
if (this->multiLine) {
request.noWrap = false;
} else {
@ -439,18 +520,23 @@ void InputComponent::updateText() { @@ -439,18 +520,23 @@ void InputComponent::updateText() {
}
std::unique_ptr<sizeResponse> textInfo = textRasterizer->size(request);
if (textInfo.get() == nullptr) {
std::cout << "InputComponent::updateText - couldn't estimate value[" << this->value << "] size" << std::endl;
std::cout << "InputComponent::updateText - couldn't estimate value[" << this->text.getValue() << "] size" << std::endl;
return;
}
//int textWidth = textInfo->first;
int estWidth = textInfo->width;
int estHeight = textInfo->height;
this->cursorStartAtX = textInfo->endingX;
this->cursorStartAtY = textInfo->endingY;
//int estWidth = textInfo->width;
//int estHeight = textInfo->height;
//this->cursorStartAtX = textInfo->endingX;
//this->cursorStartAtY = textInfo->endingY;
// if textHeight is bigger than window, adjust cursor too
/*
if (estHeight > this->height) {
this->cursorStartAtY += estHeight - this->height;
std::cout << "InputComponent::updateText - used to adj cursorStartAtY += " << (int)(estHeight - this->height) << " (" << estHeight << " - " << (int)this->height << ")" << std::endl;
//this->cursorStartAtY += estHeight - this->height;
}
this->updateCursor();
*/
//this->updateCursor(0, 0);
// why does changing the width mess shit up?
//std::cout << "InputComponent::updateText - our width: " << static_cast<int>(width) << " windowWidth: " << windowWidth << std::endl;
@ -459,7 +545,7 @@ void InputComponent::updateText() { @@ -459,7 +545,7 @@ void InputComponent::updateText() {
if (this->userInputText) {
delete this->userInputText;
}
this->userInputText = new TextComponent(value, 0, 0, 12, false, 0x000000FF, this->windowWidth, this->windowHeight);
this->userInputText = new TextComponent(this->text.getValue(), 0, 0, 12, false, 0x000000FF, this->windowWidth, this->windowHeight);
if (!userInputText->win && this->win) {
userInputText->win = this->win;
}
@ -473,10 +559,14 @@ void InputComponent::updateText() { @@ -473,10 +559,14 @@ void InputComponent::updateText() {
userInputText->y = this->y - this->windowHeight + 16;
}
userInputText->boundToPage = this->boundToPage;
userInputText->rasterStartX = 0;
userInputText->rasterStartY = 0;
userInputText->rasterStartX = this->textScrollX;
userInputText->rasterStartY = this->textScrollY;
userInputText->rasterCropX = this->textCropX;
userInputText->rasterCropY = this->textCropY;
//std::cout << "InputComponent::updateText - estWidth: " << estWidth << " width: " << static_cast<int>(this->width) << " eX: " << textInfo->endingX << std::endl;
// no longer scroll to end of text
/*
if (estWidth > this->width) {
//std::cout << "scrolling text" << std::endl;
userInputText->rasterStartX = estWidth - this->width;
@ -486,8 +576,23 @@ void InputComponent::updateText() { @@ -486,8 +576,23 @@ void InputComponent::updateText() {
//std::cout << "scrolling text" << std::endl;
userInputText->rasterStartY = estHeight - this->height; // start at one widget height from the bottom
}
*/
//
/*
// translate cursor in scroll
std::cout << "cursor at " << this->cursorStartAtX << "," << this->cursorStartAtY << " size: " << (int)this->width << "," << (int)this->height << std::endl;
// so we only care about cursorStartAtY here atm
// we get values like -58, -43, -28, -13
if (this->cursorStartAtX > this->width) {
userInputText->rasterStartX = this->cursorStartAtX - this->width;
}
if (this->multiLine && -(this->cursorStartAtY + userInputText->height) > this->height) {
std::cout << "scrolling y start: " << (-(this->cursorStartAtY + userInputText->height) - this->height) << std::endl;
userInputText->rasterStartY = -this->cursorStartAtY - this->height;
}
*/
//std::cout << "InputComponent::updateText - textHeight: " << estHeight << " inputHeight: " << static_cast<int>(height) << " eY: " << textInfo->endingY << " y0max:" << textInfo->y0max << " rasterStartY: " << userInputText->rasterStartY << " lines: " << textInfo->lines << std::endl;
// wrap if multiLine, otherwise don't
// don't wrap if multiLine, otherwise wrap
userInputText->noWrap = !this->multiLine;
userInputText->resize(this->windowWidth, this->windowHeight, this->width); // need to make sure there's a texture

33
src/graphics/components/InputComponent.h

@ -6,25 +6,10 @@ @@ -6,25 +6,10 @@
#include "BoxComponent.h"
#include "TextComponent.h"
#include "../../scheduler.h"
#include "../../TextBlock.h"
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) { }
@ -35,9 +20,10 @@ public: @@ -35,9 +20,10 @@ public:
void render();
std::string getValue();
void setValue(std::string newValue);
// FIXME: change to using std::string
void addChar(char c);
void backSpace();
void updateCursor();
void updateCursor(int x, int y);
void updateText();
TextComponent *userInputText = nullptr;
BoxComponent *cursorBox = nullptr;
@ -48,14 +34,19 @@ public: @@ -48,14 +34,19 @@ public:
bool showCursor = true;
std::shared_ptr<timer_handle> cursorTimer = nullptr;
// store for cursor
int cursorStartAtX;
int cursorStartAtY;
int textScrollX = 0;
int textScrollY = 0;
int textCropX = 0;
int textCropY = 0;
int cursorLastX = 0;
int cursorLastY = 0;
int cursorCharX = 0;
int cursorCharY = 0;
TextBlock text;
TagNode *node = nullptr;
bool multiLine = false; // textarea control
protected:
std::string value="";
//protected:
//std::string value="";
};
#endif

Loading…
Cancel
Save