clean up some of the UI filter stuff, show list descriptions rather than names when choosing list to filter on (nw)

This commit is contained in:
Vas Crabb 2017-08-18 18:26:26 +10:00
parent 3f39b31287
commit 73107179b5
8 changed files with 181 additions and 251 deletions

View File

@ -130,8 +130,6 @@ files {
MAME_DIR .. "src/frontend/mame/ui/viewgfx.h",
MAME_DIR .. "src/frontend/mame/ui/auditmenu.cpp",
MAME_DIR .. "src/frontend/mame/ui/auditmenu.h",
MAME_DIR .. "src/frontend/mame/ui/custmenu.cpp",
MAME_DIR .. "src/frontend/mame/ui/custmenu.h",
MAME_DIR .. "src/frontend/mame/ui/custui.cpp",
MAME_DIR .. "src/frontend/mame/ui/custui.h",
MAME_DIR .. "src/frontend/mame/ui/datmenu.cpp",

View File

@ -1,118 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Maurizio Petrarota
/*********************************************************************
ui/custmenu.cpp
Internal UI user interface.
*********************************************************************/
#include "emu.h"
#include "ui/custmenu.h"
#include <algorithm>
namespace ui {
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
//-------------------------------------------------
// set software regions
//-------------------------------------------------
void c_sw_region::set(std::string const &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));
}
std::string c_sw_region::getname(std::string const &str) const
{
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)
{
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);
}
//-------------------------------------------------
// set software years
//-------------------------------------------------
void c_sw_year::set(std::string &str)
{
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);
}
//-------------------------------------------------
// set software publishers
//-------------------------------------------------
void c_sw_publisher::set(std::string const &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 != name))
ui.emplace(pos, std::move(name));
}
std::string c_sw_publisher::getname(std::string const &str) const
{
size_t found = str.find("(");
if (found != std::string::npos)
return (str.substr(0, found - 1));
else
return str;
}
} // namespace ui

View File

@ -1,68 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Maurizio Petrarota
/***************************************************************************
ui/custmenu.h
Internal UI user interface.
***************************************************************************/
#ifndef MAME_FRONTEND_UI_CUSTMENU_H
#define MAME_FRONTEND_UI_CUSTMENU_H
#pragma once
namespace ui {
// Software region
struct c_sw_region
{
std::vector<std::string> ui;
void set(std::string const &str);
std::string getname(std::string const &str) const;
};
// Software publishers
struct c_sw_publisher
{
std::vector<std::string> ui;
void set(std::string const &str);
std::string getname(std::string const &str) const;
};
// Software device type
struct c_sw_type
{
std::vector<std::string> ui;
void set(std::string &str);
};
// Software list
struct c_sw_list
{
std::vector<std::string> name;
std::vector<std::string> description;
};
// Software years
struct c_sw_year
{
std::vector<std::string> ui;
void set(std::string &str);
};
struct s_filter
{
c_sw_region region;
c_sw_publisher publisher;
c_sw_year year;
c_sw_type type;
c_sw_list swlist;
};
} // namespace ui
#endif /* MAME_FRONTEND_UI_CUSTMENU_H */

View File

@ -11,14 +11,13 @@
#include "emu.h"
#include "ui/selgame.h"
#include "ui/ui.h"
#include "ui/miscmenu.h"
#include "ui/auditmenu.h"
#include "ui/inifile.h"
#include "ui/miscmenu.h"
#include "ui/optsmenu.h"
#include "ui/selector.h"
#include "ui/selsoft.h"
#include "ui/custmenu.h"
#include "ui/auditmenu.h"
#include "ui/ui.h"
#include "../info.h"

View File

