diff --git a/source/service_menu.cpp b/source/service_menu.cpp index 8593349..83c09cb 100644 --- a/source/service_menu.cpp +++ b/source/service_menu.cpp @@ -1,3 +1,4 @@ +// --- Includes --- #include "service_menu.h" #include "MenuOption.h" #include "screen.h" @@ -11,11 +12,19 @@ // --- Singleton --- ServiceMenu *ServiceMenu::instance_ = nullptr; + +// Inicializa la instancia singleton void ServiceMenu::init() { ServiceMenu::instance_ = new ServiceMenu(); } + +// Libera la instancia singleton void ServiceMenu::destroy() { delete ServiceMenu::instance_; } + +// Devuelve la instancia singleton ServiceMenu *ServiceMenu::get() { return ServiceMenu::instance_; } -// --- Constructor --- +// --- Constructor y setup --- + +// Constructor: inicializa textos, mensaje UI y estado inicial ServiceMenu::ServiceMenu() : element_text_(Resource::get()->getText("04b_25_flat")), title_text_(Resource::get()->getText("04b_25_flat_2x")), @@ -29,8 +38,18 @@ ServiceMenu::ServiceMenu() reset(); } -// --- Métodos públicos --- +// Alterna la visibilidad del menú de servicio. +// Si se desactiva, reinicia el menú al estado inicial. +void ServiceMenu::toggle() +{ + enabled_ = !enabled_; + if (!enabled_) + { + reset(); + } +} +// Inicializa todas las opciones del menú void ServiceMenu::initializeOptions() { options_.clear(); @@ -75,6 +94,38 @@ void ServiceMenu::initializeOptions() precalculateMenuWidths(); } +// Reinicia el menú al estado inicial +void ServiceMenu::reset() +{ + selected_ = 0; + previous_settings_group_ = current_settings_group_ = SettingsGroup::MAIN; + title_ = settingsGroupToString(current_settings_group_); + initializeOptions(); + updateMenu(current_settings_group_); + setAnchors(); +} + +// --- Métodos de navegación y selección --- + +// Sube el selector una posición en la lista de opciones +void ServiceMenu::setSelectorUp() +{ + if (display_options_.empty()) + return; + selected_ = (selected_ > 0) ? selected_ - 1 : display_options_.size() - 1; + playMenuSound(); +} + +// Baja el selector una posición en la lista de opciones +void ServiceMenu::setSelectorDown() +{ + if (display_options_.empty()) + return; + selected_ = (selected_ + 1) % display_options_.size(); + playMenuSound(); +} + +// Ajusta el valor de la opción seleccionada si es ajustable void ServiceMenu::adjustOption(bool adjust_up) { if (display_options_.empty() || selected_ >= display_options_.size()) @@ -90,16 +141,19 @@ void ServiceMenu::adjustOption(bool adjust_up) } } +// Ejecuta la acción de la opción seleccionada o navega a un submenú void ServiceMenu::selectOption() { if (display_options_.empty() || selected_ >= display_options_.size()) return; + // Guarda la selección en el menú principal if (current_settings_group_ == SettingsGroup::MAIN) main_menu_selected_ = selected_; auto &selected_option = display_options_.at(selected_); + // Si es una carpeta, navega al subgrupo correspondiente if (auto folder = dynamic_cast(selected_option)) { previous_settings_group_ = current_settings_group_; @@ -112,14 +166,348 @@ void ServiceMenu::selectOption() return; } + // Si es una acción, ejecútala if (selected_option->getBehavior() == MenuOption::Behavior::SELECT) { selected_option->executeAction(); } } -// --- Métodos de Cálculo de Ancho (Reincorporados y adaptados) --- +// Vuelve al grupo de opciones anterior o cierra el menú si está en el principal +void ServiceMenu::moveBack() +{ + if (current_settings_group_ == SettingsGroup::MAIN) + { + enabled_ = false; + return; + } + else + { + if (previous_settings_group_ == SettingsGroup::MAIN) + selected_ = main_menu_selected_; + else + selected_ = 0; + current_settings_group_ = previous_settings_group_; + updateMenu(current_settings_group_); + setOptionsPosition(); + playMenuSound(); + } +} +// --- Métodos de renderizado --- + +// Dibuja el menú de servicio y el mensaje de reinicio si corresponde +void ServiceMenu::render() +{ + if (!enabled_) + return; + + // --- Fondo y marco del menú --- + if (aspect_ == Aspect::ASPECT1) + { + SDL_FRect shadowRect = {rect_.x + 5, rect_.y + 5, rect_.w, rect_.h}; + SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0, 0, 0, 64); + SDL_RenderFillRect(Screen::get()->getRenderer(), &shadowRect); + } + const Uint8 ALPHA = aspect_ == Aspect::ASPECT1 ? 255 : 255; + SDL_SetRenderDrawColor(Screen::get()->getRenderer(), bg_color_.r, bg_color_.g, bg_color_.b, ALPHA); + SDL_RenderFillRect(Screen::get()->getRenderer(), &rect_); + SDL_SetRenderDrawColor(Screen::get()->getRenderer(), title_color_.r, title_color_.g, title_color_.b, 255); + SDL_RenderRect(Screen::get()->getRenderer(), &rect_); + + // --- Mensaje de reinicio (animado) --- + restart_message_ui_->render(); + + // --- Título del menú --- + int y = rect_.y + title_padding_; + title_text_->writeDX(TEXT_COLOR | TEXT_CENTER, param.game.game_area.center_x, y, title_, -4, title_color_); + + // --- Línea separadora --- + y = rect_.y + upper_height_; + SDL_SetRenderDrawColor(Screen::get()->getRenderer(), title_color_.r, title_color_.g, title_color_.b, 255); + SDL_RenderLine(Screen::get()->getRenderer(), rect_.x + OPTIONS_HORIZONTAL_PADDING_, y, rect_.x + rect_.w - OPTIONS_HORIZONTAL_PADDING_, y); + + // --- Opciones del menú --- + y = options_y_; + for (size_t i = 0; i < option_pairs_.size(); ++i) + { + if (getGroupAlignment(current_settings_group_) == GroupAlignment::LEFT) + { + // Opción alineada a la izquierda + element_text_->writeColored(rect_.x + OPTIONS_HORIZONTAL_PADDING_, y, option_pairs_.at(i).first, i == selected_ ? selected_color_ : text_color_, -2); + const int X = rect_.x + rect_.w - OPTIONS_HORIZONTAL_PADDING_ - element_text_->lenght(std::string(option_pairs_.at(i).second), -2); + element_text_->writeColored(X, y, std::string(option_pairs_.at(i).second), i == selected_ ? selected_color_ : text_color_, -2); + } + else + { + // Opción centrada + element_text_->writeDX(TEXT_CENTER | TEXT_COLOR, rect_.x + rect_.w / 2, y, option_pairs_.at(i).first, -2, i == selected_ ? selected_color_ : text_color_); + } + y += options_height_ + options_padding_; + } +} + +// --- Métodos de actualización y animación --- + +// Actualiza el estado del menú y la animación del mensaje de reinicio +void ServiceMenu::update() +{ + if (resizing_) + { + updateResizeAnimation(); + return; + } + if (enabled_) + { + updateCounter(); + selected_color_ = getSelectedColor(); + } + + // Detecta cambios en el estado de pending_changes y muestra/oculta el mensaje animado + bool now_pending = Options::pending_changes.has_pending_changes; + if (now_pending != last_pending_changes_) + { + if (now_pending) + { + const float MSG_X = param.game.game_area.center_x; + const float MSG_Y = rect_.y + RESET_TEXT_POS_Y_; + restart_message_ui_->show(MSG_X, MSG_Y); + } + else + { + restart_message_ui_->hide(); + } + last_pending_changes_ = now_pending; + } + // Actualiza la animación del mensaje + restart_message_ui_->update(); +} + +// --- Métodos de layout y animación del menú --- + +// Calcula y establece los anclajes y dimensiones del menú +void ServiceMenu::setAnchors() +{ + const size_t MAX_ENTRIES = findLargestGroupSize(); + options_height_ = element_text_->getCharacterSize(); + options_padding_ = 5; + title_height_ = title_text_->getCharacterSize(); + title_padding_ = title_height_ / 2; + upper_height_ = (title_padding_ * 2) + title_height_; + lower_padding_ = (options_padding_ * 3); + lower_height_ = ((MAX_ENTRIES > 0 ? MAX_ENTRIES - 1 : 0) * (options_height_ + options_padding_)) + options_height_ + (lower_padding_ * 2); + width_ = 240; + height_ = upper_height_ + lower_height_; + rect_ = {(param.game.width - width_) / 2.0f, (param.game.height - height_) / 2.0f, static_cast(width_), static_cast(height_)}; + setOptionsPosition(); +} + +// Calcula la posición vertical de las opciones +void ServiceMenu::setOptionsPosition() +{ + resize(); + SDL_FRect new_rect = {(param.game.width - width_) / 2.0f, (param.game.height - height_) / 2.0f, static_cast(width_), static_cast(height_)}; + options_y_ = new_rect.y + upper_height_ + lower_padding_; +} + +// Redimensiona el menú y prepara la animación si es necesario +void ServiceMenu::resize() +{ + int menu_width = getMenuWidthForGroup(current_settings_group_); + width_ = menu_width; + lower_height_ = ((display_options_.size() > 0 ? display_options_.size() - 1 : 0) * (options_height_ + options_padding_)) + options_height_ + (lower_padding_ * 2); + height_ = upper_height_ + lower_height_; + SDL_FRect new_rect = {(param.game.width - width_) / 2.0f, (param.game.height - height_) / 2.0f, static_cast(width_), static_cast(height_)}; + if (rect_.x != new_rect.x || rect_.y != new_rect.y || rect_.w != new_rect.w || rect_.h != new_rect.h) + { + rect_anim_from_ = rect_; + rect_anim_to_ = new_rect; + resize_anim_step_ = 0; + resizing_ = true; + } + else + { + rect_ = new_rect; + resizing_ = false; + } +} + +// Actualiza la animación de resize del menú y la posición del mensaje de reinicio +void ServiceMenu::updateResizeAnimation() +{ + if (!resizing_) + return; + ++resize_anim_step_; + float t = static_cast(resize_anim_step_) / resize_anim_steps_; + if (t >= 1.0f) + { + rect_ = rect_anim_to_; + resizing_ = false; + restart_message_ui_->setBaseY(rect_.y + RESET_TEXT_POS_Y_); + return; + } + float ease = 1 - (1 - t) * (1 - t); + rect_.x = rect_anim_from_.x + (rect_anim_to_.x - rect_anim_from_.x) * ease; + rect_.y = rect_anim_from_.y + (rect_anim_to_.y - rect_anim_from_.y) * ease; + rect_.w = rect_anim_from_.w + (rect_anim_to_.w - rect_anim_from_.w) * ease; + rect_.h = rect_anim_from_.h + (rect_anim_to_.h - rect_anim_from_.h) * ease; +} + +// --- Métodos utilitarios --- + +// Actualiza el contador interno para animaciones de color +void ServiceMenu::updateCounter() +{ + static Uint64 lastUpdate = SDL_GetTicks(); + Uint64 currentTicks = SDL_GetTicks(); + if (currentTicks - lastUpdate >= 50) + { + counter_++; + lastUpdate = currentTicks; + } +} + +// Devuelve el color animado del elemento seleccionado +Color ServiceMenu::getSelectedColor() const +{ + static std::array colors = {Color(0xFF, 0xFB, 0x8A), Color(0xFF, 0xE4, 0x5D), Color(0xFF, 0xD1, 0x3C), Color(0xFF, 0xBF, 0x23), Color(0xFF, 0xAA, 0x12), Color(0xE6, 0x9A, 0x08), Color(0xE6, 0x9A, 0x08), Color(0xFF, 0xAA, 0x12), Color(0xFF, 0xBF, 0x23), Color(0xFF, 0xD1, 0x3C), Color(0xFF, 0xE4, 0x5D), Color(0xFF, 0xFB, 0x8A)}; + return colors.at(counter_ % colors.size()); +} + +// Reproduce el sonido de navegación del menú +void ServiceMenu::playMenuSound() { Audio::get()->playSound(MENU_SOUND_); } + +// Actualiza el menú según el grupo seleccionado +void ServiceMenu::updateMenu(SettingsGroup group) +{ + title_ = settingsGroupToString(group); + AdjustListValues(); + option_pairs_ = getOptionPairs(group); + display_options_ = getOptionsByGroup(group); + resize(); +} + +// Devuelve el tamaño del grupo con más opciones +int ServiceMenu::findLargestGroupSize() const +{ + std::unordered_map group_counts; + for (const auto &option : options_) + ++group_counts[option->getGroup()]; + int max_size = 0; + for (const auto &pair : group_counts) + if (pair.second > max_size) + max_size = pair.second; + return max_size; +} + +// Devuelve la alineación de las opciones para el grupo dado +ServiceMenu::GroupAlignment ServiceMenu::getGroupAlignment(SettingsGroup group) const +{ + switch (group) + { + case SettingsGroup::VIDEO: + case SettingsGroup::AUDIO: + case SettingsGroup::SETTINGS: + return GroupAlignment::LEFT; + default: + return GroupAlignment::CENTERED; + } +} + +// Devuelve el nombre del grupo como string para el título +std::string ServiceMenu::settingsGroupToString(SettingsGroup group) const +{ + switch (group) + { + case SettingsGroup::MAIN: + return Lang::getText("[SERVICE_MENU] TITLE"); + case SettingsGroup::VIDEO: + return Lang::getText("[SERVICE_MENU] VIDEO"); + case SettingsGroup::AUDIO: + return Lang::getText("[SERVICE_MENU] AUDIO"); + case SettingsGroup::SETTINGS: + return Lang::getText("[SERVICE_MENU] SETTINGS"); + case SettingsGroup::SYSTEM: + return Lang::getText("[SERVICE_MENU] SYSTEM"); + default: + return Lang::getText("[SERVICE_MENU] TITLE"); + } +} + +// Devuelve las opciones del grupo como pares (nombre, valor) +ServiceMenu::OptionPairs ServiceMenu::getOptionPairs(SettingsGroup group) const +{ + OptionPairs option_pairs; + for (const auto &option : options_) + { + if (option->getGroup() == group && !option->isHidden()) + { + option_pairs.emplace_back(option->getCaption(), option->getValueAsString()); + } + } + return option_pairs; +} + +// Devuelve las opciones del grupo como un vector de punteros +std::vector ServiceMenu::getOptionsByGroup(SettingsGroup group) +{ + std::vector filtered_options; + for (auto &option : options_) + { + if (option->getGroup() == group && !option->isHidden()) + { + filtered_options.push_back(option.get()); + } + } + return filtered_options; +} + +// Busca una opción por su caption +MenuOption *ServiceMenu::getOptionByCaption(const std::string &caption) +{ + for (auto &option : options_) + { + if (option->getCaption() == caption) + { + return option.get(); + } + } + return nullptr; +} + +// Aplica la configuración del grupo seleccionado +void ServiceMenu::applySettings(SettingsGroup group) +{ + if (group == SettingsGroup::VIDEO) + Screen::get()->applySettings(); + if (group == SettingsGroup::AUDIO) + Audio::get()->applySettings(); + if (group == SettingsGroup::SETTINGS) + { + auto option = getOptionByCaption(Lang::getText("[SERVICE_MENU] SHUTDOWN")); + if (option) + { + option->setHidden(!Options::settings.shutdown_enabled); + display_options_ = getOptionsByGroup(group); + } + } +} + +// Sincroniza los valores de las opciones tipo lista +void ServiceMenu::AdjustListValues() +{ + for (auto &option : options_) + { + if (auto list_option = dynamic_cast(option.get())) + { + list_option->sync(); + } + } +} + +// --- Métodos de cálculo de ancho de menú --- + +// Calcula el ancho óptimo para cada grupo de menú void ServiceMenu::precalculateMenuWidths() { for (int &w : group_menu_widths_) @@ -153,316 +541,8 @@ void ServiceMenu::precalculateMenuWidths() } } +// Devuelve el ancho precalculado para un grupo de menú int ServiceMenu::getMenuWidthForGroup(SettingsGroup group) const { return group_menu_widths_[static_cast(group)]; } - -// --- Resto de métodos --- -// (Incluyendo el resto de definiciones que ya tenías para que el archivo esté completo) - -void ServiceMenu::toggle() -{ - enabled_ = !enabled_; - if (!enabled_) - { - reset(); - } -} - -void ServiceMenu::render() -{ - if (enabled_) - { - int y = rect_.y; - if (aspect_ == Aspect::ASPECT1) - { - SDL_FRect shadowRect = {rect_.x + 5, rect_.y + 5, rect_.w, rect_.h}; - SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0, 0, 0, 64); - SDL_RenderFillRect(Screen::get()->getRenderer(), &shadowRect); - } - const Uint8 ALPHA = aspect_ == Aspect::ASPECT1 ? 255 : 255; - SDL_SetRenderDrawColor(Screen::get()->getRenderer(), bg_color_.r, bg_color_.g, bg_color_.b, ALPHA); - SDL_RenderFillRect(Screen::get()->getRenderer(), &rect_); - SDL_SetRenderDrawColor(Screen::get()->getRenderer(), title_color_.r, title_color_.g, title_color_.b, 255); - SDL_RenderRect(Screen::get()->getRenderer(), &rect_); - restart_message_ui_->render(); - y += title_padding_; - title_text_->writeDX(TEXT_COLOR | TEXT_CENTER, param.game.game_area.center_x, y, title_, -4, title_color_); - y = rect_.y + upper_height_; - SDL_SetRenderDrawColor(Screen::get()->getRenderer(), title_color_.r, title_color_.g, title_color_.b, 255); - SDL_RenderLine(Screen::get()->getRenderer(), rect_.x + OPTIONS_HORIZONTAL_PADDING_, y, rect_.x + rect_.w - OPTIONS_HORIZONTAL_PADDING_, y); - y = options_y_; - for (size_t i = 0; i < option_pairs_.size(); ++i) - { - if (getGroupAlignment(current_settings_group_) == GroupAlignment::LEFT) - { - element_text_->writeColored(rect_.x + OPTIONS_HORIZONTAL_PADDING_, y, option_pairs_.at(i).first, i == selected_ ? selected_color_ : text_color_, -2); - const int X = rect_.x + rect_.w - OPTIONS_HORIZONTAL_PADDING_ - element_text_->lenght(std::string(option_pairs_.at(i).second), -2); - element_text_->writeColored(X, y, std::string(option_pairs_.at(i).second), i == selected_ ? selected_color_ : text_color_, -2); - } - else - { - element_text_->writeDX(TEXT_CENTER | TEXT_COLOR, rect_.x + rect_.w / 2, y, option_pairs_.at(i).first, -2, i == selected_ ? selected_color_ : text_color_); - } - y += options_height_ + options_padding_; - } - } -} -void ServiceMenu::update() -{ - if (resizing_) - { - updateResizeAnimation(); - return; - } - if (enabled_) - { - updateCounter(); - selected_color_ = getSelectedColor(); - } - bool now_pending = Options::pending_changes.has_pending_changes; - if (now_pending != last_pending_changes_) - { - if (now_pending) - { - const float MSG_X = param.game.game_area.center_x; - const float MSG_Y = rect_.y + RESET_TEXT_POS_Y_; - restart_message_ui_->show(MSG_X, MSG_Y); - } - else - { - restart_message_ui_->hide(); - } - last_pending_changes_ = now_pending; - } - restart_message_ui_->update(); -} -void ServiceMenu::reset() -{ - selected_ = 0; - previous_settings_group_ = current_settings_group_ = SettingsGroup::MAIN; - title_ = settingsGroupToString(current_settings_group_); - initializeOptions(); - updateMenu(current_settings_group_); - setAnchors(); -} -void ServiceMenu::setSelectorUp() -{ - if (display_options_.empty()) - return; - selected_ = (selected_ > 0) ? selected_ - 1 : display_options_.size() - 1; - playMenuSound(); -} -void ServiceMenu::setSelectorDown() -{ - if (display_options_.empty()) - return; - selected_ = (selected_ + 1) % display_options_.size(); - playMenuSound(); -} -void ServiceMenu::moveBack() -{ - if (current_settings_group_ == SettingsGroup::MAIN) - { - enabled_ = false; - return; - } - else - { - if (previous_settings_group_ == SettingsGroup::MAIN) - selected_ = main_menu_selected_; - else - selected_ = 0; - current_settings_group_ = previous_settings_group_; - updateMenu(current_settings_group_); - setOptionsPosition(); - playMenuSound(); - } -} -void ServiceMenu::setAnchors() -{ - const size_t MAX_ENTRIES = findLargestGroupSize(); - options_height_ = element_text_->getCharacterSize(); - options_padding_ = 5; - title_height_ = title_text_->getCharacterSize(); - title_padding_ = title_height_ / 2; - upper_height_ = (title_padding_ * 2) + title_height_; - lower_padding_ = (options_padding_ * 3); - lower_height_ = ((MAX_ENTRIES > 0 ? MAX_ENTRIES - 1 : 0) * (options_height_ + options_padding_)) + options_height_ + (lower_padding_ * 2); - width_ = 240; - height_ = upper_height_ + lower_height_; - rect_ = {(param.game.width - width_) / 2.0f, (param.game.height - height_) / 2.0f, static_cast(width_), static_cast(height_)}; - setOptionsPosition(); -} -void ServiceMenu::setOptionsPosition() -{ - resize(); - SDL_FRect new_rect = {(param.game.width - width_) / 2.0f, (param.game.height - height_) / 2.0f, static_cast(width_), static_cast(height_)}; - options_y_ = new_rect.y + upper_height_ + lower_padding_; -} -void ServiceMenu::resize() -{ - int menu_width = getMenuWidthForGroup(current_settings_group_); - width_ = menu_width; - lower_height_ = ((display_options_.size() > 0 ? display_options_.size() - 1 : 0) * (options_height_ + options_padding_)) + options_height_ + (lower_padding_ * 2); - height_ = upper_height_ + lower_height_; - SDL_FRect new_rect = {(param.game.width - width_) / 2.0f, (param.game.height - height_) / 2.0f, static_cast(width_), static_cast(height_)}; - if (rect_.x != new_rect.x || rect_.y != new_rect.y || rect_.w != new_rect.w || rect_.h != new_rect.h) - { - rect_anim_from_ = rect_; - rect_anim_to_ = new_rect; - resize_anim_step_ = 0; - resizing_ = true; - } - else - { - rect_ = new_rect; - resizing_ = false; - } -} -void ServiceMenu::updateResizeAnimation() -{ - if (!resizing_) - return; - ++resize_anim_step_; - float t = static_cast(resize_anim_step_) / resize_anim_steps_; - if (t >= 1.0f) - { - rect_ = rect_anim_to_; - resizing_ = false; - return; - } - float ease = 1 - (1 - t) * (1 - t); - rect_.x = rect_anim_from_.x + (rect_anim_to_.x - rect_anim_from_.x) * ease; - rect_.y = rect_anim_from_.y + (rect_anim_to_.y - rect_anim_from_.y) * ease; - rect_.w = rect_anim_from_.w + (rect_anim_to_.w - rect_anim_from_.w) * ease; - rect_.h = rect_anim_from_.h + (rect_anim_to_.h - rect_anim_from_.h) * ease; - restart_message_ui_->setBaseY(rect_.y + RESET_TEXT_POS_Y_); -} -void ServiceMenu::updateCounter() -{ - static Uint64 lastUpdate = SDL_GetTicks(); - Uint64 currentTicks = SDL_GetTicks(); - if (currentTicks - lastUpdate >= 50) - { - counter_++; - lastUpdate = currentTicks; - } -} -Color ServiceMenu::getSelectedColor() const -{ - static std::array colors = {Color(0xFF, 0xFB, 0x8A), Color(0xFF, 0xE4, 0x5D), Color(0xFF, 0xD1, 0x3C), Color(0xFF, 0xBF, 0x23), Color(0xFF, 0xAA, 0x12), Color(0xE6, 0x9A, 0x08), Color(0xE6, 0x9A, 0x08), Color(0xFF, 0xAA, 0x12), Color(0xFF, 0xBF, 0x23), Color(0xFF, 0xD1, 0x3C), Color(0xFF, 0xE4, 0x5D), Color(0xFF, 0xFB, 0x8A)}; - return colors.at(counter_ % colors.size()); -} -void ServiceMenu::playMenuSound() { Audio::get()->playSound(MENU_SOUND_); } -void ServiceMenu::updateMenu(SettingsGroup group) -{ - title_ = settingsGroupToString(group); - AdjustListValues(); - option_pairs_ = getOptionPairs(group); - display_options_ = getOptionsByGroup(group); - resize(); -} -int ServiceMenu::findLargestGroupSize() const -{ - std::unordered_map group_counts; - for (const auto &option : options_) - ++group_counts[option->getGroup()]; - int max_size = 0; - for (const auto &pair : group_counts) - if (pair.second > max_size) - max_size = pair.second; - return max_size; -} -ServiceMenu::GroupAlignment ServiceMenu::getGroupAlignment(SettingsGroup group) const -{ - switch (group) - { - case SettingsGroup::VIDEO: - case SettingsGroup::AUDIO: - case SettingsGroup::SETTINGS: - return GroupAlignment::LEFT; - default: - return GroupAlignment::CENTERED; - } -} -std::string ServiceMenu::settingsGroupToString(SettingsGroup group) const -{ - switch (group) - { - case SettingsGroup::MAIN: - return Lang::getText("[SERVICE_MENU] TITLE"); - case SettingsGroup::VIDEO: - return Lang::getText("[SERVICE_MENU] VIDEO"); - case SettingsGroup::AUDIO: - return Lang::getText("[SERVICE_MENU] AUDIO"); - case SettingsGroup::SETTINGS: - return Lang::getText("[SERVICE_MENU] SETTINGS"); - case SettingsGroup::SYSTEM: - return Lang::getText("[SERVICE_MENU] SYSTEM"); - default: - return Lang::getText("[SERVICE_MENU] TITLE"); - } -} -ServiceMenu::OptionPairs ServiceMenu::getOptionPairs(SettingsGroup group) const -{ - OptionPairs option_pairs; - for (const auto &option : options_) - { - if (option->getGroup() == group && !option->isHidden()) - { - option_pairs.emplace_back(option->getCaption(), option->getValueAsString()); - } - } - return option_pairs; -} -std::vector ServiceMenu::getOptionsByGroup(SettingsGroup group) -{ - std::vector filtered_options; - for (auto &option : options_) - { - if (option->getGroup() == group && !option->isHidden()) - { - filtered_options.push_back(option.get()); - } - } - return filtered_options; -} -MenuOption *ServiceMenu::getOptionByCaption(const std::string &caption) -{ - for (auto &option : options_) - { - if (option->getCaption() == caption) - { - return option.get(); - } - } - return nullptr; -} -void ServiceMenu::applySettings(SettingsGroup group) -{ - if (group == SettingsGroup::VIDEO) - Screen::get()->applySettings(); - if (group == SettingsGroup::AUDIO) - Audio::get()->applySettings(); - if (group == SettingsGroup::SETTINGS) - { - auto option = getOptionByCaption(Lang::getText("[SERVICE_MENU] SHUTDOWN")); - if (option) - { - option->setHidden(!Options::settings.shutdown_enabled); - display_options_ = getOptionsByGroup(group); - } - } -} -void ServiceMenu::AdjustListValues() -{ - for (auto &option : options_) - { - if (auto list_option = dynamic_cast(option.get())) - { - list_option->sync(); - } - } -}