diff options
author | dec05eba <dec05eba@protonmail.com> | 2018-04-20 01:29:54 +0200 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2018-04-20 01:31:23 +0200 |
commit | 391f7fd6d832cb40f74fb37f9e0af7ff33db202f (patch) | |
tree | 1d3e2b54dfade403da579a23029ae98f1a5c8f5b /src/MessageBoard.cpp | |
parent | c670ad2839d886107189a5a0d0854a02aa0ace53 (diff) |
Add message board, in the middle of text selection
Diffstat (limited to 'src/MessageBoard.cpp')
-rw-r--r-- | src/MessageBoard.cpp | 229 |
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); + } + } + } +} |