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.
This commit is contained in:
Vas Crabb 2024-12-19 02:38:41 +11:00
parent 582390256c
commit a183c9f966
4 changed files with 54 additions and 20 deletions

View File

@ -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<std::string> 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<menu_file_manager>(mui, container, warnings);
menu::stack_push_special_main<menu_file_manager>(mui, container, std::move(warnings));
mui.show_menu();
// make sure MAME is paused

View File

@ -13,9 +13,11 @@
#pragma once
#include "ui/menu.h"
#include "ui/text.h"
#include "notifier.h"
#include <optional>
#include <string>
#include <vector>
@ -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<util::notifier_subscription> m_notifiers;
std::optional<text_layout> m_warnings_layout;
device_image_interface *m_selected_device;
};

View File

@ -243,7 +243,7 @@ bool menu_main::handle(event const *ev)
break;
case IMAGE_MENU_FILE_MANAGER:
menu::stack_push<menu_file_manager>(ui(), container(), nullptr);
menu::stack_push<menu_file_manager>(ui(), container(), std::string());
break;
case TAPE_CONTROL:

View File

@ -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<osd_options &>(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<std::reference_wrapper<const std::string>> 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<const std::string> &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<const std::string> &img) { warning << "\"" << img.get() << "\""; },
[&warning]() { warning << ","; });
[&warning] (const std::reference_wrapper<const std::string> &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;
}