Polymorphic machine/software list filters:

* Localisable filter names
* Uniform interface for most filters without far less special-casing
* Stacking year/manufacturer/etc. does OR rather than useless AND
* Prevent stacking contradictory filters (e.g. parents and clones)
* Fix alignment of filter list
* Removed most of the lambdas added the other day
* There's no longer an implicit "not BIOS" filter
* Can't add (un)available to custom machine filter (will address)
This commit is contained in:
Vas Crabb 2017-08-09 23:22:19 +10:00
parent ba14f72569
commit 651d8ee692
11 changed files with 1769 additions and 1740 deletions

View File

@ -11,571 +11,108 @@
#include "emu.h"
#include "ui/custmenu.h"
#include "ui/ui.h"
#include "ui/selector.h"
#include "ui/inifile.h"
#include "rendfont.h"
#include <algorithm>
namespace ui {
/**************************************************
MENU CUSTOM FILTER
**************************************************/
namespace {
constexpr char const *region_lists[] = {
"arab", "arg", "asia", "aus", "aut",
"bel", "blr", "bra",
"can", "chi", "chn", "cze",
"den",
"ecu", "esp", "euro",
"fin", "fra",
"gbr", "ger", "gre",
"hkg", "hun",
"irl", "isr", "isv", "ita",
"jpn",
"kaz", "kor",
"lat", "lux",
"mex",
"ned", "nld", "nor", "nzl",
"pol",
"rus",
"slo", "spa", "sui", "swe",
"tha", "tpe", "tw",
"uk", "ukr", "usa" };
} // anonymous namespace
//-------------------------------------------------
// ctor / dtor
// set software regions
//-------------------------------------------------
menu_custom_filter::menu_custom_filter(mame_ui_manager &mui, render_container &container, bool _single_menu)
: menu(mui, container)
, m_single_menu(_single_menu)
, m_added(false)
void c_sw_region::set(std::string &str)
{
std::string name(getname(str));
std::vector<std::string>::iterator const pos(std::lower_bound(ui.begin(), ui.end(), name));
if ((ui.end() == pos) || (*pos != str))
ui.emplace(pos, std::move(name));
}
menu_custom_filter::~menu_custom_filter()
std::string c_sw_region::getname(std::string const &str) const
{
if (m_single_menu)
reset_topmost(reset_options::SELECT_FIRST);
save_custom_filters();
}
std::string fullname(str);
strmakelower(fullname);
size_t found = fullname.find("(");
//-------------------------------------------------
// handle
//-------------------------------------------------
void menu_custom_filter::handle()
{
bool changed = false;
m_added = false;
// process the menu
const event *menu_event = process(PROCESS_LR_REPEAT);
if (menu_event != nullptr && menu_event->itemref != nullptr)
if (found != std::string::npos)
{
switch ((uintptr_t)menu_event->itemref)
{
case MAIN_FILTER:
if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
{
(menu_event->iptkey == IPT_UI_RIGHT) ? custfltr::main++ : custfltr::main--;
changed = true;
}
break;
size_t ends = fullname.find_first_not_of("abcdefghijklmnopqrstuvwxyz", found + 1);
std::string temp(fullname.substr(found + 1, ends - found - 1));
case ADD_FILTER:
if (menu_event->iptkey == IPT_UI_SELECT)
{
custfltr::numother++;
custfltr::other[custfltr::numother] = machine_filter::UNAVAILABLE;
++custfltr::other[custfltr::numother];
m_added = true;
}
break;
case REMOVE_FILTER:
if (menu_event->iptkey == IPT_UI_SELECT)
{
custfltr::other[custfltr::numother] = machine_filter::UNAVAILABLE;
++custfltr::other[custfltr::numother];
custfltr::numother--;
changed = true;
}
break;
}
if ((uintptr_t)menu_event->itemref >= OTHER_FILTER && (uintptr_t)menu_event->itemref < OTHER_FILTER + MAX_CUST_FILTER)
{
int pos = (int)((uintptr_t)menu_event->itemref - OTHER_FILTER);
if (menu_event->iptkey == IPT_UI_LEFT && custfltr::other[pos] > machine_filter::UNAVAILABLE + 1)
{
custfltr::other[pos]--;
for ( ; custfltr::other[pos] > machine_filter::UNAVAILABLE && (custfltr::other[pos] == machine_filter::CATEGORY
|| custfltr::other[pos] == machine_filter::FAVORITE); custfltr::other[pos]--) { };
changed = true;
}
else if (menu_event->iptkey == IPT_UI_RIGHT && custfltr::other[pos] < machine_filter::LAST - 1)
{
custfltr::other[pos]++;
for ( ; custfltr::other[pos] < machine_filter::LAST && (custfltr::other[pos] == machine_filter::CATEGORY
|| custfltr::other[pos] == machine_filter::FAVORITE); custfltr::other[pos]++) { };
changed = true;
}
else if (menu_event->iptkey == IPT_UI_SELECT)
{
std::vector<machine_filter::type> types;
std::vector<std::string> names;
types.reserve(machine_filter::COUNT);
names.reserve(machine_filter::COUNT);
int sel(-1);
for (machine_filter::type index = machine_filter::FIRST; index < machine_filter::COUNT; ++index)
{
if ((index > machine_filter::UNAVAILABLE) && (index != machine_filter::CATEGORY) && (index != machine_filter::FAVORITE) && (index != machine_filter::CUSTOM))
{
if (custfltr::other[pos] == index)
sel = types.size();
types.emplace_back(index);
names.emplace_back(machine_filter::display_name(index));
}
}
menu::stack_push<menu_selector>(ui(), container(), std::move(names), sel, [this, pos, t = std::move(types)] (int selection) { custfltr::other[pos] = t[selection]; reset(reset_options::REMEMBER_REF); });
}
}
else if ((uintptr_t)menu_event->itemref >= YEAR_FILTER && (uintptr_t)menu_event->itemref < YEAR_FILTER + MAX_CUST_FILTER)
{
int pos = (int)((uintptr_t)menu_event->itemref - YEAR_FILTER);
if (menu_event->iptkey == IPT_UI_LEFT && custfltr::year[pos] > 0)
{
custfltr::year[pos]--;
changed = true;
}
else if (menu_event->iptkey == IPT_UI_RIGHT && custfltr::year[pos] < c_year::ui.size() - 1)
{
custfltr::year[pos]++;
changed = true;
}
else if (menu_event->iptkey == IPT_UI_SELECT)
{
menu::stack_push<menu_selector>(ui(), container(), std::vector<std::string>(c_year::ui), custfltr::year[pos], [this, pos] (int selection) { custfltr::year[pos] = selection; reset(reset_options::REMEMBER_REF); });
}
}
else if ((uintptr_t)menu_event->itemref >= MNFCT_FILTER && (uintptr_t)menu_event->itemref < MNFCT_FILTER + MAX_CUST_FILTER)
{
int pos = (int)((uintptr_t)menu_event->itemref - MNFCT_FILTER);
if (menu_event->iptkey == IPT_UI_LEFT && custfltr::mnfct[pos] > 0)
{
custfltr::mnfct[pos]--;
changed = true;
}
else if (menu_event->iptkey == IPT_UI_RIGHT && custfltr::mnfct[pos] < c_mnfct::ui.size() - 1)
{
custfltr::mnfct[pos]++;
changed = true;
}
else if (menu_event->iptkey == IPT_UI_SELECT)
{
menu::stack_push<menu_selector>(ui(), container(), std::vector<std::string>(c_mnfct::ui), custfltr::mnfct[pos], [this, pos] (int selection) { custfltr::mnfct[pos] = selection; reset(reset_options::REMEMBER_REF); });
}
}
for (auto & elem : region_lists)
if (temp == elem)
return (str.substr(found + 1, ends - found - 1));
}
if (changed)
reset(reset_options::REMEMBER_REF);
else if (m_added)
reset(reset_options::SELECT_FIRST);
return std::string("<none>");
}
//-------------------------------------------------
// populate
// set software device type
//-------------------------------------------------
void menu_custom_filter::populate(float &customtop, float &custombottom)
void c_sw_type::set(std::string &str)
{
// add main filter
uint32_t arrow_flags = get_arrow_flags<uint16_t>(machine_filter::ALL, machine_filter::UNAVAILABLE, custfltr::main);
item_append(_("Main filter"), machine_filter::display_name(custfltr::main), arrow_flags, (void *)(uintptr_t)MAIN_FILTER);
// add other filters
for (int x = 1; x <= custfltr::numother; x++)
{
item_append(menu_item_type::SEPARATOR);
// add filter items
arrow_flags = get_arrow_flags<uint16_t>(machine_filter::UNAVAILABLE + 1, machine_filter::LAST - 1, custfltr::other[x]);
item_append(_("Other filter"), machine_filter::display_name(custfltr::other[x]), arrow_flags, (void *)(uintptr_t)(OTHER_FILTER + x));
if (m_added)
selected = item.size() - 2;
// add manufacturer subitem
if (custfltr::other[x] == machine_filter::MANUFACTURER && c_mnfct::ui.size() > 0)
{
arrow_flags = get_arrow_flags<uint16_t>(0, c_mnfct::ui.size() - 1, custfltr::mnfct[x]);
std::string fbuff(_("^!Manufacturer"));
convert_command_glyph(fbuff);
item_append(fbuff, c_mnfct::ui[custfltr::mnfct[x]], arrow_flags, (void *)(uintptr_t)(MNFCT_FILTER + x));
}
// add year subitem
else if (custfltr::other[x] == machine_filter::YEAR && c_year::ui.size() > 0)
{
arrow_flags = get_arrow_flags<uint16_t>(0, c_year::ui.size() - 1, custfltr::year[x]);
std::string fbuff(_("^!Year"));
convert_command_glyph(fbuff);
item_append(fbuff, c_year::ui[custfltr::year[x]], arrow_flags, (void *)(uintptr_t)(YEAR_FILTER + x));
}
}
item_append(menu_item_type::SEPARATOR);
if (custfltr::numother > 0)
item_append(_("Remove last filter"), "", 0, (void *)(uintptr_t)REMOVE_FILTER);
if (custfltr::numother < MAX_CUST_FILTER - 2)
item_append(_("Add filter"), "", 0, (void *)(uintptr_t)ADD_FILTER);
item_append(menu_item_type::SEPARATOR);
customtop = ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
std::vector<std::string>::iterator const pos(std::lower_bound(ui.begin(), ui.end(), str));
if ((ui.end() == pos) || (*pos != str))
ui.emplace(pos, str);
}
//-------------------------------------------------
// perform our special rendering
// set software years
//-------------------------------------------------
void menu_custom_filter::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
void c_sw_year::set(std::string &str)
{
char const *const text[] = { _("Select custom filters:") };
draw_text_box(
std::begin(text), std::end(text),
origx1, origx2, origy1 - top, origy1 - UI_BOX_TB_BORDER,
ui::text_layout::CENTER, ui::text_layout::NEVER, false,
UI_TEXT_COLOR, UI_GREEN_COLOR, 1.0f);
std::vector<std::string>::iterator const pos(std::lower_bound(ui.begin(), ui.end(), str));
if ((ui.end() == pos) || (*pos != str))
ui.emplace(pos, str);
}
//-------------------------------------------------
// save custom filters info to file
// set software publishers
//-------------------------------------------------
void menu_custom_filter::save_custom_filters()
void c_sw_publisher::set(std::string &str)
{
// attempt to open the output file
emu_file file(ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
if (file.open("custom_", emulator_info::get_configname(), "_filter.ini") == osd_file::error::NONE)
{
// generate custom filters info
std::ostringstream cinfo;
util::stream_format(cinfo, "Total filters = %d\n", (custfltr::numother + 1));
util::stream_format(cinfo, "Main filter = %s\n", machine_filter::config_name(custfltr::main));
for (int x = 1; x <= custfltr::numother; x++)
{
util::stream_format(cinfo, "Other filter = %s\n", machine_filter::config_name(custfltr::other[x]));
if (custfltr::other[x] == machine_filter::MANUFACTURER)
util::stream_format(cinfo, " Manufacturer filter = %s\n", c_mnfct::ui[custfltr::mnfct[x]]);
else if (custfltr::other[x] == machine_filter::YEAR)
util::stream_format(cinfo, " Year filter = %s\n", c_year::ui[custfltr::year[x]]);
}
file.puts(cinfo.str().c_str());
file.close();
}
std::string name(getname(str));
std::vector<std::string>::iterator const pos(std::lower_bound(ui.begin(), ui.end(), name));
if ((ui.end() == pos) || (*pos != str))
ui.emplace(pos, std::move(name));
}
/**************************************************
MENU CUSTOM SOFTWARE FILTER
**************************************************/
//-------------------------------------------------
// ctor / dtor
//-------------------------------------------------
menu_swcustom_filter::menu_swcustom_filter(mame_ui_manager &mui, render_container &container, const game_driver *_driver, s_filter &_filter)
: menu(mui, container)
, m_added(false)
, m_filter(_filter)
, m_driver(_driver)
std::string c_sw_publisher::getname(std::string const &str) const
{
}
size_t found = str.find("(");
menu_swcustom_filter::~menu_swcustom_filter()
{
reset_topmost(reset_options::SELECT_FIRST);
save_sw_custom_filters();
}
//-------------------------------------------------
// handle
//-------------------------------------------------
void menu_swcustom_filter::handle()
{
bool changed = false;
m_added = false;
// process the menu
const event *menu_event = process(PROCESS_LR_REPEAT);
if (menu_event != nullptr && menu_event->itemref != nullptr)
{
switch ((uintptr_t)menu_event->itemref)
{
case MAIN_FILTER:
if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
{
(menu_event->iptkey == IPT_UI_RIGHT) ? sw_custfltr::main++ : sw_custfltr::main--;
changed = true;
}
break;
case ADD_FILTER:
if (menu_event->iptkey == IPT_UI_SELECT)
{
sw_custfltr::numother++;
sw_custfltr::other[sw_custfltr::numother] = software_filter::UNAVAILABLE;
++sw_custfltr::other[sw_custfltr::numother];
m_added = true;
}
break;
case REMOVE_FILTER:
if (menu_event->iptkey == IPT_UI_SELECT)
{
sw_custfltr::other[sw_custfltr::numother] = software_filter::UNAVAILABLE;
++sw_custfltr::other[sw_custfltr::numother];
sw_custfltr::numother--;
changed = true;
}
break;
}
if ((uintptr_t)menu_event->itemref >= OTHER_FILTER && (uintptr_t)menu_event->itemref < OTHER_FILTER + MAX_CUST_FILTER)
{
int pos = (int)((uintptr_t)menu_event->itemref - OTHER_FILTER);
if (menu_event->iptkey == IPT_UI_LEFT && sw_custfltr::other[pos] > software_filter::UNAVAILABLE + 1)
{
sw_custfltr::other[pos]--;
changed = true;
}
else if (menu_event->iptkey == IPT_UI_RIGHT && sw_custfltr::other[pos] < software_filter::LAST - 1)
{
sw_custfltr::other[pos]++;
changed = true;
}
else if (menu_event->iptkey == IPT_UI_SELECT)
{
std::vector<software_filter::type> types;
std::vector<std::string> names;
types.reserve(software_filter::COUNT);
names.reserve(software_filter::COUNT);
uint16_t sel(0);
for (software_filter::type index = software_filter::FIRST; index < software_filter::COUNT; ++index)
{
if ((index >= software_filter::UNAVAILABLE) && (index != software_filter::CUSTOM))
{
if (sw_custfltr::other[pos] == index)
sel = types.size();
types.emplace_back(index);
names.emplace_back(software_filter::display_name(index));
}
}
menu::stack_push<menu_selector>(ui(), container(), std::move(names), sel, [this, pos, t = std::move(types)] (int selection) { sw_custfltr::other[pos] = t[selection]; reset(reset_options::REMEMBER_REF); });
}
}
else if ((uintptr_t)menu_event->itemref >= YEAR_FILTER && (uintptr_t)menu_event->itemref < YEAR_FILTER + MAX_CUST_FILTER)
{
int pos = (int)((uintptr_t)menu_event->itemref - YEAR_FILTER);
if (menu_event->iptkey == IPT_UI_LEFT && sw_custfltr::year[pos] > 0)
{
sw_custfltr::year[pos]--;
changed = true;
}
else if (menu_event->iptkey == IPT_UI_RIGHT && sw_custfltr::year[pos] < m_filter.year.ui.size() - 1)
{
sw_custfltr::year[pos]++;
changed = true;
}
else if (menu_event->iptkey == IPT_UI_SELECT)
{
menu::stack_push<menu_selector>(ui(), container(), std::vector<std::string>(m_filter.year.ui), sw_custfltr::year[pos], [this, pos] (int selection) { sw_custfltr::year[pos] = selection; reset(reset_options::REMEMBER_REF); });
}
}
else if ((uintptr_t)menu_event->itemref >= TYPE_FILTER && (uintptr_t)menu_event->itemref < TYPE_FILTER + MAX_CUST_FILTER)
{
int pos = (int)((uintptr_t)menu_event->itemref - TYPE_FILTER);
if (menu_event->iptkey == IPT_UI_LEFT && sw_custfltr::type[pos] > 0)
{
sw_custfltr::type[pos]--;
changed = true;
}
else if (menu_event->iptkey == IPT_UI_RIGHT && sw_custfltr::type[pos] < m_filter.type.ui.size() - 1)
{
sw_custfltr::type[pos]++;
changed = true;
}
else if (menu_event->iptkey == IPT_UI_SELECT)
{
menu::stack_push<menu_selector>(ui(), container(), std::vector<std::string>(m_filter.type.ui), sw_custfltr::type[pos], [this, pos] (int selection) { sw_custfltr::type[pos] = selection; reset(reset_options::REMEMBER_REF); });
}
}
else if ((uintptr_t)menu_event->itemref >= MNFCT_FILTER && (uintptr_t)menu_event->itemref < MNFCT_FILTER + MAX_CUST_FILTER)
{
int pos = (int)((uintptr_t)menu_event->itemref - MNFCT_FILTER);
if (menu_event->iptkey == IPT_UI_LEFT && sw_custfltr::mnfct[pos] > 0)
{
sw_custfltr::mnfct[pos]--;
changed = true;
}
else if (menu_event->iptkey == IPT_UI_RIGHT && sw_custfltr::mnfct[pos] < m_filter.publisher.ui.size() - 1)
{
sw_custfltr::mnfct[pos]++;
changed = true;
}
else if (menu_event->iptkey == IPT_UI_SELECT)
{
menu::stack_push<menu_selector>(ui(), container(), std::vector<std::string>(m_filter.publisher.ui), sw_custfltr::mnfct[pos], [this, pos] (int selection) { sw_custfltr::mnfct[pos] = selection; reset(reset_options::REMEMBER_REF); });
}
}
else if ((uintptr_t)menu_event->itemref >= REGION_FILTER && (uintptr_t)menu_event->itemref < REGION_FILTER + MAX_CUST_FILTER)
{
int pos = (int)((uintptr_t)menu_event->itemref - REGION_FILTER);
if (menu_event->iptkey == IPT_UI_LEFT && sw_custfltr::region[pos] > 0)
{
sw_custfltr::region[pos]--;
changed = true;
}
else if (menu_event->iptkey == IPT_UI_RIGHT && sw_custfltr::region[pos] < m_filter.region.ui.size() - 1)
{
sw_custfltr::region[pos]++;
changed = true;
}
else if (menu_event->iptkey == IPT_UI_SELECT)
{
menu::stack_push<menu_selector>(ui(), container(), std::vector<std::string>(m_filter.region.ui), sw_custfltr::region[pos], [this, pos] (int selection) { sw_custfltr::region[pos] = selection; reset(reset_options::REMEMBER_REF); });
}
}
else if ((uintptr_t)menu_event->itemref >= LIST_FILTER && (uintptr_t)menu_event->itemref < LIST_FILTER + MAX_CUST_FILTER)
{
int pos = (int)((uintptr_t)menu_event->itemref - LIST_FILTER);
if (menu_event->iptkey == IPT_UI_LEFT && sw_custfltr::list[pos] > 0)
{
sw_custfltr::list[pos]--;
changed = true;
}
else if (menu_event->iptkey == IPT_UI_RIGHT && sw_custfltr::list[pos] < m_filter.swlist.name.size() - 1)
{
sw_custfltr::list[pos]++;
changed = true;
}
else if (menu_event->iptkey == IPT_UI_SELECT)
{
menu::stack_push<menu_selector>(ui(), container(), std::vector<std::string>(m_filter.swlist.description), sw_custfltr::list[pos], [this, pos] (int selection) { sw_custfltr::list[pos] = selection; reset(reset_options::REMEMBER_REF); });
}
}
}
if (changed)
reset(reset_options::REMEMBER_REF);
else if (m_added)
reset(reset_options::SELECT_FIRST);
}
//-------------------------------------------------
// populate
//-------------------------------------------------
void menu_swcustom_filter::populate(float &customtop, float &custombottom)
{
// add main filter
uint32_t arrow_flags = get_arrow_flags<uint16_t>(software_filter::ALL, software_filter::UNAVAILABLE, sw_custfltr::main);
item_append(_("Main filter"), software_filter::display_name(sw_custfltr::main), arrow_flags, (void *)(uintptr_t)MAIN_FILTER);
// add other filters
for (int x = 1; x <= sw_custfltr::numother; x++)
{
item_append(menu_item_type::SEPARATOR);
// add filter items
arrow_flags = get_arrow_flags<uint16_t>(software_filter::UNAVAILABLE + 1, software_filter::LAST - 1, sw_custfltr::other[x]);
item_append(_("Other filter"), software_filter::display_name(sw_custfltr::other[x]), arrow_flags, (void *)(uintptr_t)(OTHER_FILTER + x));
if (m_added)
selected = item.size() - 2;
// add publisher subitem
if (sw_custfltr::other[x] == software_filter::PUBLISHERS && m_filter.publisher.ui.size())
{
arrow_flags = get_arrow_flags<uint16_t>(0, m_filter.publisher.ui.size() - 1, sw_custfltr::mnfct[x]);
std::string fbuff(_("^!Publisher"));
convert_command_glyph(fbuff);
item_append(fbuff, m_filter.publisher.ui[sw_custfltr::mnfct[x]], arrow_flags, (void *)(uintptr_t)(MNFCT_FILTER + x));
}
// add year subitem
else if (sw_custfltr::other[x] == software_filter::YEARS && m_filter.year.ui.size())
{
arrow_flags = get_arrow_flags<uint16_t>(0, m_filter.year.ui.size() - 1, sw_custfltr::year[x]);
std::string fbuff(_("^!Year"));
convert_command_glyph(fbuff);
item_append(fbuff, m_filter.year.ui[sw_custfltr::year[x]], arrow_flags, (void *)(uintptr_t)(YEAR_FILTER + x));
}
// add year subitem
else if (sw_custfltr::other[x] == software_filter::LIST && m_filter.swlist.name.size())
{
arrow_flags = get_arrow_flags<uint16_t>(0, m_filter.swlist.name.size() - 1, sw_custfltr::list[x]);
std::string fbuff(_("^!Software List"));
convert_command_glyph(fbuff);
item_append(fbuff, m_filter.swlist.description[sw_custfltr::list[x]], arrow_flags, (void *)(uintptr_t)(LIST_FILTER + x));
}
// add device type subitem
else if (sw_custfltr::other[x] == software_filter::DEVICE_TYPE && m_filter.type.ui.size())
{
arrow_flags = get_arrow_flags<uint16_t>(0, m_filter.type.ui.size() - 1, sw_custfltr::type[x]);
std::string fbuff(_("^!Device type"));
convert_command_glyph(fbuff);
item_append(fbuff, m_filter.type.ui[sw_custfltr::type[x]], arrow_flags, (void *)(uintptr_t)(TYPE_FILTER + x));
}
// add region subitem
else if (sw_custfltr::other[x] == software_filter::REGION && m_filter.region.ui.size())
{
arrow_flags = get_arrow_flags<uint16_t>(0, m_filter.region.ui.size() - 1, sw_custfltr::region[x]);
std::string fbuff(_("^!Region"));
convert_command_glyph(fbuff);
item_append(fbuff, m_filter.region.ui[sw_custfltr::region[x]], arrow_flags, (void *)(uintptr_t)(REGION_FILTER + x));
}
}
item_append(menu_item_type::SEPARATOR);
if (sw_custfltr::numother > 0)
item_append(_("Remove last filter"), "", 0, (void *)(uintptr_t)REMOVE_FILTER);
if (sw_custfltr::numother < MAX_CUST_FILTER - 2)
item_append(_("Add filter"), "", 0, (void *)(uintptr_t)ADD_FILTER);
item_append(menu_item_type::SEPARATOR);
customtop = ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
}
//-------------------------------------------------
// perform our special rendering
//-------------------------------------------------
void menu_swcustom_filter::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
{
char const *const text[] = { _("Select custom filters:") };
draw_text_box(
std::begin(text), std::end(text),
origx1, origx2, origy1 - top, origy1 - UI_BOX_TB_BORDER,
ui::text_layout::CENTER, ui::text_layout::NEVER, false,
UI_TEXT_COLOR, UI_GREEN_COLOR, 1.0f);
}
//-------------------------------------------------
// save custom filters info to file
//-------------------------------------------------
void menu_swcustom_filter::save_sw_custom_filters()
{
// attempt to open the output file
emu_file file(ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
if (file.open("custom_", m_driver->name, "_filter.ini") == osd_file::error::NONE)
{
// generate custom filters info
std::ostringstream cinfo;
util::stream_format(cinfo, "Total filters = %d\n", (sw_custfltr::numother + 1));
util::stream_format(cinfo, "Main filter = %s\n", software_filter::config_name(sw_custfltr::main));
for (int x = 1; x <= sw_custfltr::numother; x++)
{
util::stream_format(cinfo, "Other filter = %s\n", software_filter::config_name(sw_custfltr::other[x]));
if (sw_custfltr::other[x] == software_filter::PUBLISHERS)
util::stream_format(cinfo, " Manufacturer filter = %s\n", m_filter.publisher.ui[sw_custfltr::mnfct[x]]);
else if (sw_custfltr::other[x] == software_filter::LIST)
util::stream_format(cinfo, " Software List filter = %s\n", m_filter.swlist.name[sw_custfltr::list[x]]);
else if (sw_custfltr::other[x] == software_filter::YEARS)
util::stream_format(cinfo, " Year filter = %s\n", m_filter.year.ui[sw_custfltr::year[x]]);
else if (sw_custfltr::other[x] == software_filter::DEVICE_TYPE)
util::stream_format(cinfo, " Type filter = %s\n", m_filter.type.ui[sw_custfltr::type[x]]);
else if (sw_custfltr::other[x] == software_filter::REGION)
util::stream_format(cinfo, " Region filter = %s\n", m_filter.region.ui[sw_custfltr::region[x]]);
}
file.puts(cinfo.str().c_str());
file.close();
}
if (found != std::string::npos)
return (str.substr(0, found - 1));
else
return str;
}
} // namespace ui

View File

@ -14,33 +14,29 @@
#pragma once
#include "ui/menu.h"
#include "ui/utils.h"
namespace ui {
// Software region
struct c_sw_region
{
std::vector<std::string> ui;
uint16_t actual;
void set(std::string &str);
std::string getname(std::string &str);
std::string getname(std::string const &str) const;
};
// Software publishers
struct c_sw_publisher
{
std::vector<std::string> ui;
uint16_t actual;
void set(std::string &str);
std::string getname(std::string &str);
std::string getname(std::string const &str) const;
};
// Software device type
struct c_sw_type
{
std::vector<std::string> ui;
uint16_t actual;
void set(std::string &str);
};
@ -49,14 +45,12 @@ struct c_sw_list
{
std::vector<std::string> name;
std::vector<std::string> description;
uint16_t actual;
};
// Software years
struct c_sw_year
{
std::vector<std::string> ui;
uint16_t actual;
void set(std::string &str);
};
@ -69,73 +63,6 @@ struct s_filter
c_sw_list swlist;
};
//-------------------------------------------------
// custom software filter menu class
//-------------------------------------------------
class menu_swcustom_filter : public menu
{
public:
menu_swcustom_filter(mame_ui_manager &mui, render_container &container, const game_driver *_driver, s_filter &_filter);
virtual ~menu_swcustom_filter() override;
protected:
virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
private:
enum
{
MAIN_FILTER = 1,
ADD_FILTER,
REMOVE_FILTER,
MNFCT_FILTER,
YEAR_FILTER = MNFCT_FILTER + MAX_CUST_FILTER + 1,
REGION_FILTER = YEAR_FILTER + MAX_CUST_FILTER + 1,
TYPE_FILTER = REGION_FILTER + MAX_CUST_FILTER + 1,
LIST_FILTER = TYPE_FILTER + MAX_CUST_FILTER + 1,
OTHER_FILTER = LIST_FILTER + MAX_CUST_FILTER + 1
};
virtual void populate(float &customtop, float &custombottom) override;
virtual void handle() override;
void save_sw_custom_filters();
bool m_added;
s_filter &m_filter;
const game_driver *m_driver;
};
//-------------------------------------------------
// custom filter menu class
//-------------------------------------------------
class menu_custom_filter : public menu
{
public:
menu_custom_filter(mame_ui_manager &mui, render_container &container, bool _single_menu = false);
virtual ~menu_custom_filter() override;
protected:
virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
private:
enum
{
MAIN_FILTER = 1,
ADD_FILTER,
REMOVE_FILTER,
MNFCT_FILTER,
YEAR_FILTER = MNFCT_FILTER + MAX_CUST_FILTER + 1,
SCREEN_FILTER = YEAR_FILTER + MAX_CUST_FILTER + 1,
OTHER_FILTER = SCREEN_FILTER + MAX_CUST_FILTER + 1
};
virtual void populate(float &customtop, float &custombottom) override;
virtual void handle() override;
void save_custom_filters();
bool m_single_menu, m_added;
};
} // namespace ui
#endif /* MAME_FRONTEND_UI_CUSTMENU_H */

View File

@ -42,7 +42,7 @@ menu_game_options::menu_game_options(mame_ui_manager &mui, render_container &con
menu_game_options::~menu_game_options()
{
main_filters::actual = machine_filter::type(m_main);
main_filters::actual = m_main;
reset_topmost(reset_options::SELECT_FIRST);
ui().save_ui_options();
ui_globals::switch_image = true;
@ -71,180 +71,163 @@ void menu_game_options::handle()
if (menu_event != nullptr && menu_event->itemref != nullptr)
switch ((uintptr_t)menu_event->itemref)
{
case FILTER_MENU:
case FILTER_MENU:
if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
{
if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
{
(menu_event->iptkey == IPT_UI_RIGHT) ? ++m_main : --m_main;
changed = true;
}
else if (menu_event->iptkey == IPT_UI_SELECT)
{
std::vector<std::string> s_sel(machine_filter::COUNT);
for (unsigned index = 0; index < s_sel.size(); ++index)
s_sel[index] = machine_filter::display_name(machine_filter::type(index));
menu::stack_push<menu_selector>(
ui(), container(), std::move(s_sel), m_main,
[this] (int selection)
{
m_main = selection;
reset(reset_options::REMEMBER_REF);
});
}
break;
(menu_event->iptkey == IPT_UI_RIGHT) ? ++m_main : --m_main;
changed = true;
}
case FILE_CATEGORY_FILTER:
else if (menu_event->iptkey == IPT_UI_SELECT)
{
if (menu_event->iptkey == IPT_UI_LEFT)
{
mame_machine_manager::instance()->inifile().move_file(-1);
changed = true;
}
else if (menu_event->iptkey == IPT_UI_RIGHT)
{
mame_machine_manager::instance()->inifile().move_file(1);
changed = true;
}
else if (menu_event->iptkey == IPT_UI_SELECT)
{
inifile_manager &ifile = mame_machine_manager::instance()->inifile();
int total = ifile.total();
std::vector<std::string> s_sel(total);
mame_machine_manager::instance()->inifile().set_cat(0);
for (size_t index = 0; index < total; ++index)
s_sel[index] = ifile.get_file(index);
std::vector<std::string> s_sel(machine_filter::COUNT);
for (unsigned index = 0; index < s_sel.size(); ++index)
s_sel[index] = machine_filter::display_name(machine_filter::type(index));
menu::stack_push<menu_selector>(
ui(), container(), std::move(s_sel), ifile.cur_file(),
[this] (int selection)
{
mame_machine_manager::instance()->inifile().set_file(selection);
mame_machine_manager::instance()->inifile().set_cat(0);
reset(reset_options::REMEMBER_REF);
});
}
break;
menu::stack_push<menu_selector>(
ui(), container(), std::move(s_sel), m_main,
[this] (int selection)
{
m_main = machine_filter::type(selection);
reset(reset_options::REMEMBER_REF);
});
}
case CATEGORY_FILTER:
break;
case FILE_CATEGORY_FILTER:
if (menu_event->iptkey == IPT_UI_LEFT)
{
if (menu_event->iptkey == IPT_UI_LEFT)
{
mame_machine_manager::instance()->inifile().move_cat(-1);
changed = true;
}
else if (menu_event->iptkey == IPT_UI_RIGHT)
{
mame_machine_manager::instance()->inifile().move_cat(1);
changed = true;
}
else if (menu_event->iptkey == IPT_UI_SELECT)
{
inifile_manager &ifile = mame_machine_manager::instance()->inifile();
int total = ifile.cat_total();
std::vector<std::string> s_sel(total);
for (int index = 0; index < total; ++index)
s_sel[index] = ifile.get_category(index);
menu::stack_push<menu_selector>(
ui(), container(), std::move(s_sel), ifile.cur_cat(),
[this] (int selection)
{
mame_machine_manager::instance()->inifile().cur_cat() = selection;
mame_machine_manager::instance()->inifile().set_cat(selection);
reset(reset_options::REMEMBER_REF);
});
}
break;
mame_machine_manager::instance()->inifile().move_file(-1);
changed = true;
}
case MANUFACT_CAT_FILTER:
if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
{
(menu_event->iptkey == IPT_UI_RIGHT) ? c_mnfct::actual++ : c_mnfct::actual--;
changed = true;
}
else if (menu_event->iptkey == IPT_UI_SELECT)
{
menu::stack_push<menu_selector>(
ui(), container(), std::vector<std::string>(c_mnfct::ui), c_mnfct::actual,
[this] (int selection)
{
c_mnfct::actual = selection;
reset(reset_options::REMEMBER_REF);
});
}
else if (menu_event->iptkey == IPT_UI_RIGHT)
{
mame_machine_manager::instance()->inifile().move_file(1);
changed = true;
}
else if (menu_event->iptkey == IPT_UI_SELECT)
{
inifile_manager &ifile = mame_machine_manager::instance()->inifile();
int total = ifile.total();
std::vector<std::string> s_sel(total);
mame_machine_manager::instance()->inifile().set_cat(0);
for (size_t index = 0; index < total; ++index)
s_sel[index] = ifile.get_file(index);
break;
case YEAR_CAT_FILTER:
if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
{
(menu_event->iptkey == IPT_UI_RIGHT) ? c_year::actual++ : c_year::actual--;
changed = true;
}
else if (menu_event->iptkey == IPT_UI_SELECT)
{
menu::stack_push<menu_selector>(
ui(), container(), std::vector<std::string>(c_year::ui), c_year::actual,
[this] (int selection)
{
c_year::actual = selection;
reset(reset_options::REMEMBER_REF);
});
}
menu::stack_push<menu_selector>(
ui(), container(), std::move(s_sel), ifile.cur_file(),
[this] (int selection)
{
mame_machine_manager::instance()->inifile().set_file(selection);
mame_machine_manager::instance()->inifile().set_cat(0);
reset(reset_options::REMEMBER_REF);
});
}
break;
case CATEGORY_FILTER:
if (menu_event->iptkey == IPT_UI_LEFT)
{
mame_machine_manager::instance()->inifile().move_cat(-1);
changed = true;
}
else if (menu_event->iptkey == IPT_UI_RIGHT)
{
mame_machine_manager::instance()->inifile().move_cat(1);
changed = true;
}
else if (menu_event->iptkey == IPT_UI_SELECT)
{
inifile_manager &ifile = mame_machine_manager::instance()->inifile();
int total = ifile.cat_total();
std::vector<std::string> s_sel(total);
for (int index = 0; index < total; ++index)
s_sel[index] = ifile.get_category(index);
break;
case CONF_DIR:
if (menu_event->iptkey == IPT_UI_SELECT)
menu::stack_push<menu_directory>(ui(), container());
break;
case MISC_MENU:
if (menu_event->iptkey == IPT_UI_SELECT)
{
menu::stack_push<submenu>(ui(), container(), submenu::misc_options);
ui_globals::reset = true;
}
break;
case SOUND_MENU:
if (menu_event->iptkey == IPT_UI_SELECT)
{
menu::stack_push<menu_sound_options>(ui(), container());
ui_globals::reset = true;
}
break;
case DISPLAY_MENU:
if (menu_event->iptkey == IPT_UI_SELECT)
{
menu::stack_push<submenu>(ui(), container(), submenu::video_options);
ui_globals::reset = true;
}
break;
case CUSTOM_MENU:
if (menu_event->iptkey == IPT_UI_SELECT)
menu::stack_push<menu_custom_ui>(ui(), container());
break;
case CONTROLLER_MENU:
if (menu_event->iptkey == IPT_UI_SELECT)
menu::stack_push<submenu>(ui(), container(), submenu::control_options);
break;
case CGI_MENU:
if (menu_event->iptkey == IPT_UI_SELECT)
menu::stack_push<menu_input_groups>(ui(), container());
break;
case CUSTOM_FILTER:
if (menu_event->iptkey == IPT_UI_SELECT)
menu::stack_push<menu_custom_filter>(ui(), container());
break;
case ADVANCED_MENU:
if (menu_event->iptkey == IPT_UI_SELECT)
{
menu::stack_push<submenu>(ui(), container(), submenu::advanced_options);
ui_globals::reset = true;
}
break;
case SAVE_CONFIG:
if (menu_event->iptkey == IPT_UI_SELECT)
ui().save_main_option();
break;
menu::stack_push<menu_selector>(
ui(), container(), std::move(s_sel), ifile.cur_cat(),
[this] (int selection)
{
mame_machine_manager::instance()->inifile().cur_cat() = selection;
mame_machine_manager::instance()->inifile().set_cat(selection);
reset(reset_options::REMEMBER_REF);
});
}
break;
case FILTER_ADJUST:
if (menu_event->iptkey == IPT_UI_LEFT)
{
changed = main_filters::filters.find(m_main)->second->adjust_left();
}
else if (menu_event->iptkey == IPT_UI_RIGHT)
{
changed = main_filters::filters.find(m_main)->second->adjust_right();
}
else if (menu_event->iptkey == IPT_UI_SELECT)
{
main_filters::filters.find(m_main)->second->show_ui(
ui(),
container(),
[this] (machine_filter &filter)
{
if (machine_filter::CUSTOM == filter.get_type())
{
emu_file file(ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
if (file.open("custom_", emulator_info::get_configname(), "_filter.ini") == osd_file::error::NONE)
{
filter.save_ini(file, 0);
file.close();
}
}
reset_options::REMEMBER_REF;
});
}
break;
case CONF_DIR:
if (menu_event->iptkey == IPT_UI_SELECT)
menu::stack_push<menu_directory>(ui(), container());
break;
case MISC_MENU:
if (menu_event->iptkey == IPT_UI_SELECT)
{
menu::stack_push<submenu>(ui(), container(), submenu::misc_options);
ui_globals::reset = true;
}
break;
case SOUND_MENU:
if (menu_event->iptkey == IPT_UI_SELECT)
{
menu::stack_push<menu_sound_options>(ui(), container());
ui_globals::reset = true;
}
break;
case DISPLAY_MENU:
if (menu_event->iptkey == IPT_UI_SELECT)
{
menu::stack_push<submenu>(ui(), container(), submenu::video_options);
ui_globals::reset = true;
}
break;
case CUSTOM_MENU:
if (menu_event->iptkey == IPT_UI_SELECT)
menu::stack_push<menu_custom_ui>(ui(), container());
break;
case CONTROLLER_MENU:
if (menu_event->iptkey == IPT_UI_SELECT)
menu::stack_push<submenu>(ui(), container(), submenu::control_options);
break;
case CGI_MENU:
if (menu_event->iptkey == IPT_UI_SELECT)
menu::stack_push<menu_input_groups>(ui(), container());
break;
case ADVANCED_MENU:
if (menu_event->iptkey == IPT_UI_SELECT)
{
menu::stack_push<submenu>(ui(), container(), submenu::advanced_options);
ui_globals::reset = true;
}
break;
case SAVE_CONFIG:
if (menu_event->iptkey == IPT_UI_SELECT)
ui().save_main_option();
break;
}
if (changed)
@ -264,45 +247,38 @@ void menu_game_options::populate(float &customtop, float &custombottom)
// add filter item
uint32_t arrow_flags = get_arrow_flags<uint16_t>(machine_filter::FIRST, machine_filter::LAST, m_main);
item_append(_("Filter"), machine_filter::display_name(machine_filter::type(m_main)), arrow_flags, (void *)(uintptr_t)FILTER_MENU);
if (machine_filter::CATEGORY == m_main)
{
item_append(_("Filter"), machine_filter::display_name(m_main), arrow_flags, (void *)(uintptr_t)FILTER_MENU);
if (mame_machine_manager::instance()->inifile().total() > 0)
{
inifile_manager &inif = mame_machine_manager::instance()->inifile();
// add category subitem
if (m_main == machine_filter::CATEGORY && mame_machine_manager::instance()->inifile().total() > 0)
{
inifile_manager &inif = mame_machine_manager::instance()->inifile();
arrow_flags = get_arrow_flags(uint16_t(0), uint16_t(inif.total() - 1), inif.cur_file());
fbuff = _(" ^!File");
convert_command_glyph(fbuff);
item_append(fbuff, inif.get_file(), arrow_flags, (void *)(uintptr_t)FILE_CATEGORY_FILTER);
arrow_flags = get_arrow_flags(uint16_t(0), uint16_t(inif.total() - 1), inif.cur_file());
fbuff = _(" ^!File");
convert_command_glyph(fbuff);
item_append(fbuff, inif.get_file(), arrow_flags, (void *)(uintptr_t)FILE_CATEGORY_FILTER);
arrow_flags = get_arrow_flags(uint16_t(0), uint16_t(inif.cat_total() - 1), inif.cur_cat());
fbuff = _(" ^!Category");
convert_command_glyph(fbuff);
item_append(fbuff, inif.get_category(), arrow_flags, (void *)(uintptr_t)CATEGORY_FILTER);
}
}
else
{
auto active_filter(main_filters::filters.find(m_main));
if (main_filters::filters.end() == active_filter)
active_filter = main_filters::filters.emplace(m_main, machine_filter::create(m_main)).first;
item_append(_("Filter"), active_filter->second->display_name(), arrow_flags, (void *)(uintptr_t)FILTER_MENU);
arrow_flags = get_arrow_flags(uint16_t(0), uint16_t(inif.cat_total() - 1), inif.cur_cat());
fbuff = _(" ^!Category");
convert_command_glyph(fbuff);
item_append(fbuff, inif.get_category(), arrow_flags, (void *)(uintptr_t)CATEGORY_FILTER);
}
// add manufacturer subitem
else if (m_main == machine_filter::MANUFACTURER && c_mnfct::ui.size() > 0)
{
arrow_flags = get_arrow_flags(uint16_t(0), uint16_t(c_mnfct::ui.size() - 1), c_mnfct::actual);
fbuff = _("^!Manufacturer");
convert_command_glyph(fbuff);
item_append(fbuff, c_mnfct::ui[c_mnfct::actual], arrow_flags, (void *)(uintptr_t)MANUFACT_CAT_FILTER);
}
// add year subitem
else if (m_main == machine_filter::YEAR && c_year::ui.size() > 0)
{
arrow_flags = get_arrow_flags(uint16_t(0), uint16_t(c_year::ui.size() - 1), c_year::actual);
fbuff.assign(_("^!Year"));
convert_command_glyph(fbuff);
item_append(fbuff, c_year::ui[c_year::actual], arrow_flags, (void *)(uintptr_t)YEAR_CAT_FILTER);
}
// add custom subitem
else if (m_main == machine_filter::CUSTOM)
{
fbuff = _("^!Setup custom filter");
convert_command_glyph(fbuff);
item_append(fbuff, "", 0, (void *)(uintptr_t)CUSTOM_FILTER);
// add subitem if the filter wants it
if (active_filter->second->wants_adjuster())
{
std::string name("^!");
convert_command_glyph(name);
item_append(name, active_filter->second->adjust_text(), active_filter->second->arrow_flags(), (void *)(FILTER_ADJUST));
}
}
item_append(menu_item_type::SEPARATOR);

View File

@ -7,13 +7,14 @@
UI main options menu manager.
***************************************************************************/
#pragma once
#ifndef MAME_FRONTEND_UI_OPTSMENU_H
#define MAME_FRONTEND_UI_OPTSMENU_H
#pragma once
#include "ui/menu.h"
#include "ui/utils.h"
namespace ui {
class menu_game_options : public menu
@ -30,8 +31,7 @@ private:
{
FILTER_MENU = 1,
FILE_CATEGORY_FILTER,
MANUFACT_CAT_FILTER,
YEAR_CAT_FILTER,
FILTER_ADJUST,
CATEGORY_FILTER,
CONF_DIR,
DISPLAY_MENU,
@ -42,14 +42,13 @@ private:
ADVANCED_MENU,
SAVE_OPTIONS,
CGI_MENU,
CUSTOM_FILTER,
SAVE_CONFIG
};
virtual void populate(float &customtop, float &custombottom) override;
virtual void handle() override;
uint16_t m_main;
machine_filter::type m_main;
};
} // namespace ui

View File

@ -74,49 +74,40 @@ menu_select_game::menu_select_game(mame_ui_manager &mui, render_container &conta
if (!load_available_machines())
build_available_list();
// load custom filter
load_custom_filters();
if (first_start)
{
reselect_last::set_driver(moptions.last_used_machine());
std::string tmp(moptions.last_used_filter());
std::size_t found = tmp.find_first_of(",");
std::size_t const found = tmp.find_first_of(",");
std::string fake_ini;
if (found == std::string::npos)
last_filter = tmp;
{
fake_ini = util::string_format("%s = 1\n", tmp);
}
else
{
last_filter = tmp.substr(0, found);
sub_filter = tmp.substr(found + 1);
std::string const sub_filter(tmp.substr(found + 1));
tmp.resize(found);
fake_ini = util::string_format("%s = %s\n", tmp, sub_filter);
}
main_filters::actual = machine_filter::ALL;
for (machine_filter::type ind = machine_filter::FIRST; ind < machine_filter::COUNT; ++ind)
emu_file file(ui().options().ui_path(), OPEN_FLAG_READ);
if (file.open_ram(fake_ini.c_str(), fake_ini.size()) == osd_file::error::NONE)
{
if (last_filter == machine_filter::config_name(ind))
machine_filter::ptr flt(machine_filter::create(file));
if (flt)
{
main_filters::actual = ind;
break;
main_filters::actual = flt->get_type();
main_filters::filters.emplace(main_filters::actual, std::move(flt));
}
file.close();
}
if (main_filters::actual == machine_filter::CATEGORY)
main_filters::actual = machine_filter::ALL;
else if (main_filters::actual == machine_filter::MANUFACTURER)
{
for (size_t id = 0; id < c_mnfct::ui.size(); ++id)
if (sub_filter == c_mnfct::ui[id])
c_mnfct::actual = id;
}
else if (main_filters::actual == machine_filter::YEAR)
{
for (size_t id = 0; id < c_year::ui.size(); ++id)
if (sub_filter == c_year::ui[id])
c_year::actual = id;
}
first_start = false;
}
// do this after processing the last used filter setting so it overwrites the placeholder
load_custom_filters();
if (!moptions.remember_last())
reselect_last::reset();
@ -151,11 +142,17 @@ menu_select_game::~menu_select_game()
else if (swinfo && m_prev_selected)
last_driver = reinterpret_cast<ui_software_info *>(m_prev_selected)->shortname;
std::string filter(machine_filter::config_name(main_filters::actual));
if (main_filters::actual == machine_filter::MANUFACTURER)
filter.append(",").append(c_mnfct::ui[c_mnfct::actual]);
else if (main_filters::actual == machine_filter::YEAR)
filter.append(",").append(c_year::ui[c_year::actual]);
std::string filter;
auto const active_filter(main_filters::filters.find(main_filters::actual));
if (main_filters::filters.end() != active_filter)
{
char const *val(active_filter->second->filter_text());
filter = val ? util::string_format("%s,%s", active_filter->second->config_name(), val) : active_filter->second->config_name();
}
else
{
filter = machine_filter::config_name(main_filters::actual);
}
ui_options &mopt = ui().options();
mopt.set_value(OPTION_LAST_USED_FILTER, filter.c_str(), OPTION_PRIORITY_CMDLINE);
@ -423,43 +420,38 @@ void menu_select_game::handle()
if (check_filter)
{
m_search.clear();
if (l_hover == machine_filter::CATEGORY)
switch (l_hover)
{
case machine_filter::CATEGORY:
// FIXME: this should be unified with the other filters
main_filters::actual = machine_filter::type(l_hover);
menu::stack_push<menu_game_options>(ui(), container());
}
else if (l_hover == machine_filter::CUSTOM)
{
main_filters::actual = machine_filter::type(l_hover);
menu::stack_push<menu_custom_filter>(ui(), container(), true);
}
else if (l_hover == machine_filter::MANUFACTURER)
{
menu::stack_push<menu_selector>(
ui(), container(), std::vector<std::string>(c_mnfct::ui), c_mnfct::actual,
[this] (int selection)
{
c_mnfct::actual = selection;
main_filters::actual = machine_filter::type(l_hover);
reset(reset_options::SELECT_FIRST);
});
}
else if (l_hover == machine_filter::YEAR)
{
menu::stack_push<menu_selector>(
ui(), container(), std::vector<std::string>(c_year::ui), c_year::actual,
[this] (int selection)
{
c_year::actual = selection;
main_filters::actual = machine_filter::type(l_hover);
reset(reset_options::SELECT_FIRST);
});
}
else
{
break;
default:
if (l_hover >= machine_filter::ALL)
main_filters::actual = machine_filter::type(l_hover);
reset(reset_options::SELECT_FIRST);
{
auto it(main_filters::filters.find(machine_filter::type(l_hover)));
if (main_filters::filters.end() == it)
it = main_filters::filters.emplace(machine_filter::type(l_hover), machine_filter::create(machine_filter::type(l_hover))).first;
it->second->show_ui(
ui(),
container(),
[this] (machine_filter &filter)
{
machine_filter::type const new_type(filter.get_type());
if (machine_filter::CUSTOM == new_type)
{
emu_file file(ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
if (file.open("custom_", emulator_info::get_configname(), "_filter.ini") == osd_file::error::NONE)
{
filter.save_ini(file, 0);
file.close();
}
}
main_filters::actual = new_type;
reset(reset_options::SELECT_FIRST);
});
}
}
}
}
@ -479,7 +471,9 @@ void menu_select_game::populate(float &customtop, float &custombottom)
{
// if search is not empty, find approximate matches
if (!m_search.empty())
{
populate_search();
}
else
{
// reset search string
@ -489,21 +483,27 @@ void menu_select_game::populate(float &customtop, float &custombottom)
// if filter is set on category, build category list
switch (main_filters::actual)
{
case machine_filter::ALL:
m_displaylist = m_sortedlist;
break;
case machine_filter::AVAILABLE:
m_displaylist = m_availsortedlist;
break;
case machine_filter::UNAVAILABLE:
m_displaylist = m_unavailsortedlist;
break;
case machine_filter::CATEGORY:
build_category();
break;
case machine_filter::MANUFACTURER:
build_list(c_mnfct::ui[c_mnfct::actual].c_str());
break;
case machine_filter::YEAR:
build_list(c_year::ui[c_year::actual].c_str());
break;
case machine_filter::CUSTOM:
build_custom();
break;
default:
build_list();
break;
{
auto const it(main_filters::filters.find(main_filters::actual));
std::copy_if(
m_sortedlist.begin(),
m_sortedlist.end(),
std::back_inserter(m_displaylist),
[&flt = *it->second] (game_driver const *drv) { return flt.apply(*drv); });
}
}
// iterate over entries
@ -906,139 +906,6 @@ void menu_select_game::inkey_special(const event *menu_event)
}
//-------------------------------------------------
// build list
//-------------------------------------------------
void menu_select_game::build_list(const char *filter_text, int filter, bool bioscheck, std::vector<const game_driver *> s_drivers)
{
if (s_drivers.empty())
{
filter = main_filters::actual;
if (filter == machine_filter::AVAILABLE)
s_drivers = m_availsortedlist;
else if (filter == machine_filter::UNAVAILABLE)
s_drivers = m_unavailsortedlist;
else
s_drivers = m_sortedlist;
}
for (auto & s_driver : s_drivers)
{
if (!bioscheck && filter != machine_filter::BIOS && (s_driver->flags & machine_flags::IS_BIOS_ROOT) != 0)
continue;
switch (filter)
{
case machine_filter::ALL:
case machine_filter::AVAILABLE:
case machine_filter::UNAVAILABLE:
m_displaylist.push_back(s_driver);
break;
case machine_filter::WORKING:
if (!(s_driver->flags & machine_flags::NOT_WORKING))
m_displaylist.push_back(s_driver);
break;
case machine_filter::NOT_MECHANICAL:
if (!(s_driver->flags & machine_flags::MECHANICAL))
m_displaylist.push_back(s_driver);
break;
case machine_filter::BIOS:
if (s_driver->flags & machine_flags::IS_BIOS_ROOT)
m_displaylist.push_back(s_driver);
break;
case machine_filter::PARENT:
case machine_filter::CLONES:
{
bool cloneof = strcmp(s_driver->parent, "0");
if (cloneof)
{
auto cx = driver_list::find(s_driver->parent);
if (cx != -1 && ((driver_list::driver(cx).flags & machine_flags::IS_BIOS_ROOT) != 0))
cloneof = false;
}
if (filter == machine_filter::CLONES && cloneof)
m_displaylist.push_back(s_driver);
else if (filter == machine_filter::PARENT && !cloneof)
m_displaylist.push_back(s_driver);
}
break;
case machine_filter::NOT_WORKING:
if (s_driver->flags & machine_flags::NOT_WORKING)
m_displaylist.push_back(s_driver);
break;
case machine_filter::MECHANICAL:
if (s_driver->flags & machine_flags::MECHANICAL)
m_displaylist.push_back(s_driver);
break;
case machine_filter::SAVE:
if (s_driver->flags & machine_flags::SUPPORTS_SAVE)
m_displaylist.push_back(s_driver);
break;
case machine_filter::NOSAVE:
if (!(s_driver->flags & machine_flags::SUPPORTS_SAVE))
m_displaylist.push_back(s_driver);
break;
case machine_filter::YEAR:
if (!core_stricmp(filter_text, s_driver->year))
m_displaylist.push_back(s_driver);
break;
case machine_filter::VERTICAL:
if (s_driver->flags & ORIENTATION_SWAP_XY)
m_displaylist.push_back(s_driver);
break;
case machine_filter::HORIZONTAL:
if (!(s_driver->flags & ORIENTATION_SWAP_XY))
m_displaylist.push_back(s_driver);
break;
case machine_filter::MANUFACTURER:
{
std::string name = c_mnfct::getname(s_driver->manufacturer);
if (!core_stricmp(filter_text, name.c_str()))
m_displaylist.push_back(s_driver);
}
break;
case machine_filter::CHD:
{
auto entries = rom_build_entries(s_driver->rom);
for (const rom_entry &rom : entries)
if (ROMENTRY_ISREGION(&rom) && ROMREGION_ISDISKDATA(&rom))
{
m_displaylist.push_back(s_driver);
break;
}
}
break;
case machine_filter::NOCHD:
{
auto entries = rom_build_entries(s_driver->rom);
bool found = false;
for (const rom_entry &rom : entries)
if (ROMENTRY_ISREGION(&rom) && ROMREGION_ISDISKDATA(&rom))
{
found = true;
break;
}
if (!found)
m_displaylist.push_back(s_driver);
}
break;
}
}
}
//-------------------------------------------------
// change what's displayed in the info box
//-------------------------------------------------
@ -1074,55 +941,6 @@ void menu_select_game::change_info_pane(int delta)
}
}
//-------------------------------------------------
// build custom display list
//-------------------------------------------------
void menu_select_game::build_custom()
{
std::vector<const game_driver *> s_drivers;
bool bioscheck = false;
if (custfltr::main == machine_filter::AVAILABLE)
s_drivers = m_availsortedlist;
else if (custfltr::main == machine_filter::UNAVAILABLE)
s_drivers = m_unavailsortedlist;
else
s_drivers = m_sortedlist;
for (auto & elem : s_drivers)
{
m_displaylist.push_back(elem);
}
for (int count = 1; count <= custfltr::numother; ++count)
{
int filter = custfltr::other[count];
if (filter == machine_filter::BIOS)
bioscheck = true;
}
for (int count = 1; count <= custfltr::numother; ++count)
{
int filter = custfltr::other[count];
s_drivers = m_displaylist;
m_displaylist.clear();
switch (filter)
{
case machine_filter::YEAR:
build_list(c_year::ui[custfltr::year[count]].c_str(), filter, bioscheck, s_drivers);
break;
case machine_filter::MANUFACTURER:
build_list(c_mnfct::ui[custfltr::mnfct[count]].c_str(), filter, bioscheck, s_drivers);
break;
default:
build_list(nullptr, filter, bioscheck, s_drivers);
break;
}
}
}
//-------------------------------------------------
// build category list
//-------------------------------------------------
@ -1378,24 +1196,27 @@ void menu_select_game::init_sorted_list()
return;
// generate full list
std::unordered_set<std::string> manufacturers, years;
for (int x = 0; x < driver_list::total(); ++x)
{
const game_driver *driver = &driver_list::driver(x);
if (driver == &GAME_NAME(___empty))
continue;
if (driver->flags & machine_flags::IS_BIOS_ROOT)
m_isabios++;
game_driver const &driver(driver_list::driver(x));
if (&driver != &GAME_NAME(___empty))
{
if (driver.flags & machine_flags::IS_BIOS_ROOT)
m_isabios++;
m_sortedlist.push_back(driver);
c_mnfct::set(driver->manufacturer);
c_year::set(driver->year);
m_sortedlist.push_back(&driver);
manufacturers.emplace(c_mnfct::getname(driver.manufacturer));
years.emplace(driver.year);
}
}
for (auto & e : c_mnfct::uimap)
c_mnfct::ui.emplace_back(e.first);
// sort manufacturers - years and driver
std::stable_sort(c_mnfct::ui.begin(), c_mnfct::ui.end());
for (auto it = manufacturers.begin(); manufacturers.end() != it; it = manufacturers.erase(it))
c_mnfct::ui.emplace_back(*it);
std::sort(c_mnfct::ui.begin(), c_mnfct::ui.end(), [] (std::string const &x, std::string const &y) { return 0 > core_stricmp(x.c_str(), y.c_str()); });
for (auto it = years.begin(); years.end() != it; it = years.erase(it))
c_year::ui.emplace_back(*it);
std::stable_sort(c_year::ui.begin(), c_year::ui.end());
std::stable_sort(m_sortedlist.begin(), m_sortedlist.end(), sorted_game_list);
}
@ -1457,60 +1278,12 @@ bool menu_select_game::load_available_machines()
void menu_select_game::load_custom_filters()
{
// attempt to open the output file
emu_file file(ui().options().ui_path(), OPEN_FLAG_READ);
if (file.open("custom_", emulator_info::get_configname(), "_filter.ini") == osd_file::error::NONE)
{
char buffer[MAX_CHAR_INFO];
// get number of filters
file.gets(buffer, MAX_CHAR_INFO);
char *pb = strchr(buffer, '=');
custfltr::numother = atoi(++pb) - 1;
// get main filter
file.gets(buffer, MAX_CHAR_INFO);
pb = strchr(buffer, '=') + 2;
for (machine_filter::type y = machine_filter::FIRST; y < machine_filter::COUNT; ++y)
{
char const *const name(machine_filter::config_name(y));
if (!strncmp(pb, name, strlen(name)))
{
custfltr::main = y;
break;
}
}
for (int x = 1; x <= custfltr::numother; ++x)
{
file.gets(buffer, MAX_CHAR_INFO);
char *cb = strchr(buffer, '=') + 2;
for (machine_filter::type y = machine_filter::FIRST; y < machine_filter::COUNT; ++y)
{
char const *const name(machine_filter::config_name(y));
if (!strncmp(cb, name, strlen(name)))
{
custfltr::other[x] = y;
if (y == machine_filter::MANUFACTURER)
{
file.gets(buffer, MAX_CHAR_INFO);
char *ab = strchr(buffer, '=') + 2;
for (size_t z = 0; z < c_mnfct::ui.size(); ++z)
if (!strncmp(ab, c_mnfct::ui[z].c_str(), c_mnfct::ui[z].length()))
custfltr::mnfct[x] = z;
}
else if (y == machine_filter::YEAR)
{
file.gets(buffer, MAX_CHAR_INFO);
char *db = strchr(buffer, '=') + 2;
for (size_t z = 0; z < c_year::ui.size(); ++z)
if (!strncmp(db, c_year::ui[z].c_str(), c_year::ui[z].length()))
custfltr::year[x] = z;
}
}
}
}
machine_filter::ptr flt(machine_filter::create(file));
if (flt)
main_filters::filters[flt->get_type()] = std::move(flt); // not emplace/insert - could replace bogus filter from ui.ini line
file.close();
}
@ -1527,13 +1300,13 @@ float menu_select_game::draw_left_panel(float x1, float y1, float x2, float y2)
if (ui_globals::panels_status == SHOW_PANELS || ui_globals::panels_status == HIDE_RIGHT_PANEL)
{
auto const active_filter(main_filters::filters.find(main_filters::actual));
float origy1 = y1;
float origy2 = y2;
float text_size = ui().options().infos_size();
float line_height_max = line_height * text_size;
float left_width = 0.0f;
int line_count = machine_filter::COUNT;
int afilter = main_filters::actual;
int phover = HOVER_FILTER_FIRST;
float sc = y2 - y1 - (2.0f * UI_BOX_TB_BORDER);
@ -1544,7 +1317,9 @@ float menu_select_game::draw_left_panel(float x1, float y1, float x2, float y2)
line_height_max = line_height * text_size;
}
float text_sign = ui().get_string_width("_# ", text_size);
std::string tmp("_# ");
convert_command_glyph(tmp);
float text_sign = ui().get_string_width(tmp.c_str(), text_size);
for (machine_filter::type x = machine_filter::FIRST; x < machine_filter::COUNT; ++x)
{
float total_width;
@ -1569,7 +1344,21 @@ float menu_select_game::draw_left_panel(float x1, float y1, float x2, float y2)
for (machine_filter::type filter = machine_filter::FIRST; filter < machine_filter::COUNT; ++filter)
{
std::string str(machine_filter::display_name(filter));
std::string str;
if (main_filters::filters.end() != active_filter)
{
str = active_filter->second->adorned_display_name(filter);
}
else
{
if (main_filters::actual == filter)
{
str = std::string("_> ") + str;
convert_command_glyph(str);
}
str.append(machine_filter::display_name(filter));
}
rgb_t bgcolor = UI_TEXT_BG_COLOR;
rgb_t fgcolor = UI_TEXT_COLOR;
@ -1589,35 +1378,7 @@ float menu_select_game::draw_left_panel(float x1, float y1, float x2, float y2)
hilight_main_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(1));
}
float x1t = x1 + text_sign;
if (afilter == machine_filter::CUSTOM)
{
if (filter == custfltr::main)
{
str = std::string("@custom1 ") + str;
x1t -= text_sign;
}
else
{
for (int count = 1; count <= custfltr::numother; ++count)
{
int cfilter = custfltr::other[count];
if (cfilter == filter)
{
str = string_format("@custom%d %s", count + 1, str);
x1t -= text_sign;
break;
}
}
}
convert_command_glyph(str);
}
else if (filter == main_filters::actual)
{
str = std::string("_> ") + str;
x1t -= text_sign;
convert_command_glyph(str);
}
float const x1t = x1 + ((str == machine_filter::display_name(filter)) ? text_sign : 0.0f);
ui().draw_text_full(container(), str.c_str(), x1t, y1, x2 - x1, ui::text_layout::LEFT, ui::text_layout::NEVER,
mame_ui_manager::NORMAL, fgcolor, bgcolor, nullptr, nullptr, text_size);
@ -1705,32 +1466,27 @@ void menu_select_game::make_topbox_text(std::string &line0, std::string &line1,
(driver_list::total() - 1),
m_isabios);
std::string filtered;
if (isfavorite())
{
line1.clear();
}
if (main_filters::actual == machine_filter::CATEGORY && inifile.total() > 0)
{
filtered = string_format(_("%1$s (%2$s - %3$s) - "),
line1 = string_format(_("%1$s (%2$s - %3$s) - Search: %4$s_"),
machine_filter::display_name(main_filters::actual),
inifile.get_file(),
inifile.get_category());
inifile.get_category(),
m_search);
}
else if (main_filters::actual == machine_filter::MANUFACTURER)
{
filtered = string_format(_("%1$s (%2$s) - "),
machine_filter::display_name(main_filters::actual),
c_mnfct::ui[c_mnfct::actual]);
}
else if (main_filters::actual == machine_filter::YEAR)
{
filtered = string_format(_("%1$s (%2$s) - "),
machine_filter::display_name(main_filters::actual),
c_year::ui[c_year::actual]);
}
// display the current typeahead
if (isfavorite())
line1.clear();
else
line1 = string_format(_("%1$s Search: %2$s_"), filtered, m_search);
{
auto const it(main_filters::filters.find(main_filters::actual));
char const *const filter((main_filters::filters.end() != it) ? it->second->filter_text() : nullptr);
if (filter)
line1 = string_format(_("%1$s: %2$s - Search: %3$s_"), it->second->display_name(), filter, m_search);
else
line1 = string_format(_("Search: %1$s_"), m_search);
}
line2.clear();
}

View File

@ -69,10 +69,8 @@ private:
// internal methods
void change_info_pane(int delta);
void build_custom();
void build_category();
void build_available_list();
void build_list(const char *filter_text = nullptr, int filter = 0, bool bioscheck = false, std::vector<const game_driver *> vec = {});
bool isfavorite() const;
void populate_search();

View File

@ -29,11 +29,6 @@
namespace ui {
static const char *region_lists[] = { "arab", "arg", "asia", "aus", "aut", "bel", "blr", "bra", "can", "chi", "chn", "cze", "den",
"ecu", "esp", "euro", "fin", "fra", "gbr", "ger", "gre", "hkg", "hun", "irl", "isr",
"isv", "ita", "jpn", "kaz", "kor", "lat", "lux", "mex", "ned", "nld", "nor", "nzl",
"pol", "rus", "slo", "spa", "sui", "swe", "tha", "tpe", "tw", "uk", "ukr", "usa" };
//-------------------------------------------------
// compares two items in the software list and
// sort them by parent-clone
@ -269,41 +264,28 @@ void menu_select_software::handle()
if (check_filter)
{
m_search.clear();
auto handler =
[this] (uint16_t &actual, int selection)
{
actual = selection;
m_filter_type = software_filter::type(l_sw_hover);
reset(reset_options::SELECT_FIRST);
};
using std::placeholders::_1;
switch (l_sw_hover)
{
case software_filter::REGION:
menu::stack_push<menu_selector>(ui(), container(), std::vector<std::string>(m_filter.region.ui), m_filter.region.actual, std::bind(handler, std::ref(m_filter.region.actual), _1));
break;
case software_filter::YEARS:
menu::stack_push<menu_selector>(ui(), container(), std::vector<std::string>(m_filter.year.ui), m_filter.year.actual, std::bind(handler, std::ref(m_filter.year.actual), _1));
break;
case software_filter::LIST:
menu::stack_push<menu_selector>(ui(), container(), std::vector<std::string>(m_filter.swlist.description), m_filter.swlist.actual, std::bind(handler, std::ref(m_filter.swlist.actual), _1));
break;
case software_filter::DEVICE_TYPE:
menu::stack_push<menu_selector>(ui(), container(), std::vector<std::string>(m_filter.type.ui), m_filter.type.actual, std::bind(handler, std::ref(m_filter.type.actual), _1));
break;
case software_filter::PUBLISHERS:
menu::stack_push<menu_selector>(ui(), container(), std::vector<std::string>(m_filter.publisher.ui), m_filter.publisher.actual, std::bind(handler, std::ref(m_filter.publisher.actual), _1));
break;
case software_filter::CUSTOM:
m_filter_type = software_filter::type(l_sw_hover);
menu::stack_push<menu_swcustom_filter>(ui(), container(), m_driver, m_filter);
break;
default:
m_filter_type = software_filter::type(l_sw_hover);
reset(reset_options::SELECT_FIRST);
break;
}
filter_map::const_iterator it(m_filters.find(software_filter::type(l_sw_hover)));
if (m_filters.end() == it)
it = m_filters.emplace(software_filter::type(l_sw_hover), software_filter::create(software_filter::type(l_sw_hover), m_filter_data)).first;
it->second->show_ui(
ui(),
container(),
[this, driver = m_driver] (software_filter &filter)
{
software_filter::type const new_type(filter.get_type());
if (software_filter::CUSTOM == new_type)
{
emu_file file(ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
if (file.open("custom_", driver->name, "_filter.ini") == osd_file::error::NONE)
{
filter.save_ini(file, 0);
file.close();
}
}
m_filter_type = new_type;
reset(reset_options::SELECT_FIRST);
});
}
}
@ -335,36 +317,11 @@ void menu_select_software::populate(float &customtop, float &custombottom)
m_displaylist.clear();
m_tmp.clear();
switch (m_filter_type)
{
case software_filter::PUBLISHERS:
build_list(m_tmp, m_filter.publisher.ui[m_filter.publisher.actual].c_str());
break;
case software_filter::LIST:
build_list(m_tmp, m_filter.swlist.name[m_filter.swlist.actual].c_str());
break;
case software_filter::YEARS:
build_list(m_tmp, m_filter.year.ui[m_filter.year.actual].c_str());
break;
case software_filter::DEVICE_TYPE:
build_list(m_tmp, m_filter.type.ui[m_filter.type.actual].c_str());
break;
case software_filter::REGION:
build_list(m_tmp, m_filter.region.ui[m_filter.region.actual].c_str());
break;
case software_filter::CUSTOM:
build_custom();
break;
default:
build_list(m_tmp);
break;
}
filter_map::const_iterator const it(m_filters.find(m_filter_type));
if (m_filters.end() == it)
m_displaylist = m_sortedlist;
else
it->second->apply(std::begin(m_sortedlist), std::end(m_sortedlist), std::back_inserter(m_displaylist));
// iterate over entries
for (size_t curitem = 0; curitem < m_displaylist.size(); ++curitem)
@ -419,8 +376,8 @@ void menu_select_software::build_software_list()
// iterate thru all software lists
for (software_list_device &swlist : software_list_device_iterator(config.root_device()))
{
m_filter.swlist.name.push_back(swlist.list_name());
m_filter.swlist.description.push_back(swlist.description());
m_filter_data.swlist.name.push_back(swlist.list_name());
m_filter_data.swlist.description.push_back(swlist.description());
for (const software_info &swinfo : swlist.get_info())
{
const software_part &part = swinfo.parts().front();
@ -443,10 +400,10 @@ void menu_select_software::build_software_list()
ui_software_info tmpmatches(swinfo, part, *m_driver, swlist.list_name(), instance_name, type_name);
m_filter.region.set(tmpmatches.longname);
m_filter.publisher.set(tmpmatches.publisher);
m_filter.year.set(tmpmatches.year);
m_filter.type.set(tmpmatches.devicetype);
m_filter_data.region.set(tmpmatches.longname);
m_filter_data.publisher.set(tmpmatches.publisher);
m_filter_data.year.set(tmpmatches.year);
m_filter_data.type.set(tmpmatches.devicetype);
m_swinfo.emplace_back(std::move(tmpmatches));
}
}
@ -482,7 +439,7 @@ void menu_select_software::build_software_list()
std::string searchstr, curpath;
const osd::directory::entry *dir;
for (auto & elem : m_filter.swlist.name)
for (auto & elem : m_filter_data.swlist.name)
{
path_iterator path(machine().options().media_path());
while (path.next(curpath))
@ -514,10 +471,10 @@ void menu_select_software::build_software_list()
// sort array
std::stable_sort(m_swinfo.begin() + 1, m_swinfo.end(), compare_software);
std::stable_sort(m_filter.region.ui.begin(), m_filter.region.ui.end());
std::stable_sort(m_filter.year.ui.begin(), m_filter.year.ui.end());
std::stable_sort(m_filter.type.ui.begin(), m_filter.type.ui.end());
std::stable_sort(m_filter.publisher.ui.begin(), m_filter.publisher.ui.end());
std::stable_sort(m_filter_data.region.ui.begin(), m_filter_data.region.ui.end());
std::stable_sort(m_filter_data.year.ui.begin(), m_filter_data.year.ui.end());
std::stable_sort(m_filter_data.type.ui.begin(), m_filter_data.type.ui.end());
std::stable_sort(m_filter_data.publisher.ui.begin(), m_filter_data.publisher.ui.end());
for (size_t x = 1; x < m_swinfo.size(); ++x)
m_sortedlist.push_back(&m_swinfo[x]);
@ -596,253 +553,13 @@ void menu_select_software::load_sw_custom_filters()
emu_file file(ui().options().ui_path(), OPEN_FLAG_READ);
if (file.open("custom_", m_driver->name, "_filter.ini") == osd_file::error::NONE)
{
char buffer[MAX_CHAR_INFO];
// get number of filters
file.gets(buffer, MAX_CHAR_INFO);
char *pb = strchr(buffer, '=');
sw_custfltr::numother = atoi(++pb) - 1;
// get main filter
file.gets(buffer, MAX_CHAR_INFO);
pb = strchr(buffer, '=') + 2;
for (software_filter::type y = software_filter::FIRST; y < software_filter::COUNT; ++y)
{
char const *const name(software_filter::config_name(y));
if (!strncmp(pb, name, strlen(name)))
{
sw_custfltr::main = y;
break;
}
}
for (int x = 1; x <= sw_custfltr::numother; ++x)
{
file.gets(buffer, MAX_CHAR_INFO);
char *cb = strchr(buffer, '=') + 2;
for (software_filter::type y = software_filter::FIRST; y < software_filter::COUNT; ++y)
{
char const *const name(software_filter::config_name(y));
if (!strncmp(cb, name, strlen(name)))
{
sw_custfltr::other[x] = y;
if (y == software_filter::PUBLISHERS)
{
file.gets(buffer, MAX_CHAR_INFO);
char *ab = strchr(buffer, '=') + 2;
for (size_t z = 0; z < m_filter.publisher.ui.size(); ++z)
if (!strncmp(ab, m_filter.publisher.ui[z].c_str(), m_filter.publisher.ui[z].length()))
sw_custfltr::mnfct[x] = z;
}
else if (y == software_filter::YEARS)
{
file.gets(buffer, MAX_CHAR_INFO);
char *db = strchr(buffer, '=') + 2;
for (size_t z = 0; z < m_filter.year.ui.size(); ++z)
if (!strncmp(db, m_filter.year.ui[z].c_str(), m_filter.year.ui[z].length()))
sw_custfltr::year[x] = z;
}
else if (y == software_filter::LIST)
{
file.gets(buffer, MAX_CHAR_INFO);
char *gb = strchr(buffer, '=') + 2;
for (size_t z = 0; z < m_filter.swlist.name.size(); ++z)
if (!strncmp(gb, m_filter.swlist.name[z].c_str(), m_filter.swlist.name[z].length()))
sw_custfltr::list[x] = z;
}
else if (y == software_filter::DEVICE_TYPE)
{
file.gets(buffer, MAX_CHAR_INFO);
char *fb = strchr(buffer, '=') + 2;
for (size_t z = 0; z < m_filter.type.ui.size(); ++z)
if (!strncmp(fb, m_filter.type.ui[z].c_str(), m_filter.type.ui[z].length()))
sw_custfltr::type[x] = z;
}
else if (y == software_filter::REGION)
{
file.gets(buffer, MAX_CHAR_INFO);
char *eb = strchr(buffer, '=') + 2;
for (size_t z = 0; z < m_filter.region.ui.size(); ++z)
if (!strncmp(eb, m_filter.region.ui[z].c_str(), m_filter.region.ui[z].length()))
sw_custfltr::region[x] = z;
}
}
}
}
software_filter::ptr flt(software_filter::create(file, m_filter_data));
if (flt)
m_filters.emplace(flt->get_type(), std::move(flt));
file.close();
}
}
//-------------------------------------------------
// set software regions
//-------------------------------------------------
void c_sw_region::set(std::string &str)
{
std::string name = getname(str);
if (std::find(ui.begin(), ui.end(), name) != ui.end())
return;
ui.push_back(name);
}
std::string c_sw_region::getname(std::string &str)
{
std::string fullname(str);
strmakelower(fullname);
size_t found = fullname.find("(");
if (found != std::string::npos)
{
size_t ends = fullname.find_first_not_of("abcdefghijklmnopqrstuvwxyz", found + 1);
std::string temp(fullname.substr(found + 1, ends - found - 1));
for (auto & elem : region_lists)
if (temp == elem)
return (str.substr(found + 1, ends - found - 1));
}
return std::string("<none>");
}
//-------------------------------------------------
// set software device type
//-------------------------------------------------
void c_sw_type::set(std::string &str)
{
if (std::find(ui.begin(), ui.end(), str) != ui.end())
return;
ui.push_back(str);
}
//-------------------------------------------------
// set software years
//-------------------------------------------------
void c_sw_year::set(std::string &str)
{
if (std::find(ui.begin(), ui.end(), str) != ui.end())
return;
ui.push_back(str);
}
//-------------------------------------------------
// set software publishers
//-------------------------------------------------
void c_sw_publisher::set(std::string &str)
{
std::string name = getname(str);
if (std::find(ui.begin(), ui.end(), name) != ui.end())
return;
ui.push_back(name);
}
std::string c_sw_publisher::getname(std::string &str)
{
size_t found = str.find("(");
if (found != std::string::npos)
return (str.substr(0, found - 1));
else
return str;
}
//-------------------------------------------------
// build display list
//-------------------------------------------------
void menu_select_software::build_list(std::vector<ui_software_info *> &s_drivers, const char *filter_text, int filter)
{
if (s_drivers.empty() && filter == -1)
{
filter = m_filter_type;
s_drivers = m_sortedlist;
}
// iterate over entries
for (auto & s_driver : s_drivers)
{
switch (filter)
{
case software_filter::PARENTS:
if (s_driver->parentname.empty())
m_displaylist.push_back(s_driver);
break;
case software_filter::CLONES:
if (!s_driver->parentname.empty())
m_displaylist.push_back(s_driver);
break;
case software_filter::AVAILABLE:
if (s_driver->available)
m_displaylist.push_back(s_driver);
break;
case software_filter::UNAVAILABLE:
if (!s_driver->available)
m_displaylist.push_back(s_driver);
break;
case software_filter::SUPPORTED:
if (s_driver->supported == SOFTWARE_SUPPORTED_YES)
m_displaylist.push_back(s_driver);
break;
case software_filter::PARTIAL_SUPPORTED:
if (s_driver->supported == SOFTWARE_SUPPORTED_PARTIAL)
m_displaylist.push_back(s_driver);
break;
case software_filter::UNSUPPORTED:
if (s_driver->supported == SOFTWARE_SUPPORTED_NO)
m_displaylist.push_back(s_driver);
break;
case software_filter::REGION:
{
std::string name = m_filter.region.getname(s_driver->longname);
if(!name.empty() && name == filter_text)
m_displaylist.push_back(s_driver);
}
break;
case software_filter::PUBLISHERS:
{
std::string name = m_filter.publisher.getname(s_driver->publisher);
if(!name.empty() && name == filter_text)
m_displaylist.push_back(s_driver);
}
break;
case software_filter::YEARS:
if(s_driver->year == filter_text)
m_displaylist.push_back(s_driver);
break;
case software_filter::LIST:
if(s_driver->listname == filter_text)
m_displaylist.push_back(s_driver);
break;
case software_filter::DEVICE_TYPE:
if(s_driver->devicetype == filter_text)
m_displaylist.push_back(s_driver);
break;
default:
m_displaylist.push_back(s_driver);
break;
}
}
}
//-------------------------------------------------
// find approximate matches
//-------------------------------------------------
@ -881,46 +598,6 @@ void menu_select_software::find_matches(const char *str, int count)
(index < count) ? m_searchlist[index] = nullptr : m_searchlist[count] = nullptr;
}
//-------------------------------------------------
// build custom display list
//-------------------------------------------------
void menu_select_software::build_custom()
{
std::vector<ui_software_info *> s_drivers;
build_list(m_sortedlist, nullptr, sw_custfltr::main);
for (int count = 1; count <= sw_custfltr::numother; ++count)
{
software_filter::type filter = sw_custfltr::other[count];
s_drivers = m_displaylist;
m_displaylist.clear();
switch (filter)
{
case software_filter::YEARS:
build_list(s_drivers, m_filter.year.ui[sw_custfltr::year[count]].c_str(), filter);
break;
case software_filter::LIST:
build_list(s_drivers, m_filter.swlist.name[sw_custfltr::list[count]].c_str(), filter);
break;
case software_filter::DEVICE_TYPE:
build_list(s_drivers, m_filter.type.ui[sw_custfltr::type[count]].c_str(), filter);
break;
case software_filter::PUBLISHERS:
build_list(s_drivers, m_filter.publisher.ui[sw_custfltr::mnfct[count]].c_str(), filter);
break;
case software_filter::REGION:
build_list(s_drivers, m_filter.region.ui[sw_custfltr::region[count]].c_str(), filter);
break;
default:
build_list(s_drivers, nullptr, filter);
break;
}
}
}
//-------------------------------------------------
// draw left box
//-------------------------------------------------
@ -929,6 +606,9 @@ float menu_select_software::draw_left_panel(float x1, float y1, float x2, float
{
if (ui_globals::panels_status == SHOW_PANELS || ui_globals::panels_status == HIDE_RIGHT_PANEL)
{
filter_map::const_iterator active_filter(m_filters.find(m_filter_type));
if (m_filters.end() == active_filter)
active_filter = m_filters.emplace(m_filter_type, software_filter::create(m_filter_type, m_filter_data)).first;
float origy1 = y1;
float origy2 = y2;
float text_size = 0.75f;
@ -946,7 +626,9 @@ float menu_select_software::draw_left_panel(float x1, float y1, float x2, float
line_height = l_height * text_size;
}
float text_sign = ui().get_string_width("_# ", text_size);
std::string tmp("_# ");
convert_command_glyph(tmp);
float text_sign = ui().get_string_width(tmp.c_str(), text_size);
for (software_filter::type x = software_filter::FIRST; x < software_filter::COUNT; ++x)
{
float total_width;
@ -971,7 +653,7 @@ float menu_select_software::draw_left_panel(float x1, float y1, float x2, float
for (software_filter::type filter = software_filter::FIRST; filter < software_filter::COUNT; ++filter)
{
std::string str(software_filter::display_name(filter));
std::string const str(active_filter->second->adorned_display_name(filter));
rgb_t bgcolor = UI_TEXT_BG_COLOR;
rgb_t fgcolor = UI_TEXT_COLOR;
@ -994,35 +676,7 @@ float menu_select_software::draw_left_panel(float x1, float y1, float x2, float
hilight_main_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(1));
}
float x1t = x1 + text_sign;
if (m_filter_type == software_filter::CUSTOM)
{
if (filter == sw_custfltr::main)
{
str = std::string("@custom1 ") + str;
x1t -= text_sign;
}
else
{
for (int count = 1; count <= sw_custfltr::numother; ++count)
{
int cfilter = sw_custfltr::other[count];
if (cfilter == filter)
{
str = string_format("@custom%d %s", count + 1, str);
x1t -= text_sign;
break;
}
}
}
convert_command_glyph(str);
}
else if (filter == m_filter_type)
{
str = std::string("_> ") + str;
x1t -= text_sign;
convert_command_glyph(str);
}
float const x1t = x1 + ((str == software_filter::display_name(filter)) ? text_sign : 0.0f);
ui().draw_text_full(container(), str.c_str(), x1t, y1, x2 - x1, ui::text_layout::LEFT, ui::text_layout::NEVER,
mame_ui_manager::NORMAL, fgcolor, bgcolor, nullptr, nullptr, text_size);
@ -1097,19 +751,12 @@ void menu_select_software::make_topbox_text(std::string &line0, std::string &lin
line0 = string_format(_("%1$s %2$s ( %3$d / %4$d software packages )"), emulator_info::get_appname(), bare_build_version, vis_item, m_swinfo.size() - 1);
line1 = string_format(_("Driver: \"%1$s\" software list "), m_driver->type.fullname());
std::string filtered;
if (m_filter_type == software_filter::REGION && m_filter.region.ui.size())
filtered = string_format(_("Region: %1$s -"), m_filter.region.ui[m_filter.region.actual]);
else if (m_filter_type == software_filter::PUBLISHERS)
filtered = string_format(_("Publisher: %1$s -"), m_filter.publisher.ui[m_filter.publisher.actual]);
else if (m_filter_type == software_filter::YEARS)
filtered = string_format(_("Year: %1$s -"), m_filter.year.ui[m_filter.year.actual]);
else if (m_filter_type == software_filter::LIST)
filtered = string_format(_("Software List: %1$s -"), m_filter.swlist.description[m_filter.swlist.actual]);
else if (m_filter_type == software_filter::DEVICE_TYPE)
filtered = string_format(_("Device type: %1$s -"), m_filter.type.ui[m_filter.type.actual]);
line2 = string_format(_("%s Search: %s_"), filtered, m_search);
filter_map::const_iterator const it(m_filters.find(m_filter_type));
char const *const filter((m_filters.end() != it) ? it->second->filter_text() : nullptr);
if (filter)
line2 = string_format(_("%1$s: %2$s - Search: %3$s_"), it->second->display_name(), filter, m_search);
else
line2 = string_format(_("Search: %1$s_"), m_search);
}

View File

@ -14,6 +14,8 @@
#include "ui/custmenu.h"
#include "ui/selmenu.h"
#include "ui/utils.h"
namespace ui {
@ -30,10 +32,13 @@ protected:
private:
enum { VISIBLE_GAMES_IN_SEARCH = 200 };
typedef std::map<software_filter::type, software_filter::ptr> filter_map;
std::string m_search;
const game_driver *m_driver;
bool m_has_empty_start;
s_filter m_filter;
s_filter m_filter_data;
filter_map m_filters;
software_filter::type m_filter_type;
int highlight;
@ -56,8 +61,6 @@ private:
std::vector<ui_software_info> m_swinfo;
void build_software_list();
void build_list(std::vector<ui_software_info *> &vec, const char *filter_text = nullptr, int filter = -1);
void build_custom();
void find_matches(const char *str, int count);
void load_sw_custom_filters();

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause
// copyright-holders:Maurizio Petrarota
// copyright-holders:Maurizio Petrarota, Vas Crabb
/***************************************************************************
ui/utils.h
@ -14,10 +14,111 @@
#include "unicode.h"
#include <algorithm>
#include <limits>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
class mame_ui_manager;
class render_container;
// TODO: namespace this thing
struct ui_software_info
{
ui_software_info() { }
// info for software list item
ui_software_info(
software_info const &info,
software_part const &p,
game_driver const &d,
std::string const &li,
std::string const &is,
std::string const &de);
// info for starting empty
ui_software_info(game_driver const &d);
// copyable/movable
ui_software_info(ui_software_info const &) = default;
ui_software_info(ui_software_info &&) = default;
ui_software_info &operator=(ui_software_info const &) = default;
ui_software_info &operator=(ui_software_info &&) = default;
bool operator==(ui_software_info const &r)
{
return shortname == r.shortname && longname == r.longname && parentname == r.parentname
&& year == r.year && publisher == r.publisher && supported == r.supported
&& part == r.part && driver == r.driver && listname == r.listname
&& interface == r.interface && instance == r.instance && startempty == r.startempty
&& parentlongname == r.parentlongname && usage == r.usage && devicetype == r.devicetype;
}
std::string shortname;
std::string longname;
std::string parentname;
std::string year;
std::string publisher;
uint8_t supported = 0;
std::string part;
const game_driver *driver = nullptr;
std::string listname;
std::string interface;
std::string instance;
uint8_t startempty = 0;
std::string parentlongname;
std::string usage;
std::string devicetype;
bool available = false;
};
namespace ui {
class machine_filter
struct s_filter; // FIXME: this is declared in custmenu.h, it shouldn't be
template <class Impl, typename Entry>
class filter_base
{
public:
typedef std::unique_ptr<Impl> ptr;
virtual ~filter_base() { }
virtual char const *config_name() const = 0;
virtual char const *display_name() const = 0;
virtual char const *filter_text() const = 0;
virtual bool apply(Entry const &info) const = 0;
virtual void show_ui(mame_ui_manager &mui, render_container &container, std::function<void (Impl &)> &&handler) = 0;
virtual bool wants_adjuster() const = 0;
virtual char const *adjust_text() const = 0;
virtual uint32_t arrow_flags() const = 0;
virtual bool adjust_left() = 0;
virtual bool adjust_right() = 0;
virtual void save_ini(emu_file &file, unsigned indent) const = 0;
template <typename InputIt, class OutputIt>
void apply(InputIt first, InputIt last, OutputIt dest) const
{
std::copy_if(first, last, dest, [this] (Entry const *info) { return apply(*info); });
}
protected:
using entry_type = Entry;
filter_base() { }
};
class machine_filter : public filter_base<machine_filter, game_driver>
{
public:
enum type : uint16_t
@ -32,7 +133,7 @@ public:
CATEGORY,
FAVORITE,
BIOS,
PARENT,
PARENTS,
CLONES,
MANUFACTURER,
YEAR,
@ -49,14 +150,28 @@ public:
LAST = COUNT - 1
};
virtual type get_type() const = 0;
virtual std::string adorned_display_name(type n) const = 0;
static ptr create(type n) { return create(n, nullptr, nullptr, 0); }
static ptr create(emu_file &file) { return create(file, 0); }
static char const *config_name(type n);
static char const *display_name(type n);
using filter_base<machine_filter, game_driver>::config_name;
using filter_base<machine_filter, game_driver>::display_name;
protected:
machine_filter();
static ptr create(type n, char const *value, emu_file *file, unsigned indent);
static ptr create(emu_file &file, unsigned indent);
};
DECLARE_ENUM_INCDEC_OPERATORS(machine_filter::type)
class software_filter
class software_filter : public filter_base<software_filter, ui_software_info>
{
public:
enum type : uint16_t
@ -66,7 +181,7 @@ public:
UNAVAILABLE,
PARENTS,
CLONES,
YEARS,
YEAR,
PUBLISHERS,
SUPPORTED,
PARTIAL_SUPPORTED,
@ -81,8 +196,22 @@ public:
LAST = COUNT - 1
};
virtual type get_type() const = 0;
virtual std::string adorned_display_name(type n) const = 0;
static ptr create(type n, s_filter const &data) { return create(n, data, nullptr, nullptr, 0); }
static ptr create(emu_file &file, s_filter const &data) { return create(file, data, 0); }
static char const *config_name(type n);
static char const *display_name(type n);
using filter_base<software_filter, ui_software_info>::config_name;
using filter_base<software_filter, ui_software_info>::display_name;
protected:
software_filter();
static ptr create(type n, s_filter const &data, char const *value, emu_file *file, unsigned indent);
static ptr create(emu_file &file, s_filter const &data, unsigned indent);
};
DECLARE_ENUM_INCDEC_OPERATORS(software_filter::type)
@ -151,73 +280,7 @@ enum
HOVER_RP_LAST = (HOVER_RP_FIRST) + 1 + RP_LAST
};
// GLOBAL STRUCTURES
struct ui_software_info
{
ui_software_info() { }
// info for software list item
ui_software_info(
software_info const &info,
software_part const &p,
game_driver const &d,
std::string const &li,
std::string const &is,
std::string const &de);
// info for starting empty
ui_software_info(game_driver const &d);
// copyable/movable
ui_software_info(ui_software_info const &) = default;
ui_software_info(ui_software_info &&) = default;
ui_software_info &operator=(ui_software_info const &) = default;
ui_software_info &operator=(ui_software_info &&) = default;
bool operator==(ui_software_info const &r)
{
return shortname == r.shortname && longname == r.longname && parentname == r.parentname
&& year == r.year && publisher == r.publisher && supported == r.supported
&& part == r.part && driver == r.driver && listname == r.listname
&& interface == r.interface && instance == r.instance && startempty == r.startempty
&& parentlongname == r.parentlongname && usage == r.usage && devicetype == r.devicetype;
}
std::string shortname;
std::string longname;
std::string parentname;
std::string year;
std::string publisher;
uint8_t supported = 0;
std::string part;
const game_driver *driver = nullptr;
std::string listname;
std::string interface;
std::string instance;
uint8_t startempty = 0;
std::string parentlongname;
std::string usage;
std::string devicetype;
bool available = false;
};
// Manufacturers
struct c_mnfct
{
static void set(const char *str);
static std::string getname(const char *str);
static std::vector<std::string> ui;
static std::unordered_map<std::string, int> uimap;
static uint16_t actual;
};
// Years
struct c_year
{
static void set(const char *str);
static std::vector<std::string> ui;
static uint16_t actual;
};
// FIXME: this stuff shouldn't all be globals
// GLOBAL CLASS
struct ui_globals
@ -229,30 +292,23 @@ struct ui_globals
static bool has_icons;
};
struct main_filters { static ui::machine_filter::type actual; };
// Custom filter
struct custfltr
// Manufacturers
struct c_mnfct
{
static ui::machine_filter::type main;
static uint16_t numother;
static ui::machine_filter::type other[MAX_CUST_FILTER];
static uint16_t mnfct[MAX_CUST_FILTER];
static uint16_t screen[MAX_CUST_FILTER];
static uint16_t year[MAX_CUST_FILTER];
static std::string getname(const char *str);
static std::vector<std::string> ui;
};
// Software custom filter
struct sw_custfltr
// Years
struct c_year
{
static ui::software_filter::type main;
static uint16_t numother;
static ui::software_filter::type other[MAX_CUST_FILTER];
static uint16_t mnfct[MAX_CUST_FILTER];
static uint16_t year[MAX_CUST_FILTER];
static uint16_t region[MAX_CUST_FILTER];
static uint16_t type[MAX_CUST_FILTER];
static uint16_t list[MAX_CUST_FILTER];
static std::vector<std::string> ui;
};
struct main_filters
{
static ui::machine_filter::type actual;
static std::map<ui::machine_filter::type, ui::machine_filter::ptr> filters;
};
// GLOBAL FUNCTIONS

View File

@ -2015,7 +2015,7 @@ DRIVER_INIT_MEMBER(neogeo_state, neogeo)
/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT */
CONS( 1990, neogeo, 0, 0, mvs, neogeo_6slot, neogeo_state, neogeo, "SNK", "Neo-Geo", MACHINE_IS_BIOS_ROOT | MACHINE_SUPPORTS_SAVE )
CONS( 1990, neogeo, 0, 0, mvs, neogeo_6slot, neogeo_state, neogeo, "SNK", "Neo-Geo MVS", MACHINE_IS_BIOS_ROOT | MACHINE_SUPPORTS_SAVE )
CONS( 1990, aes, 0, 0, aes, aes, aes_state, 0, "SNK", "Neo-Geo AES", MACHINE_SUPPORTS_SAVE )