diff options
Diffstat (limited to 'src/frontend/mame/ui/datmenu.cpp')
-rw-r--r-- | src/frontend/mame/ui/datmenu.cpp | 587 |
1 files changed, 298 insertions, 289 deletions
diff --git a/src/frontend/mame/ui/datmenu.cpp b/src/frontend/mame/ui/datmenu.cpp index bd39e72a6cd..492bdd38e41 100644 --- a/src/frontend/mame/ui/datmenu.cpp +++ b/src/frontend/mame/ui/datmenu.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Maurizio Petrarota +// copyright-holders:Maurizio Petrarota, Vas Crabb /********************************************************************* ui/datmenu.cpp @@ -9,52 +9,63 @@ *********************************************************************/ #include "emu.h" +#include "ui/datmenu.h" +#include "ui/systemlist.h" #include "ui/ui.h" -#include "ui/datmenu.h" -#include "ui/utils.h" +#include "luaengine.h" #include "mame.h" + +#include "drivenum.h" #include "rendfont.h" #include "softlist.h" #include "uiinput.h" -#include "luaengine.h" #include <cmath> +#include <limits> +#include <string_view> namespace ui { + //------------------------------------------------- -// ctor / dtor +// construct for currently running or specified +// system //------------------------------------------------- -menu_dats_view::menu_dats_view(mame_ui_manager &mui, render_container &container, const game_driver *driver) - : menu(mui, container) - , m_actual(0) - , m_driver((driver == nullptr) ? &mui.machine().system() : driver) +menu_dats_view::menu_dats_view(mame_ui_manager &mui, render_container &container, const ui_system_info *system) + : menu_textbox(mui, container) + , m_system(!system ? &system_list::instance().systems()[driver_list::find(mui.machine().system().name)] : system) , m_swinfo(nullptr) , m_issoft(false) - + , m_current_tab(0) + , m_tab_line(1.0F, 0.0F) + , m_clicked_tab(-1) { - for (device_image_interface& image : image_interface_iterator(mui.machine().root_device())) + set_process_flags(PROCESS_LR_ALWAYS | PROCESS_CUSTOM_NAV); + for (device_image_interface& image : image_interface_enumerator(mui.machine().root_device())) { - if (image.filename()) + if (image.loaded_through_softlist()) { - m_list = strensure(image.software_list_name()); + m_list = image.software_list_name(); m_short = image.software_entry()->shortname(); m_long = image.software_entry()->longname(); m_parent = image.software_entry()->parentname(); + break; } } + std::vector<std::string> lua_list; - if (mame_machine_manager::instance()->lua()->call_plugin("data_list", driver ? driver->name : "", lua_list)) + if (mame_machine_manager::instance()->lua()->call_plugin("data_list", system ? system->driver->name : "", lua_list)) { int count = 0; + m_items_list.reserve(lua_list.size()); for (std::string& item : lua_list) { std::string version; mame_machine_manager::instance()->lua()->call_plugin("data_version", count, version); - m_items_list.emplace_back(item.c_str(), count, std::move(version)); + m_items_list.emplace_back(std::move(item), count, std::move(version)); count++; } } @@ -64,29 +75,38 @@ menu_dats_view::menu_dats_view(mame_ui_manager &mui, render_container &container // ctor //------------------------------------------------- -menu_dats_view::menu_dats_view(mame_ui_manager &mui, render_container &container, const ui_software_info *swinfo, const game_driver *driver) - : menu(mui, container) - , m_actual(0) - , m_driver((driver == nullptr) ? &mui.machine().system() : driver) - , m_swinfo(swinfo) - , m_list(swinfo->listname) - , m_short(swinfo->shortname) - , m_long(swinfo->longname) - , m_parent(swinfo->parentname) +menu_dats_view::menu_dats_view(mame_ui_manager &mui, render_container &container, const ui_software_info &swinfo) + : menu_textbox(mui, container) + , m_system(nullptr) + , m_swinfo(&swinfo) , m_issoft(true) - + , m_current_tab(0) + , m_list(swinfo.listname) + , m_short(swinfo.shortname) + , m_long(swinfo.longname) + , m_parent(swinfo.parentname) + , m_tab_line(1.0F, 0.0F) + , m_clicked_tab(-1) { - if (swinfo != nullptr && !swinfo->usage.empty()) - m_items_list.emplace_back(_("Software Usage"), 0, ""); + set_process_flags(PROCESS_LR_ALWAYS | PROCESS_CUSTOM_NAV); + std::vector<std::string> lua_list; - if(mame_machine_manager::instance()->lua()->call_plugin("data_list", std::string(m_short).append(1, ',').append(m_list).c_str(), lua_list)) + bool const retrieved(mame_machine_manager::instance()->lua()->call_plugin("data_list", std::string(m_short).append(1, ',').append(m_list).c_str(), lua_list)); + + if (!swinfo.infotext.empty() || retrieved) + m_items_list.reserve((!swinfo.infotext.empty() ? 1 : 0) + (retrieved ? lua_list.size() : 0)); + + if (!swinfo.infotext.empty()) + m_items_list.emplace_back(_("Software List Info"), -1, ""); + + if (retrieved) { - int count = 1; - for(std::string &item : lua_list) + int count = 0; + for (std::string &item : lua_list) { std::string version; - mame_machine_manager::instance()->lua()->call_plugin("data_version", count - 1, version); - m_items_list.emplace_back(item.c_str(), count, std::move(version)); + mame_machine_manager::instance()->lua()->call_plugin("data_version", count, version); + m_items_list.emplace_back(std::move(item), count, std::move(version)); count++; } } @@ -101,330 +121,319 @@ menu_dats_view::~menu_dats_view() } //------------------------------------------------- -// handle +// add text to layout //------------------------------------------------- -void menu_dats_view::handle() +void menu_dats_view::add_info_text(text_layout &layout, std::string_view text, rgb_t color, float size) { - const event *menu_event = process(FLAG_UI_DATS); - if (menu_event != nullptr) + char justify = 'l'; // left justify by default + if ((text.length() > 3) && (text[0] == '#') && (text[1] == 'j')) { - if (menu_event->iptkey == IPT_UI_LEFT && m_actual > 0) + auto const eol = text.find('\n'); + if ((std::string_view::npos != eol) && (2 < eol)) { - m_actual--; - reset(reset_options::SELECT_FIRST); + justify = text[2]; + text.remove_prefix(eol + 1); } + } - if (menu_event->iptkey == IPT_UI_RIGHT && m_actual < m_items_list.size() - 1) + if ('2' == justify) + { + while (!text.empty()) { - m_actual++; - reset(reset_options::SELECT_FIRST); + // pop a line from the front + auto const eol = text.find('\n'); + std::string_view const line = (std::string_view::npos != eol) + ? text.substr(0, eol + 1) + : text; + text.remove_prefix(line.length()); + + // split on the first tab + auto const split = line.find('\t'); + if (std::string_view::npos != split) + { + layout.add_text(line.substr(0, split), text_layout::text_justify::LEFT, color, rgb_t::transparent(), size); + layout.add_text(" ", text_layout::text_justify::LEFT, color, rgb_t::transparent(), size); + layout.add_text(line.substr(split + 1), text_layout::text_justify::RIGHT, color, rgb_t::transparent(), size); + } + else + { + layout.add_text(line, text_layout::text_justify::LEFT, color, rgb_t::transparent(), size); + } } } -} - -//------------------------------------------------- -// populate -//------------------------------------------------- - -void menu_dats_view::populate(float &customtop, float &custombottom) -{ - bool paused = machine().paused(); - if (!paused) - machine().pause(); - - (m_issoft == true) ? get_data_sw() : get_data(); - - item_append(menu_item_type::SEPARATOR, (FLAG_UI_DATS | FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW)); - customtop = 2.0f * ui().get_line_height() + 4.0f * ui().box_tb_border(); - custombottom = ui().get_line_height() + 3.0f * ui().box_tb_border(); + else + { + // use the same alignment for all the text + auto const j = + ('c' == justify) ? text_layout::text_justify::CENTER : + ('r' == justify) ? text_layout::text_justify::RIGHT : + text_layout::text_justify::LEFT; + layout.add_text(text, j, color, rgb_t::transparent(), size); + } - if (!paused) - machine().resume(); } //------------------------------------------------- -// draw - draw dats menu +// handle //------------------------------------------------- -void menu_dats_view::draw(uint32_t flags) +bool menu_dats_view::handle(event const *ev) { - float const aspect = machine().render().ui_aspect(&container()); - float const line_height = ui().get_line_height(); - float const ud_arrow_width = line_height * aspect; - float const gutter_width = 0.52f * line_height * aspect; - float const visible_width = 1.0f - (2.0f * ui().box_lr_border() * aspect); - float const visible_left = (1.0f - visible_width) * 0.5f; - float const extra_height = 2.0f * line_height; - float const visible_extra_menu_height = get_customtop() + get_custombottom() + extra_height; - int const visible_items = item_count() - 2; - - // determine effective positions taking into account the hilighting arrows - float const effective_width = visible_width - 2.0f * gutter_width; - float const effective_left = visible_left + gutter_width; - - draw_background(); - map_mouse(); - - // account for extra space at the top and bottom - float visible_main_menu_height = 1.0f - 2.0f * ui().box_tb_border() - visible_extra_menu_height; - m_visible_lines = int(std::trunc(visible_main_menu_height / line_height)); - visible_main_menu_height = float(m_visible_lines) * line_height; - - // compute top/left of inner menu area by centering, if the menu is at the bottom of the extra, adjust - float const visible_top = ((1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f) + get_customtop(); - - // compute left box size - float x1 = visible_left; - float y1 = visible_top - ui().box_tb_border(); - float x2 = x1 + visible_width; - float y2 = visible_top + visible_main_menu_height + ui().box_tb_border() + extra_height; - float line = visible_top + float(m_visible_lines) * line_height; - - ui().draw_outlined_box(container(), x1, y1, x2, y2, ui().colors().background_color()); - - m_visible_lines = (std::min)(visible_items, m_visible_lines); - top_line = (std::max)(0, top_line); - if (top_line + m_visible_lines >= visible_items) - top_line = visible_items - m_visible_lines; - - clear_hover(); - int const n_loop = (std::min)(visible_items, m_visible_lines); - for (int linenum = 0; linenum < n_loop; linenum++) + if (ev) { - float const line_y = visible_top + float(linenum) * line_height; - int const itemnum = top_line + linenum; - menu_item const &pitem = item(itemnum); - char const *const itemtext = pitem.text.c_str(); - float const line_x0 = x1 + 0.5f * UI_LINE_WIDTH; - float const line_y0 = line_y; - float const line_x1 = x2 - 0.5f * UI_LINE_WIDTH; - float const line_y1 = line_y + line_height; - - rgb_t fgcolor = ui().colors().text_color(); - rgb_t bgcolor = ui().colors().text_bg_color(); - - if (!linenum && top_line) + // don't bother with parent event handling if we need to redraw anyway + switch (ev->iptkey) { - // if we're on the top line, display the up arrow - if (mouse_in_rect(line_x0, line_y0, line_x1, line_y1)) + case IPT_UI_LEFT: + if (m_current_tab > 0) { - fgcolor = ui().colors().mouseover_color(); - bgcolor = ui().colors().mouseover_bg_color(); - highlight(line_x0, line_y0, line_x1, line_y1, bgcolor); - set_hover(HOVER_ARROW_UP); + m_current_tab--; + m_tab_line = std::make_pair(1.0F, 0.0F); + m_clicked_tab = -1; + reset_layout(); + return true; } - draw_arrow( - 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height, - 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, - fgcolor, ROT0); - } - else if ((linenum == m_visible_lines - 1) && (itemnum != visible_items - 1)) - { - // if we're on the bottom line, display the down arrow - if (mouse_in_rect(line_x0, line_y0, line_x1, line_y1)) + break; + + case IPT_UI_RIGHT: + if ((m_current_tab + 1) < m_items_list.size()) { - fgcolor = ui().colors().mouseover_color(); - bgcolor = ui().colors().mouseover_bg_color(); - highlight(line_x0, line_y0, line_x1, line_y1, bgcolor); - set_hover(HOVER_ARROW_DOWN); + m_current_tab++; + m_tab_line = std::make_pair(1.0F, 0.0F); + m_clicked_tab = -1; + reset_layout(); + return true; } - draw_arrow( - 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height, - 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, - fgcolor, ROT0 ^ ORIENTATION_FLIP_Y); - } - else if (pitem.subtext.empty()) - { - // draw dats text - ui().draw_text_full( - container(), itemtext, - effective_left, line_y, effective_width, - ui::text_layout::LEFT, ui::text_layout::NEVER, - mame_ui_manager::NORMAL, fgcolor, bgcolor, - nullptr, nullptr); + break; } } - for (size_t count = visible_items; count < item_count(); count++) - { - menu_item const &pitem = item(count); - char const *const itemtext = pitem.text.c_str(); - float const line_x0 = x1 + 0.5f * UI_LINE_WIDTH; - float const line_y0 = line; - float const line_x1 = x2 - 0.5f * UI_LINE_WIDTH; - float const line_y1 = line + line_height; - rgb_t const fgcolor = ui().colors().selected_color(); - rgb_t const bgcolor = ui().colors().selected_bg_color(); - - if (mouse_in_rect(line_x0, line_y0, line_x1, line_y1) && is_selectable(pitem)) - set_hover(count); - - if (pitem.type == menu_item_type::SEPARATOR) - { - container().add_line( - visible_left, line + 0.5f * line_height, visible_left + visible_width, line + 0.5f * line_height, - UI_LINE_WIDTH, ui().colors().text_color(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); - } - else - { - highlight(line_x0, line_y0, line_x1, line_y1, bgcolor); - ui().draw_text_full( - container(), itemtext, - effective_left, line, effective_width, - ui::text_layout::CENTER, ui::text_layout::TRUNCATE, - mame_ui_manager::NORMAL, fgcolor, bgcolor, - nullptr, nullptr); - } - line += line_height; - } + return menu_textbox::handle(ev); +} - // if there is something special to add, do it by calling the virtual method - custom_render(get_selection_ref(), get_customtop(), get_custombottom(), x1, y1, x2, y2); +//------------------------------------------------- +// populate +//------------------------------------------------- - // return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow - m_visible_items = m_visible_lines - (top_line != 0) - (top_line + m_visible_lines != visible_items); +void menu_dats_view::populate() +{ +} + +//------------------------------------------------- +// recompute metrics +//------------------------------------------------- + +void menu_dats_view::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + menu_textbox::recompute_metrics(width, height, aspect); + + m_tab_line = std::make_pair(1.0F, 0.0F); + m_clicked_tab = -1; + + set_custom_space(2.0F * line_height() + 4.0F * tb_border(), line_height() + 3.0F * tb_border()); } //------------------------------------------------- // perform our special rendering //------------------------------------------------- -void menu_dats_view::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) +void menu_dats_view::custom_render(uint32_t flags, void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) { - float maxwidth = origx2 - origx1; - float width; - std::string driver = (m_issoft == true) ? m_swinfo->longname : m_driver->type.fullname(); + float maxwidth; + std::string_view const driver = m_issoft ? m_swinfo->longname : m_system->description; - float const lr_border = ui().box_lr_border() * machine().render().ui_aspect(&container()); - ui().draw_text_full(container(), driver.c_str(), 0.0f, 0.0f, 1.0f, ui::text_layout::CENTER, ui::text_layout::TRUNCATE, - mame_ui_manager::NONE, rgb_t::white(), rgb_t::black(), &width, nullptr); - width += 2 * lr_border; - maxwidth = std::max(maxwidth, width); + maxwidth = std::max(origx2 - origx1, get_string_width(driver) + (2.0F * lr_border())); // compute our bounds - float x1 = 0.5f - 0.5f * maxwidth; + float x1 = 0.5F - (0.5F * maxwidth); float x2 = x1 + maxwidth; float y1 = origy1 - top; - float y2 = origy1 - 2.0f * ui().box_tb_border() - ui().get_line_height(); + float y2 = y1 + (2.0F * tb_border()) + line_height(); // draw a box ui().draw_outlined_box(container(), x1, y1, x2, y2, UI_GREEN_COLOR); - // take off the borders - x1 += lr_border; - x2 -= lr_border; - y1 += ui().box_tb_border(); + draw_text_normal( + driver, + x1 + lr_border(), y1 + tb_border(), x2 - x1 - (2.0F * lr_border()), + text_layout::text_justify::CENTER, ui::text_layout::word_wrapping::NEVER, + ui().colors().text_color()); - ui().draw_text_full(container(), driver.c_str(), x1, y1, x2 - x1, ui::text_layout::CENTER, ui::text_layout::NEVER, - mame_ui_manager::NORMAL, ui().colors().text_color(), ui().colors().text_bg_color(), nullptr, nullptr); + // draw a box + ui().draw_outlined_box(container(), x1, origy1 - line_height() - tb_border(), x2, origy1, ui().colors().background_color()); - maxwidth = 0; - for (auto & elem : m_items_list) + // calculate geometry of tab line + if (m_tab_line.first >= m_tab_line.second) { - ui().draw_text_full(container(), elem.label.c_str(), 0.0f, 0.0f, 1.0f, ui::text_layout::CENTER, ui::text_layout::NEVER, - mame_ui_manager::NONE, rgb_t::white(), rgb_t::black(), &width, nullptr); - maxwidth += width; - } + m_tab_line = std::make_pair(origy1 - line_height(), origy1); - float space = (1.0f - maxwidth) / (m_items_list.size() * 2); - - // compute our bounds - x1 -= lr_border; - x2 += lr_border; - y1 = y2 + ui().box_tb_border(); - y2 += ui().get_line_height() + 2.0f * ui().box_tb_border(); + // FIXME: deal with overflow when there are a lot of tabs + float total(0.0F); + for (auto const &elem : m_items_list) + total += get_string_width(elem.label); + float const space((1.0F - total) / (m_items_list.size() * 2.0F)); - // draw a box - ui().draw_outlined_box(container(), x1, y1, x2, y2, ui().colors().background_color()); - - // take off the borders - y1 += ui().box_tb_border(); + float left(x1 + (space * 0.5F)); + for (auto &elem : m_items_list) + { + float const width(get_string_width(elem.label)); + elem.bounds = std::make_pair(left, left + width + space); + left += width + (space * 2.0F); + } + } // draw the text within it - int x = 0; - for (auto & elem : m_items_list) + for (int i = 0; m_items_list.size() > i; ++i) { - x1 += space; - rgb_t fcolor = (m_actual == x) ? rgb_t(0xff, 0xff, 0xff, 0x00) : ui().colors().text_color(); - rgb_t bcolor = (m_actual == x) ? rgb_t(0xff, 0xff, 0xff, 0xff) : ui().colors().text_bg_color(); - ui().draw_text_full(container(), elem.label.c_str(), x1, y1, 1.0f, ui::text_layout::LEFT, ui::text_layout::NEVER, mame_ui_manager::NONE, fcolor, bcolor, &width, nullptr); - - if (bcolor != ui().colors().text_bg_color()) - ui().draw_textured_box(container(), x1 - (space / 2), y1, x1 + width + (space / 2), y2, bcolor, rgb_t(255, 43, 43, 43), - hilight_main_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(1)); - - ui().draw_text_full(container(), elem.label.c_str(), x1, y1, 1.0f, ui::text_layout::LEFT, ui::text_layout::NEVER, mame_ui_manager::NORMAL, fcolor, bcolor, &width, nullptr); - x1 += width + space; - ++x; - } - - // bottom - std::string revision; - revision.assign(_("Revision: ")).append(m_items_list[m_actual].revision); - ui().draw_text_full(container(), revision.c_str(), 0.0f, 0.0f, 1.0f, ui::text_layout::CENTER, ui::text_layout::TRUNCATE, mame_ui_manager::NONE, rgb_t::white(), rgb_t::black(), &width, nullptr); - width += 2 * lr_border; - maxwidth = std::max(origx2 - origx1, width); - - // compute our bounds - x1 = 0.5f - 0.5f * maxwidth; - x2 = x1 + maxwidth; - y1 = origy2 + ui().box_tb_border(); - y2 = origy2 + bottom; + auto &elem(m_items_list[i]); - // draw a box - ui().draw_outlined_box(container(), x1, y1, x2, y2, UI_GREEN_COLOR); + rgb_t fgcolor; + rgb_t bgcolor; + if (i == m_current_tab) + { + fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00); + bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff); + ui().draw_textured_box( + container(), + elem.bounds.first, m_tab_line.first, elem.bounds.second, m_tab_line.second, + bgcolor, rgb_t(255, 43, 43, 43), + hilight_main_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(1)); + } + else + { + bool const hovered(pointer_in_rect(elem.bounds.first, m_tab_line.first, elem.bounds.second, m_tab_line.second)); + if ((i == m_clicked_tab) && hovered) + { + fgcolor = ui().colors().selected_color(); + bgcolor = ui().colors().selected_bg_color(); + highlight(elem.bounds.first, m_tab_line.first, elem.bounds.second, m_tab_line.second, bgcolor); + } + else if ((i == m_clicked_tab) || (hovered && pointer_idle())) + { + fgcolor = ui().colors().mouseover_color(); + bgcolor = ui().colors().mouseover_bg_color(); + highlight(elem.bounds.first, m_tab_line.first, elem.bounds.second, m_tab_line.second, bgcolor); + } + else + { + fgcolor = ui().colors().text_color(); + bgcolor = ui().colors().text_bg_color(); + } + } - // take off the borders - x1 += lr_border; - x2 -= lr_border; - y1 += ui().box_tb_border(); + ui().draw_text_full( + container(), + elem.label, + elem.bounds.first, m_tab_line.first, elem.bounds.second - elem.bounds.first, + text_layout::text_justify::CENTER, text_layout::word_wrapping::NEVER, + mame_ui_manager::NORMAL, fgcolor, bgcolor, + nullptr, nullptr, + line_height()); + } - // draw the text within it - ui().draw_text_full(container(), revision.c_str(), x1, y1, x2 - x1, ui::text_layout::CENTER, ui::text_layout::TRUNCATE, - mame_ui_manager::NORMAL, ui().colors().text_color(), ui().colors().text_bg_color(), nullptr, nullptr); + // bottom + if (!m_items_list.empty()) + { + std::string const revision(util::string_format(_("Revision: %1$s"), m_items_list[m_current_tab].revision)); + float const width(get_text_width( + revision, + 0.0F, 0.0F, 1.0F, + text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE)); + maxwidth = std::max(origx2 - origx1, width + (2.0F * lr_border())); + + // compute our bounds + x1 = 0.5F - (0.5F * maxwidth); + x2 = x1 + maxwidth; + y1 = origy2 + tb_border(); + y2 = origy2 + bottom; + + // draw a box + ui().draw_outlined_box(container(), x1, y1, x2, y2, UI_GREEN_COLOR); + + // draw the text within it + draw_text_normal( + revision, + x1 + lr_border(), y1 + tb_border(), x2 - x1 - (2.0F * lr_border()), + text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, + ui().colors().text_color()); + } } //------------------------------------------------- -// load data from DATs +// custom pointer handling //------------------------------------------------- -void menu_dats_view::get_data() +std::tuple<int, bool, bool> menu_dats_view::custom_pointer_updated(bool changed, ui_event const &uievt) { - std::vector<int> xstart, xend; - std::string buffer; - mame_machine_manager::instance()->lua()->call_plugin("data", m_items_list[m_actual].option, buffer); - - float const aspect = machine().render().ui_aspect(&container()); - float const line_height = ui().get_line_height(); - float const gutter_width = 0.52f * line_height * aspect; - float const visible_width = 1.0f - (2.0f * ui().box_lr_border() * aspect); - float const effective_width = visible_width - 2.0f * gutter_width; - - auto lines = ui().wrap_text(container(), buffer.c_str(), 0.0f, 0.0f, effective_width, xstart, xend); - for (int x = 0; x < lines; ++x) + if (0 <= m_clicked_tab) { - std::string tempbuf(buffer.substr(xstart[x], xend[x] - xstart[x])); - if ((tempbuf[0] != '#') || x) - item_append(tempbuf, "", (FLAG_UI_DATS | FLAG_DISABLE), (void *)(uintptr_t)(x + 1)); + if ((ui_event::type::POINTER_ABORT != uievt.event_type) && uievt.pointer_released & 0x01) + { + // primary button released - take action if still on the tab + bool const hit(pointer_in_rect( + m_items_list[m_clicked_tab].bounds.first, m_tab_line.first, + m_items_list[m_clicked_tab].bounds.second, m_tab_line.second)); + if (hit && (m_current_tab != m_clicked_tab)) + { + m_current_tab = m_clicked_tab; + m_tab_line = std::make_pair(1.0F, 0.0F); + reset_layout(); + } + m_clicked_tab = -1; + return std::make_tuple(hit ? IPT_CUSTOM : IPT_INVALID, false, true); + } + else if ((ui_event::type::POINTER_ABORT == uievt.event_type) || (uievt.pointer_buttons & ~u32(0x01))) + { + // treat pressing another button as cancellation + m_clicked_tab = -1; + return std::make_tuple(IPT_INVALID, false, true); + } + return std::make_tuple(IPT_INVALID, true, false); } + else if (pointer_idle() && (uievt.pointer_pressed & 0x01) && !(uievt.pointer_buttons & ~u32(0x01))) + { + // primary click - see if it's over a tab + auto const [x, y] = pointer_location(); + if ((y >= m_tab_line.first) && (y < m_tab_line.second)) + { + for (int i = 0; m_items_list.size() > i; ++i) + { + if ((x >= m_items_list[i].bounds.first) && (x < m_items_list[i].bounds.second)) + { + m_clicked_tab = i; + return std::make_tuple(IPT_INVALID, true, true); + } + } + } + } + + // let the base class have a look + return menu_textbox::custom_pointer_updated(changed, uievt); } -void menu_dats_view::get_data_sw() -{ - std::vector<int> xstart; - std::vector<int> xend; - std::string buffer; - if (m_items_list[m_actual].option == 0) - buffer = m_swinfo->usage; - else - mame_machine_manager::instance()->lua()->call_plugin("data", m_items_list[m_actual].option - 1, buffer); +//------------------------------------------------- +// populate selected DAT text +//------------------------------------------------- - auto lines = ui().wrap_text(container(), buffer.c_str(), 0.0f, 0.0f, 1.0f - (4.0f * ui().box_lr_border() * machine().render().ui_aspect(&container())), xstart, xend); - for (int x = 0; x < lines; ++x) +void menu_dats_view::populate_text(std::optional<text_layout> &layout, float &width, int &lines) +{ + if (!layout || (layout->width() != width)) { - std::string tempbuf(buffer.substr(xstart[x], xend[x] - xstart[x])); - item_append(tempbuf, "", (FLAG_UI_DATS | FLAG_DISABLE), (void *)(uintptr_t)(x + 1)); + m_tab_line = std::make_pair(1.0F, 0.0F); + m_clicked_tab = -1; + + std::string buffer; + if (!m_items_list.empty()) + { + if (0 > m_items_list[m_current_tab].option) + buffer = m_swinfo->infotext; + else + mame_machine_manager::instance()->lua()->call_plugin("data", m_items_list[m_current_tab].option, buffer); + } + layout.emplace(create_layout(width)); + add_info_text(*layout, buffer, ui().colors().text_color()); + lines = std::numeric_limits<int>::max(); } } |