summaryrefslogtreecommitdiffstats
path: root/src/frontend/mame/ui/analogipt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/mame/ui/analogipt.cpp')
-rw-r--r--src/frontend/mame/ui/analogipt.cpp269
1 files changed, 207 insertions, 62 deletions
diff --git a/src/frontend/mame/ui/analogipt.cpp b/src/frontend/mame/ui/analogipt.cpp
index 209a84b4f06..3cc732cb82c 100644
--- a/src/frontend/mame/ui/analogipt.cpp
+++ b/src/frontend/mame/ui/analogipt.cpp
@@ -12,6 +12,7 @@
#include "ui/analogipt.h"
#include <algorithm>
+#include <iterator>
#include <string>
#include <utility>
@@ -50,7 +51,10 @@ menu_analog::menu_analog(mame_ui_manager &mui, render_container &container)
: menu(mui, container)
, m_item_data()
, m_field_data()
+ , m_prompt()
, m_visible_fields(0U)
+ , m_top_field(0)
+ , m_hide_menu(false)
{
set_process_flags(PROCESS_LR_REPEAT);
}
@@ -71,29 +75,96 @@ void menu_analog::custom_render(void *selectedref, float top, float bottom, floa
for (field_data &data : m_field_data)
namewidth = (std::min)((std::max)(ui().get_string_width(data.field.get().name()), namewidth), nameavail);
- // make a box
+ // make a box or two
+ rgb_t const fgcolor(ui().colors().text_color());
+ float const lineheight(ui().get_line_height());
+ float const border(ui().box_tb_border());
float const boxleft((1.0f - namewidth - extrawidth) / 2.0f);
float const boxright(boxleft + namewidth + extrawidth);
- ui().draw_outlined_box(container(), boxleft, y2 + ui().box_tb_border(), boxright, y2 + bottom, ui().colors().background_color());
+ float boxtop;
+ float boxbottom;
+ float firstliney;
+ int visible_fields;
+ if (m_hide_menu)
+ {
+ if (m_prompt.empty())
+ m_prompt = util::string_format(_("Press %s to show menu"), ui().get_general_input_setting(IPT_UI_ON_SCREEN_DISPLAY));
+ draw_text_box(
+ &m_prompt, &m_prompt + 1,
+ boxleft, boxright, y - top, y - top + lineheight + (border * 2.0f),
+ text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false,
+ fgcolor, ui().colors().background_color(), 1.0f);
+ boxtop = y - top + lineheight + (border * 3.0f);
+ firstliney = y - top + lineheight + (border * 4.0f);
+ visible_fields = std::min<int>(m_field_data.size(), int((y2 + bottom - border - firstliney) / lineheight));
+ boxbottom = firstliney + (lineheight * visible_fields) + border;
+ }
+ else
+ {
+ boxtop = y2 + border;
+ boxbottom = y2 + bottom;
+ firstliney = y2 + (border * 2.0f);
+ visible_fields = m_visible_fields;
+ }
+ ui().draw_outlined_box(container(), boxleft, boxtop, boxright, boxbottom, ui().colors().background_color());
+
+ // force the field being configured to be visible
+ ioport_field *const selfield(selectedref ? &reinterpret_cast<item_data *>(selectedref)->field.get() : nullptr);
+ if (!m_hide_menu && selfield)
+ {
+ auto const found(
+ std::find_if(
+ m_field_data.begin(),
+ m_field_data.end(),
+ [selfield] (field_data const &d) { return &d.field.get() == selfield; }));
+ if (m_field_data.end() != found)
+ {
+ auto const i(std::distance(m_field_data.begin(), found));
+ if (m_top_field > i)
+ m_top_field = i;
+ if ((m_top_field + visible_fields) <= i)
+ m_top_field = i - m_visible_fields + 1;
+ }
+ }
+ if (0 > m_top_field)
+ m_top_field = 0;
+ if ((m_top_field + visible_fields) > m_field_data.size())
+ m_top_field = m_field_data.size() - visible_fields;
// show live fields
- namewidth += ui().get_line_height() * aspect;
- unsigned line(0U);
+ namewidth += lineheight * aspect;
float const nameleft(boxleft + (ui().box_lr_border() * aspect));
float const indleft(nameleft + namewidth);
float const indright(indleft + 0.4f);
- ioport_field *const selfield(selectedref ? &reinterpret_cast<item_data *>(selectedref)->field.get() : nullptr);
- for (field_data &data : m_field_data)
+ for (unsigned line = 0; visible_fields > line; ++line)
{
+ // draw arrows if scrolling is possible and menu is hidden
+ float const liney(firstliney + (lineheight * line));
+ if (m_hide_menu)
+ {
+ bool const uparrow(!line && m_top_field);
+ bool const downarrow(((visible_fields - 1) == line) && ((m_field_data.size() - 1) > (line + m_top_field)));
+ if (uparrow || downarrow)
+ {
+ float const arrowwidth = lineheight * aspect;
+ draw_arrow(
+ 0.5f * (nameleft + indright - arrowwidth), liney + (0.25f * lineheight),
+ 0.5f * (nameleft + indright + arrowwidth), liney + (0.75f * lineheight),
+ fgcolor, line ? (ROT0 ^ ORIENTATION_FLIP_Y) : ROT0);
+ continue;
+ }
+ }
+
+ // draw the field name, using the selected colour if it's being configured
+ field_data &data(m_field_data[line + m_top_field]);
bool const selected(&data.field.get() == selfield);
- rgb_t const fgcolor(selected ? ui().colors().selected_color() : ui().colors().text_color());
- float const liney(y2 + (ui().box_tb_border() * 2.0f) + (ui().get_line_height() * line));
+ rgb_t const fieldcolor(selected ? ui().colors().selected_color() : fgcolor);
ui().draw_text_full(
container(),
data.field.get().name(),
nameleft, liney, namewidth,
text_layout::text_justify::LEFT, text_layout::word_wrapping::NEVER,
- mame_ui_manager::NORMAL, fgcolor, ui().colors().text_bg_color());
+ mame_ui_manager::NORMAL, fieldcolor, ui().colors().text_bg_color());
ioport_value cur(0U);
data.field.get().live().analog->read(cur);
@@ -102,8 +173,8 @@ void menu_analog::custom_render(void *selectedref, float top, float bottom, floa
if (data.field.get().analog_reverse())
fill = 1.0f - fill;
- float const indtop(liney + (ui().get_line_height() * 0.2f));
- float const indbottom(liney + (ui().get_line_height() * 0.8f));
+ float const indtop(liney + (lineheight * 0.2f));
+ float const indbottom(liney + (lineheight * 0.8f));
if (data.origin > fill)
container().add_rect(indleft + (fill * 0.4f), indtop, indleft + (data.origin * 0.4f), indbottom, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
else
@@ -114,10 +185,6 @@ void menu_analog::custom_render(void *selectedref, float top, float bottom, floa
container().add_line(indleft, indbottom, indleft, indtop, UI_LINE_WIDTH, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
if (data.show_neutral)
container().add_line(indleft + (data.neutral * 0.4f), indtop, indleft + (data.neutral * 0.4f), indbottom, UI_LINE_WIDTH, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
-
- // TODO: ensure field being configured is visible
- if (++line >= m_visible_fields)
- break;
}
}
@@ -125,53 +192,133 @@ void menu_analog::custom_render(void *selectedref, float top, float bottom, floa
void menu_analog::handle(event const *ev)
{
// handle events
- if (ev && ev->itemref)
+ if (ev)
{
- item_data &data(*reinterpret_cast<item_data *>(ev->itemref));
- int newval(data.cur);
-
- switch (ev->iptkey)
+ if (IPT_UI_ON_SCREEN_DISPLAY == ev->iptkey)
{
- // if selected, reset to default value
- case IPT_UI_SELECT:
- newval = data.defvalue;
- break;
-
- // left decrements
- case IPT_UI_LEFT:
- newval -= machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1;
- break;
-
- // right increments
- case IPT_UI_RIGHT:
- newval += machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1;
- break;
+ m_hide_menu = !m_hide_menu;
+ set_process_flags(PROCESS_LR_REPEAT | (m_hide_menu ? (PROCESS_CUSTOM_NAV | PROCESS_CUSTOM_ONLY) : 0));
}
-
- // clamp to range
- if (newval < data.min)
- newval = data.min;
- if (newval > data.max)
- newval = data.max;
-
- // if things changed, update
- if (newval != data.cur)
+ else if (m_hide_menu)
{
- ioport_field::user_settings settings;
+ switch (ev->iptkey)
+ {
+ case IPT_UI_UP:
+ --m_top_field;
+ break;
+ case IPT_UI_DOWN:
+ ++m_top_field;
+ break;
+ case IPT_UI_HOME:
+ m_top_field = 0;
+ break;
+ case IPT_UI_END:
+ m_top_field = m_field_data.size();
+ break;
+ }
+ }
+ else if (ev->itemref)
+ {
+ item_data &data(*reinterpret_cast<item_data *>(ev->itemref));
+ int newval(data.cur);
- // get the settings and set the new value
- data.field.get().get_user_settings(settings);
- switch (data.type)
+ switch (ev->iptkey)
{
- case ANALOG_ITEM_KEYSPEED: settings.delta = newval; break;
- case ANALOG_ITEM_CENTERSPEED: settings.centerdelta = newval; break;
- case ANALOG_ITEM_REVERSE: settings.reverse = newval; break;
- case ANALOG_ITEM_SENSITIVITY: settings.sensitivity = newval; break;
+ // if selected, reset to default value
+ case IPT_UI_SELECT:
+ newval = data.defvalue;
+ break;
+
+ // left decrements
+ case IPT_UI_LEFT:
+ newval -= machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1;
+ break;
+
+ // right increments
+ case IPT_UI_RIGHT:
+ newval += machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1;
+ break;
+
+ // move to first item for previous device
+ case IPT_UI_PREV_GROUP:
+ {
+ auto current = std::distance(m_item_data.data(), &data);
+ device_t const *dev(&data.field.get().device());
+ bool found_break = false;
+ while (0 < current)
+ {
+ if (!found_break)
+ {
+ device_t const *prev(&m_item_data[--current].field.get().device());
+ if (prev != dev)
+ {
+ dev = prev;
+ found_break = true;
+ }
+ }
+ else if (&m_item_data[current - 1].field.get().device() != dev)
+ {
+ set_selection(&m_item_data[current]);
+ set_top_line(selected_index() - 1);
+ break;
+ }
+ else
+ {
+ --current;
+ }
+ if (found_break && !current)
+ {
+ set_selection(&m_item_data[current]);
+ set_top_line(selected_index() - 1);
+ break;
+ }
+ }
+ }
+ break;
+
+ // move to first item for next device
+ case IPT_UI_NEXT_GROUP:
+ {
+ auto current = std::distance(m_item_data.data(), &data);
+ device_t const *const dev(&data.field.get().device());
+ while (m_item_data.size() > ++current)
+ {
+ if (&m_item_data[current].field.get().device() != dev)
+ {
+ set_selection(&m_item_data[current]);
+ set_top_line(selected_index() - 1);
+ break;
+ }
+ }
+ }
+ break;
}
- data.field.get().set_user_settings(settings);
- // rebuild the menu
- reset(reset_options::REMEMBER_POSITION);
+ // clamp to range
+ if (newval < data.min)
+ newval = data.min;
+ if (newval > data.max)
+ newval = data.max;
+
+ // if things changed, update
+ if (newval != data.cur)
+ {
+ ioport_field::user_settings settings;
+
+ // get the settings and set the new value
+ data.field.get().get_user_settings(settings);
+ switch (data.type)
+ {
+ case ANALOG_ITEM_KEYSPEED: settings.delta = newval; break;
+ case ANALOG_ITEM_CENTERSPEED: settings.centerdelta = newval; break;
+ case ANALOG_ITEM_REVERSE: settings.reverse = newval; break;
+ case ANALOG_ITEM_SENSITIVITY: settings.sensitivity = newval; break;
+ }
+ data.field.get().set_user_settings(settings);
+
+ // rebuild the menu
+ reset(reset_options::REMEMBER_POSITION);
+ }
}
}
}
@@ -184,7 +331,6 @@ void menu_analog::populate(float &customtop, float &custombottom)
find_fields();
device_t *prev_owner(nullptr);
- bool first_entry(true);
ioport_field *field(nullptr);
ioport_field::user_settings settings;
@@ -202,11 +348,10 @@ void menu_analog::populate(float &customtop, float &custombottom)
if (&field->device() != prev_owner)
{
prev_owner = &field->device();
- if (first_entry)
- first_entry = false;
+ if (prev_owner->owner())
+ item_append(string_format(_("%1$s [root%2$s]"), prev_owner->type().fullname(), prev_owner->tag()), FLAG_UI_HEADING | FLAG_DISABLE, nullptr);
else
- item_append(menu_item_type::SEPARATOR);
- item_append(string_format("[root%s]", prev_owner->tag()), 0, nullptr);
+ item_append(string_format(_("[root%1$s]"), prev_owner->tag()), FLAG_UI_HEADING | FLAG_DISABLE, nullptr);
}
}
@@ -304,9 +449,9 @@ void menu_analog::find_fields()
}
}
- // restrict live display to 60% height plus borders
- if ((ui().get_line_height() * m_field_data.size()) > 0.6f)
- m_visible_fields = unsigned(0.6f / ui().get_line_height());
+ // restrict live display to 40% height plus borders
+ if ((ui().get_line_height() * m_field_data.size()) > 0.4f)
+ m_visible_fields = unsigned(0.4f / ui().get_line_height());
else
m_visible_fields = m_field_data.size();
}