aboutsummaryrefslogtreecommitdiff
path: root/src/Text.cpp
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2018-05-07 23:00:21 +0200
committerdec05eba <dec05eba@protonmail.com>2018-05-07 23:01:04 +0200
commit2b7d030551a357272f9cc39e347855bd2e3faba2 (patch)
tree93d9eabaf6ba62629b9258a4314338ac8f89fc2a /src/Text.cpp
parent29bd3e7c65af79b3f8837c7786ffbda3c93c3ebb (diff)
Improve text editing, use Text object for chatbar
Improve text rendering by not using floating point position
Diffstat (limited to 'src/Text.cpp')
-rw-r--r--src/Text.cpp140
1 files changed, 115 insertions, 25 deletions
diff --git a/src/Text.cpp b/src/Text.cpp
index f78c6b7..6fa1fcc 100644
--- a/src/Text.cpp
+++ b/src/Text.cpp
@@ -5,6 +5,7 @@
#include "../include/ColorScheme.hpp"
#include <SFML/Graphics/RectangleShape.hpp>
#include <cmath>
+#include <process.hpp>
namespace dchat
{
@@ -59,9 +60,19 @@ namespace dchat
this->str = str;
dirty = true;
dirtyText = true;
+ if(str.getSize() < caretIndex)
+ {
+ caretIndex = str.getSize();
+ dirtyCaret = true;
+ }
}
}
+ const sf::String& Text::getString() const
+ {
+ return str;
+ }
+
void Text::setPosition(float x, float y)
{
position.x = x;
@@ -91,6 +102,16 @@ namespace dchat
}
}
+ unsigned int Text::getCharacterSize() const
+ {
+ return characterSize;
+ }
+
+ const sf::Font* Text::getFont() const
+ {
+ return font;
+ }
+
void Text::setFillColor(sf::Color color)
{
if(color != this->color)
@@ -323,7 +344,7 @@ namespace dchat
{
textElement.position.y = glyphPos.y;
// TODO: Find a better way to do this, @totalHeight is wrong because we add emojiSize and then vspace
- glyphPos.y += emojiSize - vspace;
+ glyphPos.y += floor(emojiSize - vspace);
}
else
{
@@ -333,7 +354,7 @@ namespace dchat
if(glyphPos.x > maxWidth)
{
glyphPos.x = 0.0f;
- glyphPos.y += vspace + lineSpacing;
+ glyphPos.y += floor(vspace + lineSpacing);
}
boundingBox.width = std::max(boundingBox.width, glyphPos.x);
@@ -341,7 +362,7 @@ namespace dchat
}
usize vertexOffset = vertices.getVertexCount();
- vertices.resize(vertices.getVertexCount() + (4 * textElement.text.size));
+ vertices.resize(vertices.getVertexCount() + 4 * (textElement.text.size + 1));
textElement.position = glyphPos;
for(size_t i = 0; i < textElement.text.size; ++i)
{
@@ -356,7 +377,10 @@ namespace dchat
{
case ' ':
{
- vertices[vertexStart].position = sf::Vector2f(glyphPos.x, glyphPos.y - vspace);
+ vertices[vertexStart + 0] = { sf::Vector2f(glyphPos.x, glyphPos.y - vspace), sf::Color::Transparent, sf::Vector2f() };
+ vertices[vertexStart + 1] = { sf::Vector2f(glyphPos.x + hspace, glyphPos.y - vspace), sf::Color::Transparent, sf::Vector2f() };
+ vertices[vertexStart + 2] = { sf::Vector2f(glyphPos.x + hspace, glyphPos.y), sf::Color::Transparent, sf::Vector2f() };
+ vertices[vertexStart + 3] = { sf::Vector2f(glyphPos.x, glyphPos.y), sf::Color::Transparent, sf::Vector2f() };
glyphPos.x += hspace;
if(glyphPos.x > maxWidth * 0.5f)
{
@@ -367,7 +391,10 @@ namespace dchat
}
case '\t':
{
- vertices[vertexStart].position = sf::Vector2f(glyphPos.x, glyphPos.y - vspace);
+ vertices[vertexStart + 0] = { sf::Vector2f(glyphPos.x, glyphPos.y - vspace), sf::Color::Transparent, sf::Vector2f() };
+ vertices[vertexStart + 1] = { sf::Vector2f(glyphPos.x + hspace * TAB_WIDTH, glyphPos.y - vspace), sf::Color::Transparent, sf::Vector2f() };
+ vertices[vertexStart + 2] = { sf::Vector2f(glyphPos.x + hspace * TAB_WIDTH, glyphPos.y), sf::Color::Transparent, sf::Vector2f() };
+ vertices[vertexStart + 3] = { sf::Vector2f(glyphPos.x, glyphPos.y), sf::Color::Transparent, sf::Vector2f() };
glyphPos.x += (hspace * TAB_WIDTH);
if(glyphPos.x > maxWidth * 0.5f)
{
@@ -378,15 +405,21 @@ namespace dchat
}
case '\n':
{
- vertices[vertexStart].position = sf::Vector2f(glyphPos.x, glyphPos.y - vspace);
+ vertices[vertexStart + 0] = { sf::Vector2f(glyphPos.x, glyphPos.y - vspace), sf::Color::Transparent, sf::Vector2f() };
+ vertices[vertexStart + 1] = { sf::Vector2f(0.0f, glyphPos.y), sf::Color::Transparent, sf::Vector2f() };
+ vertices[vertexStart + 2] = { sf::Vector2f(0.0f, glyphPos.y), sf::Color::Transparent, sf::Vector2f() };
+ vertices[vertexStart + 3] = { sf::Vector2f(0.0f, glyphPos.y), sf::Color::Transparent, sf::Vector2f() };
glyphPos.x = 0.0f;
- glyphPos.y += vspace + lineSpacing;
+ glyphPos.y += floor(vspace + lineSpacing);
continue;
}
case '\v':
{
- vertices[vertexStart].position = sf::Vector2f(glyphPos.x, glyphPos.y - vspace);
- glyphPos.y += (vspace * TAB_WIDTH) + lineSpacing;
+ vertices[vertexStart + 0] = { sf::Vector2f(glyphPos.x, glyphPos.y - vspace), sf::Color::Transparent, sf::Vector2f() };
+ vertices[vertexStart + 1] = { sf::Vector2f(0.0f, glyphPos.y), sf::Color::Transparent, sf::Vector2f() };
+ vertices[vertexStart + 2] = { sf::Vector2f(0.0f, glyphPos.y), sf::Color::Transparent, sf::Vector2f() };
+ vertices[vertexStart + 3] = { sf::Vector2f(0.0f, glyphPos.y), sf::Color::Transparent, sf::Vector2f() };
+ glyphPos.y += floor(vspace * TAB_WIDTH + lineSpacing);
continue;
}
}
@@ -405,7 +438,7 @@ namespace dchat
{
sf::Vector2f &vertexPos = vertices[vertexOffset + j * 4 + k].position;
vertexPos.x -= lastSpacingAccumulatedOffset;
- vertexPos.y += vspace + lineSpacing;
+ vertexPos.y += floor(vspace + lineSpacing);
}
}
@@ -416,7 +449,7 @@ namespace dchat
else
glyphPos.x = 0.0f;
- glyphPos.y += vspace + lineSpacing;
+ glyphPos.y += floor(vspace + lineSpacing);
}
sf::Vector2f vertexTopLeft(glyphPos.x + glyph.bounds.left, glyphPos.y + glyph.bounds.top);
@@ -439,6 +472,11 @@ namespace dchat
glyphPos.x += glyph.advance;
}
+ vertices[vertices.getVertexCount() - 4] = { sf::Vector2f(glyphPos.x, glyphPos.y - vspace), sf::Color::Transparent, sf::Vector2f() };
+ vertices[vertices.getVertexCount() - 3] = { sf::Vector2f(glyphPos.x, glyphPos.y - vspace), sf::Color::Transparent, sf::Vector2f() };
+ vertices[vertices.getVertexCount() - 2] = { sf::Vector2f(glyphPos.x, glyphPos.y - vspace), sf::Color::Transparent, sf::Vector2f() };
+ vertices[vertices.getVertexCount() - 1] = { sf::Vector2f(glyphPos.x, glyphPos.y - vspace), sf::Color::Transparent, sf::Vector2f() };
+
if(textElement.type != TextElement::Type::TEXT)
{
prevCodePoint = 0;
@@ -494,8 +532,16 @@ namespace dchat
}
usize vertexIndex = caretIndex * 4;
- const sf::Vertex &topLeftVertex = vertices[vertexIndex];
- caretPosition = topLeftVertex.position;
+ if(vertexIndex == 0)
+ {
+ float vspace = font->getLineSpacing(characterSize);
+ caretPosition = sf::Vector2f(0.0f, -vspace);
+ }
+ else
+ {
+ const sf::Vertex &topLeftVertex = vertices[vertexIndex];
+ caretPosition = topLeftVertex.position;
+ }
}
bool Text::isCaretAtEnd() const
@@ -511,15 +557,16 @@ namespace dchat
int numVertices = vertices.getVertexCount();
if(numVertices < 4) return 0;
- usize vertexIndex = caretIndex * 4;
+ usize vertexIndex = startIndex * 4;
const sf::Vertex &startTopLeftVertex = vertices[vertexIndex];
int startRow = getRowByPosition(startTopLeftVertex.position);
- for(int i = startIndex * 4; i >= 0; i -= 4)
+ for(int i = startIndex * 4; i > 0; i -= 4)
{
const sf::Vertex &topLeftVertex = vertices[i];
int row = getRowByPosition(topLeftVertex.position);
if(row != startRow)
{
+ printf("start of line %u, startIndex: %u\n", i, startIndex * 4);
return std::max(0, i / 4 + 1);
}
}
@@ -533,7 +580,7 @@ namespace dchat
int numVertices = vertices.getVertexCount();
if(numVertices < 4) return 0;
- usize vertexIndex = caretIndex * 4;
+ usize vertexIndex = startIndex * 4;
const sf::Vertex &startTopLeftVertex = vertices[vertexIndex];
int startRow = getRowByPosition(startTopLeftVertex.position);
for(int i = startIndex * 4; i < numVertices; i += 4)
@@ -555,7 +602,7 @@ namespace dchat
int numVertices = vertices.getVertexCount();
if(numVertices < 4) return 0;
- usize vertexIndex = caretIndex * 4;
+ usize vertexIndex = startIndex * 4;
const sf::Vertex &startTopLeftVertex = vertices[vertexIndex];
int startRow = getRowByPosition(startTopLeftVertex.position);
int closestIndex = -1;
@@ -589,7 +636,7 @@ namespace dchat
int numVertices = vertices.getVertexCount();
if(numVertices < 4) return 0;
- usize vertexIndex = caretIndex * 4;
+ usize vertexIndex = startIndex * 4;
const sf::Vertex &startTopLeftVertex = vertices[vertexIndex];
int startRow = getRowByPosition(startTopLeftVertex.position);
int closestIndex = -1;
@@ -623,11 +670,23 @@ namespace dchat
return static_cast<int>(1.0f + position.y / (vspace + lineSpacing));
}
+ static std::string getClipboard()
+ {
+ std::string result;
+ TinyProcessLib::Process process("xsel -o -b", "", [&result](const char *bytes, size_t n)
+ {
+ result.append(bytes, n);
+ });
+ if(process.get_exit_status() != 0)
+ fprintf(stderr, "Failed to get clipboard content\n");
+ return result;
+ }
+
void Text::processEvent(const sf::Event &event)
{
- if(!editable || textElements.size() == 0) return;
+ if(!editable) return;
- bool caretAtEnd = textElements[0].text.size == 0 || caretIndex == textElements[0].text.size;
+ bool caretAtEnd = textElements.size() == 0 || textElements[0].text.size == 0 || caretIndex == textElements[0].text.size;
if(event.type == sf::Event::KeyPressed)
{
@@ -645,8 +704,8 @@ namespace dchat
{
auto strBefore = str.substring(0, caretIndex - 1);
auto strAfter = str.substring(caretIndex);
- setString(strBefore + strAfter);
--caretIndex;
+ setString(strBefore + strAfter);
dirtyCaret = true;
}
else if(event.key.code == sf::Keyboard::Delete && !caretAtEnd)
@@ -671,22 +730,52 @@ namespace dchat
{
caretMoveDirection = CaretMoveDirection::END;
}
+ else if(event.key.code == sf::Keyboard::Return)
+ {
+ if(sf::Keyboard::isKeyPressed(sf::Keyboard::LShift) || sf::Keyboard::isKeyPressed(sf::Keyboard::RShift))
+ {
+ if(caretAtEnd)
+ str += '\n';
+ else
+ {
+ auto strBefore = str.substring(0, caretIndex);
+ auto strAfter = str.substring(caretIndex);
+ str = strBefore + '\n' + strAfter;
+ }
+
+ ++caretIndex;
+ dirty = true;
+ dirtyText = true;
+ dirtyCaret = true;
+ }
+ }
}
else if(event.type == sf::Event::TextEntered)
{
if(event.text.unicode == 8 || event.text.unicode == 127) // backspace, del
return;
+ sf::String stringToAdd;
+ if(event.text.unicode == 22) // ctrl+v
+ {
+ auto clipboardString = getClipboard();
+ stringToAdd = sf::String::fromUtf8(clipboardString.begin(), clipboardString.end());
+ }
+ else if(event.text.unicode >= 32 || event.text.unicode == 9) // 9 == tab
+ stringToAdd = event.text.unicode;
+ else
+ return;
+
if(caretAtEnd)
- str += event.text.unicode;
+ str += stringToAdd;
else
{
auto strBefore = str.substring(0, caretIndex);
auto strAfter = str.substring(caretIndex);
- str = strBefore + event.text.unicode + strAfter;
+ str = strBefore + stringToAdd + strAfter;
}
- ++caretIndex;
+ caretIndex += stringToAdd.getSize();
dirty = true;
dirtyText = true;
dirtyCaret = true;
@@ -727,7 +816,7 @@ namespace dchat
//colRect.contains()
//if(pos.x + maxWidth <= 0.0f || pos.x >= maxWidth || pos.y + totalHeight <= 0.0f || pos.y >= target.getSize().y) return;
if(pos.y + getHeight() <= 0.0f || pos.y >= target.getSize().y) return;
-
+ /*
if(editable)
{
sf::RectangleShape editBox(sf::Vector2f(std::max(maxWidth, boundingBox.width), boundingBox.height));
@@ -735,6 +824,7 @@ namespace dchat
editBox.setFillColor(ColorScheme::getBackgroundColor() + sf::Color(10, 10, 10));
target.draw(editBox);
}
+ */
states.transform.translate(pos);
states.texture = &font->getTexture(characterSize);