diff options
author | 2021-10-31 12:31:16 +1100 | |
---|---|---|
committer | 2021-10-31 12:31:16 +1100 | |
commit | d64ea5331b2312f81df464fb22dcef0191216d86 (patch) | |
tree | a3f3784371da401e6a675e5b6b9734b88281a08d /src/frontend/mame/ui/textbox.cpp | |
parent | cfffc54b61cabc5ef9533396bf87324eb5eeb63e (diff) |
-frontend: Refactored menu event handling and fixed a number of issues. (#8777)
* Moved common code for drawing about box, info viewer, and other text box menus to a base class; removed the last of the info viewer logic and the multi-line item hack from the base menu class.
* Added previous/next group navigation for general inputs and plugin input selection menus.
* Moved message catalog logic to lib/util, allowing osd and emu to use localised messages.
* Made the base menu class use the UI manager’s feature for holding session state rather than a static map and mutex.
* Improved menu event handling model, and fixed many issues, particularly with menus behaving badly when hidden/shown.
* Added better support for menus that don’t participate in the usual menu stack, like the menuless sliders and the save/load state menus.
* Made a number of menus refresh state when being shown after being hidden (fixes MT08121 among other issues).
* Fixed indication of mounted slot option in the slot option details menu.
* Improved appearance of background menus when emulation isn't running - draw all menus in the stack, and darken the background menus to make the edges of the active menu clearer.
* Fixed locale issues in -listxml.
-debugger: Made GUI debuggers more uniform.
* Added new memory view features to Win32 debugger.
* Fixed spelling of hexadecimal in Cocoa debugger and added decimal address option.
* Fixed duplicate keyboard shortcut in Cocoa debugger (Shift-Cmd-D was both new device window and 64-bit float format).
* Made keyboard shortcuts slightly more consistent across debuggers.
-plugins: Moved input selection menu and sequence polling code to a common library. Fixed the issue that prevented keyboard inputs being mapped with -steadykey on.
-docs: Started adding some documentation for MAME's internal UI, and updated the list of example front-ends.
-Regenerated message catalog sources. For translators, the new strings are mostly:
* The names of the inputs provided by the OS-dependent layer for things like fullscreen and video features. These show up in the user interface inputs menu.
* The names for automatically generated views. These show up in the video options menu - test with a system with a lot of screens to see more variants.
* The input macro plugin UI.
* A few format strings for analog input assignments.
* A few strings for the about box header.
Diffstat (limited to 'src/frontend/mame/ui/textbox.cpp')
-rw-r--r-- | src/frontend/mame/ui/textbox.cpp | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/src/frontend/mame/ui/textbox.cpp b/src/frontend/mame/ui/textbox.cpp new file mode 100644 index 00000000000..177f39a0f53 --- /dev/null +++ b/src/frontend/mame/ui/textbox.cpp @@ -0,0 +1,237 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + ui/textbox.cpp + + Menu that displays a non-interactive text box + +***************************************************************************/ + +#include "emu.h" +#include "textbox.h" + +#include "ui/ui.h" +#include "ui/utils.h" + +#include <string_view> + + +namespace ui { + +//------------------------------------------------- +// constructor +//------------------------------------------------- + +menu_textbox::menu_textbox(mame_ui_manager &mui, render_container &container) + : menu(mui, container) + , m_layout() + , m_layout_width(-1.0f) + , m_desired_width(-1.0f) + , m_desired_lines(-1) + , m_top_line(0) +{ +} + + +//------------------------------------------------- +// destructor +//------------------------------------------------- + +menu_textbox::~menu_textbox() +{ +} + + +//------------------------------------------------- +// reset_layout - force repopulate and scroll to +// top +//------------------------------------------------- + +void menu_textbox::reset_layout() +{ + m_layout = std::nullopt; + m_top_line = 0; +} + + +//------------------------------------------------- +// handle_key - handle basic navigation keys +//------------------------------------------------- + +void menu_textbox::handle_key(int key) +{ + switch (key) + { + case IPT_UI_UP: + --m_top_line; + break; + + case IPT_UI_DOWN: + ++m_top_line; + break; + + case IPT_UI_PAGE_UP: + m_top_line -= m_window_lines - 3; + break; + + case IPT_UI_PAGE_DOWN: + m_top_line += m_window_lines - 3; + break; + + case IPT_UI_HOME: + m_top_line = 0; + break; + + case IPT_UI_END: + m_top_line = m_layout->lines() - m_window_lines; + break; + } +} + + +//------------------------------------------------- +// custom_mouse_scroll - handle scroll events +//------------------------------------------------- + +bool menu_textbox::custom_mouse_scroll(int lines) +{ + m_top_line += lines; + return true; +} + + +//------------------------------------------------- +// draw - draw the menu +//------------------------------------------------- + +void menu_textbox::draw(uint32_t flags) +{ + 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; + + // determine effective positions taking into account the hilighting arrows + float const maximum_width = visible_width - 2.0f * gutter_width; + + draw_background(); + map_mouse(); + + // account for extra space at the top and bottom and the separator/item for closing + float visible_main_menu_height = 1.0f - 2.0f * ui().box_tb_border() - visible_extra_menu_height; + m_window_lines = int(std::trunc(visible_main_menu_height / line_height)); + + // lay out the text if necessary + if (!m_layout || (m_layout_width != maximum_width)) + { + m_desired_width = maximum_width; + populate_text(m_layout, m_desired_width, m_desired_lines); + m_layout_width = maximum_width; + } + m_window_lines = (std::min)(m_desired_lines, m_window_lines); + visible_main_menu_height = float(m_window_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(); + + // get width required to draw the sole menu item + menu_item const &pitem = item(0); + std::string_view const itemtext = pitem.text; + float const itemwidth = gutter_width + ui().get_string_width(itemtext) + gutter_width; + float const draw_width = std::min(maximum_width, std::max(itemwidth, m_desired_width)); + + // compute text box size + float const x1 = visible_left + ((maximum_width - draw_width) * 0.5f); + float const y1 = visible_top - ui().box_tb_border(); + float const x2 = visible_left + visible_width - ((maximum_width - draw_width) * 0.5f); + float const y2 = visible_top + visible_main_menu_height + ui().box_tb_border() + extra_height; + float const effective_left = x1 + gutter_width; + float const line_x0 = x1 + 0.5f * UI_LINE_WIDTH; + float const line_x1 = x2 - 0.5f * UI_LINE_WIDTH; + float const separator = visible_top + float(m_window_lines) * line_height; + + ui().draw_outlined_box(container(), x1, y1, x2, y2, ui().colors().background_color()); + + int const visible_items = m_layout->lines(); + m_window_lines = (std::min)(visible_items, m_window_lines); + m_top_line = (std::max)(0, m_top_line); + if (m_top_line + m_window_lines >= visible_items) + m_top_line = visible_items - m_window_lines; + + clear_hover(); + if (m_top_line) + { + // if we're on the top line, display the up arrow + rgb_t fgcolor = ui().colors().text_color(); + if (mouse_in_rect(line_x0, visible_top, line_x1, visible_top + line_height)) + { + fgcolor = ui().colors().mouseover_color(); + highlight( + line_x0, visible_top, + line_x1, visible_top + line_height, + ui().colors().mouseover_bg_color()); + set_hover(HOVER_ARROW_UP); + } + draw_arrow( + 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, visible_top + 0.25f * line_height, + 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, visible_top + 0.75f * line_height, + fgcolor, ROT0); + } + if ((m_top_line + m_window_lines) < visible_items) + { + // if we're on the bottom line, display the down arrow + float const line_y = visible_top + float(m_window_lines - 1) * line_height; + rgb_t fgcolor = ui().colors().text_color(); + if (mouse_in_rect(line_x0, line_y, line_x1, line_y + line_height)) + { + fgcolor = ui().colors().mouseover_color(); + highlight( + line_x0, line_y, + line_x1, line_y + line_height, + ui().colors().mouseover_bg_color()); + set_hover(HOVER_ARROW_DOWN); + } + 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); + } + + // draw visible lines, minus 1 for top arrow and 1 for bottom arrow + auto const text_lines = m_window_lines - (m_top_line ? 1 : 0) - (m_top_line + m_window_lines != visible_items); + m_layout->emit( + container(), + m_top_line ? (m_top_line + 1) : 0, text_lines, + effective_left, visible_top + (m_top_line ? line_height : 0.0f)); + + // add visual separator before the "return to prevous menu" item + container().add_line( + x1, separator + (0.5f * line_height), + x2, separator + (0.5f * line_height), + UI_LINE_WIDTH, ui().colors().text_color(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + + float const line_y0 = separator + line_height; + float const line_y1 = line_y0 + line_height; + + if (mouse_in_rect(line_x0, line_y0, line_x1, line_y1) && is_selectable(pitem)) + set_hover(0); + + highlight(line_x0, line_y0, line_x1, line_y1, ui().colors().selected_bg_color()); + ui().draw_text_full( + container(), itemtext, + effective_left, line_y0, draw_width, + text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, + mame_ui_manager::NORMAL, + ui().colors().selected_color(), ui().colors().selected_bg_color(), + nullptr, nullptr); + + // 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); +} + +} // namespace ui |