summaryrefslogtreecommitdiffstatshomepage
path: root/src/frontend/mame/ui/datmenu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/mame/ui/datmenu.cpp')
-rw-r--r--src/frontend/mame/ui/datmenu.cpp587
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();
}
}