From a183c9f96642fc23f2620e6ec4829ecc8de7a85e Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Thu, 19 Dec 2024 02:38:41 +1100 Subject: [PATCH] ui/ui.cpp: Make failure to mount required media fatal if file manager can't be displayed. ui/filemngr.cpp: Show warnings in a box above the menu so they can be wrapped rather than being truncated to the point of being useless. --- src/frontend/mame/ui/filemngr.cpp | 38 ++++++++++++++++++++++++------- src/frontend/mame/ui/filemngr.h | 7 ++++-- src/frontend/mame/ui/mainmenu.cpp | 2 +- src/frontend/mame/ui/ui.cpp | 27 ++++++++++++++-------- 4 files changed, 54 insertions(+), 20 deletions(-) diff --git a/src/frontend/mame/ui/filemngr.cpp b/src/frontend/mame/ui/filemngr.cpp index f9a99474a15..75a0fb02f77 100644 --- a/src/frontend/mame/ui/filemngr.cpp +++ b/src/frontend/mame/ui/filemngr.cpp @@ -38,9 +38,9 @@ namespace ui { // ctor //------------------------------------------------- -menu_file_manager::menu_file_manager(mame_ui_manager &mui, render_container &container, const char *warnings) +menu_file_manager::menu_file_manager(mame_ui_manager &mui, render_container &container, std::string &&warnings) : menu(mui, container) - , m_warnings(warnings ? warnings : "") + , m_warnings(std::move(warnings)) , m_selected_device(nullptr) { // The warning string is used when accessing from the force_file_manager call, i.e. @@ -66,7 +66,18 @@ void menu_file_manager::recompute_metrics(uint32_t width, uint32_t height, float { menu::recompute_metrics(width, height, aspect); - set_custom_space(0.0F, line_height() + 3.0F * tb_border()); + if (!m_warnings.empty()) + { + m_warnings_layout.reset(); + + float const max_width(1.0F - (4.0F * lr_border())); + m_warnings_layout.emplace(create_layout(max_width, text_layout::text_justify::LEFT)); + m_warnings_layout->add_text(m_warnings, ui().colors().text_color()); + } + + set_custom_space( + m_warnings_layout ? ((m_warnings_layout->lines() * line_height()) + 3.0F * tb_border()) : 0.0F, + line_height() + 3.0F * tb_border()); } @@ -76,6 +87,20 @@ void menu_file_manager::recompute_metrics(uint32_t width, uint32_t height, float void menu_file_manager::custom_render(uint32_t flags, void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) { + // show the warnings if any + if (m_warnings_layout) + { + ui().draw_outlined_box( + container(), + ((1.0F + m_warnings_layout->actual_width()) * 0.5F) + lr_border(), origy1 - (3.0F * tb_border()) - (m_warnings_layout->lines() * line_height()), + ((1.0F - m_warnings_layout->actual_width()) * 0.5F) - lr_border(), origy1 - tb_border(), + ui().colors().background_color()); + m_warnings_layout->emit( + container(), + (1.0F - m_warnings_layout->actual_width()) * 0.5F, + origy1 - (2.0F * tb_border()) - (m_warnings_layout->lines() * line_height())); + } + // access the path std::string_view path = m_selected_device && m_selected_device->exists() ? m_selected_device->filename() : std::string_view(); extra_text_render(top, bottom, origx1, origy1, origx2, origy2, std::string_view(), path); @@ -122,9 +147,6 @@ void menu_file_manager::populate() { m_notifiers.clear(); - if (!m_warnings.empty()) - item_append(m_warnings, FLAG_DISABLE, nullptr); - // cycle through all devices for this system bool missing_mandatory = false; std::unordered_set devtags; @@ -246,11 +268,11 @@ bool menu_file_manager::handle(event const *ev) } // force file manager menu -void menu_file_manager::force_file_manager(mame_ui_manager &mui, render_container &container, const char *warnings) +void menu_file_manager::force_file_manager(mame_ui_manager &mui, render_container &container, std::string &&warnings) { // drop any existing menus and start the file manager menu::stack_reset(mui); - menu::stack_push_special_main(mui, container, warnings); + menu::stack_push_special_main(mui, container, std::move(warnings)); mui.show_menu(); // make sure MAME is paused diff --git a/src/frontend/mame/ui/filemngr.h b/src/frontend/mame/ui/filemngr.h index ba031a0ab21..2c303d2cc97 100644 --- a/src/frontend/mame/ui/filemngr.h +++ b/src/frontend/mame/ui/filemngr.h @@ -13,9 +13,11 @@ #pragma once #include "ui/menu.h" +#include "ui/text.h" #include "notifier.h" +#include #include #include @@ -25,9 +27,9 @@ namespace ui { class menu_file_manager : public menu { public: - static void force_file_manager(mame_ui_manager &mui, render_container &container, const char *warnings); + static void force_file_manager(mame_ui_manager &mui, render_container &container, std::string &&warnings); - menu_file_manager(mame_ui_manager &mui, render_container &container, const char *warnings); + menu_file_manager(mame_ui_manager &mui, render_container &container, std::string &&warnings); virtual ~menu_file_manager(); protected: @@ -42,6 +44,7 @@ private: std::string const m_warnings; std::vector m_notifiers; + std::optional m_warnings_layout; device_image_interface *m_selected_device; }; diff --git a/src/frontend/mame/ui/mainmenu.cpp b/src/frontend/mame/ui/mainmenu.cpp index 22a2c01f6c1..16b7396e7f5 100644 --- a/src/frontend/mame/ui/mainmenu.cpp +++ b/src/frontend/mame/ui/mainmenu.cpp @@ -243,7 +243,7 @@ bool menu_main::handle(event const *ev) break; case IMAGE_MENU_FILE_MANAGER: - menu::stack_push(ui(), container(), nullptr); + menu::stack_push(ui(), container(), std::string()); break; case TAPE_CONTROL: diff --git a/src/frontend/mame/ui/ui.cpp b/src/frontend/mame/ui/ui.cpp index 89e1fd6bd62..dbfd5531be6 100644 --- a/src/frontend/mame/ui/ui.cpp +++ b/src/frontend/mame/ui/ui.cpp @@ -629,15 +629,15 @@ static void output_joined_collection(const TColl &collection, TEmitMemberFunc em void mame_ui_manager::display_startup_screens(bool first_time) { const int maxstate = 3; - int str = machine().options().seconds_to_run(); + int const str = machine().options().seconds_to_run(); bool show_gameinfo = !machine().options().skip_gameinfo(); - bool show_warnings = true, show_mandatory_fileman = true; + bool show_warnings = true; bool video_none = strcmp(downcast(machine().options()).video(), OSDOPTVAL_NONE) == 0; // disable everything if we are using -str for 300 or fewer seconds, or if we're the empty driver, // or if we are debugging, or if there's no mame window to send inputs to - if (!first_time || (str > 0 && str < 60*5) || &machine().system() == &GAME_NAME(___empty) || (machine().debug_flags & DEBUG_FLAG_ENABLED) != 0 || video_none) - show_gameinfo = show_warnings = show_mandatory_fileman = false; + if (!first_time || (str > 0 && str < 60*5) || &machine().system() == &GAME_NAME(___empty) || (machine().debug_flags & DEBUG_FLAG_ENABLED) || video_none) + show_gameinfo = show_warnings = false; #if defined(__EMSCRIPTEN__) // also disable for the JavaScript port since the startup screens do not run asynchronously @@ -773,16 +773,25 @@ void mame_ui_manager::display_startup_screens(bool first_time) case 2: std::vector> mandatory_images = mame_machine_manager::instance()->missing_mandatory_images(); - if (!mandatory_images.empty() && show_mandatory_fileman) + if (!mandatory_images.empty()) { std::ostringstream warning; + if ((str > 0) || (machine().debug_flags & DEBUG_FLAG_ENABLED) || video_none) + { + warning << "Images must be mounted for the following devices: "; + output_joined_collection(mandatory_images, + [&warning] (const std::reference_wrapper &img) { warning << img.get(); }, + [&warning] () { warning << ", "; }); + + throw emu_fatalerror(std::move(warning).str()); + } + warning << _("This system requires media images to be mounted for the following device(s): "); - output_joined_collection(mandatory_images, - [&warning](const std::reference_wrapper &img) { warning << "\"" << img.get() << "\""; }, - [&warning]() { warning << ","; }); + [&warning] (const std::reference_wrapper &img) { warning << '"' << img.get() << '"'; }, + [&warning] () { warning << ", "; }); - ui::menu_file_manager::force_file_manager(*this, machine().render().ui_container(), warning.str().c_str()); + ui::menu_file_manager::force_file_manager(*this, machine().render().ui_container(), std::move(warning).str()); } break; }