claude: treballant en el nou define_buttons
This commit is contained in:
95
source/ui/action_list_option.cpp
Normal file
95
source/ui/action_list_option.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
#include "action_list_option.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "text.h"
|
||||
|
||||
ActionListOption::ActionListOption(
|
||||
const std::string& caption,
|
||||
ServiceMenu::SettingsGroup group,
|
||||
std::vector<std::string> options,
|
||||
ValueGetter getter,
|
||||
ValueSetter setter,
|
||||
ActionExecutor action_executor,
|
||||
bool hidden) : MenuOption(caption, group, hidden),
|
||||
options_(std::move(options)),
|
||||
value_getter_(std::move(getter)),
|
||||
value_setter_(std::move(setter)),
|
||||
action_executor_(std::move(action_executor)),
|
||||
current_index_(0) {
|
||||
updateCurrentIndex();
|
||||
}
|
||||
|
||||
auto ActionListOption::getBehavior() const -> Behavior {
|
||||
// Puede tanto ajustar valor (lista) como ejecutar acción (botón)
|
||||
return Behavior::BOTH;
|
||||
}
|
||||
|
||||
auto ActionListOption::getValueAsString() const -> std::string {
|
||||
if (value_getter_) {
|
||||
return value_getter_();
|
||||
}
|
||||
|
||||
if (current_index_ < options_.size()) {
|
||||
return options_[current_index_];
|
||||
}
|
||||
|
||||
return options_.empty() ? "" : options_[0];
|
||||
}
|
||||
|
||||
auto ActionListOption::getMaxValueWidth(Text* text) const -> int {
|
||||
int max_width = 0;
|
||||
for (const auto& option : options_) {
|
||||
int width = text->lenght(option, -2);
|
||||
if (width > max_width) {
|
||||
max_width = width;
|
||||
}
|
||||
}
|
||||
return max_width;
|
||||
}
|
||||
|
||||
void ActionListOption::adjustValue(bool up) {
|
||||
if (options_.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (up) {
|
||||
current_index_ = (current_index_ + 1) % options_.size();
|
||||
} else {
|
||||
current_index_ = (current_index_ == 0) ? options_.size() - 1 : current_index_ - 1;
|
||||
}
|
||||
|
||||
// Aplicar el cambio usando el setter
|
||||
if (value_setter_ && current_index_ < options_.size()) {
|
||||
value_setter_(options_[current_index_]);
|
||||
}
|
||||
}
|
||||
|
||||
void ActionListOption::executeAction() {
|
||||
if (action_executor_) {
|
||||
action_executor_();
|
||||
}
|
||||
}
|
||||
|
||||
void ActionListOption::sync() {
|
||||
updateCurrentIndex();
|
||||
}
|
||||
|
||||
void ActionListOption::updateCurrentIndex() {
|
||||
current_index_ = findCurrentIndex();
|
||||
}
|
||||
|
||||
auto ActionListOption::findCurrentIndex() const -> size_t {
|
||||
if (!value_getter_ || options_.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const std::string current_value = value_getter_();
|
||||
auto it = std::find(options_.begin(), options_.end(), current_value);
|
||||
|
||||
if (it != options_.end()) {
|
||||
return static_cast<size_t>(std::distance(options_.begin(), it));
|
||||
}
|
||||
|
||||
return 0; // Valor por defecto si no se encuentra
|
||||
}
|
||||
42
source/ui/action_list_option.h
Normal file
42
source/ui/action_list_option.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include "menu_option.h"
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class ActionListOption : public MenuOption {
|
||||
public:
|
||||
using ValueGetter = std::function<std::string()>;
|
||||
using ValueSetter = std::function<void(const std::string&)>;
|
||||
using ActionExecutor = std::function<void()>;
|
||||
|
||||
ActionListOption(
|
||||
const std::string& caption,
|
||||
ServiceMenu::SettingsGroup group,
|
||||
std::vector<std::string> options,
|
||||
ValueGetter getter,
|
||||
ValueSetter setter,
|
||||
ActionExecutor action_executor,
|
||||
bool hidden = false
|
||||
);
|
||||
|
||||
// Implementaciones de MenuOption
|
||||
[[nodiscard]] auto getBehavior() const -> Behavior override;
|
||||
[[nodiscard]] auto getValueAsString() const -> std::string override;
|
||||
[[nodiscard]] auto getMaxValueWidth(Text* text) const -> int override;
|
||||
void adjustValue(bool up) override;
|
||||
void executeAction() override;
|
||||
void sync(); //override;
|
||||
|
||||
private:
|
||||
std::vector<std::string> options_;
|
||||
ValueGetter value_getter_;
|
||||
ValueSetter value_setter_;
|
||||
ActionExecutor action_executor_;
|
||||
size_t current_index_;
|
||||
|
||||
void updateCurrentIndex();
|
||||
[[nodiscard]] auto findCurrentIndex() const -> size_t;
|
||||
};
|
||||
@@ -17,8 +17,9 @@
|
||||
class MenuOption {
|
||||
public:
|
||||
enum class Behavior {
|
||||
ADJUST,
|
||||
SELECT
|
||||
ADJUST, // Solo puede ajustar valor (como IntOption, BoolOption, ListOption)
|
||||
SELECT, // Solo puede ejecutar acción (como ActionOption, FolderOption)
|
||||
BOTH // Puede tanto ajustar como ejecutar acción (como ActionListOption)
|
||||
};
|
||||
|
||||
MenuOption(std::string caption, ServiceMenu::SettingsGroup group, bool hidden = false)
|
||||
|
||||
@@ -45,27 +45,39 @@ void MenuRenderer::render(const ServiceMenu *menu_state) {
|
||||
// Dibuja las opciones
|
||||
y = options_y_;
|
||||
const auto &option_pairs = menu_state->getOptionPairs();
|
||||
const auto &display_options = menu_state->getDisplayOptions();
|
||||
|
||||
for (size_t i = 0; i < option_pairs.size(); ++i) {
|
||||
const bool IS_SELECTED = (i == menu_state->getSelectedIndex());
|
||||
const Color ¤t_color = IS_SELECTED ? param.service_menu.selected_color : param.service_menu.text_color;
|
||||
|
||||
if (menu_state->getCurrentGroupAlignment() == ServiceMenu::GroupAlignment::LEFT) {
|
||||
// Para opciones alineadas a la izquierda, truncamos el valor si es necesario
|
||||
const int AVAILABLE_WIDTH = rect_.w - (ServiceMenu::OPTIONS_HORIZONTAL_PADDING * 2) -
|
||||
element_text_->lenght(option_pairs.at(i).first, -2) -
|
||||
ServiceMenu::MIN_GAP_OPTION_VALUE;
|
||||
|
||||
const std::string TRUNCATED_VALUE = getTruncatedValue(option_pairs.at(i).second, AVAILABLE_WIDTH);
|
||||
|
||||
const int available_width = rect_.w - (ServiceMenu::OPTIONS_HORIZONTAL_PADDING * 2) -
|
||||
element_text_->lenght(option_pairs.at(i).first, -2) -
|
||||
ServiceMenu::MIN_GAP_OPTION_VALUE;
|
||||
|
||||
std::string truncated_value = getTruncatedValue(option_pairs.at(i).second, available_width);
|
||||
|
||||
// Si la opción tiene Behavior::BOTH, añadir indicador visual
|
||||
if (i < display_options.size() && display_options[i]->getBehavior() == MenuOption::Behavior::BOTH) {
|
||||
truncated_value = "► " + truncated_value + " ◄";
|
||||
}
|
||||
|
||||
element_text_->writeColored(rect_.x + ServiceMenu::OPTIONS_HORIZONTAL_PADDING, y, option_pairs.at(i).first, current_color, -2);
|
||||
const int X = rect_.x + rect_.w - ServiceMenu::OPTIONS_HORIZONTAL_PADDING - element_text_->lenght(TRUNCATED_VALUE, -2);
|
||||
element_text_->writeColored(X, y, TRUNCATED_VALUE, current_color, -2);
|
||||
const int X = rect_.x + rect_.w - ServiceMenu::OPTIONS_HORIZONTAL_PADDING - element_text_->lenght(truncated_value, -2);
|
||||
element_text_->writeColored(X, y, truncated_value, current_color, -2);
|
||||
} else {
|
||||
// Para opciones centradas, también truncamos si es necesario
|
||||
const int AVAILABLE_WIDTH = rect_.w - (ServiceMenu::OPTIONS_HORIZONTAL_PADDING * 2);
|
||||
const std::string TRUNCATED_CAPTION = getTruncatedValue(option_pairs.at(i).first, AVAILABLE_WIDTH);
|
||||
|
||||
element_text_->writeDX(TEXT_CENTER | TEXT_COLOR, rect_.x + rect_.w / 2, y, TRUNCATED_CAPTION, -2, current_color);
|
||||
const int available_width = rect_.w - (ServiceMenu::OPTIONS_HORIZONTAL_PADDING * 2);
|
||||
std::string truncated_caption = getTruncatedValue(option_pairs.at(i).first, available_width);
|
||||
|
||||
// Si la opción tiene Behavior::BOTH, añadir indicador visual
|
||||
if (i < display_options.size() && display_options[i]->getBehavior() == MenuOption::Behavior::BOTH) {
|
||||
truncated_caption = "► " + truncated_caption + " ◄";
|
||||
}
|
||||
|
||||
element_text_->writeDX(TEXT_CENTER | TEXT_COLOR, rect_.x + rect_.w / 2, y, truncated_caption, -2, current_color);
|
||||
}
|
||||
y += options_height_ + options_padding_;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#include "section.hpp" // Para Name, name, Options, options
|
||||
#include "ui/ui_message.h" // Para UIMessage
|
||||
#include "utils.h" // Para Zone
|
||||
#include "action_list_option.h" // Para ActionListOption
|
||||
#include "define_buttons.h" // Para DefineButtons
|
||||
|
||||
// Singleton
|
||||
ServiceMenu *ServiceMenu::instance = nullptr;
|
||||
@@ -32,6 +34,7 @@ ServiceMenu::ServiceMenu()
|
||||
|
||||
renderer_ = std::make_unique<MenuRenderer>(this, element_text, title_text);
|
||||
restart_message_ui_ = std::make_unique<UIMessage>(element_text, Lang::getText("[SERVICE_MENU] NEED_RESTART_MESSAGE"), param.service_menu.title_color);
|
||||
define_buttons_ = std::make_unique<DefineButtons>();
|
||||
|
||||
reset();
|
||||
}
|
||||
@@ -55,6 +58,11 @@ void ServiceMenu::render() {
|
||||
const float MSG_Y = renderer_->getRect().y + 39.0F;
|
||||
restart_message_ui_->setPosition(MSG_X, MSG_Y);
|
||||
restart_message_ui_->render();
|
||||
|
||||
// Renderizar DefineButtons si está activo (se dibuja por encima de todo)
|
||||
if (define_buttons_ && define_buttons_->isEnabled()) {
|
||||
define_buttons_->render();
|
||||
}
|
||||
}
|
||||
|
||||
void ServiceMenu::update() {
|
||||
@@ -70,6 +78,22 @@ void ServiceMenu::update() {
|
||||
last_pending_changes_ = now_pending;
|
||||
}
|
||||
restart_message_ui_->update();
|
||||
|
||||
// Actualizar DefineButtons
|
||||
if (define_buttons_) {
|
||||
define_buttons_->update();
|
||||
|
||||
// Si DefineButtons ha terminado, deshabilitarlo
|
||||
if (define_buttons_->isEnabled() && define_buttons_->isFinished()) {
|
||||
// Pequeño delay antes de cerrar
|
||||
static int finish_delay = 0;
|
||||
finish_delay++;
|
||||
if (finish_delay > 60) { // 1 segundo a 60 FPS
|
||||
define_buttons_->disable();
|
||||
finish_delay = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServiceMenu::reset() {
|
||||
@@ -247,8 +271,8 @@ auto ServiceMenu::countOptionsInGroup(SettingsGroup group) const -> size_t {
|
||||
void ServiceMenu::initializeOptions() {
|
||||
options_.clear();
|
||||
|
||||
// CONTROLS
|
||||
options_.push_back(std::make_unique<ListOption>(
|
||||
// CONTROLS - Usando ActionListOption para mandos
|
||||
options_.push_back(std::make_unique<ActionListOption>(
|
||||
Lang::getText("[SERVICE_MENU] CONTROLLER1"),
|
||||
SettingsGroup::CONTROLS,
|
||||
Input::get()->getControllerNames(),
|
||||
@@ -257,9 +281,16 @@ void ServiceMenu::initializeOptions() {
|
||||
},
|
||||
[](const std::string &val) {
|
||||
Options::gamepad_manager.assignGamepadToPlayer(Player::Id::PLAYER1, Input::get()->getGamepadByName(val), val);
|
||||
},
|
||||
[this]() {
|
||||
// Acción: configurar botones del mando del jugador 1
|
||||
auto* gamepad = &Options::gamepad_manager.getGamepad(Player::Id::PLAYER1);
|
||||
if (gamepad && gamepad->instance) {
|
||||
define_buttons_->enable(gamepad);
|
||||
}
|
||||
}));
|
||||
|
||||
options_.push_back(std::make_unique<ListOption>(
|
||||
options_.push_back(std::make_unique<ActionListOption>(
|
||||
Lang::getText("[SERVICE_MENU] CONTROLLER2"),
|
||||
SettingsGroup::CONTROLS,
|
||||
Input::get()->getControllerNames(),
|
||||
@@ -268,8 +299,16 @@ void ServiceMenu::initializeOptions() {
|
||||
},
|
||||
[](const std::string &val) {
|
||||
Options::gamepad_manager.assignGamepadToPlayer(Player::Id::PLAYER2, Input::get()->getGamepadByName(val), val);
|
||||
},
|
||||
[this]() {
|
||||
// Acción: configurar botones del mando del jugador 2
|
||||
auto* gamepad = &Options::gamepad_manager.getGamepad(Player::Id::PLAYER2);
|
||||
if (gamepad && gamepad->instance) {
|
||||
define_buttons_->enable(gamepad);
|
||||
}
|
||||
}));
|
||||
|
||||
// CONTROLS - Opción para teclado (solo lista, sin acción)
|
||||
options_.push_back(std::make_unique<ListOption>(
|
||||
Lang::getText("[SERVICE_MENU] KEYBOARD"),
|
||||
SettingsGroup::CONTROLS,
|
||||
@@ -277,13 +316,16 @@ void ServiceMenu::initializeOptions() {
|
||||
Lang::getText("[SERVICE_MENU] PLAYER1"),
|
||||
Lang::getText("[SERVICE_MENU] PLAYER2")},
|
||||
[]() {
|
||||
return Lang::getNameFromCode(Options::pending_changes.new_language);
|
||||
// Aquí deberías devolver el jugador actual asignado al teclado
|
||||
// Por ahora devuelvo "Jugador 1" como ejemplo
|
||||
return Lang::getText("[SERVICE_MENU] PLAYER1");
|
||||
},
|
||||
[](const std::string &val) {
|
||||
Options::pending_changes.new_language = Lang::getCodeFromName(val);
|
||||
Options::checkPendingChanges();
|
||||
// Aquí asignarías el teclado al jugador seleccionado
|
||||
// Implementación pendiente según tu sistema de input
|
||||
}));
|
||||
|
||||
// CONTROLS - Acción para intercambiar mandos
|
||||
options_.push_back(std::make_unique<ActionOption>(
|
||||
Lang::getText("[SERVICE_MENU] SWAP_CONTROLLERS"),
|
||||
SettingsGroup::CONTROLS,
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
class MenuOption;
|
||||
class MenuRenderer;
|
||||
class DefineButtons; // Forward declaration
|
||||
|
||||
class ServiceMenu {
|
||||
public:
|
||||
@@ -52,6 +53,7 @@ class ServiceMenu {
|
||||
void adjustOption(bool adjust_up);
|
||||
void selectOption();
|
||||
void moveBack();
|
||||
void checkEvents(const SDL_Event &event); // Nuevo método para eventos
|
||||
|
||||
// --- Getters para que el Renderer pueda leer el estado ---
|
||||
[[nodiscard]] auto isEnabled() const -> bool { return enabled_; }
|
||||
@@ -81,6 +83,9 @@ class ServiceMenu {
|
||||
std::unique_ptr<UIMessage> restart_message_ui_;
|
||||
bool last_pending_changes_ = false;
|
||||
|
||||
// --- Configuración de botones ---
|
||||
std::unique_ptr<DefineButtons> define_buttons_;
|
||||
|
||||
// --- La Vista ---
|
||||
std::unique_ptr<MenuRenderer> renderer_;
|
||||
|
||||
@@ -109,4 +114,4 @@ class ServiceMenu {
|
||||
|
||||
// --- Instancia singleton ---
|
||||
static ServiceMenu *instance;
|
||||
};
|
||||
};
|
||||
172
source/ui/window_message.cpp
Normal file
172
source/ui/window_message.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
#include "window_message.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
#include "param.h"
|
||||
#include "screen.h"
|
||||
#include "text.h"
|
||||
|
||||
WindowMessage::WindowMessage(
|
||||
std::shared_ptr<Text> text_renderer,
|
||||
const std::string& title,
|
||||
const Color& bg_color,
|
||||
const Color& border_color,
|
||||
const Color& title_color,
|
||||
const Color& text_color
|
||||
) : text_renderer_(std::move(text_renderer)),
|
||||
title_(title),
|
||||
bg_color_(bg_color),
|
||||
border_color_(border_color),
|
||||
title_color_(title_color),
|
||||
text_color_(text_color) {
|
||||
}
|
||||
|
||||
void WindowMessage::render() {
|
||||
if (!visible_) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_Renderer* renderer = Screen::get()->getRenderer();
|
||||
|
||||
// Dibujar fondo con transparencia
|
||||
SDL_SetRenderDrawColor(renderer, bg_color_.r, bg_color_.g, bg_color_.b, bg_color_.a);
|
||||
SDL_RenderFillRect(renderer, &rect_);
|
||||
|
||||
// Dibujar borde
|
||||
SDL_SetRenderDrawColor(renderer, border_color_.r, border_color_.g, border_color_.b, border_color_.a);
|
||||
SDL_RenderRect(renderer, &rect_);
|
||||
|
||||
float current_y = rect_.y + padding_;
|
||||
|
||||
// Dibujar título si existe
|
||||
if (!title_.empty()) {
|
||||
text_renderer_->writeCentered(
|
||||
rect_.x + rect_.w / 2.0f,
|
||||
current_y,
|
||||
title_
|
||||
//title_color_
|
||||
);
|
||||
current_y += text_renderer_->getCharacterSize() + line_spacing_ * 2;
|
||||
|
||||
// Línea separadora debajo del título
|
||||
SDL_SetRenderDrawColor(renderer, border_color_.r, border_color_.g, border_color_.b, border_color_.a);
|
||||
SDL_RenderLine(renderer,
|
||||
rect_.x + padding_, current_y - line_spacing_,
|
||||
rect_.x + rect_.w - padding_, current_y - line_spacing_);
|
||||
}
|
||||
|
||||
// Dibujar textos
|
||||
for (const auto& text : texts_) {
|
||||
text_renderer_->writeCentered(
|
||||
rect_.x + rect_.w / 2.0f,
|
||||
current_y,
|
||||
text
|
||||
//text_color_
|
||||
);
|
||||
current_y += text_renderer_->getCharacterSize() + line_spacing_;
|
||||
}
|
||||
}
|
||||
|
||||
void WindowMessage::update() {
|
||||
// Por ahora no hay animaciones, pero se puede extender
|
||||
}
|
||||
|
||||
void WindowMessage::show() {
|
||||
visible_ = true;
|
||||
}
|
||||
|
||||
void WindowMessage::hide() {
|
||||
visible_ = false;
|
||||
}
|
||||
|
||||
void WindowMessage::setTitle(const std::string& title) {
|
||||
title_ = title;
|
||||
}
|
||||
|
||||
void WindowMessage::setText(const std::string& text) {
|
||||
texts_.clear();
|
||||
texts_.push_back(text);
|
||||
}
|
||||
|
||||
void WindowMessage::setTexts(const std::vector<std::string>& texts) {
|
||||
texts_ = texts;
|
||||
}
|
||||
|
||||
void WindowMessage::addText(const std::string& text) {
|
||||
texts_.push_back(text);
|
||||
}
|
||||
|
||||
void WindowMessage::clearTexts() {
|
||||
texts_.clear();
|
||||
}
|
||||
|
||||
void WindowMessage::setPosition(float x, float y) {
|
||||
rect_.x = x;
|
||||
rect_.y = y;
|
||||
}
|
||||
|
||||
void WindowMessage::setSize(float width, float height) {
|
||||
rect_.w = width;
|
||||
rect_.h = height;
|
||||
}
|
||||
|
||||
void WindowMessage::centerOnScreen() {
|
||||
rect_.x = (param.game.width - rect_.w) / 2.0f;
|
||||
rect_.y = (param.game.height - rect_.h) / 2.0f;
|
||||
}
|
||||
|
||||
void WindowMessage::autoSize() {
|
||||
calculateAutoSize();
|
||||
}
|
||||
|
||||
void WindowMessage::calculateAutoSize() {
|
||||
float content_width = calculateContentWidth();
|
||||
float content_height = calculateContentHeight();
|
||||
|
||||
rect_.w = content_width + (padding_ * 2);
|
||||
rect_.h = content_height + (padding_ * 2);
|
||||
|
||||
// Aplicar límites mínimos y máximos
|
||||
rect_.w = std::max(rect_.w, 200.0f);
|
||||
rect_.h = std::max(rect_.h, 100.0f);
|
||||
|
||||
// No exceder el 80% de la pantalla
|
||||
rect_.w = std::min(rect_.w, param.game.width * 0.8f);
|
||||
rect_.h = std::min(rect_.h, param.game.height * 0.8f);
|
||||
}
|
||||
|
||||
auto WindowMessage::calculateContentHeight() const -> float {
|
||||
float height = 0;
|
||||
|
||||
// Altura del título
|
||||
if (!title_.empty()) {
|
||||
height += text_renderer_->getCharacterSize() + line_spacing_ * 2; // Espacio extra para separador
|
||||
}
|
||||
|
||||
// Altura de los textos
|
||||
if (!texts_.empty()) {
|
||||
height += (texts_.size() * text_renderer_->getCharacterSize());
|
||||
height += ((texts_.size() - 1) * line_spacing_); // Espaciado entre líneas
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
auto WindowMessage::calculateContentWidth() const -> float {
|
||||
float max_width = 200.0f; // Ancho mínimo
|
||||
|
||||
// Ancho del título
|
||||
if (!title_.empty()) {
|
||||
float title_width = text_renderer_->lenght(title_, -2);
|
||||
max_width = std::max(max_width, title_width);
|
||||
}
|
||||
|
||||
// Ancho de los textos
|
||||
for (const auto& text : texts_) {
|
||||
float text_width = text_renderer_->lenght(text, -2);
|
||||
max_width = std::max(max_width, text_width);
|
||||
}
|
||||
|
||||
return max_width;
|
||||
}
|
||||
84
source/ui/window_message.h
Normal file
84
source/ui/window_message.h
Normal file
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "color.h"
|
||||
|
||||
class Text;
|
||||
|
||||
class WindowMessage {
|
||||
public:
|
||||
WindowMessage(
|
||||
std::shared_ptr<Text> text_renderer,
|
||||
const std::string& title = "",
|
||||
const Color& bg_color = Color{40, 40, 60, 220},
|
||||
const Color& border_color = Color{100, 100, 120, 255},
|
||||
const Color& title_color = Color{255, 255, 255, 255},
|
||||
const Color& text_color = Color{200, 200, 200, 255}
|
||||
);
|
||||
|
||||
// Métodos principales
|
||||
void render();
|
||||
void update();
|
||||
|
||||
// Control de visibilidad
|
||||
void show();
|
||||
void hide();
|
||||
[[nodiscard]] auto isVisible() const -> bool { return visible_; }
|
||||
|
||||
// Configuración de contenido
|
||||
void setTitle(const std::string& title);
|
||||
void setText(const std::string& text);
|
||||
void setTexts(const std::vector<std::string>& texts);
|
||||
void addText(const std::string& text);
|
||||
void clearTexts();
|
||||
|
||||
// Configuración de posición y tamaño
|
||||
void setPosition(float x, float y);
|
||||
void setSize(float width, float height);
|
||||
void centerOnScreen();
|
||||
void autoSize(); // Ajusta automáticamente al contenido
|
||||
|
||||
// Configuración de colores
|
||||
void setBackgroundColor(const Color& color) { bg_color_ = color; }
|
||||
void setBorderColor(const Color& color) { border_color_ = color; }
|
||||
void setTitleColor(const Color& color) { title_color_ = color; }
|
||||
void setTextColor(const Color& color) { text_color_ = color; }
|
||||
|
||||
// Configuración de espaciado
|
||||
void setPadding(float padding) { padding_ = padding; }
|
||||
void setLineSpacing(float spacing) { line_spacing_ = spacing; }
|
||||
|
||||
// Getters
|
||||
[[nodiscard]] auto getRect() const -> const SDL_FRect& { return rect_; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<Text> text_renderer_;
|
||||
|
||||
// Estado de visibilidad
|
||||
bool visible_ = false;
|
||||
|
||||
// Contenido
|
||||
std::string title_;
|
||||
std::vector<std::string> texts_;
|
||||
|
||||
// Posición y tamaño
|
||||
SDL_FRect rect_{0, 0, 300, 200};
|
||||
float padding_ = 15.0f;
|
||||
float line_spacing_ = 5.0f;
|
||||
|
||||
// Colores
|
||||
Color bg_color_;
|
||||
Color border_color_;
|
||||
Color title_color_;
|
||||
Color text_color_;
|
||||
|
||||
// Métodos privados
|
||||
void calculateAutoSize();
|
||||
[[nodiscard]] auto calculateContentHeight() const -> float;
|
||||
[[nodiscard]] auto calculateContentWidth() const -> float;
|
||||
};
|
||||
Reference in New Issue
Block a user