clang-format
This commit is contained in:
@@ -5,81 +5,81 @@
|
||||
|
||||
namespace Logger {
|
||||
|
||||
// Colores ANSI
|
||||
inline constexpr const char* RESET = "\033[0m";
|
||||
inline constexpr const char* RED = "\033[31m";
|
||||
inline constexpr const char* GREEN = "\033[32m";
|
||||
inline constexpr const char* YELLOW = "\033[33m";
|
||||
inline constexpr const char* BLUE = "\033[34m";
|
||||
inline constexpr const char* MAGENTA = "\033[35m";
|
||||
inline constexpr const char* CYAN = "\033[36m";
|
||||
inline constexpr const char* WHITE = "\033[37m";
|
||||
// Colores ANSI
|
||||
inline constexpr const char* RESET = "\033[0m";
|
||||
inline constexpr const char* RED = "\033[31m";
|
||||
inline constexpr const char* GREEN = "\033[32m";
|
||||
inline constexpr const char* YELLOW = "\033[33m";
|
||||
inline constexpr const char* BLUE = "\033[34m";
|
||||
inline constexpr const char* MAGENTA = "\033[35m";
|
||||
inline constexpr const char* CYAN = "\033[36m";
|
||||
inline constexpr const char* WHITE = "\033[37m";
|
||||
|
||||
// Ancho total global para alineación
|
||||
inline constexpr size_t TOTAL_WIDTH = 52;
|
||||
// Ancho total global para alineación
|
||||
inline constexpr size_t TOTAL_WIDTH = 52;
|
||||
|
||||
// Sección
|
||||
inline void section(const std::string& title, const std::string& color = CYAN) {
|
||||
std::cout << "\n"
|
||||
<< color
|
||||
<< "========================================\n"
|
||||
<< " " << title << "\n"
|
||||
<< "========================================"
|
||||
<< RESET << "\n";
|
||||
}
|
||||
|
||||
// Info
|
||||
inline void info(const std::string& msg, const std::string& color = WHITE) {
|
||||
std::cout << " " << color << msg << RESET << "\n";
|
||||
}
|
||||
|
||||
// Put
|
||||
inline void put(const std::string& msg, const std::string& color = WHITE) {
|
||||
std::cout << color << msg << RESET << "\n";
|
||||
}
|
||||
|
||||
// Error
|
||||
inline void error(const std::string& msg) {
|
||||
std::cout << RED << msg << RESET << "\n";
|
||||
}
|
||||
|
||||
// CR
|
||||
inline void cr() {
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
// Dots genérico
|
||||
inline void dots(const std::string& prefix,
|
||||
const std::string& middle,
|
||||
const std::string& suffix,
|
||||
const std::string& suffix_color = GREEN) {
|
||||
size_t field_width = TOTAL_WIDTH > (prefix.size() + suffix.size())
|
||||
? TOTAL_WIDTH - prefix.size() - suffix.size()
|
||||
: 0;
|
||||
|
||||
std::string field_text;
|
||||
if (middle.size() < field_width) {
|
||||
field_text = middle + std::string(field_width - middle.size(), '.');
|
||||
} else {
|
||||
field_text = middle.substr(0, field_width);
|
||||
// Sección
|
||||
inline void section(const std::string& title, const std::string& color = CYAN) {
|
||||
std::cout << "\n"
|
||||
<< color
|
||||
<< "========================================\n"
|
||||
<< " " << title << "\n"
|
||||
<< "========================================"
|
||||
<< RESET << "\n";
|
||||
}
|
||||
|
||||
std::cout << " " << prefix << field_text
|
||||
<< suffix_color << suffix << RESET
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
// Status con true/false, usando dots y sufijos fijos
|
||||
inline void status(const std::string& name, bool ok) {
|
||||
// Ambos sufijos tienen 9 caracteres → alineación perfecta
|
||||
constexpr const char* OK_LABEL = "[ OK ]";
|
||||
constexpr const char* ERROR_LABEL = "[ ERROR ]";
|
||||
|
||||
if (ok) {
|
||||
dots(" ", name, OK_LABEL, GREEN);
|
||||
} else {
|
||||
dots(" ", name, ERROR_LABEL, RED);
|
||||
// Info
|
||||
inline void info(const std::string& msg, const std::string& color = WHITE) {
|
||||
std::cout << " " << color << msg << RESET << "\n";
|
||||
}
|
||||
|
||||
// Put
|
||||
inline void put(const std::string& msg, const std::string& color = WHITE) {
|
||||
std::cout << color << msg << RESET << "\n";
|
||||
}
|
||||
|
||||
// Error
|
||||
inline void error(const std::string& msg) {
|
||||
std::cout << RED << msg << RESET << "\n";
|
||||
}
|
||||
|
||||
// CR
|
||||
inline void cr() {
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
// Dots genérico
|
||||
inline void dots(const std::string& prefix,
|
||||
const std::string& middle,
|
||||
const std::string& suffix,
|
||||
const std::string& suffix_color = GREEN) {
|
||||
size_t field_width = TOTAL_WIDTH > (prefix.size() + suffix.size())
|
||||
? TOTAL_WIDTH - prefix.size() - suffix.size()
|
||||
: 0;
|
||||
|
||||
std::string field_text;
|
||||
if (middle.size() < field_width) {
|
||||
field_text = middle + std::string(field_width - middle.size(), '.');
|
||||
} else {
|
||||
field_text = middle.substr(0, field_width);
|
||||
}
|
||||
|
||||
std::cout << " " << prefix << field_text
|
||||
<< suffix_color << suffix << RESET
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
// Status con true/false, usando dots y sufijos fijos
|
||||
inline void status(const std::string& name, bool ok) {
|
||||
// Ambos sufijos tienen 9 caracteres → alineación perfecta
|
||||
constexpr const char* OK_LABEL = "[ OK ]";
|
||||
constexpr const char* ERROR_LABEL = "[ ERROR ]";
|
||||
|
||||
if (ok) {
|
||||
dots(" ", name, OK_LABEL, GREEN);
|
||||
} else {
|
||||
dots(" ", name, ERROR_LABEL, RED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Logger
|
||||
|
||||
@@ -13,207 +13,207 @@
|
||||
|
||||
// --- Clase MenuOption: interfaz base para todas las opciones del menú ---
|
||||
class MenuOption {
|
||||
public:
|
||||
// --- Enums ---
|
||||
enum class Behavior {
|
||||
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)
|
||||
};
|
||||
public:
|
||||
// --- Enums ---
|
||||
enum class Behavior {
|
||||
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)
|
||||
};
|
||||
|
||||
// --- Constructor y destructor ---
|
||||
MenuOption(std::string caption, ServiceMenu::SettingsGroup group, bool hidden = false)
|
||||
: caption_(std::move(caption)),
|
||||
group_(group),
|
||||
hidden_(hidden) {}
|
||||
virtual ~MenuOption() = default;
|
||||
// --- Constructor y destructor ---
|
||||
MenuOption(std::string caption, ServiceMenu::SettingsGroup group, bool hidden = false)
|
||||
: caption_(std::move(caption)),
|
||||
group_(group),
|
||||
hidden_(hidden) {}
|
||||
virtual ~MenuOption() = default;
|
||||
|
||||
// --- Getters ---
|
||||
[[nodiscard]] auto getCaption() const -> const std::string& { return caption_; }
|
||||
[[nodiscard]] auto getGroup() const -> ServiceMenu::SettingsGroup { return group_; }
|
||||
[[nodiscard]] auto isHidden() const -> bool { return hidden_; }
|
||||
void setHidden(bool hidden) { hidden_ = hidden; }
|
||||
// --- Getters ---
|
||||
[[nodiscard]] auto getCaption() const -> const std::string& { return caption_; }
|
||||
[[nodiscard]] auto getGroup() const -> ServiceMenu::SettingsGroup { return group_; }
|
||||
[[nodiscard]] auto isHidden() const -> bool { return hidden_; }
|
||||
void setHidden(bool hidden) { hidden_ = hidden; }
|
||||
|
||||
[[nodiscard]] virtual auto getBehavior() const -> Behavior = 0;
|
||||
[[nodiscard]] virtual auto getValueAsString() const -> std::string { return ""; }
|
||||
virtual void adjustValue(bool adjust_up) {}
|
||||
[[nodiscard]] virtual auto getTargetGroup() const -> ServiceMenu::SettingsGroup { return ServiceMenu::SettingsGroup::MAIN; }
|
||||
virtual void executeAction() {}
|
||||
[[nodiscard]] virtual auto getBehavior() const -> Behavior = 0;
|
||||
[[nodiscard]] virtual auto getValueAsString() const -> std::string { return ""; }
|
||||
virtual void adjustValue(bool adjust_up) {}
|
||||
[[nodiscard]] virtual auto getTargetGroup() const -> ServiceMenu::SettingsGroup { return ServiceMenu::SettingsGroup::MAIN; }
|
||||
virtual void executeAction() {}
|
||||
|
||||
virtual auto getMaxValueWidth(Text* text_renderer) const -> int { return 0; } // Método virtual para que cada opción calcule el ancho de su valor más largo
|
||||
virtual auto getMaxValueWidth(Text* text_renderer) const -> int { return 0; } // Método virtual para que cada opción calcule el ancho de su valor más largo
|
||||
|
||||
protected:
|
||||
// --- Variables ---
|
||||
std::string caption_;
|
||||
ServiceMenu::SettingsGroup group_;
|
||||
bool hidden_;
|
||||
protected:
|
||||
// --- Variables ---
|
||||
std::string caption_;
|
||||
ServiceMenu::SettingsGroup group_;
|
||||
bool hidden_;
|
||||
};
|
||||
|
||||
// --- Clases Derivadas ---
|
||||
|
||||
class BoolOption : public MenuOption {
|
||||
public:
|
||||
BoolOption(const std::string& cap, ServiceMenu::SettingsGroup grp, bool* var)
|
||||
: MenuOption(cap, grp),
|
||||
linked_variable_(var) {}
|
||||
public:
|
||||
BoolOption(const std::string& cap, ServiceMenu::SettingsGroup grp, bool* var)
|
||||
: MenuOption(cap, grp),
|
||||
linked_variable_(var) {}
|
||||
|
||||
[[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::ADJUST; }
|
||||
[[nodiscard]] auto getValueAsString() const -> std::string override {
|
||||
return *linked_variable_ ? Lang::getText("[SERVICE_MENU] ON") : Lang::getText("[SERVICE_MENU] OFF");
|
||||
}
|
||||
void adjustValue(bool /*adjust_up*/) override {
|
||||
*linked_variable_ = !*linked_variable_;
|
||||
}
|
||||
auto getMaxValueWidth(Text* text_renderer) const -> int override {
|
||||
return std::max(
|
||||
text_renderer->length(Lang::getText("[SERVICE_MENU] ON"), -2),
|
||||
text_renderer->length(Lang::getText("[SERVICE_MENU] OFF"), -2));
|
||||
}
|
||||
[[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::ADJUST; }
|
||||
[[nodiscard]] auto getValueAsString() const -> std::string override {
|
||||
return *linked_variable_ ? Lang::getText("[SERVICE_MENU] ON") : Lang::getText("[SERVICE_MENU] OFF");
|
||||
}
|
||||
void adjustValue(bool /*adjust_up*/) override {
|
||||
*linked_variable_ = !*linked_variable_;
|
||||
}
|
||||
auto getMaxValueWidth(Text* text_renderer) const -> int override {
|
||||
return std::max(
|
||||
text_renderer->length(Lang::getText("[SERVICE_MENU] ON"), -2),
|
||||
text_renderer->length(Lang::getText("[SERVICE_MENU] OFF"), -2));
|
||||
}
|
||||
|
||||
private:
|
||||
bool* linked_variable_;
|
||||
private:
|
||||
bool* linked_variable_;
|
||||
};
|
||||
|
||||
class IntOption : public MenuOption {
|
||||
public:
|
||||
IntOption(const std::string& cap, ServiceMenu::SettingsGroup grp, int* var, int min, int max, int step)
|
||||
: MenuOption(cap, grp),
|
||||
linked_variable_(var),
|
||||
min_value_(min),
|
||||
max_value_(max),
|
||||
step_value_(step) {}
|
||||
public:
|
||||
IntOption(const std::string& cap, ServiceMenu::SettingsGroup grp, int* var, int min, int max, int step)
|
||||
: MenuOption(cap, grp),
|
||||
linked_variable_(var),
|
||||
min_value_(min),
|
||||
max_value_(max),
|
||||
step_value_(step) {}
|
||||
|
||||
[[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::ADJUST; }
|
||||
[[nodiscard]] auto getValueAsString() const -> std::string override { return std::to_string(*linked_variable_); }
|
||||
void adjustValue(bool adjust_up) override {
|
||||
int new_value = *linked_variable_ + (adjust_up ? step_value_ : -step_value_);
|
||||
*linked_variable_ = std::clamp(new_value, min_value_, max_value_);
|
||||
}
|
||||
auto getMaxValueWidth(Text* text_renderer) const -> int override {
|
||||
int max_width = 0;
|
||||
[[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::ADJUST; }
|
||||
[[nodiscard]] auto getValueAsString() const -> std::string override { return std::to_string(*linked_variable_); }
|
||||
void adjustValue(bool adjust_up) override {
|
||||
int new_value = *linked_variable_ + (adjust_up ? step_value_ : -step_value_);
|
||||
*linked_variable_ = std::clamp(new_value, min_value_, max_value_);
|
||||
}
|
||||
auto getMaxValueWidth(Text* text_renderer) const -> int override {
|
||||
int max_width = 0;
|
||||
|
||||
// Iterar por todos los valores posibles en el rango
|
||||
for (int value = min_value_; value <= max_value_; value += step_value_) {
|
||||
int width = text_renderer->length(std::to_string(value), -2);
|
||||
max_width = std::max(max_width, width);
|
||||
}
|
||||
|
||||
return max_width;
|
||||
// Iterar por todos los valores posibles en el rango
|
||||
for (int value = min_value_; value <= max_value_; value += step_value_) {
|
||||
int width = text_renderer->length(std::to_string(value), -2);
|
||||
max_width = std::max(max_width, width);
|
||||
}
|
||||
|
||||
private:
|
||||
int* linked_variable_;
|
||||
int min_value_, max_value_, step_value_;
|
||||
return max_width;
|
||||
}
|
||||
|
||||
private:
|
||||
int* linked_variable_;
|
||||
int min_value_, max_value_, step_value_;
|
||||
};
|
||||
|
||||
class ListOption : public MenuOption {
|
||||
public:
|
||||
ListOption(const std::string& cap, ServiceMenu::SettingsGroup grp, std::vector<std::string> values, std::function<std::string()> current_value_getter, std::function<void(const std::string&)> new_value_setter)
|
||||
: MenuOption(cap, grp),
|
||||
value_list_(std::move(values)),
|
||||
getter_(std::move(current_value_getter)),
|
||||
setter_(std::move(new_value_setter)) {
|
||||
sync();
|
||||
}
|
||||
public:
|
||||
ListOption(const std::string& cap, ServiceMenu::SettingsGroup grp, std::vector<std::string> values, std::function<std::string()> current_value_getter, std::function<void(const std::string&)> new_value_setter)
|
||||
: MenuOption(cap, grp),
|
||||
value_list_(std::move(values)),
|
||||
getter_(std::move(current_value_getter)),
|
||||
setter_(std::move(new_value_setter)) {
|
||||
sync();
|
||||
}
|
||||
|
||||
void sync() {
|
||||
std::string current_value = getter_();
|
||||
for (size_t i = 0; i < value_list_.size(); ++i) {
|
||||
if (value_list_[i] == current_value) {
|
||||
list_index_ = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::ADJUST; }
|
||||
[[nodiscard]] auto getValueAsString() const -> std::string override {
|
||||
return value_list_.empty() ? "" : value_list_[list_index_];
|
||||
}
|
||||
void adjustValue(bool adjust_up) override {
|
||||
if (value_list_.empty()) {
|
||||
void sync() {
|
||||
std::string current_value = getter_();
|
||||
for (size_t i = 0; i < value_list_.size(); ++i) {
|
||||
if (value_list_[i] == current_value) {
|
||||
list_index_ = i;
|
||||
return;
|
||||
}
|
||||
size_t size = value_list_.size();
|
||||
list_index_ = (adjust_up) ? (list_index_ + 1) % size
|
||||
: (list_index_ + size - 1) % size;
|
||||
setter_(value_list_[list_index_]);
|
||||
}
|
||||
auto getMaxValueWidth(Text* text_renderer) const -> int override {
|
||||
int max_w = 0;
|
||||
for (const auto& val : value_list_) {
|
||||
max_w = std::max(max_w, text_renderer->length(val, -2));
|
||||
}
|
||||
return max_w;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::string> value_list_;
|
||||
std::function<std::string()> getter_;
|
||||
std::function<void(const std::string&)> setter_;
|
||||
size_t list_index_{0};
|
||||
[[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::ADJUST; }
|
||||
[[nodiscard]] auto getValueAsString() const -> std::string override {
|
||||
return value_list_.empty() ? "" : value_list_[list_index_];
|
||||
}
|
||||
void adjustValue(bool adjust_up) override {
|
||||
if (value_list_.empty()) {
|
||||
return;
|
||||
}
|
||||
size_t size = value_list_.size();
|
||||
list_index_ = (adjust_up) ? (list_index_ + 1) % size
|
||||
: (list_index_ + size - 1) % size;
|
||||
setter_(value_list_[list_index_]);
|
||||
}
|
||||
auto getMaxValueWidth(Text* text_renderer) const -> int override {
|
||||
int max_w = 0;
|
||||
for (const auto& val : value_list_) {
|
||||
max_w = std::max(max_w, text_renderer->length(val, -2));
|
||||
}
|
||||
return max_w;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::string> value_list_;
|
||||
std::function<std::string()> getter_;
|
||||
std::function<void(const std::string&)> setter_;
|
||||
size_t list_index_{0};
|
||||
};
|
||||
|
||||
class FolderOption : public MenuOption {
|
||||
public:
|
||||
FolderOption(const std::string& cap, ServiceMenu::SettingsGroup grp, ServiceMenu::SettingsGroup target)
|
||||
: MenuOption(cap, grp),
|
||||
target_group_(target) {}
|
||||
public:
|
||||
FolderOption(const std::string& cap, ServiceMenu::SettingsGroup grp, ServiceMenu::SettingsGroup target)
|
||||
: MenuOption(cap, grp),
|
||||
target_group_(target) {}
|
||||
|
||||
[[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::SELECT; }
|
||||
[[nodiscard]] auto getTargetGroup() const -> ServiceMenu::SettingsGroup override { return target_group_; }
|
||||
[[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::SELECT; }
|
||||
[[nodiscard]] auto getTargetGroup() const -> ServiceMenu::SettingsGroup override { return target_group_; }
|
||||
|
||||
private:
|
||||
ServiceMenu::SettingsGroup target_group_;
|
||||
private:
|
||||
ServiceMenu::SettingsGroup target_group_;
|
||||
};
|
||||
|
||||
class ActionOption : public MenuOption {
|
||||
public:
|
||||
ActionOption(const std::string& cap, ServiceMenu::SettingsGroup grp, std::function<void()> action, bool hidden = false)
|
||||
: MenuOption(cap, grp, hidden),
|
||||
action_(std::move(action)) {}
|
||||
public:
|
||||
ActionOption(const std::string& cap, ServiceMenu::SettingsGroup grp, std::function<void()> action, bool hidden = false)
|
||||
: MenuOption(cap, grp, hidden),
|
||||
action_(std::move(action)) {}
|
||||
|
||||
[[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::SELECT; }
|
||||
void executeAction() override {
|
||||
if (action_) {
|
||||
action_();
|
||||
}
|
||||
[[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::SELECT; }
|
||||
void executeAction() override {
|
||||
if (action_) {
|
||||
action_();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<void()> action_;
|
||||
private:
|
||||
std::function<void()> action_;
|
||||
};
|
||||
|
||||
// Opción de lista con acción
|
||||
class ActionListOption : public MenuOption {
|
||||
public:
|
||||
using ValueGetter = std::function<std::string()>;
|
||||
using ValueSetter = std::function<void(const std::string&)>;
|
||||
using ActionExecutor = std::function<void()>;
|
||||
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)
|
||||
: MenuOption(caption, group, hidden),
|
||||
options_(std::move(options)),
|
||||
value_getter_(std::move(getter)),
|
||||
value_setter_(std::move(setter)),
|
||||
action_executor_(std::move(action_executor)) {
|
||||
updateCurrentIndex();
|
||||
}
|
||||
ActionListOption(const std::string& caption, ServiceMenu::SettingsGroup group, std::vector<std::string> options, ValueGetter getter, ValueSetter setter, ActionExecutor action_executor, bool hidden = false)
|
||||
: MenuOption(caption, group, hidden),
|
||||
options_(std::move(options)),
|
||||
value_getter_(std::move(getter)),
|
||||
value_setter_(std::move(setter)),
|
||||
action_executor_(std::move(action_executor)) {
|
||||
updateCurrentIndex();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::BOTH; }
|
||||
[[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(); // Sincroniza con el valor actual
|
||||
[[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::BOTH; }
|
||||
[[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(); // Sincroniza con el valor actual
|
||||
|
||||
private:
|
||||
std::vector<std::string> options_;
|
||||
ValueGetter value_getter_;
|
||||
ValueSetter value_setter_;
|
||||
ActionExecutor action_executor_;
|
||||
size_t current_index_{0};
|
||||
private:
|
||||
std::vector<std::string> options_;
|
||||
ValueGetter value_getter_;
|
||||
ValueSetter value_setter_;
|
||||
ActionExecutor action_executor_;
|
||||
size_t current_index_{0};
|
||||
|
||||
void updateCurrentIndex();
|
||||
[[nodiscard]] auto findCurrentIndex() const -> size_t;
|
||||
void updateCurrentIndex();
|
||||
[[nodiscard]] auto findCurrentIndex() const -> size_t;
|
||||
};
|
||||
@@ -15,115 +15,115 @@ class MenuOption;
|
||||
class Text;
|
||||
|
||||
class MenuRenderer {
|
||||
public:
|
||||
// --- Nuevo: Enum para el modo de posicionamiento ---
|
||||
enum class PositionMode {
|
||||
CENTERED, // La ventana se centra en el punto especificado
|
||||
FIXED // La esquina superior izquierda coincide con el punto
|
||||
};
|
||||
public:
|
||||
// --- Nuevo: Enum para el modo de posicionamiento ---
|
||||
enum class PositionMode {
|
||||
CENTERED, // La ventana se centra en el punto especificado
|
||||
FIXED // La esquina superior izquierda coincide con el punto
|
||||
};
|
||||
|
||||
MenuRenderer(const ServiceMenu* menu_state, std::shared_ptr<Text> element_text, std::shared_ptr<Text> title_text);
|
||||
MenuRenderer(const ServiceMenu* menu_state, std::shared_ptr<Text> element_text, std::shared_ptr<Text> title_text);
|
||||
|
||||
// --- Métodos principales de la vista ---
|
||||
void render(const ServiceMenu* menu_state);
|
||||
void update(const ServiceMenu* menu_state, float delta_time);
|
||||
// --- Métodos principales de la vista ---
|
||||
void render(const ServiceMenu* menu_state);
|
||||
void update(const ServiceMenu* menu_state, float delta_time);
|
||||
|
||||
// --- Nuevos: Métodos de control de visibilidad y animación ---
|
||||
void show(const ServiceMenu* menu_state);
|
||||
void hide();
|
||||
[[nodiscard]] auto isVisible() const -> bool { return visible_; }
|
||||
[[nodiscard]] auto isFullyVisible() const -> bool { return visible_ && !show_hide_animation_.active && !resize_animation_.active; }
|
||||
[[nodiscard]] auto isAnimating() const -> bool { return resize_animation_.active || show_hide_animation_.active; }
|
||||
// --- Nuevos: Métodos de control de visibilidad y animación ---
|
||||
void show(const ServiceMenu* menu_state);
|
||||
void hide();
|
||||
[[nodiscard]] auto isVisible() const -> bool { return visible_; }
|
||||
[[nodiscard]] auto isFullyVisible() const -> bool { return visible_ && !show_hide_animation_.active && !resize_animation_.active; }
|
||||
[[nodiscard]] auto isAnimating() const -> bool { return resize_animation_.active || show_hide_animation_.active; }
|
||||
|
||||
// --- Nuevos: Métodos de configuración de posición ---
|
||||
void setPosition(float x, float y, PositionMode mode);
|
||||
// --- Nuevos: Métodos de configuración de posición ---
|
||||
void setPosition(float x, float y, PositionMode mode);
|
||||
|
||||
// Método para notificar al renderer que el layout puede haber cambiado
|
||||
void onLayoutChanged(const ServiceMenu* menu_state);
|
||||
void setLayout(const ServiceMenu* menu_state);
|
||||
// Método para notificar al renderer que el layout puede haber cambiado
|
||||
void onLayoutChanged(const ServiceMenu* menu_state);
|
||||
void setLayout(const ServiceMenu* menu_state);
|
||||
|
||||
// Getters
|
||||
[[nodiscard]] auto getRect() const -> const SDL_FRect& { return rect_; }
|
||||
// Getters
|
||||
[[nodiscard]] auto getRect() const -> const SDL_FRect& { return rect_; }
|
||||
|
||||
private:
|
||||
// --- Referencias a los renderizadores de texto ---
|
||||
std::shared_ptr<Text> element_text_;
|
||||
std::shared_ptr<Text> title_text_;
|
||||
private:
|
||||
// --- Referencias a los renderizadores de texto ---
|
||||
std::shared_ptr<Text> element_text_;
|
||||
std::shared_ptr<Text> title_text_;
|
||||
|
||||
// --- Variables de estado de la vista (layout y animación) ---
|
||||
SDL_FRect rect_{};
|
||||
SDL_FRect border_rect_{};
|
||||
size_t width_ = 0;
|
||||
size_t height_ = 0;
|
||||
size_t options_height_ = 0;
|
||||
size_t options_padding_ = 0;
|
||||
size_t options_y_ = 0;
|
||||
size_t title_height_ = 0;
|
||||
size_t title_padding_ = 0;
|
||||
size_t upper_height_ = 0;
|
||||
size_t lower_height_ = 0;
|
||||
size_t lower_padding_ = 0;
|
||||
Uint32 color_counter_ = 0;
|
||||
bool visible_ = false;
|
||||
// --- Variables de estado de la vista (layout y animación) ---
|
||||
SDL_FRect rect_{};
|
||||
SDL_FRect border_rect_{};
|
||||
size_t width_ = 0;
|
||||
size_t height_ = 0;
|
||||
size_t options_height_ = 0;
|
||||
size_t options_padding_ = 0;
|
||||
size_t options_y_ = 0;
|
||||
size_t title_height_ = 0;
|
||||
size_t title_padding_ = 0;
|
||||
size_t upper_height_ = 0;
|
||||
size_t lower_height_ = 0;
|
||||
size_t lower_padding_ = 0;
|
||||
Uint32 color_counter_ = 0;
|
||||
bool visible_ = false;
|
||||
|
||||
// --- Posicionamiento ---
|
||||
PositionMode position_mode_ = PositionMode::CENTERED;
|
||||
float anchor_x_ = 0.0F;
|
||||
float anchor_y_ = 0.0F;
|
||||
// --- Posicionamiento ---
|
||||
PositionMode position_mode_ = PositionMode::CENTERED;
|
||||
float anchor_x_ = 0.0F;
|
||||
float anchor_y_ = 0.0F;
|
||||
|
||||
// --- Límites de tamaño máximo ---
|
||||
size_t max_menu_width_ = 0;
|
||||
size_t max_menu_height_ = 0;
|
||||
// --- Límites de tamaño máximo ---
|
||||
size_t max_menu_width_ = 0;
|
||||
size_t max_menu_height_ = 0;
|
||||
|
||||
// --- Estructuras de Animación ---
|
||||
struct ResizeAnimation {
|
||||
bool active = false;
|
||||
float start_width, start_height;
|
||||
float target_width, target_height;
|
||||
float elapsed = 0.0F;
|
||||
float duration = 0.2F;
|
||||
// --- Estructuras de Animación ---
|
||||
struct ResizeAnimation {
|
||||
bool active = false;
|
||||
float start_width, start_height;
|
||||
float target_width, target_height;
|
||||
float elapsed = 0.0F;
|
||||
float duration = 0.2F;
|
||||
|
||||
void start(float from_w, float from_h, float to_w, float to_h);
|
||||
void stop();
|
||||
} resize_animation_;
|
||||
void start(float from_w, float from_h, float to_w, float to_h);
|
||||
void stop();
|
||||
} resize_animation_;
|
||||
|
||||
struct ShowHideAnimation {
|
||||
enum class Type { NONE,
|
||||
SHOWING,
|
||||
HIDING };
|
||||
Type type = Type::NONE;
|
||||
bool active = false;
|
||||
float target_width, target_height;
|
||||
float elapsed = 0.0F;
|
||||
float duration = 0.25F;
|
||||
struct ShowHideAnimation {
|
||||
enum class Type { NONE,
|
||||
SHOWING,
|
||||
HIDING };
|
||||
Type type = Type::NONE;
|
||||
bool active = false;
|
||||
float target_width, target_height;
|
||||
float elapsed = 0.0F;
|
||||
float duration = 0.25F;
|
||||
|
||||
void startShow(float to_w, float to_h);
|
||||
void startHide();
|
||||
void stop();
|
||||
} show_hide_animation_;
|
||||
void startShow(float to_w, float to_h);
|
||||
void startHide();
|
||||
void stop();
|
||||
} show_hide_animation_;
|
||||
|
||||
// --- Anchos precalculados ---
|
||||
std::array<int, ServiceMenu::SETTINGS_GROUP_SIZE> group_menu_widths_ = {};
|
||||
// --- Anchos precalculados ---
|
||||
std::array<int, ServiceMenu::SETTINGS_GROUP_SIZE> group_menu_widths_ = {};
|
||||
|
||||
// --- Métodos privados de la vista ---
|
||||
void initializeMaxSizes();
|
||||
void setAnchors(const ServiceMenu* menu_state);
|
||||
auto calculateNewRect(const ServiceMenu* menu_state) -> SDL_FRect;
|
||||
void resize(const ServiceMenu* menu_state);
|
||||
void setSize(const ServiceMenu* menu_state);
|
||||
// --- Métodos privados de la vista ---
|
||||
void initializeMaxSizes();
|
||||
void setAnchors(const ServiceMenu* menu_state);
|
||||
auto calculateNewRect(const ServiceMenu* menu_state) -> SDL_FRect;
|
||||
void resize(const ServiceMenu* menu_state);
|
||||
void setSize(const ServiceMenu* menu_state);
|
||||
|
||||
void updateAnimations(float delta_time);
|
||||
void updateResizeAnimation(float delta_time);
|
||||
void updateShowHideAnimation(float delta_time);
|
||||
void updatePosition();
|
||||
void updateAnimations(float delta_time);
|
||||
void updateResizeAnimation(float delta_time);
|
||||
void updateShowHideAnimation(float delta_time);
|
||||
void updatePosition();
|
||||
|
||||
void precalculateMenuWidths(const std::vector<std::unique_ptr<MenuOption>>& all_options, const ServiceMenu* menu_state);
|
||||
[[nodiscard]] auto getMenuWidthForGroup(ServiceMenu::SettingsGroup group) const -> int;
|
||||
[[nodiscard]] auto getAnimatedSelectedColor() const -> Color;
|
||||
void updateColorCounter();
|
||||
auto setRect(SDL_FRect rect) -> SDL_FRect;
|
||||
[[nodiscard]] auto getTruncatedValueWidth(const std::string& value, int available_width) const -> int;
|
||||
[[nodiscard]] auto getTruncatedValue(const std::string& value, int available_width) const -> std::string;
|
||||
[[nodiscard]] static auto easeOut(float t) -> float;
|
||||
[[nodiscard]] auto shouldShowContent() const -> bool;
|
||||
void precalculateMenuWidths(const std::vector<std::unique_ptr<MenuOption>>& all_options, const ServiceMenu* menu_state);
|
||||
[[nodiscard]] auto getMenuWidthForGroup(ServiceMenu::SettingsGroup group) const -> int;
|
||||
[[nodiscard]] auto getAnimatedSelectedColor() const -> Color;
|
||||
void updateColorCounter();
|
||||
auto setRect(SDL_FRect rect) -> SDL_FRect;
|
||||
[[nodiscard]] auto getTruncatedValueWidth(const std::string& value, int available_width) const -> int;
|
||||
[[nodiscard]] auto getTruncatedValue(const std::string& value, int available_width) const -> std::string;
|
||||
[[nodiscard]] static auto easeOut(float t) -> float;
|
||||
[[nodiscard]] auto shouldShowContent() const -> bool;
|
||||
};
|
||||
@@ -15,98 +15,98 @@ class Texture;
|
||||
|
||||
// --- Clase Notifier: gestiona las notificaciones en pantalla (singleton) ---
|
||||
class Notifier {
|
||||
public:
|
||||
// --- Enums ---
|
||||
enum class Position {
|
||||
TOP, // Parte superior
|
||||
BOTTOM, // Parte inferior
|
||||
LEFT, // Lado izquierdo
|
||||
MIDDLE, // Centro
|
||||
RIGHT, // Lado derecho
|
||||
};
|
||||
public:
|
||||
// --- Enums ---
|
||||
enum class Position {
|
||||
TOP, // Parte superior
|
||||
BOTTOM, // Parte inferior
|
||||
LEFT, // Lado izquierdo
|
||||
MIDDLE, // Centro
|
||||
RIGHT, // Lado derecho
|
||||
};
|
||||
|
||||
// --- Métodos de singleton ---
|
||||
static void init(const std::string& icon_file, std::shared_ptr<Text> text); // Inicializa el singleton
|
||||
static void destroy(); // Libera el singleton
|
||||
static auto get() -> Notifier*; // Obtiene la instancia
|
||||
// --- Métodos de singleton ---
|
||||
static void init(const std::string& icon_file, std::shared_ptr<Text> text); // Inicializa el singleton
|
||||
static void destroy(); // Libera el singleton
|
||||
static auto get() -> Notifier*; // Obtiene la instancia
|
||||
|
||||
// --- Métodos principales ---
|
||||
void render(); // Dibuja las notificaciones por pantalla
|
||||
void update(float delta_time); // Actualiza el estado de las notificaciones
|
||||
// --- Métodos principales ---
|
||||
void render(); // Dibuja las notificaciones por pantalla
|
||||
void update(float delta_time); // Actualiza el estado de las notificaciones
|
||||
|
||||
// --- Gestión de notificaciones ---
|
||||
void show(std::vector<std::string> texts, int icon = -1, const std::string& code = std::string()); // Muestra una notificación de texto por pantalla
|
||||
[[nodiscard]] auto isActive() const -> bool { return !notifications_.empty(); } // Indica si hay notificaciones activas
|
||||
auto getCodes() -> std::vector<std::string>; // Obtiene los códigos de las notificaciones activas
|
||||
auto checkCode(const std::string& code) -> bool { return stringInVector(getCodes(), code); } // Comprueba si hay alguna notificación con un código concreto
|
||||
// --- Gestión de notificaciones ---
|
||||
void show(std::vector<std::string> texts, int icon = -1, const std::string& code = std::string()); // Muestra una notificación de texto por pantalla
|
||||
[[nodiscard]] auto isActive() const -> bool { return !notifications_.empty(); } // Indica si hay notificaciones activas
|
||||
auto getCodes() -> std::vector<std::string>; // Obtiene los códigos de las notificaciones activas
|
||||
auto checkCode(const std::string& code) -> bool { return stringInVector(getCodes(), code); } // Comprueba si hay alguna notificación con un código concreto
|
||||
|
||||
private:
|
||||
// --- Constantes de tiempo (en segundos) ---
|
||||
static constexpr float STAY_DURATION_S = 2.5F; // Tiempo que se ve la notificación (150 frames @ 60fps)
|
||||
static constexpr float ANIMATION_SPEED_PX_PER_S = 60.0F; // Velocidad de animación (1 pixel/frame @ 60fps)
|
||||
private:
|
||||
// --- Constantes de tiempo (en segundos) ---
|
||||
static constexpr float STAY_DURATION_S = 2.5F; // Tiempo que se ve la notificación (150 frames @ 60fps)
|
||||
static constexpr float ANIMATION_SPEED_PX_PER_S = 60.0F; // Velocidad de animación (1 pixel/frame @ 60fps)
|
||||
|
||||
// --- Enums privados ---
|
||||
enum class State {
|
||||
RISING, // Apareciendo
|
||||
STAY, // Visible
|
||||
VANISHING, // Desapareciendo
|
||||
FINISHED, // Terminada
|
||||
};
|
||||
// --- Enums privados ---
|
||||
enum class State {
|
||||
RISING, // Apareciendo
|
||||
STAY, // Visible
|
||||
VANISHING, // Desapareciendo
|
||||
FINISHED, // Terminada
|
||||
};
|
||||
|
||||
enum class Shape {
|
||||
ROUNDED, // Forma redondeada
|
||||
SQUARED, // Forma cuadrada
|
||||
};
|
||||
enum class Shape {
|
||||
ROUNDED, // Forma redondeada
|
||||
SQUARED, // Forma cuadrada
|
||||
};
|
||||
|
||||
// --- Estructuras privadas ---
|
||||
struct Notification {
|
||||
std::shared_ptr<Texture> texture; // Textura de la notificación
|
||||
std::shared_ptr<Sprite> sprite; // Sprite asociado
|
||||
std::vector<std::string> texts; // Textos a mostrar
|
||||
SDL_FRect rect; // Rectángulo de la notificación
|
||||
std::string code; // Código identificador de la notificación
|
||||
State state{State::RISING}; // Estado de la notificación
|
||||
Shape shape{Shape::SQUARED}; // Forma de la notificación
|
||||
float timer{0.0F}; // Timer en segundos
|
||||
int y{0}; // Posición vertical
|
||||
int travel_dist{0}; // Distancia a recorrer
|
||||
// --- Estructuras privadas ---
|
||||
struct Notification {
|
||||
std::shared_ptr<Texture> texture; // Textura de la notificación
|
||||
std::shared_ptr<Sprite> sprite; // Sprite asociado
|
||||
std::vector<std::string> texts; // Textos a mostrar
|
||||
SDL_FRect rect; // Rectángulo de la notificación
|
||||
std::string code; // Código identificador de la notificación
|
||||
State state{State::RISING}; // Estado de la notificación
|
||||
Shape shape{Shape::SQUARED}; // Forma de la notificación
|
||||
float timer{0.0F}; // Timer en segundos
|
||||
int y{0}; // Posición vertical
|
||||
int travel_dist{0}; // Distancia a recorrer
|
||||
|
||||
// Constructor
|
||||
explicit Notification()
|
||||
: texture(nullptr),
|
||||
sprite(nullptr),
|
||||
rect{0, 0, 0, 0} {}
|
||||
};
|
||||
// Constructor
|
||||
explicit Notification()
|
||||
: texture(nullptr),
|
||||
sprite(nullptr),
|
||||
rect{0, 0, 0, 0} {}
|
||||
};
|
||||
|
||||
// --- Objetos y punteros ---
|
||||
SDL_Renderer* renderer_; // El renderizador de la ventana
|
||||
std::shared_ptr<Texture> icon_texture_; // Textura para los iconos de las notificaciones
|
||||
std::shared_ptr<Text> text_; // Objeto para dibujar texto
|
||||
// --- Objetos y punteros ---
|
||||
SDL_Renderer* renderer_; // El renderizador de la ventana
|
||||
std::shared_ptr<Texture> icon_texture_; // Textura para los iconos de las notificaciones
|
||||
std::shared_ptr<Text> text_; // Objeto para dibujar texto
|
||||
|
||||
// --- Variables de estado ---
|
||||
std::vector<Notification> notifications_; // Lista de notificaciones activas
|
||||
Color bg_color_; // Color de fondo de las notificaciones
|
||||
// Nota: wait_time_ eliminado, ahora se usa STAY_DURATION_S
|
||||
bool stack_; // Indica si las notificaciones se apilan
|
||||
bool has_icons_; // Indica si el notificador tiene textura para iconos
|
||||
// --- Variables de estado ---
|
||||
std::vector<Notification> notifications_; // Lista de notificaciones activas
|
||||
Color bg_color_; // Color de fondo de las notificaciones
|
||||
// Nota: wait_time_ eliminado, ahora se usa STAY_DURATION_S
|
||||
bool stack_; // Indica si las notificaciones se apilan
|
||||
bool has_icons_; // Indica si el notificador tiene textura para iconos
|
||||
|
||||
// --- Métodos internos ---
|
||||
void clearFinishedNotifications(); // Elimina las notificaciones cuyo estado es FINISHED
|
||||
void clearAllNotifications(); // Elimina todas las notificaciones activas, sin importar el estado
|
||||
[[nodiscard]] auto shouldProcessNotification(int index) const -> bool; // Determina si una notificación debe ser procesada (según su estado y posición)
|
||||
void processNotification(int index, float delta_time); // Procesa una notificación en la posición dada: actualiza su estado y comportamiento visual
|
||||
static void playNotificationSoundIfNeeded(const Notification& notification); // Reproduce sonido asociado si es necesario (dependiendo del estado o contenido)
|
||||
void updateNotificationState(int index, float delta_time); // Actualiza el estado interno de una notificación (ej. de RISING a STAY)
|
||||
void handleRisingState(int index, float delta_time); // Lógica de animación para el estado RISING (apareciendo)
|
||||
void handleStayState(int index); // Lógica para mantener una notificación visible en el estado STAY
|
||||
void handleVanishingState(int index, float delta_time); // Lógica de animación para el estado VANISHING (desapareciendo)
|
||||
static void moveNotificationVertically(Notification& notification, float pixels_to_move); // Mueve verticalmente una notificación con la cantidad de pixels especificada
|
||||
void transitionToStayState(int index); // Cambia el estado de una notificación de RISING a STAY cuando ha alcanzado su posición final
|
||||
// --- Métodos internos ---
|
||||
void clearFinishedNotifications(); // Elimina las notificaciones cuyo estado es FINISHED
|
||||
void clearAllNotifications(); // Elimina todas las notificaciones activas, sin importar el estado
|
||||
[[nodiscard]] auto shouldProcessNotification(int index) const -> bool; // Determina si una notificación debe ser procesada (según su estado y posición)
|
||||
void processNotification(int index, float delta_time); // Procesa una notificación en la posición dada: actualiza su estado y comportamiento visual
|
||||
static void playNotificationSoundIfNeeded(const Notification& notification); // Reproduce sonido asociado si es necesario (dependiendo del estado o contenido)
|
||||
void updateNotificationState(int index, float delta_time); // Actualiza el estado interno de una notificación (ej. de RISING a STAY)
|
||||
void handleRisingState(int index, float delta_time); // Lógica de animación para el estado RISING (apareciendo)
|
||||
void handleStayState(int index); // Lógica para mantener una notificación visible en el estado STAY
|
||||
void handleVanishingState(int index, float delta_time); // Lógica de animación para el estado VANISHING (desapareciendo)
|
||||
static void moveNotificationVertically(Notification& notification, float pixels_to_move); // Mueve verticalmente una notificación con la cantidad de pixels especificada
|
||||
void transitionToStayState(int index); // Cambia el estado de una notificación de RISING a STAY cuando ha alcanzado su posición final
|
||||
|
||||
// --- Constructores y destructor privados (singleton) ---
|
||||
Notifier(const std::string& icon_file, std::shared_ptr<Text> text); // Constructor privado
|
||||
~Notifier() = default; // Destructor privado
|
||||
// --- Constructores y destructor privados (singleton) ---
|
||||
Notifier(const std::string& icon_file, std::shared_ptr<Text> text); // Constructor privado
|
||||
~Notifier() = default; // Destructor privado
|
||||
|
||||
// --- Instancia singleton ---
|
||||
static Notifier* instance; // Instancia única de Notifier
|
||||
// --- Instancia singleton ---
|
||||
static Notifier* instance; // Instancia única de Notifier
|
||||
};
|
||||
@@ -17,112 +17,112 @@ class MenuOption;
|
||||
class MenuRenderer;
|
||||
|
||||
class ServiceMenu {
|
||||
public:
|
||||
// --- Enums y constantes ---
|
||||
enum class SettingsGroup {
|
||||
CONTROLS,
|
||||
VIDEO,
|
||||
AUDIO,
|
||||
SETTINGS,
|
||||
SYSTEM,
|
||||
MAIN
|
||||
};
|
||||
enum class GroupAlignment {
|
||||
CENTERED,
|
||||
LEFT
|
||||
};
|
||||
static constexpr size_t OPTIONS_HORIZONTAL_PADDING = 20;
|
||||
static constexpr size_t MIN_WIDTH = 240;
|
||||
static constexpr size_t MIN_GAP_OPTION_VALUE = 30;
|
||||
static constexpr size_t SETTINGS_GROUP_SIZE = 6;
|
||||
public:
|
||||
// --- Enums y constantes ---
|
||||
enum class SettingsGroup {
|
||||
CONTROLS,
|
||||
VIDEO,
|
||||
AUDIO,
|
||||
SETTINGS,
|
||||
SYSTEM,
|
||||
MAIN
|
||||
};
|
||||
enum class GroupAlignment {
|
||||
CENTERED,
|
||||
LEFT
|
||||
};
|
||||
static constexpr size_t OPTIONS_HORIZONTAL_PADDING = 20;
|
||||
static constexpr size_t MIN_WIDTH = 240;
|
||||
static constexpr size_t MIN_GAP_OPTION_VALUE = 30;
|
||||
static constexpr size_t SETTINGS_GROUP_SIZE = 6;
|
||||
|
||||
using StateChangeCallback = std::function<void(bool is_active)>;
|
||||
using StateChangeCallback = std::function<void(bool is_active)>;
|
||||
|
||||
// --- Métodos de singleton ---
|
||||
static void init();
|
||||
static void destroy();
|
||||
static auto get() -> ServiceMenu*;
|
||||
ServiceMenu(const ServiceMenu&) = delete;
|
||||
auto operator=(const ServiceMenu&) -> ServiceMenu& = delete;
|
||||
// --- Métodos de singleton ---
|
||||
static void init();
|
||||
static void destroy();
|
||||
static auto get() -> ServiceMenu*;
|
||||
ServiceMenu(const ServiceMenu&) = delete;
|
||||
auto operator=(const ServiceMenu&) -> ServiceMenu& = delete;
|
||||
|
||||
// --- Métodos principales ---
|
||||
void toggle();
|
||||
void render();
|
||||
void update(float delta_time);
|
||||
void reset();
|
||||
// --- Métodos principales ---
|
||||
void toggle();
|
||||
void render();
|
||||
void update(float delta_time);
|
||||
void reset();
|
||||
|
||||
// --- Lógica de navegación ---
|
||||
void setSelectorUp();
|
||||
void setSelectorDown();
|
||||
void adjustOption(bool adjust_up);
|
||||
void selectOption();
|
||||
void moveBack();
|
||||
// --- Lógica de navegación ---
|
||||
void setSelectorUp();
|
||||
void setSelectorDown();
|
||||
void adjustOption(bool adjust_up);
|
||||
void selectOption();
|
||||
void moveBack();
|
||||
|
||||
// --- Método para manejar eventos ---
|
||||
void handleEvent(const SDL_Event& event);
|
||||
auto checkInput() -> bool;
|
||||
// --- Método para manejar eventos ---
|
||||
void handleEvent(const SDL_Event& event);
|
||||
auto checkInput() -> bool;
|
||||
|
||||
// --- Método principal para refresco externo ---
|
||||
void refresh(); // Refresca los valores y el layout del menú bajo demanda
|
||||
// --- Método principal para refresco externo ---
|
||||
void refresh(); // Refresca los valores y el layout del menú bajo demanda
|
||||
|
||||
// --- Método para registrar el callback ---
|
||||
void setStateChangeCallback(StateChangeCallback callback);
|
||||
// --- Método para registrar el callback ---
|
||||
void setStateChangeCallback(StateChangeCallback callback);
|
||||
|
||||
// --- Getters para el estado ---
|
||||
[[nodiscard]] auto isDefiningButtons() const -> bool;
|
||||
[[nodiscard]] auto isAnimating() const -> bool; // Nuevo getter
|
||||
// --- Getters para el estado ---
|
||||
[[nodiscard]] auto isDefiningButtons() const -> bool;
|
||||
[[nodiscard]] auto isAnimating() const -> bool; // Nuevo getter
|
||||
|
||||
// --- Getters para que el Renderer pueda leer el estado ---
|
||||
[[nodiscard]] auto isEnabled() const -> bool { return enabled_; }
|
||||
[[nodiscard]] auto getTitle() const -> const std::string& { return title_; }
|
||||
[[nodiscard]] auto getCurrentGroup() const -> SettingsGroup { return current_settings_group_; }
|
||||
[[nodiscard]] auto getCurrentGroupAlignment() const -> GroupAlignment;
|
||||
[[nodiscard]] auto getDisplayOptions() const -> const std::vector<MenuOption*>& { return display_options_; }
|
||||
[[nodiscard]] auto getAllOptions() const -> const std::vector<std::unique_ptr<MenuOption>>& { return options_; }
|
||||
[[nodiscard]] auto getSelectedIndex() const -> size_t { return selected_; }
|
||||
[[nodiscard]] auto getOptionPairs() const -> const std::vector<std::pair<std::string, std::string>>& { return option_pairs_; }
|
||||
[[nodiscard]] auto countOptionsInGroup(SettingsGroup group) const -> size_t;
|
||||
// --- Getters para que el Renderer pueda leer el estado ---
|
||||
[[nodiscard]] auto isEnabled() const -> bool { return enabled_; }
|
||||
[[nodiscard]] auto getTitle() const -> const std::string& { return title_; }
|
||||
[[nodiscard]] auto getCurrentGroup() const -> SettingsGroup { return current_settings_group_; }
|
||||
[[nodiscard]] auto getCurrentGroupAlignment() const -> GroupAlignment;
|
||||
[[nodiscard]] auto getDisplayOptions() const -> const std::vector<MenuOption*>& { return display_options_; }
|
||||
[[nodiscard]] auto getAllOptions() const -> const std::vector<std::unique_ptr<MenuOption>>& { return options_; }
|
||||
[[nodiscard]] auto getSelectedIndex() const -> size_t { return selected_; }
|
||||
[[nodiscard]] auto getOptionPairs() const -> const std::vector<std::pair<std::string, std::string>>& { return option_pairs_; }
|
||||
[[nodiscard]] auto countOptionsInGroup(SettingsGroup group) const -> size_t;
|
||||
|
||||
private:
|
||||
bool enabled_ = false;
|
||||
std::vector<std::unique_ptr<MenuOption>> options_;
|
||||
std::vector<MenuOption*> display_options_;
|
||||
std::vector<std::pair<std::string, std::string>> option_pairs_;
|
||||
SettingsGroup current_settings_group_;
|
||||
SettingsGroup previous_settings_group_;
|
||||
std::string title_;
|
||||
size_t selected_ = 0;
|
||||
size_t main_menu_selected_ = 0;
|
||||
std::unique_ptr<UIMessage> restart_message_ui_;
|
||||
bool last_pending_changes_ = false;
|
||||
std::unique_ptr<DefineButtons> define_buttons_;
|
||||
std::unique_ptr<MenuRenderer> renderer_;
|
||||
StateChangeCallback state_change_callback_;
|
||||
private:
|
||||
bool enabled_ = false;
|
||||
std::vector<std::unique_ptr<MenuOption>> options_;
|
||||
std::vector<MenuOption*> display_options_;
|
||||
std::vector<std::pair<std::string, std::string>> option_pairs_;
|
||||
SettingsGroup current_settings_group_;
|
||||
SettingsGroup previous_settings_group_;
|
||||
std::string title_;
|
||||
size_t selected_ = 0;
|
||||
size_t main_menu_selected_ = 0;
|
||||
std::unique_ptr<UIMessage> restart_message_ui_;
|
||||
bool last_pending_changes_ = false;
|
||||
std::unique_ptr<DefineButtons> define_buttons_;
|
||||
std::unique_ptr<MenuRenderer> renderer_;
|
||||
StateChangeCallback state_change_callback_;
|
||||
|
||||
// --- Métodos de lógica interna ---
|
||||
void updateDisplayOptions();
|
||||
void updateOptionPairs();
|
||||
void initializeOptions();
|
||||
void updateMenu();
|
||||
void applySettings();
|
||||
void applyControlsSettings();
|
||||
void applyVideoSettings();
|
||||
static void applyAudioSettings();
|
||||
void applySettingsSettings();
|
||||
[[nodiscard]] auto getOptionByCaption(const std::string& caption) const -> MenuOption*;
|
||||
void adjustListValues();
|
||||
static void playMoveSound();
|
||||
static void playAdjustSound();
|
||||
static void playSelectSound();
|
||||
static void playBackSound();
|
||||
[[nodiscard]] static auto settingsGroupToString(SettingsGroup group) -> std::string;
|
||||
void setHiddenOptions();
|
||||
void setEnabledInternal(bool enabled); // Método privado para cambiar estado y notificar
|
||||
// --- Métodos de lógica interna ---
|
||||
void updateDisplayOptions();
|
||||
void updateOptionPairs();
|
||||
void initializeOptions();
|
||||
void updateMenu();
|
||||
void applySettings();
|
||||
void applyControlsSettings();
|
||||
void applyVideoSettings();
|
||||
static void applyAudioSettings();
|
||||
void applySettingsSettings();
|
||||
[[nodiscard]] auto getOptionByCaption(const std::string& caption) const -> MenuOption*;
|
||||
void adjustListValues();
|
||||
static void playMoveSound();
|
||||
static void playAdjustSound();
|
||||
static void playSelectSound();
|
||||
static void playBackSound();
|
||||
[[nodiscard]] static auto settingsGroupToString(SettingsGroup group) -> std::string;
|
||||
void setHiddenOptions();
|
||||
void setEnabledInternal(bool enabled); // Método privado para cambiar estado y notificar
|
||||
|
||||
// --- Constructores y destructor privados (singleton) ---
|
||||
ServiceMenu();
|
||||
~ServiceMenu() = default;
|
||||
// --- Constructores y destructor privados (singleton) ---
|
||||
ServiceMenu();
|
||||
~ServiceMenu() = default;
|
||||
|
||||
// --- Instancia singleton ---
|
||||
static ServiceMenu* instance;
|
||||
// --- Instancia singleton ---
|
||||
static ServiceMenu* instance;
|
||||
};
|
||||
@@ -9,48 +9,48 @@ class Text;
|
||||
|
||||
// Clase para mostrar mensajes animados en la interfaz de usuario
|
||||
class UIMessage {
|
||||
public:
|
||||
// Constructor: recibe el renderizador de texto, el mensaje y el color
|
||||
UIMessage(std::shared_ptr<Text> text_renderer, std::string message_text, const Color& color);
|
||||
public:
|
||||
// Constructor: recibe el renderizador de texto, el mensaje y el color
|
||||
UIMessage(std::shared_ptr<Text> text_renderer, std::string message_text, const Color& color);
|
||||
|
||||
// Muestra el mensaje con animación de entrada
|
||||
void show();
|
||||
// Muestra el mensaje con animación de entrada
|
||||
void show();
|
||||
|
||||
// Oculta el mensaje con animación de salida
|
||||
void hide();
|
||||
// Oculta el mensaje con animación de salida
|
||||
void hide();
|
||||
|
||||
// Actualiza el estado de la animación (debe llamarse cada frame)
|
||||
void update(float delta_time);
|
||||
// Actualiza el estado de la animación (debe llamarse cada frame)
|
||||
void update(float delta_time);
|
||||
|
||||
// Dibuja el mensaje en pantalla si está visible
|
||||
void render();
|
||||
// Dibuja el mensaje en pantalla si está visible
|
||||
void render();
|
||||
|
||||
// Indica si el mensaje está visible actualmente
|
||||
[[nodiscard]] auto isVisible() const -> bool;
|
||||
// Indica si el mensaje está visible actualmente
|
||||
[[nodiscard]] auto isVisible() const -> bool;
|
||||
|
||||
// Permite actualizar la posición del mensaje (por ejemplo, si el menú se mueve)
|
||||
void setPosition(float new_base_x, float new_base_y);
|
||||
// Permite actualizar la posición del mensaje (por ejemplo, si el menú se mueve)
|
||||
void setPosition(float new_base_x, float new_base_y);
|
||||
|
||||
private:
|
||||
// --- Configuración ---
|
||||
std::shared_ptr<Text> text_renderer_; // Renderizador de texto
|
||||
std::string text_; // Texto del mensaje a mostrar
|
||||
Color color_; // Color del texto
|
||||
private:
|
||||
// --- Configuración ---
|
||||
std::shared_ptr<Text> text_renderer_; // Renderizador de texto
|
||||
std::string text_; // Texto del mensaje a mostrar
|
||||
Color color_; // Color del texto
|
||||
|
||||
// --- Estado ---
|
||||
bool visible_ = false; // Indica si el mensaje está visible
|
||||
bool animating_ = false; // Indica si el mensaje está en proceso de animación
|
||||
float base_x_ = 0.0F; // Posición X base donde se muestra el mensaje
|
||||
float base_y_ = 0.0F; // Posición Y base donde se muestra el mensaje
|
||||
float y_offset_ = 0.0F; // Desplazamiento vertical actual del mensaje (para animación)
|
||||
// --- Estado ---
|
||||
bool visible_ = false; // Indica si el mensaje está visible
|
||||
bool animating_ = false; // Indica si el mensaje está en proceso de animación
|
||||
float base_x_ = 0.0F; // Posición X base donde se muestra el mensaje
|
||||
float base_y_ = 0.0F; // Posición Y base donde se muestra el mensaje
|
||||
float y_offset_ = 0.0F; // Desplazamiento vertical actual del mensaje (para animación)
|
||||
|
||||
// --- Animación ---
|
||||
float start_y_ = 0.0F; // Posición Y inicial de la animación
|
||||
float target_y_ = 0.0F; // Posición Y objetivo de la animación
|
||||
float animation_timer_ = 0.0F; // Timer actual de la animación en segundos
|
||||
static constexpr float ANIMATION_DURATION_S = 0.133F; // Duración total de la animación (8 frames @ 60fps)
|
||||
static constexpr float DESP = -8.0F; // Distancia a desplazarse
|
||||
// --- Animación ---
|
||||
float start_y_ = 0.0F; // Posición Y inicial de la animación
|
||||
float target_y_ = 0.0F; // Posición Y objetivo de la animación
|
||||
float animation_timer_ = 0.0F; // Timer actual de la animación en segundos
|
||||
static constexpr float ANIMATION_DURATION_S = 0.133F; // Duración total de la animación (8 frames @ 60fps)
|
||||
static constexpr float DESP = -8.0F; // Distancia a desplazarse
|
||||
|
||||
// Actualiza la interpolación de la animación (ease out/in cubic)
|
||||
void updateAnimation(float delta_time);
|
||||
// Actualiza la interpolación de la animación (ease out/in cubic)
|
||||
void updateAnimation(float delta_time);
|
||||
};
|
||||
@@ -12,232 +12,232 @@
|
||||
#include "text.hpp" // Para Text
|
||||
|
||||
class WindowMessage {
|
||||
public:
|
||||
enum class PositionMode {
|
||||
CENTERED, // La ventana se centra en el punto especificado
|
||||
FIXED // La esquina superior izquierda coincide con el punto
|
||||
};
|
||||
public:
|
||||
enum class PositionMode {
|
||||
CENTERED, // La ventana se centra en el punto especificado
|
||||
FIXED // La esquina superior izquierda coincide con el punto
|
||||
};
|
||||
|
||||
struct Config {
|
||||
// Colores
|
||||
Color bg_color;
|
||||
Color border_color;
|
||||
Color title_color;
|
||||
Color text_color;
|
||||
struct Config {
|
||||
// Colores
|
||||
Color bg_color;
|
||||
Color border_color;
|
||||
Color title_color;
|
||||
Color text_color;
|
||||
|
||||
// Espaciado y dimensiones
|
||||
float padding{15.0F};
|
||||
float line_spacing{5.0F};
|
||||
float title_separator_spacing{10.0F}; // Espacio extra para separador del título
|
||||
// Espaciado y dimensiones
|
||||
float padding{15.0F};
|
||||
float line_spacing{5.0F};
|
||||
float title_separator_spacing{10.0F}; // Espacio extra para separador del título
|
||||
|
||||
// Límites de tamaño
|
||||
float min_width{200.0F};
|
||||
float min_height{100.0F};
|
||||
float max_width_ratio{0.8F}; // % máximo de ancho de pantalla
|
||||
float max_height_ratio{0.8F}; // % máximo de alto de pantalla
|
||||
// Límites de tamaño
|
||||
float min_width{200.0F};
|
||||
float min_height{100.0F};
|
||||
float max_width_ratio{0.8F}; // % máximo de ancho de pantalla
|
||||
float max_height_ratio{0.8F}; // % máximo de alto de pantalla
|
||||
|
||||
// Margen de seguridad para texto
|
||||
float text_safety_margin{20.0F}; // Margen extra para evitar texto cortado
|
||||
// Margen de seguridad para texto
|
||||
float text_safety_margin{20.0F}; // Margen extra para evitar texto cortado
|
||||
|
||||
// Animaciones
|
||||
float animation_duration{0.3F}; // Duración en segundos para todas las animaciones
|
||||
// Animaciones
|
||||
float animation_duration{0.3F}; // Duración en segundos para todas las animaciones
|
||||
|
||||
// Constructor con valores por defecto
|
||||
Config()
|
||||
: bg_color{40, 40, 60, 220},
|
||||
border_color{100, 100, 120, 255},
|
||||
title_color{255, 255, 255, 255},
|
||||
text_color{200, 200, 200, 255} {}
|
||||
// Constructor con valores por defecto
|
||||
Config()
|
||||
: bg_color{40, 40, 60, 220},
|
||||
border_color{100, 100, 120, 255},
|
||||
title_color{255, 255, 255, 255},
|
||||
text_color{200, 200, 200, 255} {}
|
||||
|
||||
// Constructor que convierte desde ParamServiceMenu::WindowMessage
|
||||
Config(const ParamServiceMenu::WindowMessage& param_config)
|
||||
: bg_color(param_config.bg_color),
|
||||
border_color(param_config.border_color),
|
||||
title_color(param_config.title_color),
|
||||
text_color(param_config.text_color),
|
||||
padding(param_config.padding),
|
||||
line_spacing(param_config.line_spacing),
|
||||
title_separator_spacing(param_config.title_separator_spacing),
|
||||
min_width(param_config.min_width),
|
||||
min_height(param_config.min_height),
|
||||
max_width_ratio(param_config.max_width_ratio),
|
||||
max_height_ratio(param_config.max_height_ratio),
|
||||
text_safety_margin(param_config.text_safety_margin),
|
||||
animation_duration(param_config.animation_duration) {}
|
||||
};
|
||||
// Constructor que convierte desde ParamServiceMenu::WindowMessage
|
||||
Config(const ParamServiceMenu::WindowMessage& param_config)
|
||||
: bg_color(param_config.bg_color),
|
||||
border_color(param_config.border_color),
|
||||
title_color(param_config.title_color),
|
||||
text_color(param_config.text_color),
|
||||
padding(param_config.padding),
|
||||
line_spacing(param_config.line_spacing),
|
||||
title_separator_spacing(param_config.title_separator_spacing),
|
||||
min_width(param_config.min_width),
|
||||
min_height(param_config.min_height),
|
||||
max_width_ratio(param_config.max_width_ratio),
|
||||
max_height_ratio(param_config.max_height_ratio),
|
||||
text_safety_margin(param_config.text_safety_margin),
|
||||
animation_duration(param_config.animation_duration) {}
|
||||
};
|
||||
|
||||
WindowMessage(
|
||||
std::shared_ptr<Text> text_renderer,
|
||||
std::string title = "",
|
||||
const Config& config = Config{});
|
||||
WindowMessage(
|
||||
std::shared_ptr<Text> text_renderer,
|
||||
std::string title = "",
|
||||
const Config& config = Config{});
|
||||
|
||||
// Métodos principales
|
||||
void render();
|
||||
void update(float delta_time);
|
||||
// Métodos principales
|
||||
void render();
|
||||
void update(float delta_time);
|
||||
|
||||
// Control de visibilidad
|
||||
void show();
|
||||
void hide();
|
||||
[[nodiscard]] auto isVisible() const -> bool { return visible_; }
|
||||
[[nodiscard]] auto isFullyVisible() const -> bool { return visible_ && !show_hide_animation_.active; }
|
||||
[[nodiscard]] auto isAnimating() const -> bool { return resize_animation_.active || show_hide_animation_.active; }
|
||||
// Control de visibilidad
|
||||
void show();
|
||||
void hide();
|
||||
[[nodiscard]] auto isVisible() const -> bool { return visible_; }
|
||||
[[nodiscard]] auto isFullyVisible() const -> bool { return visible_ && !show_hide_animation_.active; }
|
||||
[[nodiscard]] auto isAnimating() const -> bool { return resize_animation_.active || show_hide_animation_.active; }
|
||||
|
||||
// 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 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();
|
||||
|
||||
// Control de redimensionado automático
|
||||
void enableAutoResize(bool enabled) { auto_resize_enabled_ = enabled; }
|
||||
[[nodiscard]] auto isAutoResizeEnabled() const -> bool { return auto_resize_enabled_; }
|
||||
// Control de redimensionado automático
|
||||
void enableAutoResize(bool enabled) { auto_resize_enabled_ = enabled; }
|
||||
[[nodiscard]] auto isAutoResizeEnabled() const -> bool { return auto_resize_enabled_; }
|
||||
|
||||
// Configuración de posición y tamaño
|
||||
void setPosition(float x, float y, PositionMode mode = PositionMode::CENTERED);
|
||||
void setSize(float width, float height);
|
||||
void centerOnScreen();
|
||||
void autoSize(); // Ajusta automáticamente al contenido y reposiciona si es necesario
|
||||
// Configuración de posición y tamaño
|
||||
void setPosition(float x, float y, PositionMode mode = PositionMode::CENTERED);
|
||||
void setSize(float width, float height);
|
||||
void centerOnScreen();
|
||||
void autoSize(); // Ajusta automáticamente al contenido y reposiciona si es necesario
|
||||
|
||||
// Configuración de colores
|
||||
void setBackgroundColor(const Color& color) { config_.bg_color = color; }
|
||||
void setBorderColor(const Color& color) { config_.border_color = color; }
|
||||
void setTitleColor(const Color& color) {
|
||||
config_.title_color = color;
|
||||
updateStyles();
|
||||
}
|
||||
void setTextColor(const Color& color) {
|
||||
config_.text_color = color;
|
||||
updateStyles();
|
||||
// Configuración de colores
|
||||
void setBackgroundColor(const Color& color) { config_.bg_color = color; }
|
||||
void setBorderColor(const Color& color) { config_.border_color = color; }
|
||||
void setTitleColor(const Color& color) {
|
||||
config_.title_color = color;
|
||||
updateStyles();
|
||||
}
|
||||
void setTextColor(const Color& color) {
|
||||
config_.text_color = color;
|
||||
updateStyles();
|
||||
}
|
||||
|
||||
// Configuración de espaciado
|
||||
void setPadding(float padding) { config_.padding = padding; }
|
||||
void setLineSpacing(float spacing) { config_.line_spacing = spacing; }
|
||||
|
||||
// Configuración avanzada
|
||||
void setConfig(const Config& config) {
|
||||
config_ = config;
|
||||
updateStyles();
|
||||
}
|
||||
[[nodiscard]] auto getConfig() const -> const Config& { return config_; }
|
||||
|
||||
// Getters
|
||||
[[nodiscard]] auto getRect() const -> const SDL_FRect& { return rect_; }
|
||||
[[nodiscard]] auto getPositionMode() const -> PositionMode { return position_mode_; }
|
||||
[[nodiscard]] auto getAnchorPoint() const -> SDL_FPoint { return anchor_; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<Text> text_renderer_;
|
||||
Config config_;
|
||||
|
||||
// Estado de visibilidad y redimensionado
|
||||
bool visible_ = false;
|
||||
bool auto_resize_enabled_ = true; // Por defecto habilitado
|
||||
|
||||
// Contenido
|
||||
std::string title_;
|
||||
std::vector<std::string> texts_;
|
||||
|
||||
// Posición y tamaño
|
||||
SDL_FRect rect_{0, 0, 300, 200};
|
||||
PositionMode position_mode_ = PositionMode::CENTERED;
|
||||
SDL_FPoint anchor_{0.0F, 0.0F};
|
||||
|
||||
// Animación de redimensionado
|
||||
struct ResizeAnimation {
|
||||
bool active = false;
|
||||
float start_width, start_height;
|
||||
float target_width, target_height;
|
||||
float elapsed = 0.0F;
|
||||
|
||||
void start(float from_w, float from_h, float to_w, float to_h) {
|
||||
start_width = from_w;
|
||||
start_height = from_h;
|
||||
target_width = to_w;
|
||||
target_height = to_h;
|
||||
elapsed = 0.0F;
|
||||
active = true;
|
||||
}
|
||||
|
||||
// Configuración de espaciado
|
||||
void setPadding(float padding) { config_.padding = padding; }
|
||||
void setLineSpacing(float spacing) { config_.line_spacing = spacing; }
|
||||
|
||||
// Configuración avanzada
|
||||
void setConfig(const Config& config) {
|
||||
config_ = config;
|
||||
updateStyles();
|
||||
void stop() {
|
||||
active = false;
|
||||
elapsed = 0.0F;
|
||||
}
|
||||
[[nodiscard]] auto getConfig() const -> const Config& { return config_; }
|
||||
|
||||
// Getters
|
||||
[[nodiscard]] auto getRect() const -> const SDL_FRect& { return rect_; }
|
||||
[[nodiscard]] auto getPositionMode() const -> PositionMode { return position_mode_; }
|
||||
[[nodiscard]] auto getAnchorPoint() const -> SDL_FPoint { return anchor_; }
|
||||
[[nodiscard]] auto isFinished(float duration) const -> bool {
|
||||
return elapsed >= duration;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<Text> text_renderer_;
|
||||
Config config_;
|
||||
[[nodiscard]] auto getProgress(float duration) const -> float {
|
||||
return std::min(elapsed / duration, 1.0F);
|
||||
}
|
||||
} resize_animation_;
|
||||
|
||||
// Estado de visibilidad y redimensionado
|
||||
bool visible_ = false;
|
||||
bool auto_resize_enabled_ = true; // Por defecto habilitado
|
||||
// Animación de mostrar/ocultar
|
||||
struct ShowHideAnimation {
|
||||
enum class Type { NONE,
|
||||
SHOWING,
|
||||
HIDING };
|
||||
|
||||
// Contenido
|
||||
std::string title_;
|
||||
std::vector<std::string> texts_;
|
||||
Type type = Type::NONE;
|
||||
bool active = false;
|
||||
float target_width, target_height; // Tamaño final al mostrar
|
||||
float elapsed = 0.0F;
|
||||
|
||||
// Posición y tamaño
|
||||
SDL_FRect rect_{0, 0, 300, 200};
|
||||
PositionMode position_mode_ = PositionMode::CENTERED;
|
||||
SDL_FPoint anchor_{0.0F, 0.0F};
|
||||
void startShow(float to_w, float to_h) {
|
||||
type = Type::SHOWING;
|
||||
target_width = to_w;
|
||||
target_height = to_h;
|
||||
elapsed = 0.0F;
|
||||
active = true;
|
||||
}
|
||||
|
||||
// Animación de redimensionado
|
||||
struct ResizeAnimation {
|
||||
bool active = false;
|
||||
float start_width, start_height;
|
||||
float target_width, target_height;
|
||||
float elapsed = 0.0F;
|
||||
void startHide() {
|
||||
type = Type::HIDING;
|
||||
elapsed = 0.0F;
|
||||
active = true;
|
||||
}
|
||||
|
||||
void start(float from_w, float from_h, float to_w, float to_h) {
|
||||
start_width = from_w;
|
||||
start_height = from_h;
|
||||
target_width = to_w;
|
||||
target_height = to_h;
|
||||
elapsed = 0.0F;
|
||||
active = true;
|
||||
}
|
||||
void stop() {
|
||||
type = Type::NONE;
|
||||
active = false;
|
||||
elapsed = 0.0F;
|
||||
}
|
||||
|
||||
void stop() {
|
||||
active = false;
|
||||
elapsed = 0.0F;
|
||||
}
|
||||
[[nodiscard]] auto isFinished(float duration) const -> bool {
|
||||
return elapsed >= duration;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto isFinished(float duration) const -> bool {
|
||||
return elapsed >= duration;
|
||||
}
|
||||
[[nodiscard]] auto getProgress(float duration) const -> float {
|
||||
return std::min(elapsed / duration, 1.0F);
|
||||
}
|
||||
} show_hide_animation_;
|
||||
|
||||
[[nodiscard]] auto getProgress(float duration) const -> float {
|
||||
return std::min(elapsed / duration, 1.0F);
|
||||
}
|
||||
} resize_animation_;
|
||||
// Estilos
|
||||
Text::Style title_style_;
|
||||
Text::Style text_style_;
|
||||
|
||||
// Animación de mostrar/ocultar
|
||||
struct ShowHideAnimation {
|
||||
enum class Type { NONE,
|
||||
SHOWING,
|
||||
HIDING };
|
||||
// Métodos privados
|
||||
void calculateAutoSize();
|
||||
void updatePosition(); // Actualiza la posición según el modo y punto de anclaje
|
||||
void updateStyles(); // Actualiza los estilos de texto cuando cambian los colores
|
||||
void ensureTextFits(); // Verifica y ajusta para que todo el texto sea visible
|
||||
void triggerAutoResize(); // Inicia redimensionado automático si está habilitado
|
||||
void updateAnimation(float delta_time); // Actualiza la animación de redimensionado
|
||||
void updateShowHideAnimation(float delta_time); // Actualiza la animación de mostrar/ocultar
|
||||
void updateResizeAnimation(float delta_time); // Actualiza la animación de redimensionado
|
||||
|
||||
Type type = Type::NONE;
|
||||
bool active = false;
|
||||
float target_width, target_height; // Tamaño final al mostrar
|
||||
float elapsed = 0.0F;
|
||||
// Función de suavizado (ease-out)
|
||||
[[nodiscard]] static auto easeOut(float t) -> float;
|
||||
|
||||
void startShow(float to_w, float to_h) {
|
||||
type = Type::SHOWING;
|
||||
target_width = to_w;
|
||||
target_height = to_h;
|
||||
elapsed = 0.0F;
|
||||
active = true;
|
||||
}
|
||||
// Métodos para manejo de texto durante animación
|
||||
[[nodiscard]] auto getTruncatedText(const std::string& text, float available_width) const -> std::string;
|
||||
[[nodiscard]] auto getAvailableTextWidth() const -> float;
|
||||
[[nodiscard]] auto shouldShowContent() const -> bool; // Si mostrar el contenido (texto, líneas, etc.)
|
||||
|
||||
void startHide() {
|
||||
type = Type::HIDING;
|
||||
elapsed = 0.0F;
|
||||
active = true;
|
||||
}
|
||||
|
||||
void stop() {
|
||||
type = Type::NONE;
|
||||
active = false;
|
||||
elapsed = 0.0F;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto isFinished(float duration) const -> bool {
|
||||
return elapsed >= duration;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto getProgress(float duration) const -> float {
|
||||
return std::min(elapsed / duration, 1.0F);
|
||||
}
|
||||
} show_hide_animation_;
|
||||
|
||||
// Estilos
|
||||
Text::Style title_style_;
|
||||
Text::Style text_style_;
|
||||
|
||||
// Métodos privados
|
||||
void calculateAutoSize();
|
||||
void updatePosition(); // Actualiza la posición según el modo y punto de anclaje
|
||||
void updateStyles(); // Actualiza los estilos de texto cuando cambian los colores
|
||||
void ensureTextFits(); // Verifica y ajusta para que todo el texto sea visible
|
||||
void triggerAutoResize(); // Inicia redimensionado automático si está habilitado
|
||||
void updateAnimation(float delta_time); // Actualiza la animación de redimensionado
|
||||
void updateShowHideAnimation(float delta_time); // Actualiza la animación de mostrar/ocultar
|
||||
void updateResizeAnimation(float delta_time); // Actualiza la animación de redimensionado
|
||||
|
||||
// Función de suavizado (ease-out)
|
||||
[[nodiscard]] static auto easeOut(float t) -> float;
|
||||
|
||||
// Métodos para manejo de texto durante animación
|
||||
[[nodiscard]] auto getTruncatedText(const std::string& text, float available_width) const -> std::string;
|
||||
[[nodiscard]] auto getAvailableTextWidth() const -> float;
|
||||
[[nodiscard]] auto shouldShowContent() const -> bool; // Si mostrar el contenido (texto, líneas, etc.)
|
||||
|
||||
[[nodiscard]] auto calculateContentHeight() const -> float;
|
||||
[[nodiscard]] auto calculateContentWidth() const -> float;
|
||||
[[nodiscard]] static auto getScreenWidth() -> float;
|
||||
[[nodiscard]] static auto getScreenHeight() -> float;
|
||||
[[nodiscard]] auto calculateContentHeight() const -> float;
|
||||
[[nodiscard]] auto calculateContentWidth() const -> float;
|
||||
[[nodiscard]] static auto getScreenWidth() -> float;
|
||||
[[nodiscard]] static auto getScreenHeight() -> float;
|
||||
};
|
||||
Reference in New Issue
Block a user