aboutsummaryrefslogtreecommitdiff
path: root/src/MessageBoard.cpp
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2018-04-20 01:29:54 +0200
committerdec05eba <dec05eba@protonmail.com>2018-04-20 01:31:23 +0200
commit391f7fd6d832cb40f74fb37f9e0af7ff33db202f (patch)
tree1d3e2b54dfade403da579a23029ae98f1a5c8f5b /src/MessageBoard.cpp
parentc670ad2839d886107189a5a0d0854a02aa0ace53 (diff)
Add message board, in the middle of text selection
Diffstat (limited to 'src/MessageBoard.cpp')
-rw-r--r--src/MessageBoard.cpp229
1 files changed, 229 insertions, 0 deletions
diff --git a/src/MessageBoard.cpp b/src/MessageBoard.cpp
new file mode 100644
index 0000000..2b9115a
--- /dev/null
+++ b/src/MessageBoard.cpp
@@ -0,0 +1,229 @@
+#include "../include/MessageBoard.hpp"
+#include "../include/Settings.hpp"
+#include "../include/ResourceCache.hpp"
+#include <SFML/Graphics/RectangleShape.hpp>
+#include <SFML/Graphics/Sprite.hpp>
+#include <SFML/Window/Mouse.hpp>
+#include <SFML/Graphics/Rect.hpp>
+#include <cmath>
+
+using namespace std;
+
+namespace dchat
+{
+ const sf::Color BACKGROUND_COLOR(40, 40, 40);
+ const float USERNAME_PADDING_BOTTOM = 5.0f;
+ const float MESSAGE_PADDING_BOTTOM = 20.0f;
+
+ MessageBoard::MessageBoard(const sf::Vector2u &size) :
+ selectingText(false),
+ leftMouseButtonPressed(false)
+ {
+ updateStaticContentTexture(size);
+ }
+
+ MessageBoard::~MessageBoard()
+ {
+ for(Message *message : messages)
+ {
+ delete message;
+ }
+ }
+
+ void MessageBoard::updateStaticContentTexture(const sf::Vector2u &newSize)
+ {
+ useStaticContentTexture = staticContentTexture.create(newSize.x, newSize.y);
+ dirty = true;
+ }
+
+ void MessageBoard::addMessage(Message *message)
+ {
+ messages.push_back(message);
+ dirty = true;
+ }
+
+ void MessageBoard::processEvent(const sf::Event &event)
+ {
+ if(event.type == sf::Event::MouseButtonPressed)
+ {
+ if(event.mouseButton.button == sf::Mouse::Button::Left)
+ {
+ leftMouseButtonPressed = true;
+ mousePos.x = event.mouseButton.x;
+ mousePos.y = event.mouseButton.y;
+ }
+ }
+ else if(event.type == sf::Event::MouseButtonReleased)
+ {
+ if(event.mouseButton.button == sf::Mouse::Button::Left)
+ {
+ leftMouseButtonPressed = false;
+ mousePos.x = event.mouseButton.x;
+ mousePos.y = event.mouseButton.y;
+ }
+ }
+ else if(event.type == sf::Event::LostFocus)
+ {
+ leftMouseButtonPressed = false;
+ }
+ else if(event.type == sf::Event::MouseMoved)
+ {
+ mousePos.x = event.mouseMove.x;
+ mousePos.y = event.mouseMove.y;
+ }
+
+ if(selectingText && !leftMouseButtonPressed)
+ {
+ selectingText = false;
+ }
+ else if(!selectingText && leftMouseButtonPressed)
+ {
+ selectingText = true;
+ selectingTextStart.x = mousePos.x;
+ selectingTextStart.y = mousePos.y;
+ }
+ }
+
+ void MessageBoard::draw(sf::RenderWindow &window)
+ {
+ sf::RenderTarget *renderTarget = nullptr;
+ if(useStaticContentTexture)
+ {
+ renderTarget = &staticContentTexture;
+ if(window.getSize() != staticContentTexture.getSize())
+ updateStaticContentTexture(window.getSize());
+ }
+ else
+ {
+ renderTarget = &window;
+ dirty = true;
+ }
+
+ if(dirty)
+ {
+ dirty = false;
+ auto renderTargetSize = renderTarget->getSize();
+
+ if(useStaticContentTexture)
+ staticContentTexture.clear(BACKGROUND_COLOR);
+ else
+ {
+ sf::RectangleShape background(sf::Vector2f(renderTargetSize.x, renderTargetSize.y));
+ background.setFillColor(BACKGROUND_COLOR);
+ renderTarget->draw(background);
+ }
+
+ const sf::Font &usernameFont = ResourceCache::getFont("fonts/Roboto-Regular.ttf");
+
+ sf::Vector2f position;
+ for(Message *message : messages)
+ {
+ sf::Text usernameText(message->user->getName(), usernameFont, MessagePartText::getFontSizeScaled() * 1.3f);
+ usernameText.setFillColor(sf::Color(15, 192, 252));
+ usernameText.setPosition(position);
+ renderTarget->draw(usernameText);
+ position.y += usernameText.getCharacterSize() + USERNAME_PADDING_BOTTOM;
+
+ for(MessagePart *messagePart : message->getParts())
+ {
+ switch(messagePart->type)
+ {
+ case MessagePart::Type::TEXT:
+ {
+ MessagePartText *messagePartText = static_cast<MessagePartText*>(messagePart);
+ messagePartText->text.setFillColor(sf::Color(240, 240, 240));
+ messagePartText->text.setCharacterSize(MessagePartText::getFontSizeScaled());
+ messagePartText->text.setPosition(floor(position.x), floor(position.y + MessagePart::getSizeScaled() * 0.5f - MessagePartText::getFontSizeScaled() * 0.5f));
+ renderTarget->draw(messagePartText->text);
+ position.x += messagePartText->text.getLocalBounds().width;
+ break;
+ }
+ }
+ }
+ position.x = 0.0f;
+ position.y += MessagePart::getSizeScaled() + MESSAGE_PADDING_BOTTOM;
+ }
+
+ if(useStaticContentTexture)
+ staticContentTexture.display();
+ }
+
+ if(useStaticContentTexture)
+ window.draw(sf::Sprite(staticContentTexture.getTexture()));
+
+ if(!selectingText) return;
+
+ sf::Vector2f selectionRectStart(min((float)mousePos.x, selectingTextStart.x), min((float)mousePos.y, selectingTextStart.y));
+ sf::Vector2f selectionRectEnd(max((float)mousePos.x, selectingTextStart.x), max((float)mousePos.y, selectingTextStart.y));
+ sf::FloatRect selectionRect(selectionRectStart, selectionRectEnd - selectionRectStart);
+
+ for(Message *message : messages)
+ {
+ float messagePartStartX = -999.0f;
+ float messagePartEndX = 0.0f;
+ float messagePartX = 0.0f;
+ float messagePartStartY = 0.0f;
+
+ for(MessagePart *messagePart : message->getParts())
+ {
+ sf::Vector2f position = messagePart->getPosition();
+ sf::Vector2f size = messagePart->getSize();
+ sf::FloatRect messagePartRect(position, size);
+ if(!selectionRect.intersects(messagePartRect)) continue;
+
+ switch(messagePart->type)
+ {
+ case MessagePart::Type::TEXT:
+ {
+ MessagePartText *messagePartText = static_cast<MessagePartText*>(messagePart);
+ messagePartStartY = position.y;
+ sf::Uint32 prevCodePoint = -1;
+ for(int i = 0; i < messagePartText->text.getString().getSize(); ++i)
+ {
+ sf::Uint32 codePoint = messagePartText->text.getString()[i];
+ const sf::Glyph &glyph = messagePartText->text.getFont()->getGlyph(codePoint, messagePartText->text.getCharacterSize(), false);
+ float glyphWidth = glyph.advance;
+ if(prevCodePoint != -1)
+ glyphWidth += messagePartText->text.getFont()->getKerning(prevCodePoint, codePoint, messagePartText->text.getCharacterSize());
+
+ if(selectionRect.left < messagePartX + glyph.advance * 0.5f)
+ {
+ if(messagePartStartX < 0.0f)
+ {
+ messagePartStartX = messagePartX;
+ if(mousePos.y > messagePartStartY + MessagePart::getSizeScaled())
+ {
+ messagePartEndX = position.x + size.x;
+ goto nextMessagePart;
+ }
+ }
+ }
+
+ if(selectionRect.left + selectionRect.width > messagePartX + glyph.advance * 0.5f)
+ {
+ messagePartEndX = messagePartX + glyphWidth;
+ }
+ else
+ break;
+
+ messagePartX += glyphWidth;
+ prevCodePoint = codePoint;
+ }
+ break;
+ }
+ }
+
+ nextMessagePart:
+ ;
+ }
+
+ if(messagePartStartX >= 0.0f)
+ {
+ sf::RectangleShape selectionShape(sf::Vector2f(floor(messagePartEndX - messagePartStartX), floor(MessagePart::getSizeScaled())));
+ selectionShape.setPosition(messagePartStartX, messagePartStartY);
+ selectionShape.setFillColor(sf::Color(100, 100, 255, 100));
+ window.draw(selectionShape);
+ }
+ }
+ }
+}