aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Cache.cpp12
-rw-r--r--src/Channel.cpp2
-rw-r--r--src/ChannelTopPanel.cpp1
-rw-r--r--src/Chatbar.cpp140
-rw-r--r--src/Text.cpp140
5 files changed, 134 insertions, 161 deletions
diff --git a/src/Cache.cpp b/src/Cache.cpp
index c795595..0b4bfbf 100644
--- a/src/Cache.cpp
+++ b/src/Cache.cpp
@@ -196,6 +196,10 @@ namespace dchat
int exitStatus;
if(it->process->try_get_exit_status(exitStatus))
{
+ boost::filesystem::path filepath = getImagesDir();
+ odhtdb::Hash urlHash(it->url.data(), it->url.size());
+ filepath /= urlHash.toString();
+
ContentByUrlResult contentByUrlResult;
bool failed = exitStatus != 0;
if(failed)
@@ -204,10 +208,6 @@ namespace dchat
}
else
{
- boost::filesystem::path filepath = getImagesDir();
- odhtdb::Hash urlHash(it->url.data(), it->url.size());
- filepath /= urlHash.toString();
-
contentByUrlResult = loadImageFromFile(filepath);
if(contentByUrlResult.type == ContentByUrlResult::Type::CACHED)
{
@@ -217,7 +217,7 @@ namespace dchat
imageDownloadMutex.lock();
contentUrlCache[it->url] = contentByUrlResult;
- boost::filesystem::path downloadingFilepath = getImagesDir() / ".downloading";
+ boost::filesystem::path downloadingFilepath = filepath / ".downloading";
// Intentionally ignore failure, program should not crash if we fail to remove these files...
boost::system::error_code err;
boost::filesystem::remove(downloadingFilepath, err);
@@ -277,7 +277,7 @@ namespace dchat
odhtdb::Hash urlHash(url.data(), url.size());
filepath /= urlHash.toString();
- boost::filesystem::path downloadingFilepath = getImagesDir() / ".downloading";
+ boost::filesystem::path downloadingFilepath = filepath / ".downloading";
if(boost::filesystem::exists(downloadingFilepath))
{
// Intentionally ignore failure, program should not crash if we fail to remove these files...
diff --git a/src/Channel.cpp b/src/Channel.cpp
index 2426981..e433aee 100644
--- a/src/Channel.cpp
+++ b/src/Channel.cpp
@@ -185,7 +185,7 @@ namespace dchat
void Channel::draw(sf::RenderWindow &window, Cache &cache)
{
messageBoard.draw(window, cache);
- chatbar.draw(window);
+ chatbar.draw(window, cache);
}
void Channel::setCurrent(Channel *channel)
diff --git a/src/ChannelTopPanel.cpp b/src/ChannelTopPanel.cpp
index 1781e74..44ce007 100644
--- a/src/ChannelTopPanel.cpp
+++ b/src/ChannelTopPanel.cpp
@@ -6,6 +6,7 @@
#include "../include/ChannelSidePanel.hpp"
#include "../include/UsersSidePanel.hpp"
#include <SFML/Graphics/RectangleShape.hpp>
+#include <SFML/Graphics/Text.hpp>
#include <cmath>
namespace dchat
diff --git a/src/Chatbar.cpp b/src/Chatbar.cpp
index 55fd764..5f17c28 100644
--- a/src/Chatbar.cpp
+++ b/src/Chatbar.cpp
@@ -29,89 +29,15 @@ namespace dchat
unordered_map<string, string> binds;
Chatbar::Chatbar() :
- text("", *ResourceCache::getFont("fonts/Roboto-Regular.ttf"), FONT_SIZE * Settings::getScaling()),
- caretIndex(0),
+ text("", ResourceCache::getFont("fonts/Roboto-Regular.ttf"), FONT_SIZE * Settings::getScaling(), 0),
focused(true)
{
+ text.setEditable(true);
text.setFillColor(sf::Color(240, 240, 240));
background.setFillColor(ColorScheme::getBackgroundColor());
inputBackground.setFillColor(ColorScheme::getBackgroundColor() + sf::Color(10, 10, 10));
}
- void Chatbar::addChar(sf::Uint32 codePoint)
- {
- auto str = text.getString();
- str.insert(caretIndex, codePoint);
- text.setString(str);
- ++caretIndex;
- caretOffset = text.findCharacterPos(caretIndex) - text.getPosition();
- blinkTimer.restart();
- }
-
- void Chatbar::addString(const string &strToAdd)
- {
- if(strToAdd.empty()) return;
- auto str = text.getString();
- str.insert(caretIndex, sf::String::fromUtf8(strToAdd.begin(), strToAdd.end()));
- text.setString(str);
- caretIndex += strToAdd.size();
- caretOffset = text.findCharacterPos(caretIndex) - text.getPosition();
- blinkTimer.restart();
- }
-
- const sf::String& Chatbar::getString() const
- {
- return text.getString();
- }
-
- void Chatbar::removePreviousChar()
- {
- if(caretIndex > 0)
- {
- auto str = text.getString();
- str.erase(caretIndex - 1);
- text.setString(str);
- --caretIndex;
- caretOffset = text.findCharacterPos(caretIndex) - text.getPosition();
- }
- blinkTimer.restart();
- }
-
- void Chatbar::removeNextChar()
- {
- if(caretIndex < text.getString().getSize())
- {
- auto str = text.getString();
- str.erase(caretIndex);
- text.setString(str);
- }
- blinkTimer.restart();
- }
-
- void Chatbar::clear()
- {
- text.setString("");
- caretIndex = 0;
- caretOffset.x = 0.0f;
- caretOffset.y = 0.0f;
- blinkTimer.restart();
- }
-
- void Chatbar::moveCaretLeft()
- {
- caretIndex = max(0, caretIndex - 1);
- // TODO: Use glyph size to optimize this, no need to iterate all glyphs
- caretOffset = text.findCharacterPos(caretIndex) - text.getPosition();
- blinkTimer.restart();
- }
-
- void Chatbar::moveCaretRight()
- {
- caretIndex = min((int)text.getString().getSize(), caretIndex + 1);
- caretOffset = text.findCharacterPos(caretIndex) - text.getPosition();
- blinkTimer.restart();
- }
-
bool Chatbar::isFocused() const
{
return focused;
@@ -207,18 +133,6 @@ namespace dchat
}
}
- static string getClipboard()
- {
- 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;
- }
-
static void findReplaceAll(string &str, const string &substrToReplace, const string &stringToReplaceWith)
{
size_t findOffset = 0;
@@ -245,21 +159,20 @@ namespace dchat
{
if(!focused) return;
+ text.processEvent(event);
if(event.type == sf::Event::TextEntered)
{
- if(event.text.unicode == 8) // backspace
- removePreviousChar();
- else if(event.text.unicode == 13) // enter
+ if(event.text.unicode == 13) // enter
{
- if(!getString().isEmpty())
+ if(!text.getString().isEmpty())
{
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Key::LShift) || sf::Keyboard::isKeyPressed(sf::Keyboard::Key::RShift))
{
- addChar('\n');
+ //addChar('\n');
}
else
{
- auto chatbarMsgUtf8 = getString().toUtf8();
+ auto chatbarMsgUtf8 = text.getString().toUtf8();
string msg;
msg.resize(chatbarMsgUtf8.size());
memcpy(&msg[0], chatbarMsgUtf8.data(), chatbarMsgUtf8.size());
@@ -270,35 +183,14 @@ namespace dchat
replaceBinds(msg);
channel->addMessage(msg);
}
- clear();
+ text.setString("");
}
}
}
- else if(event.text.unicode == 127) // delete
- {
- removeNextChar();
- }
- else if(event.text.unicode == 22) // ctrl+v
- {
- // TODO: Instead of calling external xsel, use sfml clipboard functionality (in new sfml version)
- string clipboard = getClipboard();
- addString(clipboard);
- }
- else
- {
- addChar(event.text.unicode);
- }
- }
- else if(event.type == sf::Event::KeyPressed)
- {
- if(event.key.code == sf::Keyboard::Left)
- moveCaretLeft();
- else if(event.key.code == sf::Keyboard::Right)
- moveCaretRight();
}
}
- void Chatbar::draw(sf::RenderWindow &window)
+ void Chatbar::draw(sf::RenderWindow &window, Cache &cache)
{
auto windowSize = window.getSize();
@@ -320,20 +212,10 @@ namespace dchat
inputBackground.setSize(inputBackgroundSize);
inputBackground.setPosition(inputBackgroundPos);
text.setPosition(floor(inputBackgroundPos.x + BOX_PADDING_X), floor(inputBackgroundPos.y + inputBackgroundSize.y * 0.5f - fontHeight * 0.5f));
+ text.setMaxWidth(inputBackgroundSize.x - BOX_PADDING_X * 2.0f);
window.draw(inputBackground);
- window.draw(text);
-
- int blinkElapsedTime = blinkTimer.getElapsedTime().asMilliseconds();
- if(focused && blinkElapsedTime <= BLINK_TIME_VISIBLE_MS)
- {
- sf::RectangleShape caretShape(sf::Vector2f(2.0f, inputBackgroundSize.y - BOX_PADDING_Y * Settings::getScaling() * 2.0f));
- caretShape.setPosition(floor(text.getPosition().x + caretOffset.x), floor(caretOffset.y + inputBackgroundPos.y + BOX_PADDING_Y * Settings::getScaling()));
- window.draw(caretShape);
- }
-
- if(blinkElapsedTime > BLINK_TIME_VISIBLE_MS + BLINK_TIME_INVISIBLE_MS)
- blinkTimer.restart();
+ text.draw(window, cache);
}
float Chatbar::getHeight()
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);