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 --- depends/odhtdb | 2 +- fonts/Roboto License.txt | 201 +++++++++++++++++++++++++++++++++++++++++++ fonts/Roboto-Regular.LICENSE | 201 ------------------------------------------- include/Cache.hpp | 2 + include/Channel.hpp | 3 + include/ChannelTopPanel.hpp | 13 +++ include/Settings.hpp | 1 + include/UsersSidePanel.hpp | 3 - include/Video.hpp | 1 + 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 +++++++++++-- 20 files changed, 492 insertions(+), 263 deletions(-) create mode 100644 fonts/Roboto License.txt delete mode 100644 fonts/Roboto-Regular.LICENSE create mode 100644 include/ChannelTopPanel.hpp create mode 100644 src/ChannelTopPanel.cpp diff --git a/depends/odhtdb b/depends/odhtdb index 92e22dd..c98fc5b 160000 --- a/depends/odhtdb +++ b/depends/odhtdb @@ -1 +1 @@ -Subproject commit 92e22dd7f1f918ef92a31f5526bac263ef409f18 +Subproject commit c98fc5bb0170b47e7d5d451b9ab0a9bb03171061 diff --git a/fonts/Roboto License.txt b/fonts/Roboto License.txt new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/fonts/Roboto License.txt @@ -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.LICENSE b/fonts/Roboto-Regular.LICENSE deleted file mode 100644 index 261eeb9..0000000 --- a/fonts/Roboto-Regular.LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - 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/include/Cache.hpp b/include/Cache.hpp index d78324c..429f652 100644 --- a/include/Cache.hpp +++ b/include/Cache.hpp @@ -44,6 +44,7 @@ namespace dchat { public: Cache(); + ~Cache(); // Creates directory if it doesn't exist (recursively). Throws boost exception on failure static boost::filesystem::path getDchatDir(); @@ -63,5 +64,6 @@ namespace dchat std::vector imageDownloadProcesses; std::vector imageDownloadProcessesQueue; std::mutex imageDownloadMutex; + bool alive; }; } diff --git a/include/Channel.hpp b/include/Channel.hpp index 6f5495f..31a17f4 100644 --- a/include/Channel.hpp +++ b/include/Channel.hpp @@ -34,6 +34,9 @@ namespace dchat void processEvent(const sf::Event &event); void draw(sf::RenderWindow &window, Cache &cache); + + static void setCurrent(Channel *channel); + static Channel* getCurrent(); protected: odhtdb::Database *database; odhtdb::DatabaseNode databaseNodeInfo; diff --git a/include/ChannelTopPanel.hpp b/include/ChannelTopPanel.hpp new file mode 100644 index 0000000..41fe9a2 --- /dev/null +++ b/include/ChannelTopPanel.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include + +namespace dchat +{ + class ChannelTopPanel + { + public: + static void draw(sf::RenderWindow &window); + static float getHeight(); + }; +} diff --git a/include/Settings.hpp b/include/Settings.hpp index ab757ec..1228873 100644 --- a/include/Settings.hpp +++ b/include/Settings.hpp @@ -6,5 +6,6 @@ namespace dchat { public: static float getScaling(); + static void setScaling(float scaling); }; } diff --git a/include/UsersSidePanel.hpp b/include/UsersSidePanel.hpp index b2855bb..07e790c 100644 --- a/include/UsersSidePanel.hpp +++ b/include/UsersSidePanel.hpp @@ -9,9 +9,6 @@ namespace dchat class UsersSidePanel { public: - static void setCurrentChannel(Channel *channel); - static Channel* getCurrentChannel(); - static void draw(sf::RenderWindow &window); static float getWidth(); }; diff --git a/include/Video.hpp b/include/Video.hpp index 05c8396..9d6663e 100644 --- a/include/Video.hpp +++ b/include/Video.hpp @@ -41,5 +41,6 @@ namespace dchat sf::Sprite sprite; sf::Texture texture; sf::Uint8 *textureBuffer; + bool alive; }; } 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