#include "../include/ContextMenu.hpp" #include "../include/ColorScheme.hpp" #include "../include/ResourceCache.hpp" #include "../include/Settings.hpp" #include #include #include #include namespace dchat { const float PADDING_SIDE = 10.0f; const float MENU_ITEM_FONT_SIZE = 18.0f; const std::string MENU_FONT_PATH = "fonts/Nunito-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 || menuItems.empty()) 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 || menuItems.empty()) 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; } } }