From f90a5705bd65a4ebb5edc9df003a383039fec555 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 29 Apr 2018 08:17:30 +0200 Subject: Change design, fix crash when closing application --- src/Cache.cpp | 14 +++++-- src/Channel.cpp | 16 ++++++-- src/ChannelSidePanel.cpp | 34 +++++++++++++---- src/ChannelTopPanel.cpp | 97 ++++++++++++++++++++++++++++++++++++++++++++++++ src/Message.cpp | 2 +- src/MessageBoard.cpp | 52 ++++++++++++++++++++++---- src/Settings.cpp | 9 ++++- src/Text.cpp | 2 +- src/UsersSidePanel.cpp | 29 ++++++--------- src/Video.cpp | 13 ++++--- src/main.cpp | 60 ++++++++++++++++++++++++++---- 11 files changed, 270 insertions(+), 58 deletions(-) create mode 100644 src/ChannelTopPanel.cpp (limited to 'src') diff --git a/src/Cache.cpp b/src/Cache.cpp index bfa3df4..d402d36 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp @@ -95,11 +95,12 @@ namespace dchat return { (sf::Texture*)nullptr, ImageByUrlResult::Type::FAILED_DOWNLOAD }; } - Cache::Cache() + Cache::Cache() : + alive(true) { downloadWaitThread = thread([this] { - while(true) + while(alive) { for(vector::iterator it = imageDownloadProcesses.begin(); it != imageDownloadProcesses.end();) { @@ -133,7 +134,7 @@ namespace dchat ++it; } - while(imageDownloadProcesses.empty() && imageDownloadProcessesQueue.empty()) + while(alive && imageDownloadProcesses.empty() && imageDownloadProcessesQueue.empty()) this_thread::sleep_for(chrono::milliseconds(20)); if(!imageDownloadProcessesQueue.empty()) @@ -150,7 +151,12 @@ namespace dchat this_thread::sleep_for(chrono::milliseconds(20)); } }); - downloadWaitThread.detach(); + } + + Cache::~Cache() + { + alive = false; + downloadWaitThread.join(); } const ImageByUrlResult Cache::getImageByUrl(const string &url, int downloadLimitBytes) diff --git a/src/Channel.cpp b/src/Channel.cpp index ef252f6..4fa99a0 100644 --- a/src/Channel.cpp +++ b/src/Channel.cpp @@ -1,6 +1,4 @@ #include "../include/Channel.hpp" -#include "../include/UsersSidePanel.hpp" -#include "../include/ChannelSidePanel.hpp" #include #include #include @@ -9,6 +7,8 @@ using namespace std; namespace dchat { + static Channel *currentChannel; + Channel::Channel(const string &_name, const odhtdb::DatabaseNode &_databaseNodeInfo, User *_localUser, odhtdb::Database *_database) : database(_database), databaseNodeInfo(_databaseNodeInfo), @@ -131,9 +131,17 @@ namespace dchat void Channel::draw(sf::RenderWindow &window, Cache &cache) { - ChannelSidePanel::draw(window); messageBoard.draw(window, cache); chatbar.draw(window); - UsersSidePanel::draw(window); + } + + void Channel::setCurrent(Channel *channel) + { + currentChannel = channel; + } + + Channel* Channel::getCurrent() + { + return currentChannel; } } diff --git a/src/ChannelSidePanel.cpp b/src/ChannelSidePanel.cpp index f5a4063..18b581c 100644 --- a/src/ChannelSidePanel.cpp +++ b/src/ChannelSidePanel.cpp @@ -1,4 +1,5 @@ #include "../include/ChannelSidePanel.hpp" +#include "../include/ChannelTopPanel.hpp" #include "../include/ResourceCache.hpp" #include "../include/Settings.hpp" #include "../include/Channel.hpp" @@ -12,8 +13,10 @@ using namespace std; namespace dchat { vector channels; - const float width = 200.0f; + const float WIDTH = 200.0f; const unsigned int FONT_SIZE = 20; + const float PADDING_BOTTOM = 10.0f; + const float CHANNEL_NAME_BOX_HEIGHT_RATIO = 1.5f; void ChannelSidePanel::addChannel(Channel *channel) { @@ -27,27 +30,42 @@ namespace dchat void ChannelSidePanel::draw(sf::RenderWindow &window) { + float posY = ChannelTopPanel::getHeight(); auto windowSize = window.getSize(); - sf::RectangleShape rect(sf::Vector2f(width, windowSize.y)); - rect.setFillColor(sf::Color(30, 30, 30)); + sf::RectangleShape rect(sf::Vector2f(WIDTH, windowSize.y)); + rect.setPosition(0.0f, posY); + rect.setFillColor(sf::Color(35, 35, 35)); window.draw(rect); + //posY += 10.0f; const sf::Font *font = ResourceCache::getFont("fonts/Roboto-Regular.ttf"); - sf::Vector2f position(10.0f, 10.0f); + const float fontSize = FONT_SIZE * Settings::getScaling(); + const float fontHeight = font->getLineSpacing(fontSize); + const float channelBoxHeight = floor(fontHeight * CHANNEL_NAME_BOX_HEIGHT_RATIO); + + sf::Vector2f position(10.0f, posY); for(Channel *channel : channels) { + if(channel == Channel::getCurrent()) + { + rect.setFillColor(sf::Color(50, 50, 50)); + rect.setSize(sf::Vector2f(WIDTH, channelBoxHeight)); + rect.setPosition(sf::Vector2f(0.0f, position.y)); + window.draw(rect); + } + // TODO: Remove this shit sf::String str = "# "; str += sf::String::fromUtf8(channel->getName().begin(), channel->getName().end()); - sf::Text text(str, *font, FONT_SIZE * Settings::getScaling()); - text.setPosition(position); + sf::Text text(str, *font, fontSize); + text.setPosition(sf::Vector2f(position.x, floor(position.y + channelBoxHeight * 0.5f - fontHeight * 0.5f))); window.draw(text); - position.y += font->getLineSpacing(FONT_SIZE * Settings::getScaling()); + position.y += floor(fontHeight + PADDING_BOTTOM); } } float ChannelSidePanel::getWidth() { - return width; + return WIDTH; } } diff --git a/src/ChannelTopPanel.cpp b/src/ChannelTopPanel.cpp new file mode 100644 index 0000000..534f989 --- /dev/null +++ b/src/ChannelTopPanel.cpp @@ -0,0 +1,97 @@ +#include "../include/ChannelTopPanel.hpp" +#include "../include/Settings.hpp" +#include "../include/ResourceCache.hpp" +#include "../include/Channel.hpp" +#include +#include + +namespace dchat +{ + struct LineColor + { + sf::Color sideColor, centerColor; + }; + + const float FONT_SIZE = 40.0f; + const float BOTTOM_LINE_HEIGHT = 2.0f; + const float PADDING_TOP = 20.0f; + const float PADDING_BOTTOM = PADDING_TOP; + const sf::Font *FONT = ResourceCache::getFont("fonts/Roboto-Regular.ttf"); + + static void drawGradientLine(const sf::Vector2f &position, const sf::Vector2f &size, const LineColor &color, sf::RenderWindow &window) + { + sf::Vertex rectangle[] = + { + sf::Vertex(position, color.sideColor), + sf::Vertex(sf::Vector2f(position.x + size.x * 0.5f, position.y), color.centerColor), + sf::Vertex(sf::Vector2f(position.x + size.x * 0.5f, position.y + size.y), color.centerColor), + sf::Vertex(sf::Vector2f(position.x, position.y + size.y), color.sideColor), + + sf::Vertex(sf::Vector2f(position.x + size.x * 0.5f, position.y), color.centerColor), + sf::Vertex(sf::Vector2f(position.x + size.x, position.y), color.sideColor), + sf::Vertex(sf::Vector2f(position.x + size.x, position.y + size.y), color.sideColor), + sf::Vertex(sf::Vector2f(position.x + size.x * 0.5f, position.y + size.y), color.centerColor) + }; + window.draw(rectangle, 8, sf::Quads); + } + + void ChannelTopPanel::draw(sf::RenderWindow &window) + { + const sf::Color backgroundColor(40, 40, 40); + const sf::Color lineSideColor(40, 40, 40); + const sf::Color lineCenterColor(80, 40, 40); + + auto windowSize = window.getSize(); + sf::RectangleShape rect(sf::Vector2f(windowSize.x, getHeight() - BOTTOM_LINE_HEIGHT)); + rect.setFillColor(backgroundColor); + window.draw(rect); + + /* + rect.setFillColor(sf::Color(70, 40, 40)); + rect.setSize(sf::Vector2f(windowSize.x, BOTTOM_LINE_HEIGHT)); + rect.setPosition(0.0f, getHeight() - BOTTOM_LINE_HEIGHT); + window.draw(rect); + */ + sf::Vector2f bottomLinePos(0.0f, getHeight() - BOTTOM_LINE_HEIGHT); + sf::Vector2f bottomLineSize(windowSize.x, BOTTOM_LINE_HEIGHT); + + LineColor lineColor + { + .sideColor = lineSideColor, + .centerColor = lineCenterColor + }; + drawGradientLine(bottomLinePos, bottomLineSize, lineColor, window); + + Channel *currentChannel = Channel::getCurrent(); + if(!currentChannel) return; + + sf::String str = "# "; + str += sf::String::fromUtf8(currentChannel->getName().begin(), currentChannel->getName().end()); + float fontSize = FONT_SIZE * Settings::getScaling(); + sf::Text text(str, *FONT, fontSize); + auto textBounds = text.getLocalBounds(); + text.setPosition(floor((float)windowSize.x * 0.5f - textBounds.width * 0.5f), PADDING_TOP); + text.setFillColor(sf::Color(240, 240, 240)); + window.draw(text); + /* + const sf::Font *font = ResourceCache::getFont("fonts/Roboto-Regular.ttf"); + sf::Vector2f position(10.0f, 10.0f); + for(Channel *channel : channels) + { + // TODO: Remove this shit + sf::String str = "# "; + str += sf::String::fromUtf8(channel->getName().begin(), channel->getName().end()); + sf::Text text(str, *font, FONT_SIZE * Settings::getScaling()); + text.setPosition(position); + window.draw(text); + position.y += font->getLineSpacing(FONT_SIZE * Settings::getScaling()); + } + */ + } + + float ChannelTopPanel::getHeight() + { + float fontSize = FONT_SIZE * Settings::getScaling(); + return floor(FONT->getLineSpacing(fontSize) + PADDING_TOP + PADDING_BOTTOM); + } +} diff --git a/src/Message.cpp b/src/Message.cpp index b72eabe..2d7cb86 100644 --- a/src/Message.cpp +++ b/src/Message.cpp @@ -8,7 +8,7 @@ namespace dchat { Message::Message(User *_user, const std::string &_text) : user(_user), - text(sf::String::fromUtf8(_text.begin(), _text.end()), ResourceCache::getFont("fonts/Roboto-Regular.ttf"), 20 * Settings::getScaling(), 0.0f, false) + text(sf::String::fromUtf8(_text.begin(), _text.end()), ResourceCache::getFont("fonts/Roboto-Regular.ttf"), 18 * Settings::getScaling(), 0.0f, false) { } diff --git a/src/MessageBoard.cpp b/src/MessageBoard.cpp index a0f1e20..58d54f2 100644 --- a/src/MessageBoard.cpp +++ b/src/MessageBoard.cpp @@ -4,6 +4,7 @@ #include "../include/Gif.hpp" #include "../include/ChannelSidePanel.hpp" #include "../include/UsersSidePanel.hpp" +#include "../include/ChannelTopPanel.hpp" #include #include #include @@ -15,11 +16,43 @@ using namespace std; namespace dchat { + struct LineColor + { + sf::Color sideColor, centerColor; + }; + const sf::Color BACKGROUND_COLOR(40, 40, 40); const float USERNAME_PADDING_BOTTOM = 0.0f; - const float MESSAGE_PADDING_BOTTOM = 20.0f; + const float MESSAGE_PADDING_TOP = 25.0f; + const float MESSAGE_PADDING_BOTTOM = 30.0f; - const float PADDING_SIDE = 20.0f; + const float PADDING_SIDE = 40.0f; + const float PADDING_TOP = 5.0f; + const float LINE_SIDE_PADDING = 20.0f; + const float LINE_HEIGHT = 1.0f; + + const LineColor LINE_COLOR + { + .sideColor = sf::Color(50, 50, 50), + .centerColor = sf::Color(50, 50, 50) + }; + + static void drawGradientLine(const sf::Vector2f &position, const sf::Vector2f &size, const LineColor &color, sf::RenderWindow &window) + { + sf::Vertex rectangle[] = + { + sf::Vertex(position, color.sideColor), + sf::Vertex(sf::Vector2f(position.x + size.x * 0.5f, position.y), color.centerColor), + sf::Vertex(sf::Vector2f(position.x + size.x * 0.5f, position.y + size.y), color.centerColor), + sf::Vertex(sf::Vector2f(position.x, position.y + size.y), color.sideColor), + + sf::Vertex(sf::Vector2f(position.x + size.x * 0.5f, position.y), color.centerColor), + sf::Vertex(sf::Vector2f(position.x + size.x, position.y), color.sideColor), + sf::Vertex(sf::Vector2f(position.x + size.x, position.y + size.y), color.sideColor), + sf::Vertex(sf::Vector2f(position.x + size.x * 0.5f, position.y + size.y), color.centerColor) + }; + window.draw(rectangle, 8, sf::Quads); + } MessageBoard::MessageBoard(const sf::Vector2u &size) : selectingText(false), @@ -100,6 +133,7 @@ namespace dchat void MessageBoard::draw(sf::RenderWindow &window, Cache &cache) { auto windowSize = window.getSize(); + const float backgroundWidthWithoutPadding = floor(windowSize.x - ChannelSidePanel::getWidth() - UsersSidePanel::getWidth()); sf::Vector2u backgroundSize(floor(windowSize.x - ChannelSidePanel::getWidth() - UsersSidePanel::getWidth() - PADDING_SIDE * 2.0f), floor(windowSize.y)); //if(backgroundSize != staticContentTexture.getSize()) @@ -120,26 +154,30 @@ namespace dchat if(dirty) { - sf::Vector2f position; - position.x = ChannelSidePanel::getWidth() + PADDING_SIDE; + sf::Vector2f position(ChannelSidePanel::getWidth(), ChannelTopPanel::getHeight() + PADDING_TOP); position.y += scroll; for(Message *message : messages) { - sf::Text usernameText(message->user->getName(), *usernameFont, 24 * Settings::getScaling()); + position.y += MESSAGE_PADDING_TOP; + sf::Text usernameText(message->user->getName(), *usernameFont, 20 * Settings::getScaling()); float usernameTextHeight = usernameText.getFont()->getLineSpacing(usernameText.getCharacterSize()); if(position.y + usernameTextHeight > 0.0f && position.y < backgroundSize.y) { usernameText.setFillColor(sf::Color(15, 192, 252)); - usernameText.setPosition(sf::Vector2f(floor(position.x), floor(position.y))); + usernameText.setPosition(sf::Vector2f(floor(position.x + PADDING_SIDE), floor(position.y))); window.draw(usernameText); } position.y += usernameTextHeight + USERNAME_PADDING_BOTTOM; // No need to perform culling here, that is done in @Text draw function + message->text.setCharacterSize(18 * Settings::getScaling()); message->text.setMaxWidth(backgroundSize.x); - message->text.setPosition(sf::Vector2f(floor(position.x), floor(position.y))); + message->text.setPosition(sf::Vector2f(floor(position.x + PADDING_SIDE), floor(position.y))); message->text.draw(window, cache); position.y += message->text.getHeight() + MESSAGE_PADDING_BOTTOM; + + if(position.y + LINE_HEIGHT > 0.0f && position.y < backgroundSize.y) + drawGradientLine(sf::Vector2f(position.x + LINE_SIDE_PADDING, floor(position.y)), sf::Vector2f(backgroundWidthWithoutPadding - LINE_SIDE_PADDING * 2.0f, LINE_HEIGHT), LINE_COLOR, window); } } diff --git a/src/Settings.cpp b/src/Settings.cpp index 93f230c..79c4fda 100644 --- a/src/Settings.cpp +++ b/src/Settings.cpp @@ -2,6 +2,8 @@ namespace dchat { + float scaling = 1.0f; + float Settings::getScaling() { // TODO: Load scaling from settings file @@ -14,6 +16,11 @@ namespace dchat QT_SCREEN_SCALE_FACTORS QT_DEVICE_PIXEL_RATIO */ - return 1.0f; + return scaling; + } + + void Settings::setScaling(float _scaling) + { + scaling = _scaling; } } diff --git a/src/Text.cpp b/src/Text.cpp index c8da55c..204c16f 100644 --- a/src/Text.cpp +++ b/src/Text.cpp @@ -193,7 +193,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; + glyphPos.y += emojiSize - vspace; } else { diff --git a/src/UsersSidePanel.cpp b/src/UsersSidePanel.cpp index 766539b..74b58cf 100644 --- a/src/UsersSidePanel.cpp +++ b/src/UsersSidePanel.cpp @@ -1,4 +1,5 @@ #include "../include/UsersSidePanel.hpp" +#include "../include/ChannelTopPanel.hpp" #include "../include/ResourceCache.hpp" #include "../include/Settings.hpp" #include "../include/Channel.hpp" @@ -11,32 +12,24 @@ using namespace std; namespace dchat { - Channel *currentChannel = nullptr; - const float width = 200.0f; + const float WIDTH = 200.0f; const unsigned int FONT_SIZE = 20; - void UsersSidePanel::setCurrentChannel(Channel *channel) - { - currentChannel = channel; - } - - Channel* UsersSidePanel::getCurrentChannel() - { - return currentChannel; - } - void UsersSidePanel::draw(sf::RenderWindow &window) { + float posY = ChannelTopPanel::getHeight(); auto windowSize = window.getSize(); - sf::RectangleShape rect(sf::Vector2f(width, windowSize.y)); - rect.setFillColor(sf::Color(30, 30, 30)); - rect.setPosition(windowSize.x - width, 0.0f); + sf::RectangleShape rect(sf::Vector2f(WIDTH, windowSize.y)); + rect.setFillColor(sf::Color(35, 35, 35)); + rect.setPosition(windowSize.x - WIDTH, posY); window.draw(rect); + posY += 10.0f; + Channel *currentChannel = Channel::getCurrent(); if(!currentChannel) return; const sf::Font *font = ResourceCache::getFont("fonts/Roboto-Regular.ttf"); - sf::Vector2f position(rect.getPosition().x + 10.0f, 10.0f); + sf::Vector2f position(rect.getPosition().x + 10.0f, posY); for(User *user : currentChannel->getUsers()) { // TODO: Remove this shit @@ -44,12 +37,12 @@ namespace dchat sf::Text text(str, *font, FONT_SIZE * Settings::getScaling()); text.setPosition(position); window.draw(text); - position.y += font->getLineSpacing(FONT_SIZE * Settings::getScaling()); + position.y += floor(font->getLineSpacing(FONT_SIZE * Settings::getScaling())); } } float UsersSidePanel::getWidth() { - return width; + return WIDTH; } } diff --git a/src/Video.cpp b/src/Video.cpp index 7b6dcee..4ef3128 100644 --- a/src/Video.cpp +++ b/src/Video.cpp @@ -52,7 +52,8 @@ namespace dchat context(sf::ContextSettings(), width, height), mpv(nullptr), mpvGl(nullptr), - textureBuffer(new sf::Uint8[width * height * 4]) // 4 = red, green, blue and alpha + textureBuffer(new sf::Uint8[width * height * 4]), // 4 = red, green, blue and alpha + alive(true) { context.setActive(true); @@ -84,7 +85,7 @@ namespace dchat renderThread = thread([this, width, height]() { context.setActive(true); - while(true) + while(alive) { while(true) { @@ -92,7 +93,7 @@ namespace dchat if(mpvEvent->event_id == MPV_EVENT_NONE) break; else if(mpvEvent->event_id == MPV_EVENT_SHUTDOWN) - break; + return; } if(redrawCounter > 0) @@ -111,7 +112,6 @@ namespace dchat this_thread::sleep_for(chrono::milliseconds(10)); } }); - renderThread.detach(); const char *cmd[] = { "loadfile", file, nullptr }; mpv_command(mpv, cmd); @@ -120,6 +120,9 @@ namespace dchat Video::~Video() { + alive = false; + renderThread.join(); + lock_guard lock(renderMutex); context.setActive(true); if(mpvGl) @@ -128,8 +131,6 @@ namespace dchat delete[] textureBuffer; mpv_opengl_cb_uninit_gl(mpvGl); mpv_detach_destroy(mpv); - if(renderThread.joinable()) - renderThread.join(); } void Video::setPosition(float x, float y) diff --git a/src/main.cpp b/src/main.cpp index 61319fa..580b362 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,10 +1,12 @@ #include "../include/Channel.hpp" #include "../include/ChannelSidePanel.hpp" #include "../include/UsersSidePanel.hpp" +#include "../include/ChannelTopPanel.hpp" #include "../include/Cache.hpp" #include "../include/ResourceCache.hpp" #include "../include/Video.hpp" #include "../include/Command.hpp" +#include "../include/Settings.hpp" #include #include #include @@ -97,7 +99,7 @@ int main(int argc, char **argv) Channel offlineChannel("Offline"); ChannelSidePanel::addChannel(&offlineChannel); - UsersSidePanel::setCurrentChannel(&offlineChannel); + Channel::setCurrent(&offlineChannel); vector channels; @@ -150,7 +152,7 @@ int main(int argc, char **argv) ChannelSidePanel::addChannel(channel); channels.push_back(channel); - UsersSidePanel::setCurrentChannel(channel); + Channel::setCurrent(channel); channelAddStoredMessages(channel, nodeStorage); } @@ -224,10 +226,10 @@ int main(int argc, char **argv) Channel *channel = new Channel(args[0], databaseNode, newLocalUser, &database); ChannelSidePanel::addChannel(channel); channels.push_back(channel); - UsersSidePanel::setCurrentChannel(channel); + Channel::setCurrent(channel); }); - Command::add("jc", [¤tUserKeyPair, &database](const vector &args) + Command::add("jc", [¤tUserKeyPair, &database, &localNodeUsers](const vector &args) { if(args.size() != 1) { @@ -248,8 +250,47 @@ int main(int argc, char **argv) } odhtdb::DatabaseNode databaseNode = createDatabaseNodeFromJoinKey(args[0]); - database.seed(databaseNode); - // TODO: Continue this... + for(auto localNodeUser : localNodeUsers) + { + if(*databaseNode.getRequestHash() == localNodeUser.nodeHash) + { + fprintf(stderr, "You have already joined the channel %s\n", databaseNode.getRequestHash()->toString().c_str()); + return; + } + } +#if 0 + User *newLocalUser = new OnlineUser(localNodeUser.localUser); + odhtdb::DatabaseNode databaseNode(nodeDecryptionKeyResult.second, make_shared(localNodeUser.nodeHash)); + Channel *channel = new Channel(nodeStorage->nodeName, databaseNode, newLocalUser, &database); + + auto nodeUserMapByPublicKey = database.getStorage().getNodeUsers(localNodeUser.nodeHash); + for(auto nodeUserIt : *nodeUserMapByPublicKey) + { + if(nodeUserIt.second != localNodeUser.localUser) + { + User *newRemoteUser = new OnlineUser(nodeUserIt.second); + channel->addUser(newRemoteUser); + } + } + + ChannelSidePanel::addChannel(channel); + channels.push_back(channel); + Channel::setCurrent(channel); + channelAddStoredMessages(channel, nodeStorage); +#endif + }); + + Command::add("scaling", [](const vector &args) + { + if(args.size() != 1) + { + fprintf(stderr, "Expected 1 argument for command scaling, got %u argument(s)\n", args.size()); + return; + } + + float scaling = stof(args[0]); + Settings::setScaling(scaling); + printf("UI scaling set to %f\n", scaling); }); sf::Event event; @@ -272,11 +313,14 @@ int main(int argc, char **argv) sf::View view(viewRect); window.setView(view); } - UsersSidePanel::getCurrentChannel()->processEvent(event); + Channel::getCurrent()->processEvent(event); } window.clear(sf::Color(40, 40, 40)); - UsersSidePanel::getCurrentChannel()->draw(window, cache); + ChannelSidePanel::draw(window); + Channel::getCurrent()->draw(window, cache); + UsersSidePanel::draw(window); + ChannelTopPanel::draw(window); //video.draw(window); window.display(); } -- cgit v1.2.3