@ -313,8 +313,7 @@ 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_data.swlist.name.push_back(swlist.list_name());
m_filter_data.swlist.description.push_back(swlist.description());
m_filter_data.add_list(swlist.list_name(), swlist.description());
for (const software_info &swinfo : swlist.get_info())
{
const software_part &part = swinfo.parts().front();
@ -337,10 +336,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_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_filter_data.add_region(tmpmatches.longname);
m_filter_data.add_publisher(tmpmatches.publisher);
m_filter_data.add_year(tmpmatches.year);
m_filter_data.add_device_type(tmpmatches.devicetype);
m_swinfo.emplace_back(std::move(tmpmatches));
}
}
@ -375,8 +374,7 @@ void menu_select_software::build_software_list()
}
std::string searchstr, curpath;
const osd::directory::entry *dir;
for (auto & elem : m_filter_data.swlist.name)
for (auto & elem : m_filter_data.list_names())
{
path_iterator path(machine().options().media_path());
while (path.next(curpath))
@ -385,6 +383,7 @@ void menu_select_software::build_software_list()
file_enumerator fpath(searchstr.c_str());
// iterate while we get new objects
osd::directory::entry const *dir;
while ((dir = fpath.next()) != nullptr)
{
std::string name;
@ -408,10 +407,7 @@ 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_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());
m_filter_data.finalise();
for (size_t x = 1; x < m_swinfo.size(); ++x)
m_sortedlist.push_back(&m_swinfo[x]);

View File

@ -12,7 +12,6 @@
#pragma once
#include "ui/custmenu.h"
#include "ui/selmenu.h"
#include "ui/utils.h"
@ -33,7 +32,7 @@ private:
const game_driver *m_driver;
bool m_has_empty_start;
s_filter m_filter_data;
software_filter_data m_filter_data;
filter_map m_filters;
software_filter::type m_filter_type;

View File

@ -11,7 +11,6 @@
#include "emu.h"
#include "ui/utils.h"
#include "ui/custmenu.h" // FIXME: get s_filter out of here
#include "ui/inifile.h"
#include "ui/selector.h"
@ -33,7 +32,28 @@ namespace ui {
namespace {
constexpr char const *machine_filter_names[machine_filter::COUNT] = {
constexpr char const *SOFTWARE_REGIONS[] = {
"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" };
constexpr char const *MACHINE_FILTER_NAMES[machine_filter::COUNT] = {
__("Unfiltered"),
__("Available"),
__("Unavailable"),
@ -57,7 +77,7 @@ constexpr char const *machine_filter_names[machine_filter::COUNT] = {
__("Horizontal Screen"),
__("Custom Filter") };
constexpr char const *software_filter_names[software_filter::COUNT] = {
constexpr char const *SOFTWARE_FILTER_NAMES[software_filter::COUNT] = {
__("Unfiltered"),
__("Available"),
__("Unavailable"),
@ -200,6 +220,7 @@ protected:
bool have_choices() const { return !m_choices.empty(); }
bool selection_valid() const { return m_choices.size() > m_selection; }
unsigned selection_index() const { return m_selection; }
std::string const &selection_text() const { return m_choices[m_selection]; }
private:
@ -1192,7 +1213,7 @@ public:
class all_software_filter : public simple_filter_impl_base<software_filter, software_filter::ALL>
{
public:
all_software_filter(s_filter const &data, char const *value, emu_file *file, unsigned indent) { }
all_software_filter(software_filter_data const &data, char const *value, emu_file *file, unsigned indent) { }
virtual bool apply(ui_software_info const &info) const override { return true; }
};
@ -1201,7 +1222,7 @@ public:
class available_software_filter : public simple_filter_impl_base<software_filter, software_filter::AVAILABLE>
{
public:
available_software_filter(s_filter const &data, char const *value, emu_file *file, unsigned indent) { }
available_software_filter(software_filter_data const &data, char const *value, emu_file *file, unsigned indent) { }
virtual bool apply(ui_software_info const &info) const override { return info.available; }
};
@ -1210,7 +1231,7 @@ public:
class unavailable_software_filter : public simple_filter_impl_base<software_filter, software_filter::UNAVAILABLE>
{
public:
unavailable_software_filter(s_filter const &data, char const *value, emu_file *file, unsigned indent) { }
unavailable_software_filter(software_filter_data const &data, char const *value, emu_file *file, unsigned indent) { }
virtual bool apply(ui_software_info const &info) const override { return !info.available; }
};
@ -1219,7 +1240,7 @@ public:
class parents_software_filter : public simple_filter_impl_base<software_filter, software_filter::PARENTS>
{
public:
parents_software_filter(s_filter const &data, char const *value, emu_file *file, unsigned indent) { }
parents_software_filter(software_filter_data const &data, char const *value, emu_file *file, unsigned indent) { }
virtual bool apply(ui_software_info const &info) const override { return info.parentname.empty(); }
};
@ -1228,7 +1249,7 @@ public:
class clones_software_filter : public simple_filter_impl_base<software_filter, software_filter::CLONES>
{
public:
clones_software_filter(s_filter const &data, char const *value, emu_file *file, unsigned indent) { }
clones_software_filter(software_filter_data const &data, char const *value, emu_file *file, unsigned indent) { }
virtual bool apply(ui_software_info const &info) const override { return !info.parentname.empty(); }
};
@ -1237,8 +1258,8 @@ public:
class years_software_filter : public choice_filter_impl_base<software_filter, software_filter::YEAR>
{
public:
years_software_filter(s_filter const &data, char const *value, emu_file *file, unsigned indent)
: choice_filter_impl_base<software_filter, software_filter::YEAR>(data.year.ui, value)
years_software_filter(software_filter_data const &data, char const *value, emu_file *file, unsigned indent)
: choice_filter_impl_base<software_filter, software_filter::YEAR>(data.years(), value)
{
}
@ -1249,9 +1270,8 @@ public:
class publishers_software_filter : public choice_filter_impl_base<software_filter, software_filter::PUBLISHERS>
{
public:
publishers_software_filter(s_filter const &data, char const *value, emu_file *file, unsigned indent)
: choice_filter_impl_base<software_filter, software_filter::PUBLISHERS>(data.publisher.ui, value)
, m_publishers(data.publisher)
publishers_software_filter(software_filter_data const &data, char const *value, emu_file *file, unsigned indent)
: choice_filter_impl_base<software_filter, software_filter::PUBLISHERS>(data.publishers(), value)
{
}
@ -1262,19 +1282,16 @@ public:
else if (!selection_valid())
return false;
std::string const name(m_publishers.getname(info.publisher));
std::string const name(software_filter_data::extract_publisher(info.publisher));
return !name.empty() && (selection_text() == name);
}
private:
c_sw_publisher const &m_publishers;
};
class supported_software_filter : public simple_filter_impl_base<software_filter, software_filter::SUPPORTED>
{
public:
supported_software_filter(s_filter const &data, char const *value, emu_file *file, unsigned indent) { }
supported_software_filter(software_filter_data const &data, char const *value, emu_file *file, unsigned indent) { }
virtual bool apply(ui_software_info const &info) const override { return SOFTWARE_SUPPORTED_YES == info.supported; }
};
@ -1284,7 +1301,7 @@ public:
class partial_supported_software_filter : public simple_filter_impl_base<software_filter, software_filter::PARTIAL_SUPPORTED>
{
public:
partial_supported_software_filter(s_filter const &data, char const *value, emu_file *file, unsigned indent) { }
partial_supported_software_filter(software_filter_data const &data, char const *value, emu_file *file, unsigned indent) { }
virtual bool apply(ui_software_info const &info) const override { return SOFTWARE_SUPPORTED_PARTIAL == info.supported; }
};
@ -1293,7 +1310,7 @@ public:
class unsupported_software_filter : public simple_filter_impl_base<software_filter, software_filter::UNSUPPORTED>
{
public:
unsupported_software_filter(s_filter const &data, char const *value, emu_file *file, unsigned indent) { }
unsupported_software_filter(software_filter_data const &data, char const *value, emu_file *file, unsigned indent) { }
virtual bool apply(ui_software_info const &info) const override { return SOFTWARE_SUPPORTED_NO == info.supported; }
};
@ -1302,9 +1319,8 @@ public:
class region_software_filter : public choice_filter_impl_base<software_filter, software_filter::REGION>
{
public:
region_software_filter(s_filter const &data, char const *value, emu_file *file, unsigned indent)
: choice_filter_impl_base<software_filter, software_filter::REGION>(data.region.ui, value)
, m_regions(data.region)
region_software_filter(software_filter_data const &data, char const *value, emu_file *file, unsigned indent)
: choice_filter_impl_base<software_filter, software_filter::REGION>(data.regions(), value)
{
}
@ -1315,20 +1331,17 @@ public:
else if (!selection_valid())
return false;
std::string const name(m_regions.getname(info.longname));
std::string const name(software_filter_data::extract_region(info.longname));
return !name.empty() && (selection_text() == name);
}
private:
c_sw_region const &m_regions;
};
class device_type_software_filter : public choice_filter_impl_base<software_filter, software_filter::DEVICE_TYPE>
{
public:
device_type_software_filter(s_filter const &data, char const *value, emu_file *file, unsigned indent)
: choice_filter_impl_base<software_filter, software_filter::DEVICE_TYPE>(data.type.ui, value)
device_type_software_filter(software_filter_data const &data, char const *value, emu_file *file, unsigned indent)
: choice_filter_impl_base<software_filter, software_filter::DEVICE_TYPE>(data.device_types(), value)
{
}
@ -1339,12 +1352,19 @@ public:
class list_software_filter : public choice_filter_impl_base<software_filter, software_filter::LIST>
{
public:
list_software_filter(s_filter const &data, char const *value, emu_file *file, unsigned indent)
: choice_filter_impl_base<software_filter, software_filter::LIST>(data.swlist.name, value)
list_software_filter(software_filter_data const &data, char const *value, emu_file *file, unsigned indent)
: choice_filter_impl_base<software_filter, software_filter::LIST>(data.list_descriptions(), value)
, m_data(data)
{
}
virtual bool apply(ui_software_info const &info) const override { return !have_choices() || (selection_valid() && (selection_text() == info.listname)); }
virtual bool apply(ui_software_info const &info) const override
{
return !have_choices() || (selection_valid() && (m_data.list_names()[selection_index()] == info.listname));
}
private:
software_filter_data const &m_data;
};
@ -1356,7 +1376,7 @@ public:
class custom_software_filter : public composite_filter_impl_base<custom_software_filter, software_filter, software_filter::CUSTOM>
{
public:
custom_software_filter(s_filter const &data, char const *value, emu_file *file, unsigned indent)
custom_software_filter(software_filter_data const &data, char const *value, emu_file *file, unsigned indent)
: composite_filter_impl_base<custom_software_filter, software_filter, software_filter::CUSTOM>()
, m_data(data)
{
@ -1402,13 +1422,88 @@ public:
}
private:
s_filter const &m_data;
software_filter_data const &m_data;
};
} // anonymous namespace
//-------------------------------------------------
// static data for software filters
//-------------------------------------------------
void software_filter_data::add_region(std::string const &str)
{
std::string name(extract_region(str));
std::vector<std::string>::iterator const pos(std::lower_bound(m_regions.begin(), m_regions.end(), name));
if ((m_regions.end() == pos) || (*pos != str))
m_regions.emplace(pos, std::move(name));
}
void software_filter_data::add_publisher(std::string const &str)
{
std::string name(extract_publisher(str));
std::vector<std::string>::iterator const pos(std::lower_bound(m_publishers.begin(), m_publishers.end(), name));
if ((m_publishers.end() == pos) || (*pos != name))
m_publishers.emplace(pos, std::move(name));
}
void software_filter_data::add_year(std::string const &year)
{
std::vector<std::string>::iterator const pos(std::lower_bound(m_years.begin(), m_years.end(), year));
if ((m_years.end() == pos) || (*pos != year))
m_years.emplace(pos, year);
}
void software_filter_data::add_device_type(std::string const &device_type)
{
std::vector<std::string>::iterator const pos(std::lower_bound(m_device_types.begin(), m_device_types.end(), device_type));
if ((m_device_types.end() == pos) || (*pos != device_type))
m_device_types.emplace(pos, device_type);
}
void software_filter_data::add_list(std::string const &name, std::string const &description)
{
m_list_names.emplace_back(name);
m_list_descriptions.emplace_back(description);
}
void software_filter_data::finalise()
{
std::stable_sort(m_regions.begin(), m_regions.end());
std::stable_sort(m_publishers.begin(), m_publishers.end());
std::stable_sort(m_years.begin(), m_years.end());
std::stable_sort(m_device_types.begin(), m_device_types.end());
}
std::string software_filter_data::extract_region(std::string const &longname)
{
std::string fullname(longname);
strmakelower(fullname);
std::string::size_type const found(fullname.find('('));
if (found != std::string::npos)
{
std::string::size_type const ends(fullname.find_first_not_of("abcdefghijklmnopqrstuvwxyz", found + 1));
std::string const temp(fullname.substr(found + 1, ends - found - 1));
auto const match(std::find_if(
std::begin(SOFTWARE_REGIONS),
std::end(SOFTWARE_REGIONS),
[&temp] (char const *elem) { return temp == elem; }));
if (std::end(SOFTWARE_REGIONS) != match)
return longname.substr(found + 1, (std::string::npos != ends) ? (ends - found - 1) : ends);
}
return "<none>";
}
std::string software_filter_data::extract_publisher(std::string const &publisher)
{
std::string::size_type const found(publisher.find('('));
return publisher.substr(0, found - ((found && (std::string::npos != found)) ? 1 : 0));
}
//-------------------------------------------------
// public machine filter interface
//-------------------------------------------------
@ -1501,13 +1596,13 @@ machine_filter::ptr machine_filter::create(emu_file &file, unsigned indent)
char const *machine_filter::config_name(type n)
{
assert(COUNT > n);
return machine_filter_names[n];
return MACHINE_FILTER_NAMES[n];
}
char const *machine_filter::display_name(type n)
{
assert(COUNT > n);
return _(machine_filter_names[n]);
return _(MACHINE_FILTER_NAMES[n]);
}
machine_filter::machine_filter()
@ -1522,20 +1617,20 @@ machine_filter::machine_filter()
char const *software_filter::config_name(type n)
{
assert(COUNT > n);
return software_filter_names[n];
return SOFTWARE_FILTER_NAMES[n];
}
char const *software_filter::display_name(type n)
{
assert(COUNT > n);
return _(software_filter_names[n]);
return _(SOFTWARE_FILTER_NAMES[n]);
}
software_filter::software_filter()
{
}
software_filter::ptr software_filter::create(type n, s_filter const &data, char const *value, emu_file *file, unsigned indent)
software_filter::ptr software_filter::create(type n, software_filter_data const &data, char const *value, emu_file *file, unsigned indent)
{
assert(COUNT > n);
switch (n)
@ -1574,7 +1669,7 @@ software_filter::ptr software_filter::create(type n, s_filter const &data, char
return nullptr;
}
software_filter::ptr software_filter::create(emu_file &file, s_filter const &data, unsigned indent)
software_filter::ptr software_filter::create(emu_file &file, software_filter_data const &data, unsigned indent)
{
char buffer[MAX_CHAR_INFO];
if (!file.gets(buffer, ARRAY_LENGTH(buffer)))

View File

@ -79,7 +79,36 @@ struct ui_software_info
namespace ui {
struct s_filter; // FIXME: this is declared in custmenu.h, it shouldn't be
class software_filter_data
{
public:
std::vector<std::string> const &regions() const { return m_regions; }
std::vector<std::string> const &publishers() const { return m_publishers; }
std::vector<std::string> const &years() const { return m_years; }
std::vector<std::string> const &device_types() const { return m_device_types; }
std::vector<std::string> const &list_names() const { return m_list_names; }
std::vector<std::string> const &list_descriptions() const { return m_list_descriptions; }
// adding entries
void add_region(std::string const &longname);
void add_publisher(std::string const &publisher);
void add_year(std::string const &year);
void add_device_type(std::string const &device_type);
void add_list(std::string const &name, std::string const &description);
void finalise();
// use heuristics to extract meaningful parts from software list fields
static std::string extract_region(std::string const &longname);
static std::string extract_publisher(std::string const &publisher);
private:
std::vector<std::string> m_regions;
std::vector<std::string> m_publishers;
std::vector<std::string> m_years;
std::vector<std::string> m_device_types;
std::vector<std::string> m_list_names, m_list_descriptions;
};
template <class Impl, typename Entry>
class filter_base
@ -200,8 +229,8 @@ public:
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 ptr create(type n, software_filter_data const &data) { return create(n, data, nullptr, nullptr, 0); }
static ptr create(emu_file &file, software_filter_data const &data) { return create(file, data, 0); }
static char const *config_name(type n);
static char const *display_name(type n);
@ -211,8 +240,8 @@ public:
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);
static ptr create(type n, software_filter_data const &data, char const *value, emu_file *file, unsigned indent);
static ptr create(emu_file &file, software_filter_data const &data, unsigned indent);
};
DECLARE_ENUM_INCDEC_OPERATORS(software_filter::type)