From 391f7fd6d832cb40f74fb37f9e0af7ff33db202f Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 20 Apr 2018 01:29:54 +0200 Subject: Add message board, in the middle of text selection --- .gitignore | 1 + .gitmodules | 3 + .kdev4/dchat.kdev4 | 5 + README.md | 2 +- dchat.kdev4 | 4 + depends/odhtdb | 1 + fonts/Roboto-Regular.LICENSE | 201 +++++++++++++++++++++++++++++++++++++ fonts/Roboto-Regular.ttf | Bin 0 -> 171676 bytes include/Message.hpp | 23 +++++ include/MessageBoard.hpp | 32 ++++++ include/MessagePart.hpp | 38 +++++++ include/ResourceCache.hpp | 13 +++ include/Settings.hpp | 10 ++ include/User.hpp | 22 +++++ project.conf | 11 +++ src/Message.cpp | 30 ++++++ src/MessageBoard.cpp | 229 +++++++++++++++++++++++++++++++++++++++++++ src/MessagePart.cpp | 37 +++++++ src/ResourceCache.cpp | 29 ++++++ src/Settings.cpp | 19 ++++ src/User.cpp | 15 +++ src/main.cpp | 56 +++++++++++ 22 files changed, 780 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 .kdev4/dchat.kdev4 create mode 100644 dchat.kdev4 create mode 160000 depends/odhtdb create mode 100644 fonts/Roboto-Regular.LICENSE create mode 100644 fonts/Roboto-Regular.ttf create mode 100644 include/Message.hpp create mode 100644 include/MessageBoard.hpp create mode 100644 include/MessagePart.hpp create mode 100644 include/ResourceCache.hpp create mode 100644 include/Settings.hpp create mode 100644 include/User.hpp create mode 100644 project.conf create mode 100644 src/Message.cpp create mode 100644 src/MessageBoard.cpp create mode 100644 src/MessagePart.cpp create mode 100644 src/ResourceCache.cpp create mode 100644 src/Settings.cpp create mode 100644 src/User.cpp create mode 100644 src/main.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..97420ef --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +sibs-build/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..39ba254 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "depends/odhtdb"] + path = depends/odhtdb + url = git@github.com:DEC05EBA/odhtdb.git diff --git a/.kdev4/dchat.kdev4 b/.kdev4/dchat.kdev4 new file mode 100644 index 0000000..4709f83 --- /dev/null +++ b/.kdev4/dchat.kdev4 @@ -0,0 +1,5 @@ +[Buildset] +BuildItems=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x01\x00\x00\x00\n\x00d\x00c\x00h\x00a\x00t) + +[Project] +VersionControlSupport=kdevgit diff --git a/README.md b/README.md index 839e00a..eaf2658 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ -# dchat +# DcHaT Decentralized chat using odhtdb diff --git a/dchat.kdev4 b/dchat.kdev4 new file mode 100644 index 0000000..21e71cc --- /dev/null +++ b/dchat.kdev4 @@ -0,0 +1,4 @@ +[Project] +CreatedFrom= +Manager=KDevCustomBuildSystem +Name=dchat diff --git a/depends/odhtdb b/depends/odhtdb new file mode 160000 index 0000000..6e4d46f --- /dev/null +++ b/depends/odhtdb @@ -0,0 +1 @@ +Subproject commit 6e4d46f8cf911b82a10e8cd25b65fcc421bbc712 diff --git a/fonts/Roboto-Regular.LICENSE b/fonts/Roboto-Regular.LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/fonts/Roboto-Regular.LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/fonts/Roboto-Regular.ttf b/fonts/Roboto-Regular.ttf new file mode 100644 index 0000000..2c97eea Binary files /dev/null and b/fonts/Roboto-Regular.ttf differ diff --git a/include/Message.hpp b/include/Message.hpp new file mode 100644 index 0000000..c037eb3 --- /dev/null +++ b/include/Message.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "MessagePart.hpp" +#include "User.hpp" +#include +#include + +namespace dchat +{ + class Message + { + public: + Message(User *user); + virtual ~Message(); + + void addText(const std::string &text); + std::vector& getParts(); + + const User *user; + private: + std::vector messageParts; + }; +} diff --git a/include/MessageBoard.hpp b/include/MessageBoard.hpp new file mode 100644 index 0000000..f399761 --- /dev/null +++ b/include/MessageBoard.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include "Message.hpp" +#include +#include +#include +#include + +namespace dchat +{ + class MessageBoard + { + public: + MessageBoard(const sf::Vector2u &size); + ~MessageBoard(); + + void updateStaticContentTexture(const sf::Vector2u &newSize); + void addMessage(Message *message); + + void processEvent(const sf::Event &event); + void draw(sf::RenderWindow &window); + private: + sf::RenderTexture staticContentTexture; + bool useStaticContentTexture; + bool dirty; + bool selectingText; + bool leftMouseButtonPressed; + sf::Vector2f mousePos; + sf::Vector2f selectingTextStart; + std::vector messages; + }; +} diff --git a/include/MessagePart.hpp b/include/MessagePart.hpp new file mode 100644 index 0000000..e50852a --- /dev/null +++ b/include/MessagePart.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include + +namespace dchat +{ + class MessagePart + { + public: + enum class Type + { + TEXT + }; + + MessagePart(Type _type) : type(_type) {} + virtual ~MessagePart(){} + + static float getSizeScaled(); + virtual sf::Vector2f getPosition() const = 0; + virtual sf::Vector2f getSize() const = 0; + + const Type type; + }; + + class MessagePartText : public MessagePart + { + public: + MessagePartText(const std::string &text); + + static float getFontSizeScaled(); + virtual sf::Vector2f getPosition() const override; + virtual sf::Vector2f getSize() const override; + + sf::Text text; + }; +} diff --git a/include/ResourceCache.hpp b/include/ResourceCache.hpp new file mode 100644 index 0000000..d35eb8f --- /dev/null +++ b/include/ResourceCache.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include +#include + +namespace dchat +{ + class ResourceCache + { + public: + static const sf::Font& getFont(const std::string &filepath); + }; +} diff --git a/include/Settings.hpp b/include/Settings.hpp new file mode 100644 index 0000000..ab757ec --- /dev/null +++ b/include/Settings.hpp @@ -0,0 +1,10 @@ +#pragma once + +namespace dchat +{ + class Settings + { + public: + static float getScaling(); + }; +} diff --git a/include/User.hpp b/include/User.hpp new file mode 100644 index 0000000..2a8f46b --- /dev/null +++ b/include/User.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include + +namespace dchat +{ + class User + { + public: + virtual ~User(){} + virtual const std::string& getName() const = 0; + }; + + class OfflineUser : public User + { + public: + OfflineUser(const std::string &name); + virtual const std::string& getName() const override; + + std::string name; + }; +} diff --git a/project.conf b/project.conf new file mode 100644 index 0000000..58369b9 --- /dev/null +++ b/project.conf @@ -0,0 +1,11 @@ +[package] +name = "dchat" +version = "0.1.0" +type = "executable" +platforms = ["linux32", "linux64"] + +[dependencies] +sfml-window = "2.4.2" +sfml-graphics = "2.4.2" +sfml-system = "2.4.2" +boost-filesystem = "1.66.0" diff --git a/src/Message.cpp b/src/Message.cpp new file mode 100644 index 0000000..44174ec --- /dev/null +++ b/src/Message.cpp @@ -0,0 +1,30 @@ +#include "../include/Message.hpp" + +using namespace std; + +namespace dchat +{ + Message::Message(User *_user) : + user(_user) + { + + } + + Message::~Message() + { + for(MessagePart *messagePart : messageParts) + { + delete messagePart; + } + } + + void Message::addText(const string &text) + { + messageParts.push_back(new MessagePartText(text)); + } + + vector& Message::getParts() + { + return messageParts; + } +} 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 +#include +#include +#include +#include + +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(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(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); + } + } + } +} diff --git a/src/MessagePart.cpp b/src/MessagePart.cpp new file mode 100644 index 0000000..47c96bd --- /dev/null +++ b/src/MessagePart.cpp @@ -0,0 +1,37 @@ +#include "../include/MessagePart.hpp" +#include "../include/ResourceCache.hpp" +#include "../include/Settings.hpp" + +using namespace std; + +namespace dchat +{ + const float MESSAGE_PART_SIZE = 27; + + float MessagePart::getSizeScaled() + { + return MESSAGE_PART_SIZE * Settings::getScaling(); + } + + MessagePartText::MessagePartText(const string &_text) : + MessagePart(Type::TEXT), + text(_text, ResourceCache::getFont("fonts/Roboto-Regular.ttf"), MessagePartText::getFontSizeScaled()) + { + + } + + float MessagePartText::getFontSizeScaled() + { + return MessagePart::getSizeScaled() * 0.8f; + } + + sf::Vector2f MessagePartText::getPosition() const + { + return text.getPosition(); + } + + sf::Vector2f MessagePartText::getSize() const + { + return sf::Vector2f(text.getLocalBounds().width, getFontSizeScaled()); + } +} diff --git a/src/ResourceCache.cpp b/src/ResourceCache.cpp new file mode 100644 index 0000000..474360c --- /dev/null +++ b/src/ResourceCache.cpp @@ -0,0 +1,29 @@ +#include "../include/ResourceCache.hpp" +#include +#include + +using namespace std; + +namespace dchat +{ + unordered_map fonts; + + const sf::Font& ResourceCache::getFont(const string &filepath) + { + auto it = fonts.find(filepath); + if(it != fonts.end()) + return *it->second; + + sf::Font *font = new sf::Font(); + if(!font->loadFromFile(filepath)) + { + delete font; + string errMsg = "Failed to load font: "; + errMsg += filepath; + throw runtime_error(errMsg); + } + + fonts[filepath] = font; + return *font; + } +} diff --git a/src/Settings.cpp b/src/Settings.cpp new file mode 100644 index 0000000..93f230c --- /dev/null +++ b/src/Settings.cpp @@ -0,0 +1,19 @@ +#include "../include/Settings.hpp" + +namespace dchat +{ + float Settings::getScaling() + { + // TODO: Load scaling from settings file + /* + CLUTTER_SCALE + GDK_SCALE + GDK_DPI_SCALE + QT_AUTO_SCREEN_SCALE_FACTOR + QT_SCALE_FACTOR + QT_SCREEN_SCALE_FACTORS + QT_DEVICE_PIXEL_RATIO + */ + return 1.0f; + } +} diff --git a/src/User.cpp b/src/User.cpp new file mode 100644 index 0000000..6b07b5b --- /dev/null +++ b/src/User.cpp @@ -0,0 +1,15 @@ +#include "../include/User.hpp" + +namespace dchat +{ + OfflineUser::OfflineUser(const std::string &_name) : + name(_name) + { + + } + + const std::string& OfflineUser::getName() const + { + return name; + } +} diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..85f1075 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,56 @@ +#include +#include "../include/MessageBoard.hpp" +#include "../include/User.hpp" + +using namespace dchat; + +int main() +{ + sf::RenderWindow window(sf::VideoMode(1920, 1080), "dchat"); + window.setVerticalSyncEnabled(false); + window.setFramerateLimit(60); + + OfflineUser *localOfflineUser = new OfflineUser("You"); + + MessageBoard messageBoard(window.getSize()); + + { + Message *message = new Message(localOfflineUser); + message->addText(u8"hello, world!"); + messageBoard.addMessage(message); + } + + { + Message *message = new Message(localOfflineUser); + message->addText(u8"hello, world!"); + messageBoard.addMessage(message); + } + + { + Message *message = new Message(localOfflineUser); + message->addText(u8"hello, world!"); + messageBoard.addMessage(message); + } + + while (window.isOpen()) + { + sf::Event event; + while (window.pollEvent(event)) + { + if (event.type == sf::Event::Closed) + window.close(); + else if(event.type == sf::Event::Resized) + { + sf::View view(sf::FloatRect(0.0f, 0.0f, event.size.width, event.size.height)); + window.setView(view); + } + messageBoard.processEvent(event); + } + + window.clear(); + messageBoard.draw(window); + window.display(); + } + + return 0; +} -- cgit v1.2.3