/* * Copyright (C) 2017 Christopher J. Howard * * This file is part of Antkeeper Source Code. * * Antkeeper Source Code is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Antkeeper Source Code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Antkeeper Source Code. If not, see . */ #include "menu.hpp" #include "ui.hpp" #include MenuItem::MenuItem(Menu* parent, std::size_t index): parent(parent), index(index), selectedCallback(nullptr), deselectedCallback(nullptr), activatedCallback(nullptr) { label = new UILabel(); label->setMouseOverCallback(std::bind(&Menu::select, parent, index)); label->setMouseMovedCallback(std::bind(&Menu::select, parent, index)); label->setMousePressedCallback(std::bind(&Menu::activate, parent)); } MenuItem::~MenuItem() { delete label; } void MenuItem::select() { if (selectedCallback != nullptr) { selectedCallback(); } } void MenuItem::deselect() { if (deselectedCallback != nullptr) { deselectedCallback(); } } void MenuItem::activate() { if (activatedCallback != nullptr) { activatedCallback(); } } void MenuItem::setSelectedCallback(std::function callback) { this->selectedCallback = callback = callback; } void MenuItem::setDeselectedCallback(std::function callback) { this->deselectedCallback = callback; } void MenuItem::setActivatedCallback(std::function callback) { this->activatedCallback = callback; } void MenuItem::setLabel(const std::string& text) { label->setText(text); parent->resize(); } bool MenuItem::isSelected() const { return (parent->getSelectedItem() == this); } Menu::Menu(): selectedItem(nullptr), enteredCallback(nullptr), exitedCallback(nullptr), font(nullptr), lineSpacing(1.0f) { container = new UIContainer(); resize(); } Menu::~Menu() { removeItems(); delete container; } void Menu::enter() { if (enteredCallback != nullptr) { enteredCallback(); } } void Menu::exit() { if (exitedCallback != nullptr) { exitedCallback(); } } MenuItem* Menu::addItem() { // Allocate item and add to items MenuItem* item = new MenuItem(this, items.size()); items.push_back(item); // Set item label font item->label->setFont(font); item->label->setTintColor(Vector4(1.0f, 1.0f, 1.0f, 0.35f)); // Add item label to UI container container->addChild(item->label); // Resize UI container resize(); return item; } void Menu::removeItems() { for (MenuItem* item: items) { // Remove label from UI container container->removeChild(item->label); delete item; } items.clear(); resize(); } void Menu::setEnteredCallback(std::function callback) { this->enteredCallback = callback; } void Menu::setExitedCallback(std::function callback) { this->exitedCallback = callback; } void Menu::setFont(Font* font) { this->font = font; for (MenuItem* item: items) { item->label->setFont(font); } resize(); } void Menu::setLineSpacing(float spacing) { lineSpacing = spacing; resize(); } void Menu::deselect() { if (selectedItem != nullptr) { selectedItem->deselect(); selectedItem->label->setTintColor(Vector4(1.0f, 1.0f, 1.0f, 0.35f)); selectedItem = nullptr; } } void Menu::select(std::size_t index) { deselect(); MenuItem* item = items[index]; item->select(); selectedItem = item; selectedItem->label->setTintColor(Vector4(1.0f, 1.0f, 1.0f, 1.0f)); } void Menu::activate() { if (selectedItem != nullptr) { selectedItem->activate(); } } void Menu::resize() { if (!font) { container->setDimensions(Vector2(0.0f)); } else { Vector2 dimensions(0.0f); for (std::size_t i = 0; i < items.size(); ++i) { const MenuItem* item = items[i]; item->label->setTranslation(Vector2(0.0f, static_cast(font->getMetrics().getHeight() * lineSpacing * static_cast(i)))); dimensions.x = std::max(dimensions.x, item->label->getDimensions().x); if (!i) { dimensions.y += font->getMetrics().getHeight(); } else { dimensions.y += font->getMetrics().getHeight() * lineSpacing; } } container->setDimensions(dimensions); } }