diff options
author | dec05eba <dec05eba@protonmail.com> | 2018-05-08 18:06:43 +0200 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2018-05-08 18:06:51 +0200 |
commit | 15c4434de0c2cd12e09c2f41e898c0b124194a97 (patch) | |
tree | 0bf01cd49a22b7aa79304ed0e9d34ac265d8393c | |
parent | 4f6c843523f45708d8bbed25b3677f69c4208a38 (diff) |
Add context menu, add context menu to delete message
-rw-r--r-- | .gitignore | 1 | ||||
m--------- | depends/odhtdb | 0 | ||||
-rw-r--r-- | include/Channel.hpp | 9 | ||||
-rw-r--r-- | include/ColorScheme.hpp | 4 | ||||
-rw-r--r-- | include/ContextMenu.hpp | 45 | ||||
-rw-r--r-- | include/GlobalContextMenu.hpp | 19 | ||||
-rw-r--r-- | include/Message.hpp | 7 | ||||
-rw-r--r-- | include/MessageBoard.hpp | 15 | ||||
-rw-r--r-- | include/Text.hpp | 3 | ||||
-rw-r--r-- | src/Channel.cpp | 42 | ||||
-rw-r--r-- | src/ColorScheme.cpp | 7 | ||||
-rw-r--r-- | src/ContextMenu.cpp | 128 | ||||
-rw-r--r-- | src/GlobalContextMenu.cpp | 42 | ||||
-rw-r--r-- | src/Message.cpp | 3 | ||||
-rw-r--r-- | src/MessageBoard.cpp | 98 | ||||
-rw-r--r-- | src/Text.cpp | 10 | ||||
-rw-r--r-- | src/main.cpp | 21 |
17 files changed, 383 insertions, 71 deletions
@@ -1,2 +1,3 @@ sibs-build/ dchat.kdev4/ +.gdb_history diff --git a/depends/odhtdb b/depends/odhtdb -Subproject f3b18e0309ca2dbb997908583f1d44d13d9fc83 +Subproject e3b6538c17884b5985a78e3d7c507d02b7af2e7 diff --git a/include/Channel.hpp b/include/Channel.hpp index 1acfcd1..7d4cb08 100644 --- a/include/Channel.hpp +++ b/include/Channel.hpp @@ -9,6 +9,7 @@ #include <odhtdb/DatabaseNode.hpp> #include <odhtdb/Signature.hpp> #include <odhtdb/Group.hpp> +#include <odhtdb/Hash.hpp> namespace odhtdb { @@ -19,7 +20,9 @@ namespace dchat { enum class ChannelDataType : u8 { - MESSAGE, + ADD_MESSAGE, + EDIT_MESSAGE, + DELETE_MESSAGE, NICKNAME_CHANGE }; @@ -42,7 +45,11 @@ namespace dchat // If timestamp is 0, then current time is used void addLocalMessage(const std::string &msg, User *owner, u64 timestampSeconds = 0); + void addLocalMessage(const std::string &msg, User *owner, u64 timestampSeconds, const odhtdb::Hash &id); void addMessage(const std::string &msg); + void deleteLocalMessage(const odhtdb::Hash &id); + void deleteMessage(const odhtdb::Hash &id); + void addUserLocally(User *user); bool addUser(const odhtdb::Signature::PublicKey &userId, const std::string &groupId); void replaceLocalUser(User *newLocalUser); diff --git a/include/ColorScheme.hpp b/include/ColorScheme.hpp index 64dbeec..93aa640 100644 --- a/include/ColorScheme.hpp +++ b/include/ColorScheme.hpp @@ -19,5 +19,9 @@ namespace dchat static sf::Color getBackgroundColor(); static sf::Color getPanelColor(); static sf::Color getTextRegularColor(); + + static sf::Color getContextMenuBackgroundColor(); + static sf::Color getContextMenuTextColor(); + static sf::Color getContextMenuSelectedItemBackgroundColor(); }; } diff --git a/include/ContextMenu.hpp b/include/ContextMenu.hpp new file mode 100644 index 0000000..1e08d7d --- /dev/null +++ b/include/ContextMenu.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include "types.hpp" +#include <string> +#include <vector> +#include <SFML/Window/Event.hpp> +#include <SFML/Graphics/Text.hpp> +#include <SFML/Graphics/RenderWindow.hpp> +#include <functional> + +namespace dchat +{ + class ContextMenuItem; + using MenuItemClickCallbackFunc = std::function<void(ContextMenuItem *menuItem)>; + + class ContextMenuItem + { + public: + ContextMenuItem(const std::string &text, MenuItemClickCallbackFunc clickCallbackFunc); + + sf::Text text; + MenuItemClickCallbackFunc clickCallbackFunc; + }; + + class ContextMenu + { + public: + ContextMenu(); + + void addItem(const ContextMenuItem &item); + void setPosition(const sf::Vector2f &position); + void setVisible(bool visible); + + ContextMenuItem& getItemByIndex(usize index); + + void processEvent(const sf::Event &event); + void draw(sf::RenderWindow &window); + private: + std::vector<ContextMenuItem> menuItems; + sf::Vector2f position; + int focusedItem; + int pressedItem; + bool visible; + }; +} diff --git a/include/GlobalContextMenu.hpp b/include/GlobalContextMenu.hpp new file mode 100644 index 0000000..ab45e50 --- /dev/null +++ b/include/GlobalContextMenu.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "ContextMenu.hpp" +#include <SFML/Window/Event.hpp> +#include <SFML/Graphics/RenderWindow.hpp> + +namespace dchat +{ + class GlobalContextMenu + { + public: + static ContextMenu* getEditMessageContextMenu(); + static void setClickEditMessageCallbackFunc(MenuItemClickCallbackFunc callbackFunc); + static void setClickDeleteMessageCallbackFunc(MenuItemClickCallbackFunc callbackFunc); + + static void processEvent(const sf::Event &event); + static void draw(sf::RenderWindow &window); + }; +} diff --git a/include/Message.hpp b/include/Message.hpp index 2e52603..8c7f57a 100644 --- a/include/Message.hpp +++ b/include/Message.hpp @@ -10,11 +10,18 @@ namespace dchat class Message { public: + enum class Type + { + REGULAR, + EDITED + }; + // If timestamp is 0, then timestamp is not used Message(User *user, const std::string &text, u64 timestampSeconds = 0); const User *user; Text text; const u64 timestampSeconds; + Type type; }; } diff --git a/include/MessageBoard.hpp b/include/MessageBoard.hpp index a4dc5a6..a6867d2 100644 --- a/include/MessageBoard.hpp +++ b/include/MessageBoard.hpp @@ -6,7 +6,9 @@ #include <SFML/Graphics/RenderTexture.hpp> #include <SFML/Graphics/RenderWindow.hpp> #include <SFML/Window/Event.hpp> +#include <odhtdb/Hash.hpp> #include <stdexcept> +#include <mutex> namespace dchat { @@ -16,25 +18,23 @@ namespace dchat { friend class Channel; public: - MessageBoard(const sf::Vector2u &size); + MessageBoard(Channel *channel); ~MessageBoard(); void processEvent(const sf::Event &event); void draw(sf::RenderWindow &window, Cache &cache); private: void updateStaticContentTexture(const sf::Vector2u &newSize); - void addMessage(Message *message); + void addMessage(Message *message, const odhtdb::Hash &id); + void deleteMessage(const odhtdb::Hash &id); void drawDefault(sf::RenderWindow &window, Cache &cache); void drawSimple(sf::RenderWindow &window, Cache &cache); private: - sf::RenderTexture staticContentTexture; + Channel *channel; bool dirty; - bool selectingText; - bool leftMouseButtonPressed; - sf::Vector2f mousePos; - sf::Vector2f selectingTextStart; std::vector<Message*> messages; + odhtdb::MapHash<Message*> messageIdMap; double scroll; double scrollSpeed; sf::Clock frameTimer; @@ -43,5 +43,6 @@ namespace dchat sf::Vector2f backgroundSizeWithoutPadding; sf::Vector2f backgroundSize; sf::Vector2f backgroundPos; + std::mutex messageProcessMutex; }; } diff --git a/include/Text.hpp b/include/Text.hpp index d2809de..d7d1e06 100644 --- a/include/Text.hpp +++ b/include/Text.hpp @@ -40,7 +40,10 @@ namespace dchat void setPosition(float x, float y); void setPosition(const sf::Vector2f &position); + sf::Vector2f getPosition() const; + void setMaxWidth(float maxWidth); + float getMaxWidth() const; void setCharacterSize(unsigned int characterSize); unsigned int getCharacterSize() const; diff --git a/src/Channel.cpp b/src/Channel.cpp index e433aee..678dddd 100644 --- a/src/Channel.cpp +++ b/src/Channel.cpp @@ -15,15 +15,15 @@ namespace dchat database(_database), databaseNodeInfo(_databaseNodeInfo), name(_name), - messageBoard(sf::Vector2u(1.0f, 1.0f)), + messageBoard(this), localUser(_localUser ? _localUser : new OfflineUser("You")) { addUserLocally(localUser); localUser->avatarUrl = "https://discordemoji.com/assets/emoji/HanekawaSmug.gif"; - addLocalMessage(u8"[emoji](https://discordemoji.com/assets/emoji/PepeDab.gif) deaf [emoji](https://discordemoji.com/assets/emoji/COGGERS.gif)", &systemUser); - addLocalMessage(u8"[emoji](https://discordemoji.com/assets/emoji/PepeDab.gif)[emoji](https://discordemoji.com/assets/emoji/COGGERS.gif)", &systemUser); - addLocalMessage(u8"pepedab https://discordemoji.com/assets/emoji/PepeDab.gif coggers https://discordemoji.com/assets/emoji/COGGERS.gif check out this url http://www.grandtournation.com/6808/start-date-of-the-grand-tour-season-3-confirmed-mark-your-calendars/ owo", &systemUser); + addLocalMessage(u8"[emoji](https://discordemoji.com/assets/emoji/PepeDab.gif) deaf [emoji](https://discordemoji.com/assets/emoji/COGGERS.gif)", &systemUser, 0, odhtdb::Hash()); + addLocalMessage(u8"[emoji](https://discordemoji.com/assets/emoji/PepeDab.gif)[emoji](https://discordemoji.com/assets/emoji/COGGERS.gif)", &systemUser, 0, odhtdb::Hash()); + addLocalMessage(u8"pepedab https://discordemoji.com/assets/emoji/PepeDab.gif coggers https://discordemoji.com/assets/emoji/COGGERS.gif check out this url http://www.grandtournation.com/6808/start-date-of-the-grand-tour-season-3-confirmed-mark-your-calendars/ owo", &systemUser, 0, odhtdb::Hash()); if(database) database->seed(databaseNodeInfo); @@ -80,12 +80,17 @@ namespace dchat void Channel::addLocalMessage(const std::string &msg, User *owner, u64 timestampSeconds) { + addLocalMessage(msg, owner, timestampSeconds, odhtdb::Hash()); + } + + void Channel::addLocalMessage(const std::string &msg, User *owner, u64 timestampSeconds, const odhtdb::Hash &id) + { assert(owner); if(timestampSeconds == 0) { timestampSeconds = time(NULL); } - messageBoard.addMessage(new Message(owner, msg, timestampSeconds)); + messageBoard.addMessage(new Message(owner, msg, timestampSeconds), id); } void Channel::addMessage(const std::string &msg) @@ -96,14 +101,37 @@ namespace dchat assert(localOnlineUser->databaseUser->getType() == odhtdb::User::Type::LOCAL); sibs::SafeSerializer serializer; - serializer.add(ChannelDataType::MESSAGE); + serializer.add(ChannelDataType::ADD_MESSAGE); serializer.add((const u8*)msg.data(), msg.size()); database->addData(databaseNodeInfo, static_cast<const odhtdb::LocalUser*>(localOnlineUser->databaseUser), odhtdb::DataView(serializer.getBuffer().data(), serializer.getBuffer().size())); database->commit(); } else - addLocalMessage(msg, localUser, 0); + addLocalMessage(msg, localUser, 0, odhtdb::Hash()); + } + + void Channel::deleteLocalMessage(const odhtdb::Hash &id) + { + messageBoard.deleteMessage(id); + } + + void Channel::deleteMessage(const odhtdb::Hash &id) + { + if(database && localUser->type == User::Type::ONLINE) + { + auto localOnlineUser = static_cast<OnlineUser*>(localUser); + assert(localOnlineUser->databaseUser->getType() == odhtdb::User::Type::LOCAL); + + sibs::SafeSerializer serializer; + serializer.add(ChannelDataType::DELETE_MESSAGE); + serializer.add((const u8*)id.getData(), odhtdb::HASH_BYTE_SIZE); + + database->addData(databaseNodeInfo, static_cast<const odhtdb::LocalUser*>(localOnlineUser->databaseUser), odhtdb::DataView(serializer.getBuffer().data(), serializer.getBuffer().size())); + database->commit(); + } + else + deleteLocalMessage(id); } void Channel::addUserLocally(User *user) diff --git a/src/ColorScheme.cpp b/src/ColorScheme.cpp index 09dde51..4790e80 100644 --- a/src/ColorScheme.cpp +++ b/src/ColorScheme.cpp @@ -14,7 +14,10 @@ namespace dchat colorSchemeType = type; } - sf::Color ColorScheme::getBackgroundColor(){ return sf::Color(54,57,62); } - sf::Color ColorScheme::getPanelColor() { return sf::Color(47,49,54); } + sf::Color ColorScheme::getBackgroundColor(){ return sf::Color(54, 57, 62); } + sf::Color ColorScheme::getPanelColor() { return sf::Color(47, 49, 54); } sf::Color ColorScheme::getTextRegularColor() { return sf::Color(255, 255, 255); } + sf::Color ColorScheme::getContextMenuBackgroundColor() { return sf::Color(47, 49, 54); } + sf::Color ColorScheme::getContextMenuTextColor() { return sf::Color(255, 255, 255); } + sf::Color ColorScheme::getContextMenuSelectedItemBackgroundColor() { return sf::Color(37, 39, 44); } } diff --git a/src/ContextMenu.cpp b/src/ContextMenu.cpp new file mode 100644 index 0000000..317d34a --- /dev/null +++ b/src/ContextMenu.cpp @@ -0,0 +1,128 @@ +#include "../include/ContextMenu.hpp" +#include "../include/ColorScheme.hpp" +#include "../include/ResourceCache.hpp" +#include "../include/Settings.hpp" +#include <SFML/Graphics/Text.hpp> +#include <SFML/Graphics/RectangleShape.hpp> +#include <cmath> +#include <cassert> + +namespace dchat +{ + const float PADDING_SIDE = 10.0f; + const float MENU_ITEM_FONT_SIZE = 18.0f; + const std::string MENU_FONT_PATH = "fonts/Roboto-Regular.ttf"; + + ContextMenuItem::ContextMenuItem(const std::string & _text, MenuItemClickCallbackFunc _clickCallbackFunc) : + text(sf::String::fromUtf8(_text.begin(), _text.end()), *ResourceCache::getFont(MENU_FONT_PATH), MENU_ITEM_FONT_SIZE * Settings::getScaling()), + clickCallbackFunc(_clickCallbackFunc) + { + text.setFillColor(ColorScheme::getContextMenuTextColor()); + } + + ContextMenu::ContextMenu() : + focusedItem(-1), + pressedItem(-1), + visible(true) + { + + } + + void ContextMenu::addItem(const ContextMenuItem &item) + { + menuItems.push_back(item); + } + + void ContextMenu::setPosition(const sf::Vector2f &position) + { + this->position = position; + } + + void ContextMenu::setVisible(bool visible) + { + this->visible = visible; + } + + ContextMenuItem& ContextMenu::getItemByIndex(usize index) + { + assert(index < menuItems.size()); + return menuItems[index]; + } + + void ContextMenu::processEvent(const sf::Event &event) + { + if(!visible) return; + + if(event.type == sf::Event::MouseButtonPressed) + { + if(event.mouseButton.button == sf::Mouse::Button::Left) + { + pressedItem = focusedItem; + if(pressedItem == -1) + setVisible(false); + } + else + { + focusedItem = -1; + pressedItem = -1; + setVisible(false); + } + } + else if(event.type == sf::Event::MouseButtonReleased) + { + if(pressedItem != -1 && pressedItem == focusedItem) + { + assert(pressedItem < menuItems.size()); + if(menuItems[pressedItem].clickCallbackFunc) + menuItems[pressedItem].clickCallbackFunc(&menuItems[pressedItem]); + setVisible(false); + } + pressedItem = -1; + } + } + + void ContextMenu::draw(sf::RenderWindow &window) + { + if(!visible) return; + + const sf::Font *menuItemFont = ResourceCache::getFont(MENU_FONT_PATH); + float boxHeight = menuItemFont->getLineSpacing(MENU_ITEM_FONT_SIZE) * 1.5f; + + sf::Vector2f menuSize; + for(ContextMenuItem &menuItem : menuItems) + { + menuItem.text.setCharacterSize(18 * Settings::getScaling()); + menuSize.x = std::max(menuSize.x, menuItem.text.getLocalBounds().width); + menuSize.y += boxHeight; + } + menuSize.x += PADDING_SIDE * 2.0f; + menuSize.x = floor(menuSize.x); + menuSize.y = floor(menuSize.y); + + sf::Vector2f pos(floor(position.x), floor(position.y)); + sf::RectangleShape background(menuSize); + background.setPosition(pos); + background.setFillColor(ColorScheme::getContextMenuBackgroundColor()); + window.draw(background); + + auto mousePos = sf::Mouse::getPosition(window); + + focusedItem = -1; + for(int i = 0; i < menuItems.size(); ++i) + { + ContextMenuItem &menuItem = menuItems[i]; + if(mousePos.x >= pos.x && mousePos.x <= pos.x + menuSize.x && mousePos.y >= pos.y && mousePos.y <= pos.y + boxHeight && (pressedItem == -1 || i == pressedItem)) + { + sf::RectangleShape selectedItemRect(sf::Vector2f(menuSize.x, floor(boxHeight))); + selectedItemRect.setFillColor(ColorScheme::getContextMenuSelectedItemBackgroundColor()); + selectedItemRect.setPosition(floor(pos.x), floor(pos.y)); + window.draw(selectedItemRect); + focusedItem = i; + } + + menuItem.text.setPosition(floor(pos.x + PADDING_SIDE), floor(pos.y + boxHeight * 0.5f - menuItemFont->getLineSpacing(MENU_ITEM_FONT_SIZE) * 0.5f)); + window.draw(menuItem.text); + pos.y += boxHeight; + } + } +} diff --git a/src/GlobalContextMenu.cpp b/src/GlobalContextMenu.cpp new file mode 100644 index 0000000..9eddb7f --- /dev/null +++ b/src/GlobalContextMenu.cpp @@ -0,0 +1,42 @@ +#include "../include/GlobalContextMenu.hpp" + +namespace dchat +{ + static ContextMenu *editMessageContextMenu = nullptr; + + ContextMenu* GlobalContextMenu::getEditMessageContextMenu() + { + if(!editMessageContextMenu) + { + editMessageContextMenu = new ContextMenu(); + editMessageContextMenu->setVisible(false); + + ContextMenuItem editMessageItem("Edit message", nullptr); + ContextMenuItem deleteMessageItem("Delete message", nullptr); + deleteMessageItem.text.setFillColor(sf::Color::Red); + editMessageContextMenu->addItem(editMessageItem); + editMessageContextMenu->addItem(deleteMessageItem); + } + return editMessageContextMenu; + } + + void GlobalContextMenu::setClickEditMessageCallbackFunc(MenuItemClickCallbackFunc callbackFunc) + { + getEditMessageContextMenu()->getItemByIndex(0).clickCallbackFunc = callbackFunc; + } + + void GlobalContextMenu::setClickDeleteMessageCallbackFunc(MenuItemClickCallbackFunc callbackFunc) + { + getEditMessageContextMenu()->getItemByIndex(1).clickCallbackFunc = callbackFunc; + } + + void GlobalContextMenu::processEvent(const sf::Event &event) + { + getEditMessageContextMenu()->processEvent(event); + } + + void GlobalContextMenu::draw(sf::RenderWindow &window) + { + getEditMessageContextMenu()->draw(window); + } +} diff --git a/src/Message.cpp b/src/Message.cpp index 77e3cfa..a408aee 100644 --- a/src/Message.cpp +++ b/src/Message.cpp @@ -10,7 +10,8 @@ namespace dchat Message::Message(User *_user, const std::string &_text, u64 _timestampSeconds) : user(_user), text(sf::String::fromUtf8(_text.begin(), _text.end()), ResourceCache::getFont("fonts/Roboto-Regular.ttf"), 18 * Settings::getScaling(), 0.0f, false), - timestampSeconds(_timestampSeconds) + timestampSeconds(_timestampSeconds), + type(Type::REGULAR) { text.setFillColor(ColorScheme::getTextRegularColor()); } diff --git a/src/MessageBoard.cpp b/src/MessageBoard.cpp index 49d84e8..bdaccf3 100644 --- a/src/MessageBoard.cpp +++ b/src/MessageBoard.cpp @@ -8,6 +8,8 @@ #include "../include/Chatbar.hpp" #include "../include/ColorScheme.hpp" #include "../include/Theme.hpp" +#include "../include/GlobalContextMenu.hpp" +#include "../include/Channel.hpp" #include <SFML/Graphics/CircleShape.hpp> #include <SFML/Graphics/RectangleShape.hpp> #include <SFML/Graphics/Sprite.hpp> @@ -39,15 +41,14 @@ namespace dchat // Merge messages from same user that are sent within one minute const int MERGE_TEXT_TIMESTAMP_DIFF_SEC = 60; - MessageBoard::MessageBoard(const sf::Vector2u &size) : - selectingText(false), - leftMouseButtonPressed(false), + MessageBoard::MessageBoard(Channel *_channel) : + channel(_channel), scroll(0.0), scrollSpeed(0.0), totalHeight(0.0), scrollToBottom(false) { - updateStaticContentTexture(size); + } MessageBoard::~MessageBoard() @@ -65,13 +66,35 @@ namespace dchat dirty = true; } - void MessageBoard::addMessage(Message *message) + void MessageBoard::addMessage(Message *message, const odhtdb::Hash &id) { + lock_guard<mutex> lock(messageProcessMutex); messages.push_back(message); + if(!id.isEmpty()) + messageIdMap[id] = message; dirty = true; scrollToBottom = true; } + void MessageBoard::deleteMessage(const odhtdb::Hash &id) + { + lock_guard<mutex> lock(messageProcessMutex); + auto it = messageIdMap.find(id); + if(it == messageIdMap.end()) return; + + for(usize i = 0; i < messages.size(); ++i) + { + Message *message = messages[i]; + if(message == it->second) + { + delete message; + messages.erase(messages.begin() + i); + messageIdMap.erase(it); + break; + } + } + } + void MessageBoard::drawDefault(sf::RenderWindow &window, Cache &cache) { const float LINE_SPACING = 5.0f * Settings::getScaling(); @@ -253,32 +276,32 @@ namespace dchat void MessageBoard::processEvent(const sf::Event &event) { - if(event.type == sf::Event::MouseButtonPressed) + lock_guard<mutex> lock(messageProcessMutex); + for(Message *message : messages) { - if(event.mouseButton.button == sf::Mouse::Button::Left) - { - leftMouseButtonPressed = true; - mousePos.x = event.mouseButton.x; - mousePos.y = event.mouseButton.y; - } + message->text.processEvent(event); } - else if(event.type == sf::Event::MouseButtonReleased) + + if(event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Button::Right) { - if(event.mouseButton.button == sf::Mouse::Button::Left) + for(auto it : messageIdMap) { - leftMouseButtonPressed = false; - mousePos.x = event.mouseButton.x; - mousePos.y = event.mouseButton.y; + it.second->text.processEvent(event); + auto textPos = it.second->text.getPosition(); + if(event.mouseButton.x >= textPos.x && event.mouseButton.x <= textPos.x + it.second->text.getMaxWidth() && event.mouseButton.y >= textPos.y && event.mouseButton.y <= textPos.y + it.second->text.getHeight()) + { + auto contextMenu = GlobalContextMenu::getEditMessageContextMenu(); + contextMenu->setPosition(sf::Vector2f(event.mouseButton.x, event.mouseButton.y)); + contextMenu->setVisible(true); + GlobalContextMenu::setClickDeleteMessageCallbackFunc([this, it](ContextMenuItem *menuItem) + { + channel->deleteMessage(it.first); + GlobalContextMenu::setClickDeleteMessageCallbackFunc(nullptr); + }); + return; + } } - } - 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; + GlobalContextMenu::setClickDeleteMessageCallbackFunc(nullptr); } else if(event.type == sf::Event::MouseWheelScrolled && event.mouseWheelScroll.wheel == sf::Mouse::Wheel::VerticalWheel) { @@ -288,22 +311,6 @@ namespace dchat else if(scrollSpeed < -SCROLL_MAX_SPEED) scrollSpeed = -SCROLL_MAX_SPEED; } - - if(selectingText && !leftMouseButtonPressed) - { - selectingText = false; - } - else if(!selectingText && leftMouseButtonPressed) - { - selectingText = true; - selectingTextStart.x = mousePos.x; - selectingTextStart.y = mousePos.y; - } - - for(Message *message : messages) - { - message->text.processEvent(event); - } } void MessageBoard::draw(sf::RenderWindow &window, Cache &cache) @@ -331,6 +338,7 @@ namespace dchat if(dirty) { + lock_guard<mutex> lock(messageProcessMutex); switch(Theme::getType()) { case Theme::Type::DEFAULT: @@ -385,11 +393,5 @@ namespace dchat //sf::Sprite textureSprite(staticContentTexture.getTexture()); //textureSprite.setPosition(backgroundPos); //window.draw(textureSprite); - - 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); } } diff --git a/src/Text.cpp b/src/Text.cpp index 252d27f..5191ca5 100644 --- a/src/Text.cpp +++ b/src/Text.cpp @@ -84,6 +84,11 @@ namespace dchat this->position = position; } + sf::Vector2f Text::getPosition() const + { + return position; + } + void Text::setMaxWidth(float maxWidth) { if(maxWidth != this->maxWidth) @@ -93,6 +98,11 @@ namespace dchat } } + float Text::getMaxWidth() const + { + return maxWidth; + } + void Text::setCharacterSize(unsigned int characterSize) { if(characterSize != this->characterSize) diff --git a/src/main.cpp b/src/main.cpp index b1f63e9..83ef11a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,6 +8,7 @@ #include "../include/Command.hpp" #include "../include/Settings.hpp" #include "../include/ColorScheme.hpp" +#include "../include/GlobalContextMenu.hpp" #include <string> #include <SFML/Graphics.hpp> #include <cstring> @@ -75,7 +76,7 @@ void channelChangeUserNickname(Channel *channel, const StringView data, const od // We dont care if there is more data to read (malicious packet), we already got all the data we need } -void channelAddStoredMessage(Channel *channel, const odhtdb::Signature::PublicKey &creatorPublicKey, const StringView decryptedObject, u64 timestamp) +void channelAddStoredMessage(Channel *channel, const odhtdb::Hash &requestHash, const odhtdb::Signature::PublicKey &creatorPublicKey, const StringView decryptedObject, u64 timestamp) { User *user = channel->getUserByPublicKey(creatorPublicKey); if(!user) @@ -90,10 +91,18 @@ void channelAddStoredMessage(Channel *channel, const odhtdb::Signature::PublicKe StringView decryptedData((const char*)decryptedObject.data + 1, decryptedObject.size - 1); switch(channelDataType) { - case ChannelDataType::MESSAGE: + case ChannelDataType::ADD_MESSAGE: { string msg(decryptedData.data, decryptedData.size); - channel->addLocalMessage(msg, user, ntp::NtpTimestamp::fromCombined(timestamp).seconds); + channel->addLocalMessage(msg, user, ntp::NtpTimestamp::fromCombined(timestamp).seconds, requestHash); + break; + } + case ChannelDataType::DELETE_MESSAGE: + { + sibs::SafeDeserializer deserializer((const u8*)decryptedData.data, decryptedData.size); + odhtdb::Hash messageId; + deserializer.extract((u8*)messageId.getData(), odhtdb::HASH_BYTE_SIZE); + channel->deleteLocalMessage(messageId); break; } case ChannelDataType::NICKNAME_CHANGE: @@ -127,7 +136,7 @@ void channelAddStoredMessages(Channel *channel, const odhtdb::DatabaseStorageObj if(nodeStorageAddedObject->decryptedObject.operation == odhtdb::DatabaseOperation::ADD_DATA) { StringView decryptedObject((const char*)nodeStorageAddedObject->decryptedObject.data.data, nodeStorageAddedObject->decryptedObject.data.size); - channelAddStoredMessage(channel, nodeStorageAddedObject->creatorPublicKey, decryptedObject, nodeStorageAddedObject->createdTimestamp); + channelAddStoredMessage(channel, nodeStorageAddedObject->requestHash, nodeStorageAddedObject->creatorPublicKey, decryptedObject, nodeStorageAddedObject->createdTimestamp); } } } @@ -200,7 +209,7 @@ int main(int argc, char **argv) { if(*request.nodeHash == *channel->getNodeInfo().getRequestHash()) { - channelAddStoredMessage(channel, request.creatorUser->getPublicKey(), StringView((const char*)request.decryptedData.data, request.decryptedData.size), request.timestamp); + channelAddStoredMessage(channel, *request.requestHash, request.creatorUser->getPublicKey(), StringView((const char*)request.decryptedData.data, request.decryptedData.size), request.timestamp); return; } } @@ -642,6 +651,7 @@ int main(int argc, char **argv) window.setFramerateLimit(FRAMERATE_FOCUSED); //else if(event.type == sf::Event::LostFocus) // window.setFramerateLimit(FRAMERATE_NOT_FOCUSED); + GlobalContextMenu::processEvent(event); currentChannel->processEvent(event); } @@ -650,6 +660,7 @@ int main(int argc, char **argv) currentChannel->draw(window, cache); UsersSidePanel::draw(window); ChannelTopPanel::draw(window); + GlobalContextMenu::draw(window); if(waitingToJoin) { |