mirror of
https://github.com/holub/mame
synced 2025-04-20 23:42:22 +03:00
ui: make category filter work like all the other filters
* category filter is now saved/restored if it's last used * category filter can be used in composite custom filters * category filter now provides UI rather than relying on options menu * less confusing when no categories found * also de-duplicated code for drawing category list (nw) please test this everyone and let me know if there are reproducible crashes or things that don't work right - I'm trying to make the internal UI more consistent and stable
This commit is contained in:
parent
196a7ea1ce
commit
cb7a04174f
@ -2467,12 +2467,3 @@ msgstr "Gráficos: %s, Sonido: %s"
|
||||
|
||||
#~ msgid "Other filter"
|
||||
#~ msgstr "Otros filtros"
|
||||
|
||||
#~ msgid "^!Region"
|
||||
#~ msgstr "^!Región"
|
||||
|
||||
#~ msgid "^!Setup custom filter"
|
||||
#~ msgstr "^!Aplicar filtro personalizado"
|
||||
|
||||
#~ msgid "Region: %1$s -"
|
||||
#~ msgstr "Región: %1$s -"
|
||||
|
@ -45,7 +45,7 @@ constexpr char const *region_lists[] = {
|
||||
// set software regions
|
||||
//-------------------------------------------------
|
||||
|
||||
void c_sw_region::set(std::string &str)
|
||||
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));
|
||||
@ -97,11 +97,11 @@ void c_sw_year::set(std::string &str)
|
||||
// set software publishers
|
||||
//-------------------------------------------------
|
||||
|
||||
void c_sw_publisher::set(std::string &str)
|
||||
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 != str))
|
||||
if ((ui.end() == pos) || (*pos != name))
|
||||
ui.emplace(pos, std::move(name));
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ namespace ui {
|
||||
struct c_sw_region
|
||||
{
|
||||
std::vector<std::string> ui;
|
||||
void set(std::string &str);
|
||||
void set(std::string const &str);
|
||||
std::string getname(std::string const &str) const;
|
||||
};
|
||||
|
||||
@ -29,7 +29,7 @@ struct c_sw_region
|
||||
struct c_sw_publisher
|
||||
{
|
||||
std::vector<std::string> ui;
|
||||
void set(std::string &str);
|
||||
void set(std::string const &str);
|
||||
std::string getname(std::string const &str) const;
|
||||
};
|
||||
|
||||
|
@ -39,7 +39,7 @@ static const folders_entry s_folders[] =
|
||||
{ __("Samples"), OPTION_SAMPLEPATH, ADDING },
|
||||
{ __("DATs"), OPTION_HISTORY_PATH, ADDING },
|
||||
{ __("INIs"), OPTION_INIPATH, ADDING },
|
||||
{ __("Extra INIs"), OPTION_EXTRAINI_PATH, CHANGE },
|
||||
{ __("Category INIs"), OPTION_CATEGORYINI_PATH, CHANGE },
|
||||
{ __("Icons"), OPTION_ICONS_PATH, ADDING },
|
||||
{ __("Cheats"), OPTION_CHEATPATH, ADDING },
|
||||
{ __("Snapshots"), OPTION_SNAPSHOT_DIRECTORY, ADDING },
|
||||
|
@ -9,135 +9,101 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "ui/moptions.h"
|
||||
#include "ui/inifile.h"
|
||||
#include "softlist_dev.h"
|
||||
#include "drivenum.h"
|
||||
|
||||
//-------------------------------------------------
|
||||
// GLOBAL VARIABLES
|
||||
//-------------------------------------------------
|
||||
uint16_t inifile_manager::c_cat = 0;
|
||||
uint16_t inifile_manager::c_file = 0;
|
||||
#include "ui/moptions.h"
|
||||
|
||||
#include "drivenum.h"
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// ctor
|
||||
//-------------------------------------------------
|
||||
|
||||
inifile_manager::inifile_manager(running_machine &machine, ui_options &moptions)
|
||||
: m_machine(machine)
|
||||
, m_options(moptions)
|
||||
: m_options(moptions)
|
||||
, m_ini_index()
|
||||
{
|
||||
ini_index.clear();
|
||||
directory_scan();
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// scan directories and create index
|
||||
//-------------------------------------------------
|
||||
|
||||
void inifile_manager::directory_scan()
|
||||
{
|
||||
file_enumerator path(m_options.extraini_path());
|
||||
const osd::directory::entry *dir;
|
||||
|
||||
while ((dir = path.next()) != nullptr)
|
||||
if (core_filename_ends_with(dir->name, ".ini") && parseopen(dir->name))
|
||||
// scan directories and create index
|
||||
file_enumerator path(m_options.categoryini_path());
|
||||
for (osd::directory::entry const *dir = path.next(); dir; dir = path.next())
|
||||
{
|
||||
std::string name(dir->name);
|
||||
if (core_filename_ends_with(name, ".ini"))
|
||||
{
|
||||
init_category(std::string(dir->name));
|
||||
parseclose();
|
||||
emu_file file(m_options.categoryini_path(), OPEN_FLAG_READ);
|
||||
if (file.open(name) == osd_file::error::NONE)
|
||||
{
|
||||
init_category(std::move(name), file);
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
// sort
|
||||
std::stable_sort(ini_index.begin(), ini_index.end());
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// initialize category
|
||||
//-------------------------------------------------
|
||||
|
||||
void inifile_manager::init_category(std::string filename)
|
||||
{
|
||||
categoryindex index;
|
||||
char rbuf[MAX_CHAR_INFO];
|
||||
std::string readbuf;
|
||||
while (fgets(rbuf, MAX_CHAR_INFO, fp) != nullptr)
|
||||
if (rbuf[0] == '[')
|
||||
{
|
||||
readbuf = rbuf;
|
||||
auto name = readbuf.substr(1, readbuf.find("]") - 1);
|
||||
if (name == "FOLDER_SETTINGS") continue;
|
||||
index.emplace_back(name, ftell(fp));
|
||||
}
|
||||
|
||||
// sort
|
||||
std::stable_sort(index.begin(), index.end());
|
||||
|
||||
if (!index.empty())
|
||||
ini_index.emplace_back(strmakelower(filename), index);
|
||||
}
|
||||
std::stable_sort(m_ini_index.begin(), m_ini_index.end(), [] (auto const &x, auto const &y) { return 0 > core_stricmp(x.first.c_str(), y.first.c_str()); });
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// load and indexing ini files
|
||||
//-------------------------------------------------
|
||||
|
||||
void inifile_manager::load_ini_category(std::vector<int> &temp_filter)
|
||||
void inifile_manager::load_ini_category(size_t file, size_t category, std::unordered_set<game_driver const *> &result) const
|
||||
{
|
||||
if (ini_index.empty())
|
||||
return;
|
||||
|
||||
auto search_clones = false;
|
||||
std::string filename(ini_index[c_file].first);
|
||||
auto offset = ini_index[c_file].second[c_cat].second;
|
||||
|
||||
if (filename == "category.ini" || filename == "alltime.ini")
|
||||
search_clones = true;
|
||||
|
||||
if (parseopen(filename.c_str()))
|
||||
std::string const &filename(m_ini_index[file].first);
|
||||
emu_file fp(m_options.categoryini_path(), OPEN_FLAG_READ);
|
||||
if (fp.open(filename) != osd_file::error::NONE)
|
||||
{
|
||||
fseek(fp, offset, SEEK_SET);
|
||||
char rbuf[MAX_CHAR_INFO];
|
||||
std::string readbuf;
|
||||
while (fgets(rbuf, MAX_CHAR_INFO, fp) != nullptr)
|
||||
{
|
||||
readbuf = chartrimcarriage(rbuf);
|
||||
|
||||
if (readbuf.empty() || readbuf[0] == '[')
|
||||
break;
|
||||
|
||||
auto dfind = driver_list::find(readbuf.c_str());
|
||||
if (dfind != -1)
|
||||
{
|
||||
temp_filter.push_back(dfind);
|
||||
if (search_clones && driver_list::non_bios_clone(dfind) == -1)
|
||||
for (int x = 0; x < driver_list::total(); x++)
|
||||
if (readbuf == driver_list::driver(x).parent && readbuf != driver_list::driver(x).name)
|
||||
temp_filter.push_back(x);
|
||||
}
|
||||
}
|
||||
parseclose();
|
||||
osd_printf_error("Failed to open category file %s for reading\n", filename.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
int64_t const offset(m_ini_index[file].second[category].second);
|
||||
if (fp.seek(offset, SEEK_SET) || (fp.tell() != offset))
|
||||
{
|
||||
fp.close();
|
||||
osd_printf_error("Failed to seek to category offset in file %s\n", filename.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
char rbuf[MAX_CHAR_INFO];
|
||||
while (fp.gets(rbuf, MAX_CHAR_INFO) && rbuf[0] && ('[' != rbuf[0]))
|
||||
{
|
||||
auto const tail(std::find_if(std::begin(rbuf), std::prev(std::end(rbuf)), [] (char ch) { return !ch || ('\r' == ch) || ('\n' == ch); }));
|
||||
*tail = '\0';
|
||||
int const dfind(driver_list::find(rbuf));
|
||||
if (0 <= dfind)
|
||||
result.emplace(&driver_list::driver(dfind));
|
||||
}
|
||||
|
||||
fp.close();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// parseopen - Open up file for reading
|
||||
//---------------------------------------------------------
|
||||
//-------------------------------------------------
|
||||
// initialize category
|
||||
//-------------------------------------------------
|
||||
|
||||
bool inifile_manager::parseopen(const char *filename)
|
||||
void inifile_manager::init_category(std::string &&filename, emu_file &file)
|
||||
{
|
||||
emu_file file(m_options.extraini_path(), OPEN_FLAG_READ);
|
||||
if (file.open(filename) != osd_file::error::NONE)
|
||||
return false;
|
||||
|
||||
m_fullpath = file.fullpath();
|
||||
file.close();
|
||||
fp = fopen(m_fullpath.c_str(), "r");
|
||||
|
||||
fgetc(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
return true;
|
||||
categoryindex index;
|
||||
char rbuf[MAX_CHAR_INFO];
|
||||
std::string name;
|
||||
while (file.gets(rbuf, ARRAY_LENGTH(rbuf)))
|
||||
{
|
||||
if ('[' == rbuf[0])
|
||||
{
|
||||
auto const head(std::next(std::begin(rbuf)));
|
||||
auto const tail(std::find_if(head, std::end(rbuf), [] (char ch) { return !ch || (']' == ch); }));
|
||||
name.assign(head, tail);
|
||||
if ("FOLDER_SETTINGS" != name)
|
||||
index.emplace_back(std::move(name), file.tell());
|
||||
}
|
||||
}
|
||||
std::stable_sort(index.begin(), index.end(), [] (auto const &x, auto const &y) { return 0 > core_stricmp(x.first.c_str(), y.first.c_str()); });
|
||||
if (!index.empty())
|
||||
m_ini_index.emplace_back(std::move(filename), std::move(index));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
FAVORITE MANAGER
|
||||
**************************************************************************/
|
||||
|
@ -13,7 +13,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../frontend/mame/ui/utils.h"
|
||||
#include "ui/utils.h"
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// INIFILE MANAGER
|
||||
@ -27,50 +30,25 @@ public:
|
||||
// construction/destruction
|
||||
inifile_manager(running_machine &machine, ui_options &moptions);
|
||||
|
||||
// load systems from category
|
||||
void load_ini_category(size_t file, size_t category, std::unordered_set<game_driver const *> &result) const;
|
||||
|
||||
// getters
|
||||
running_machine &machine() const { return m_machine; }
|
||||
std::string get_file() { return ini_index[c_file].first; }
|
||||
std::string get_file(int file) { return ini_index[file].first; }
|
||||
std::string get_category(int cat) { return ini_index[c_file].second[cat].first; }
|
||||
std::string get_category() { return ini_index[c_file].second[c_cat].first; }
|
||||
size_t total() { return ini_index.size(); }
|
||||
size_t cat_total() { return ini_index[c_file].second.size(); }
|
||||
uint16_t &cur_file() { return c_file; }
|
||||
uint16_t &cur_cat() { return c_cat; }
|
||||
|
||||
// load games from category
|
||||
void load_ini_category(std::vector<int> &temp_filter);
|
||||
|
||||
// setters
|
||||
void move_file(int d) { c_file += d; c_cat = 0; }
|
||||
void move_cat(int d) { c_cat += d; }
|
||||
void set_cat(uint16_t i) { c_cat = i; }
|
||||
void set_file(uint16_t i) { c_file = i; }
|
||||
size_t get_file_count() const { return m_ini_index.size(); }
|
||||
std::string const &get_file_name(size_t file) const { return m_ini_index[file].first; }
|
||||
size_t get_category_count(size_t file) const { return m_ini_index[file].second.size(); }
|
||||
std::string const &get_category_name(size_t file, size_t category) const { return m_ini_index[file].second[category].first; }
|
||||
|
||||
private:
|
||||
|
||||
// ini file structure
|
||||
using categoryindex = std::vector<std::pair<std::string, long>>;
|
||||
using categoryindex = std::vector<std::pair<std::string, int64_t>>;
|
||||
|
||||
// files indices
|
||||
static uint16_t c_file, c_cat;
|
||||
std::vector<std::pair<std::string, categoryindex>> ini_index;
|
||||
|
||||
// init category index
|
||||
void init_category(std::string filename);
|
||||
|
||||
// init file index
|
||||
void directory_scan();
|
||||
|
||||
// file open/close/seek
|
||||
bool parseopen(const char *filename);
|
||||
void parseclose() { if (fp != nullptr) fclose(fp); }
|
||||
void init_category(std::string &&filename, emu_file &file);
|
||||
|
||||
// internal state
|
||||
running_machine &m_machine; // reference to our machine
|
||||
ui_options &m_options;
|
||||
std::string m_fullpath;
|
||||
FILE *fp = nullptr;
|
||||
ui_options &m_options;
|
||||
std::vector<std::pair<std::string, categoryindex> > m_ini_index;
|
||||
|
||||
};
|
||||
|
||||
//-------------------------------------------------
|
||||
|
@ -22,7 +22,7 @@ const options_entry ui_options::s_option_entries[] =
|
||||
// search path options
|
||||
{ nullptr, nullptr, OPTION_HEADER, "UI SEARCH PATH OPTIONS" },
|
||||
{ OPTION_HISTORY_PATH, "history;dats;.", OPTION_STRING, "path to history files" },
|
||||
{ OPTION_EXTRAINI_PATH, "folders", OPTION_STRING, "path to extra ini files" },
|
||||
{ OPTION_CATEGORYINI_PATH, "folders", OPTION_STRING, "path to catagory ini files" },
|
||||
{ OPTION_CABINETS_PATH, "cabinets;cabdevs", OPTION_STRING, "path to cabinets / devices image" },
|
||||
{ OPTION_CPANELS_PATH, "cpanel", OPTION_STRING, "path to control panel image" },
|
||||
{ OPTION_PCBS_PATH, "pcb", OPTION_STRING, "path to pcbs image" },
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
// core directory options
|
||||
#define OPTION_HISTORY_PATH "historypath"
|
||||
#define OPTION_EXTRAINI_PATH "extrainipath"
|
||||
#define OPTION_CATEGORYINI_PATH "categorypath"
|
||||
#define OPTION_CABINETS_PATH "cabinets_directory"
|
||||
#define OPTION_CPANELS_PATH "cpanels_directory"
|
||||
#define OPTION_PCBS_PATH "pcbs_directory"
|
||||
@ -80,7 +80,7 @@ public:
|
||||
|
||||
// Search path options
|
||||
const char *history_path() const { return value(OPTION_HISTORY_PATH); }
|
||||
const char *extraini_path() const { return value(OPTION_EXTRAINI_PATH); }
|
||||
const char *categoryini_path() const { return value(OPTION_CATEGORYINI_PATH); }
|
||||
const char *cabinets_directory() const { return value(OPTION_CABINETS_PATH); }
|
||||
const char *cpanels_directory() const { return value(OPTION_CPANELS_PATH); }
|
||||
const char *pcbs_directory() const { return value(OPTION_PCBS_PATH); }
|
||||
|
@ -13,11 +13,9 @@
|
||||
|
||||
#include "ui/ui.h"
|
||||
#include "ui/submenu.h"
|
||||
#include "ui/inifile.h"
|
||||
#include "ui/selector.h"
|
||||
#include "ui/custui.h"
|
||||
#include "ui/sndmenu.h"
|
||||
#include "ui/custmenu.h"
|
||||
#include "ui/inputmap.h"
|
||||
#include "ui/dirmenu.h"
|
||||
|
||||
@ -25,6 +23,7 @@
|
||||
#include "mameopts.h"
|
||||
#include "rendfont.h"
|
||||
|
||||
|
||||
namespace ui {
|
||||
|
||||
//-------------------------------------------------
|
||||
@ -92,65 +91,6 @@ void menu_game_options::handle()
|
||||
});
|
||||
}
|
||||
break;
|
||||
case FILE_CATEGORY_FILTER:
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
@ -247,38 +187,17 @@ 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);
|
||||
if (machine_filter::CATEGORY == m_main)
|
||||
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);
|
||||
|
||||
// add subitem if the filter wants it
|
||||
if (active_filter->second->wants_adjuster())
|
||||
{
|
||||
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();
|
||||
|
||||
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);
|
||||
|
||||
// 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));
|
||||
}
|
||||
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);
|
||||
|
@ -30,9 +30,7 @@ private:
|
||||
enum
|
||||
{
|
||||
FILTER_MENU = 1,
|
||||
FILE_CATEGORY_FILTER,
|
||||
FILTER_ADJUST,
|
||||
CATEGORY_FILTER,
|
||||
CONF_DIR,
|
||||
DISPLAY_MENU,
|
||||
CUSTOM_MENU,
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include "drivenum.h"
|
||||
#include "emuopts.h"
|
||||
#include "mame.h"
|
||||
#include "rendfont.h"
|
||||
#include "rendutil.h"
|
||||
#include "softlist_dev.h"
|
||||
#include "uiinput.h"
|
||||
@ -170,8 +169,6 @@ void menu_select_game::handle()
|
||||
if (!m_prev_selected)
|
||||
m_prev_selected = item[0].ref;
|
||||
|
||||
bool check_filter = false;
|
||||
|
||||
// if I have to load datfile, perform a hard reset
|
||||
if (ui_globals::reset)
|
||||
{
|
||||
@ -195,6 +192,7 @@ void menu_select_game::handle()
|
||||
machine().ui_input().pressed(IPT_UI_PAUSE);
|
||||
|
||||
// process the menu
|
||||
bool check_filter(false);
|
||||
const event *menu_event = process(PROCESS_LR_REPEAT);
|
||||
if (menu_event)
|
||||
{
|
||||
@ -228,7 +226,8 @@ void menu_select_game::handle()
|
||||
// this is generated when something in the left box is clicked
|
||||
m_prev_selected = nullptr;
|
||||
check_filter = true;
|
||||
highlight = l_hover;
|
||||
highlight = hover - HOVER_FILTER_FIRST;
|
||||
assert((machine_filter::FIRST <= highlight) && (machine_filter::LAST >= highlight));
|
||||
break;
|
||||
|
||||
case IPT_UI_CONFIGURE:
|
||||
@ -250,7 +249,6 @@ void menu_select_game::handle()
|
||||
}
|
||||
else if (get_focus() == focused_menu::LEFT)
|
||||
{
|
||||
l_hover = highlight;
|
||||
check_filter = true;
|
||||
m_prev_selected = nullptr;
|
||||
}
|
||||
@ -377,38 +375,29 @@ void menu_select_game::handle()
|
||||
if (check_filter)
|
||||
{
|
||||
m_search.clear();
|
||||
switch (l_hover)
|
||||
if ((machine_filter::FIRST <= highlight) && (machine_filter::LAST >= highlight))
|
||||
{
|
||||
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());
|
||||
break;
|
||||
default:
|
||||
if (l_hover >= machine_filter::ALL)
|
||||
{
|
||||
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)
|
||||
auto it(main_filters::filters.find(machine_filter::type(highlight)));
|
||||
if (main_filters::filters.end() == it)
|
||||
it = main_filters::filters.emplace(machine_filter::type(highlight), machine_filter::create(machine_filter::type(highlight))).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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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();
|
||||
}
|
||||
filter.save_ini(file, 0);
|
||||
file.close();
|
||||
}
|
||||
main_filters::actual = new_type;
|
||||
reset(reset_options::SELECT_FIRST);
|
||||
});
|
||||
}
|
||||
}
|
||||
main_filters::actual = new_type;
|
||||
reset(reset_options::SELECT_FIRST);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -449,9 +438,6 @@ void menu_select_game::populate(float &customtop, float &custombottom)
|
||||
case machine_filter::UNAVAILABLE:
|
||||
m_displaylist = m_unavailsortedlist;
|
||||
break;
|
||||
case machine_filter::CATEGORY:
|
||||
build_category();
|
||||
break;
|
||||
default:
|
||||
{
|
||||
auto const it(main_filters::filters.find(main_filters::actual));
|
||||
@ -885,22 +871,6 @@ void menu_select_game::change_info_pane(int delta)
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// build category list
|
||||
//-------------------------------------------------
|
||||
|
||||
void menu_select_game::build_category()
|
||||
{
|
||||
m_displaylist.clear();
|
||||
std::vector<int> temp_filter;
|
||||
mame_machine_manager::instance()->inifile().load_ini_category(temp_filter);
|
||||
|
||||
for (auto actual : temp_filter)
|
||||
m_displaylist.push_back(&driver_list::driver(actual));
|
||||
|
||||
std::stable_sort(m_displaylist.begin(), m_displaylist.end(), sorted_game_list);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// populate search list
|
||||
//-------------------------------------------------
|
||||
@ -1240,147 +1210,10 @@ void menu_select_game::load_custom_filters()
|
||||
|
||||
float menu_select_game::draw_left_panel(float x1, float y1, float x2, float y2)
|
||||
{
|
||||
float line_height = ui().get_line_height();
|
||||
|
||||
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 phover = HOVER_FILTER_FIRST;
|
||||
float sc = y2 - y1 - (2.0f * UI_BOX_TB_BORDER);
|
||||
|
||||
if ((line_count * line_height_max) > sc)
|
||||
{
|
||||
float lm = sc / (line_count);
|
||||
text_size = lm / line_height;
|
||||
line_height_max = line_height * 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;
|
||||
|
||||
// compute width of left hand side
|
||||
total_width = ui().get_string_width(machine_filter::display_name(x), text_size);
|
||||
total_width += text_sign;
|
||||
|
||||
// track the maximum
|
||||
if (total_width > left_width)
|
||||
left_width = total_width;
|
||||
}
|
||||
|
||||
x2 = x1 + left_width + 2.0f * UI_BOX_LR_BORDER;
|
||||
ui().draw_outlined_box(container(), x1, y1, x2, y2, UI_BACKGROUND_COLOR);
|
||||
|
||||
// take off the borders
|
||||
x1 += UI_BOX_LR_BORDER;
|
||||
x2 -= UI_BOX_LR_BORDER;
|
||||
y1 += UI_BOX_TB_BORDER;
|
||||
y2 -= UI_BOX_TB_BORDER;
|
||||
|
||||
for (machine_filter::type filter = machine_filter::FIRST; filter < machine_filter::COUNT; ++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;
|
||||
|
||||
if (mouse_in_rect(x1, y1, x2, y1 + line_height_max))
|
||||
{
|
||||
bgcolor = UI_MOUSEOVER_BG_COLOR;
|
||||
fgcolor = UI_MOUSEOVER_COLOR;
|
||||
hover = phover + filter;
|
||||
menu::highlight(x1, y1, x2, y1 + line_height_max, bgcolor);
|
||||
}
|
||||
|
||||
if (highlight == filter && get_focus() == focused_menu::LEFT)
|
||||
{
|
||||
fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00);
|
||||
bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff);
|
||||
ui().draw_textured_box(container(), x1, y1, x2, y1 + line_height_max, bgcolor, rgb_t(255, 43, 43, 43),
|
||||
hilight_main_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(1));
|
||||
}
|
||||
|
||||
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);
|
||||
y1 += line_height_max;
|
||||
}
|
||||
|
||||
x1 = x2 + UI_BOX_LR_BORDER;
|
||||
x2 = x1 + 2.0f * UI_BOX_LR_BORDER;
|
||||
y1 = origy1;
|
||||
y2 = origy2;
|
||||
float space = x2 - x1;
|
||||
float lr_arrow_width = 0.4f * space * machine().render().ui_aspect();
|
||||
rgb_t fgcolor = UI_TEXT_COLOR;
|
||||
|
||||
// set left-right arrows dimension
|
||||
float ar_x0 = 0.5f * (x2 + x1) - 0.5f * lr_arrow_width;
|
||||
float ar_y0 = 0.5f * (y2 + y1) + 0.1f * space;
|
||||
float ar_x1 = ar_x0 + lr_arrow_width;
|
||||
float ar_y1 = 0.5f * (y2 + y1) + 0.9f * space;
|
||||
|
||||
ui().draw_outlined_box(container(), x1, y1, x2, y2, rgb_t(0xEF, 0x12, 0x47, 0x7B));
|
||||
|
||||
if (mouse_in_rect(x1, y1, x2, y2))
|
||||
{
|
||||
fgcolor = UI_MOUSEOVER_COLOR;
|
||||
hover = HOVER_LPANEL_ARROW;
|
||||
}
|
||||
|
||||
draw_arrow(ar_x0, ar_y0, ar_x1, ar_y1, fgcolor, ROT90 ^ ORIENTATION_FLIP_X);
|
||||
return x2 + UI_BOX_LR_BORDER;
|
||||
}
|
||||
else
|
||||
{
|
||||
float space = x2 - x1;
|
||||
float lr_arrow_width = 0.4f * space * machine().render().ui_aspect();
|
||||
rgb_t fgcolor = UI_TEXT_COLOR;
|
||||
|
||||
// set left-right arrows dimension
|
||||
float ar_x0 = 0.5f * (x2 + x1) - 0.5f * lr_arrow_width;
|
||||
float ar_y0 = 0.5f * (y2 + y1) + 0.1f * space;
|
||||
float ar_x1 = ar_x0 + lr_arrow_width;
|
||||
float ar_y1 = 0.5f * (y2 + y1) + 0.9f * space;
|
||||
|
||||
ui().draw_outlined_box(container(), x1, y1, x2, y2, rgb_t(0xEF, 0x12, 0x47, 0x7B));
|
||||
|
||||
if (mouse_in_rect(x1, y1, x2, y2))
|
||||
{
|
||||
fgcolor = UI_MOUSEOVER_COLOR;
|
||||
hover = HOVER_LPANEL_ARROW;
|
||||
}
|
||||
|
||||
draw_arrow(ar_x0, ar_y0, ar_x1, ar_y1, fgcolor, ROT90);
|
||||
return x2 + UI_BOX_LR_BORDER;
|
||||
}
|
||||
return menu_select_launch::draw_left_panel<machine_filter>(main_filters::actual, main_filters::filters, highlight, x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// get selected software and/or driver
|
||||
//-------------------------------------------------
|
||||
@ -1401,8 +1234,6 @@ void menu_select_game::get_selection(ui_software_info const *&software, game_dri
|
||||
|
||||
void menu_select_game::make_topbox_text(std::string &line0, std::string &line1, std::string &line2) const
|
||||
{
|
||||
inifile_manager &inifile = mame_machine_manager::instance()->inifile();
|
||||
|
||||
line0 = string_format(_("%1$s %2$s ( %3$d / %4$d machines (%5$d BIOS) )"),
|
||||
emulator_info::get_appname(),
|
||||
bare_build_version,
|
||||
@ -1414,14 +1245,6 @@ void menu_select_game::make_topbox_text(std::string &line0, std::string &line1,
|
||||
{
|
||||
line1.clear();
|
||||
}
|
||||
else if (main_filters::actual == machine_filter::CATEGORY && inifile.total() > 0)
|
||||
{
|
||||
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(),
|
||||
m_search);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const it(main_filters::filters.find(main_filters::actual));
|
||||
|
@ -66,7 +66,6 @@ private:
|
||||
// internal methods
|
||||
void change_info_pane(int delta);
|
||||
|
||||
void build_category();
|
||||
void build_available_list();
|
||||
|
||||
bool isfavorite() const;
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include "drivenum.h"
|
||||
#include "emuopts.h"
|
||||
#include "rendfont.h"
|
||||
#include "rendutil.h"
|
||||
#include "softlist.h"
|
||||
#include "softlist_dev.h"
|
||||
@ -133,9 +134,11 @@ char const *const menu_select_launch::s_info_titles[] = {
|
||||
__("Sysinfo") };
|
||||
|
||||
|
||||
// instantiate possible variants of select_bios so derived classes don't get link errors
|
||||
// instantiate possible variants of these so derived classes don't get link errors
|
||||
template bool menu_select_launch::select_bios(game_driver const &, bool);
|
||||
template bool menu_select_launch::select_bios(ui_software_info const &, bool);
|
||||
template float menu_select_launch::draw_left_panel<machine_filter>(machine_filter::type current, std::map<machine_filter::type, machine_filter::ptr> const &filters, int focus, float x1, float y1, float x2, float y2);
|
||||
template float menu_select_launch::draw_left_panel<software_filter>(software_filter::type current, std::map<software_filter::type, software_filter::ptr> const &filters, int focus, float x1, float y1, float x2, float y2);
|
||||
|
||||
|
||||
menu_select_launch::system_flags::system_flags(machine_static_info const &info)
|
||||
@ -813,6 +816,127 @@ bool menu_select_launch::draw_error_text()
|
||||
}
|
||||
|
||||
|
||||
template <typename Filter>
|
||||
float menu_select_launch::draw_left_panel(
|
||||
typename Filter::type current,
|
||||
std::map<typename Filter::type, typename Filter::ptr> const &filters,
|
||||
int focus,
|
||||
float x1, float y1, float x2, float y2)
|
||||
{
|
||||
if ((ui_globals::panels_status != SHOW_PANELS) && (ui_globals::panels_status != HIDE_RIGHT_PANEL))
|
||||
return draw_collapsed_left_panel(x1, y1, x2, y2);
|
||||
|
||||
// calculate line height
|
||||
float const line_height(ui().get_line_height());
|
||||
float const text_size(ui().options().infos_size());
|
||||
float const sc(y2 - y1 - (2.0f * UI_BOX_TB_BORDER));
|
||||
float line_height_max(line_height * text_size);
|
||||
if ((Filter::COUNT * line_height_max) > sc)
|
||||
{
|
||||
float const lm(sc / Filter::COUNT);
|
||||
line_height_max = line_height * (lm / line_height);
|
||||
}
|
||||
|
||||
// calculate horizontal offset for unadorned names
|
||||
std::string tmp("_# ");
|
||||
convert_command_glyph(tmp);
|
||||
float const text_sign = ui().get_string_width(tmp.c_str(), text_size);
|
||||
|
||||
// get the maximum width of a filter name
|
||||
float left_width(0.0f);
|
||||
for (typename Filter::type x = Filter::FIRST; Filter::COUNT > x; ++x)
|
||||
left_width = std::max(ui().get_string_width(Filter::display_name(x), text_size) + text_sign, left_width);
|
||||
|
||||
// outline the box and inset by the border width
|
||||
float const origy1(y1);
|
||||
float const origy2(y2);
|
||||
x2 = x1 + left_width + 2.0f * UI_BOX_LR_BORDER;
|
||||
ui().draw_outlined_box(container(), x1, y1, x2, y2, UI_BACKGROUND_COLOR);
|
||||
x1 += UI_BOX_LR_BORDER;
|
||||
x2 -= UI_BOX_LR_BORDER;
|
||||
y1 += UI_BOX_TB_BORDER;
|
||||
y2 -= UI_BOX_TB_BORDER;
|
||||
|
||||
// now draw the rows
|
||||
auto const active_filter(filters.find(current));
|
||||
for (typename Filter::type filter = Filter::FIRST; Filter::COUNT > filter; ++filter)
|
||||
{
|
||||
std::string str;
|
||||
if (filters.end() != active_filter)
|
||||
{
|
||||
str = active_filter->second->adorned_display_name(filter);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (current == filter)
|
||||
{
|
||||
str = std::string("_> ");
|
||||
convert_command_glyph(str);
|
||||
}
|
||||
str.append(Filter::display_name(filter));
|
||||
}
|
||||
|
||||
// handle mouse hover in passing
|
||||
rgb_t bgcolor = UI_TEXT_BG_COLOR;
|
||||
rgb_t fgcolor = UI_TEXT_COLOR;
|
||||
if (mouse_in_rect(x1, y1, x2, y1 + line_height_max))
|
||||
{
|
||||
bgcolor = UI_MOUSEOVER_BG_COLOR;
|
||||
fgcolor = UI_MOUSEOVER_COLOR;
|
||||
hover = HOVER_FILTER_FIRST + filter;
|
||||
highlight(x1, y1, x2, y1 + line_height_max, bgcolor);
|
||||
}
|
||||
|
||||
// draw primary highlight if keyboard focus is here
|
||||
if ((focus == filter) && (get_focus() == focused_menu::LEFT))
|
||||
{
|
||||
fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00);
|
||||
bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff);
|
||||
ui().draw_textured_box(
|
||||
container(),
|
||||
x1, y1, x2, y1 + line_height_max,
|
||||
bgcolor, rgb_t(255, 43, 43, 43),
|
||||
hilight_main_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(1));
|
||||
}
|
||||
|
||||
// finally draw the text itself and move to the next line
|
||||
float const x1t = x1 + ((str == 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);
|
||||
y1 += line_height_max;
|
||||
}
|
||||
|
||||
x1 = x2 + UI_BOX_LR_BORDER;
|
||||
x2 = x1 + 2.0f * UI_BOX_LR_BORDER;
|
||||
y1 = origy1;
|
||||
y2 = origy2;
|
||||
float const space = x2 - x1;
|
||||
float const lr_arrow_width = 0.4f * space * machine().render().ui_aspect();
|
||||
|
||||
// set left-right arrows dimension
|
||||
float const ar_x0 = 0.5f * (x2 + x1) - 0.5f * lr_arrow_width;
|
||||
float const ar_y0 = 0.5f * (y2 + y1) + 0.1f * space;
|
||||
float const ar_x1 = ar_x0 + lr_arrow_width;
|
||||
float const ar_y1 = 0.5f * (y2 + y1) + 0.9f * space;
|
||||
|
||||
ui().draw_outlined_box(container(), x1, y1, x2, y2, rgb_t(0xef, 0x12, 0x47, 0x7b));
|
||||
|
||||
rgb_t fgcolor = UI_TEXT_COLOR;
|
||||
if (mouse_in_rect(x1, y1, x2, y2))
|
||||
{
|
||||
fgcolor = UI_MOUSEOVER_COLOR;
|
||||
hover = HOVER_LPANEL_ARROW;
|
||||
}
|
||||
|
||||
draw_arrow(ar_x0, ar_y0, ar_x1, ar_y1, fgcolor, ROT90 ^ ORIENTATION_FLIP_X);
|
||||
return x2 + UI_BOX_LR_BORDER;
|
||||
}
|
||||
|
||||
|
||||
template <typename T> bool menu_select_launch::select_bios(T const &driver, bool inlist)
|
||||
{
|
||||
s_bios biosname;
|
||||
@ -1416,15 +1540,8 @@ void menu_select_launch::handle_events(uint32_t flags, event &ev)
|
||||
ui_globals::rpanel = (HOVER_RP_FIRST - hover) * (-1);
|
||||
stop = true;
|
||||
}
|
||||
else if (hover >= HOVER_SW_FILTER_FIRST && hover <= HOVER_SW_FILTER_LAST)
|
||||
{
|
||||
l_sw_hover = (HOVER_SW_FILTER_FIRST - hover) * (-1);
|
||||
ev.iptkey = IPT_OTHER;
|
||||
stop = true;
|
||||
}
|
||||
else if (hover >= HOVER_FILTER_FIRST && hover <= HOVER_FILTER_LAST)
|
||||
{
|
||||
l_hover = (HOVER_FILTER_FIRST - hover) * (-1);
|
||||
ev.iptkey = IPT_OTHER;
|
||||
stop = true;
|
||||
}
|
||||
@ -2282,6 +2399,36 @@ void menu_select_launch::exit(running_machine &machine)
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// draw collapsed left panel
|
||||
//-------------------------------------------------
|
||||
|
||||
float menu_select_launch::draw_collapsed_left_panel(float x1, float y1, float x2, float y2)
|
||||
{
|
||||
float const space = x2 - x1;
|
||||
float const lr_arrow_width = 0.4f * space * machine().render().ui_aspect();
|
||||
|
||||
// set left-right arrows dimension
|
||||
float const ar_x0 = 0.5f * (x2 + x1) - (0.5f * lr_arrow_width);
|
||||
float const ar_y0 = 0.5f * (y2 + y1) + (0.1f * space);
|
||||
float const ar_x1 = ar_x0 + lr_arrow_width;
|
||||
float const ar_y1 = 0.5f * (y2 + y1) + (0.9f * space);
|
||||
|
||||
ui().draw_outlined_box(container(), x1, y1, x2, y2, rgb_t(0xef, 0x12, 0x47, 0x7b)); // FIXME: magic numbers in colour?
|
||||
|
||||
rgb_t fgcolor = UI_TEXT_COLOR;
|
||||
if (mouse_in_rect(x1, y1, x2, y2))
|
||||
{
|
||||
fgcolor = UI_MOUSEOVER_COLOR;
|
||||
hover = HOVER_LPANEL_ARROW;
|
||||
}
|
||||
|
||||
draw_arrow(ar_x0, ar_y0, ar_x1, ar_y1, fgcolor, ROT90);
|
||||
|
||||
return x2 + UI_BOX_LR_BORDER;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// draw infos
|
||||
//-------------------------------------------------
|
||||
|
@ -114,10 +114,16 @@ protected:
|
||||
|
||||
bool draw_error_text();
|
||||
|
||||
template <typename Filter>
|
||||
float draw_left_panel(
|
||||
typename Filter::type current,
|
||||
std::map<typename Filter::type, typename Filter::ptr> const &filters,
|
||||
int focus,
|
||||
float x1, float y1, float x2, float y2);
|
||||
|
||||
template <typename T> bool select_bios(T const &driver, bool inlist);
|
||||
bool select_part(software_info const &info, ui_software_info const &ui_info);
|
||||
|
||||
int l_hover, l_sw_hover;
|
||||
int visible_items;
|
||||
void *m_prev_selected;
|
||||
int m_total_lines;
|
||||
@ -188,6 +194,7 @@ private:
|
||||
|
||||
// draw left panel
|
||||
virtual float draw_left_panel(float x1, float y1, float x2, float y2) = 0;
|
||||
float draw_collapsed_left_panel(float x1, float y1, float x2, float y2);
|
||||
|
||||
// draw infos
|
||||
void infos_render(float x1, float y1, float x2, float y2);
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "drivenum.h"
|
||||
#include "emuopts.h"
|
||||
#include "mame.h"
|
||||
#include "rendfont.h"
|
||||
#include "rendutil.h"
|
||||
#include "softlist_dev.h"
|
||||
#include "uiinput.h"
|
||||
@ -119,12 +118,11 @@ void menu_select_software::handle()
|
||||
if (m_prev_selected == nullptr)
|
||||
m_prev_selected = item[0].ref;
|
||||
|
||||
bool check_filter = false;
|
||||
|
||||
// ignore pause keys by swallowing them before we process the menu
|
||||
machine().ui_input().pressed(IPT_UI_PAUSE);
|
||||
|
||||
// process the menu
|
||||
bool check_filter(false);
|
||||
const event *menu_event = process(PROCESS_LR_REPEAT);
|
||||
if (menu_event)
|
||||
{
|
||||
@ -137,7 +135,6 @@ void menu_select_software::handle()
|
||||
case IPT_UI_SELECT:
|
||||
if (get_focus() == focused_menu::LEFT)
|
||||
{
|
||||
l_sw_hover = highlight;
|
||||
check_filter = true;
|
||||
m_prev_selected = nullptr;
|
||||
}
|
||||
@ -201,8 +198,9 @@ void menu_select_software::handle()
|
||||
|
||||
case IPT_OTHER:
|
||||
// this is generated when something in the left box is clicked
|
||||
highlight = l_sw_hover;
|
||||
check_filter = true;
|
||||
highlight = hover - HOVER_FILTER_FIRST;
|
||||
assert((software_filter::FIRST <= highlight) && (software_filter::LAST >= highlight));
|
||||
m_prev_selected = nullptr;
|
||||
break;
|
||||
|
||||
@ -256,9 +254,9 @@ void menu_select_software::handle()
|
||||
{
|
||||
m_search.clear();
|
||||
|
||||
filter_map::const_iterator it(m_filters.find(software_filter::type(l_sw_hover)));
|
||||
filter_map::const_iterator it(m_filters.find(software_filter::type(highlight)));
|
||||
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 = m_filters.emplace(software_filter::type(highlight), software_filter::create(software_filter::type(highlight), m_filter_data)).first;
|
||||
it->second->show_ui(
|
||||
ui(),
|
||||
container(),
|
||||
@ -585,135 +583,10 @@ void menu_select_software::find_matches(const char *str, int count)
|
||||
|
||||
float menu_select_software::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)
|
||||
{
|
||||
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;
|
||||
float l_height = ui().get_line_height();
|
||||
float line_height = l_height * text_size;
|
||||
float left_width = 0.0f;
|
||||
int line_count = software_filter::COUNT;
|
||||
int phover = HOVER_SW_FILTER_FIRST;
|
||||
float sc = y2 - y1 - (2.0f * UI_BOX_TB_BORDER);
|
||||
|
||||
if ((line_count * line_height) > sc)
|
||||
{
|
||||
float lm = sc / (line_count);
|
||||
text_size = lm / l_height;
|
||||
line_height = l_height * 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;
|
||||
|
||||
// compute width of left hand side
|
||||
total_width = ui().get_string_width(software_filter::display_name(x), text_size);
|
||||
total_width += text_sign;
|
||||
|
||||
// track the maximum
|
||||
if (total_width > left_width)
|
||||
left_width = total_width;
|
||||
}
|
||||
|
||||
x2 = x1 + left_width + 2.0f * UI_BOX_LR_BORDER;
|
||||
ui().draw_outlined_box(container(), x1, y1, x2, y2, UI_BACKGROUND_COLOR);
|
||||
|
||||
// take off the borders
|
||||
x1 += UI_BOX_LR_BORDER;
|
||||
x2 -= UI_BOX_LR_BORDER;
|
||||
y1 += UI_BOX_TB_BORDER;
|
||||
y2 -= UI_BOX_TB_BORDER;
|
||||
|
||||
for (software_filter::type filter = software_filter::FIRST; filter < software_filter::COUNT; ++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;
|
||||
|
||||
if (mouse_in_rect(x1, y1, x2, y1 + line_height))
|
||||
{
|
||||
bgcolor = UI_MOUSEOVER_BG_COLOR;
|
||||
fgcolor = UI_MOUSEOVER_COLOR;
|
||||
hover = phover + filter;
|
||||
}
|
||||
|
||||
if (highlight == filter && get_focus() == focused_menu::LEFT)
|
||||
{
|
||||
fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00);
|
||||
bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff);
|
||||
}
|
||||
|
||||
if (bgcolor != UI_TEXT_BG_COLOR)
|
||||
{
|
||||
ui().draw_textured_box(container(), x1, y1, x2, y1 + line_height, bgcolor, rgb_t(255, 43, 43, 43),
|
||||
hilight_main_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(1));
|
||||
}
|
||||
|
||||
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);
|
||||
y1 += line_height;
|
||||
}
|
||||
|
||||
x1 = x2 + UI_BOX_LR_BORDER;
|
||||
x2 = x1 + 2.0f * UI_BOX_LR_BORDER;
|
||||
y1 = origy1;
|
||||
y2 = origy2;
|
||||
float space = x2 - x1;
|
||||
float lr_arrow_width = 0.4f * space * machine().render().ui_aspect();
|
||||
rgb_t fgcolor = UI_TEXT_COLOR;
|
||||
|
||||
// set left-right arrows dimension
|
||||
float ar_x0 = 0.5f * (x2 + x1) - 0.5f * lr_arrow_width;
|
||||
float ar_y0 = 0.5f * (y2 + y1) + 0.1f * space;
|
||||
float ar_x1 = ar_x0 + lr_arrow_width;
|
||||
float ar_y1 = 0.5f * (y2 + y1) + 0.9f * space;
|
||||
|
||||
ui().draw_outlined_box(container(), x1, y1, x2, y2, rgb_t(0xEF, 0x12, 0x47, 0x7B));
|
||||
|
||||
if (mouse_in_rect(x1, y1, x2, y2))
|
||||
{
|
||||
fgcolor = UI_MOUSEOVER_COLOR;
|
||||
hover = HOVER_LPANEL_ARROW;
|
||||
}
|
||||
|
||||
draw_arrow(ar_x0, ar_y0, ar_x1, ar_y1, fgcolor, ROT90 ^ ORIENTATION_FLIP_X);
|
||||
return x2 + UI_BOX_LR_BORDER;
|
||||
}
|
||||
else
|
||||
{
|
||||
float space = x2 - x1;
|
||||
float lr_arrow_width = 0.4f * space * machine().render().ui_aspect();
|
||||
rgb_t fgcolor = UI_TEXT_COLOR;
|
||||
|
||||
// set left-right arrows dimension
|
||||
float ar_x0 = 0.5f * (x2 + x1) - 0.5f * lr_arrow_width;
|
||||
float ar_y0 = 0.5f * (y2 + y1) + 0.1f * space;
|
||||
float ar_x1 = ar_x0 + lr_arrow_width;
|
||||
float ar_y1 = 0.5f * (y2 + y1) + 0.9f * space;
|
||||
|
||||
ui().draw_outlined_box(container(), x1, y1, x2, y2, rgb_t(0xEF, 0x12, 0x47, 0x7B));
|
||||
|
||||
if (mouse_in_rect(x1, y1, x2, y2))
|
||||
{
|
||||
fgcolor = UI_MOUSEOVER_COLOR;
|
||||
hover = HOVER_LPANEL_ARROW;
|
||||
}
|
||||
|
||||
draw_arrow(ar_x0, ar_y0, ar_x1, ar_y1, fgcolor, ROT90);
|
||||
return x2 + UI_BOX_LR_BORDER;
|
||||
}
|
||||
return menu_select_launch::draw_left_panel<software_filter>(m_filter_type, m_filters, highlight, x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// get selected software and/or driver
|
||||
//-------------------------------------------------
|
||||
|
@ -12,16 +12,21 @@
|
||||
#include "ui/utils.h"
|
||||
|
||||
#include "ui/custmenu.h" // FIXME: get s_filter out of here
|
||||
#include "ui/inifile.h"
|
||||
#include "ui/selector.h"
|
||||
|
||||
#include "language.h"
|
||||
#include "mame.h"
|
||||
|
||||
#include "drivenum.h"
|
||||
#include "rendfont.h"
|
||||
#include "softlist.h"
|
||||
|
||||
#include <bitset>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <unordered_set>
|
||||
|
||||
|
||||
namespace ui {
|
||||
@ -180,9 +185,9 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
choice_filter_impl_base(std::vector<std::string> const &choices, char const *value) :
|
||||
m_choices(choices),
|
||||
m_selection(0U)
|
||||
choice_filter_impl_base(std::vector<std::string> const &choices, char const *value)
|
||||
: m_choices(choices)
|
||||
, m_selection(0U)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
@ -211,6 +216,8 @@ template <class Impl, class Base, typename Base::type Type>
|
||||
class composite_filter_impl_base : public simple_filter_impl_base<Base, Type>
|
||||
{
|
||||
public:
|
||||
virtual void show_ui(mame_ui_manager &mui, render_container &container, std::function<void (Base &)> &&handler) override;
|
||||
|
||||
virtual bool wants_adjuster() const override { return true; }
|
||||
virtual char const *adjust_text() const override { return _("<set up filters>"); }
|
||||
|
||||
@ -255,14 +262,15 @@ public:
|
||||
break;
|
||||
|
||||
typename Base::type const t(flt->get_type());
|
||||
bool const r(flt->apply(info));
|
||||
if (Impl::is_inclusion(t))
|
||||
{
|
||||
inclusions.set(t);
|
||||
if (r)
|
||||
included.set(t);
|
||||
if (!included.test(t))
|
||||
{
|
||||
inclusions.set(t);
|
||||
included.set(t, flt->apply(info));
|
||||
}
|
||||
}
|
||||
else if (!r)
|
||||
else if (!flt->apply(info))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -270,8 +278,6 @@ public:
|
||||
return inclusions == included;
|
||||
}
|
||||
|
||||
virtual void show_ui(mame_ui_manager &mui, render_container &container, std::function<void (Base &)> &&handler) override;
|
||||
|
||||
protected:
|
||||
composite_filter_impl_base() { }
|
||||
|
||||
@ -308,11 +314,11 @@ private:
|
||||
mame_ui_manager &mui,
|
||||
render_container &container,
|
||||
Impl &parent,
|
||||
std::function<void (Base &filter)> &&handler) :
|
||||
menu(mui, container),
|
||||
m_parent(parent),
|
||||
m_handler(std::move(handler)),
|
||||
m_added(false)
|
||||
std::function<void (Base &filter)> &&handler)
|
||||
: menu(mui, container)
|
||||
, m_parent(parent)
|
||||
, m_handler(std::move(handler))
|
||||
, m_added(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -472,7 +478,7 @@ void composite_filter_impl_base<Impl, Base, Type>::menu_configure::populate(floa
|
||||
unsigned i = 0;
|
||||
for (i = 0; (MAX > i) && m_parent.m_filters[i]; ++i)
|
||||
{
|
||||
item_append(util::string_format("Filter %u", i + 1), m_parent.m_filters[i]->display_name(), get_arrow_flags(i), (void *)(FILTER_FIRST + i));
|
||||
item_append(util::string_format(_("Filter %1$u"), i + 1), m_parent.m_filters[i]->display_name(), get_arrow_flags(i), (void *)(FILTER_FIRST + i));
|
||||
if (m_added)
|
||||
selected = item.size() - 2;
|
||||
if (m_parent.m_filters[i]->wants_adjuster())
|
||||
@ -700,8 +706,8 @@ public:
|
||||
class manufacturer_machine_filter : public choice_filter_impl_base<machine_filter, machine_filter::MANUFACTURER>
|
||||
{
|
||||
public:
|
||||
manufacturer_machine_filter(char const *value, emu_file *file, unsigned indent) :
|
||||
choice_filter_impl_base<machine_filter, machine_filter::MANUFACTURER>(c_mnfct::ui, value)
|
||||
manufacturer_machine_filter(char const *value, emu_file *file, unsigned indent)
|
||||
: choice_filter_impl_base<machine_filter, machine_filter::MANUFACTURER>(c_mnfct::ui, value)
|
||||
{
|
||||
}
|
||||
|
||||
@ -721,8 +727,8 @@ public:
|
||||
class year_machine_filter : public choice_filter_impl_base<machine_filter, machine_filter::YEAR>
|
||||
{
|
||||
public:
|
||||
year_machine_filter(char const *value, emu_file *file, unsigned indent) :
|
||||
choice_filter_impl_base<machine_filter, machine_filter::YEAR>(c_year::ui, value)
|
||||
year_machine_filter(char const *value, emu_file *file, unsigned indent)
|
||||
: choice_filter_impl_base<machine_filter, machine_filter::YEAR>(c_year::ui, value)
|
||||
{
|
||||
}
|
||||
|
||||
@ -780,6 +786,339 @@ using favorite_machine_filter = inclusive_machine_filter_impl<machine_filt
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// category machine filter
|
||||
//-------------------------------------------------
|
||||
|
||||
class category_machine_filter : public simple_filter_impl_base<machine_filter, machine_filter::CATEGORY>
|
||||
{
|
||||
public:
|
||||
category_machine_filter(char const *value, emu_file *file, unsigned indent)
|
||||
: m_ini(0)
|
||||
, m_group(0)
|
||||
, m_include_clones(false)
|
||||
, m_adjust_text()
|
||||
, m_cache()
|
||||
, m_cache_valid(false)
|
||||
{
|
||||
inifile_manager const &mgr(mame_machine_manager::instance()->inifile());
|
||||
if (value)
|
||||
{
|
||||
char const *const split(std::strchr(value, '/'));
|
||||
std::string ini;
|
||||
if (split)
|
||||
ini.assign(value, split);
|
||||
else
|
||||
ini.assign(value);
|
||||
|
||||
for (unsigned i = 0; mgr.get_file_count() > i; ++i)
|
||||
{
|
||||
if (mgr.get_file_name(i) == ini)
|
||||
{
|
||||
m_ini = i;
|
||||
if (split)
|
||||
{
|
||||
std::string const group(split + 1);
|
||||
for (unsigned j = 0; mgr.get_category_count(i) > j; ++j)
|
||||
{
|
||||
if (mgr.get_category_name(i, j) == group)
|
||||
{
|
||||
m_group = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mgr.get_file_count() > m_ini)
|
||||
m_include_clones = include_clones_default(mgr.get_file_name(m_ini));
|
||||
|
||||
set_adjust_text();
|
||||
}
|
||||
|
||||
virtual char const *filter_text() const override
|
||||
{
|
||||
inifile_manager const &mgr(mame_machine_manager::instance()->inifile());
|
||||
return ((mgr.get_file_count() > m_ini) && (mgr.get_category_count(m_ini) > m_group)) ? m_adjust_text.c_str() : nullptr;
|
||||
}
|
||||
|
||||
virtual void show_ui(mame_ui_manager &mui, render_container &container, std::function<void (machine_filter &)> &&handler) override;
|
||||
|
||||
virtual bool wants_adjuster() const override { return mame_machine_manager::instance()->inifile().get_file_count(); }
|
||||
virtual char const *adjust_text() const override { return m_adjust_text.c_str(); }
|
||||
|
||||
virtual void save_ini(emu_file &file, unsigned indent) const override
|
||||
{
|
||||
char const *const text(filter_text());
|
||||
file.puts(util::string_format("%2$*1$s%3$s = %4$s\n", 2 * indent, "", this->config_name(), text ? text : "").c_str());
|
||||
}
|
||||
|
||||
virtual bool apply(game_driver const &drv) const override
|
||||
{
|
||||
inifile_manager const &mgr(mame_machine_manager::instance()->inifile());
|
||||
if (!mgr.get_file_count())
|
||||
return true;
|
||||
else if ((mgr.get_file_count() <= m_ini) || (mgr.get_category_count(m_ini) <= m_group))
|
||||
return false;
|
||||
|
||||
if (!m_cache_valid)
|
||||
mame_machine_manager::instance()->inifile().load_ini_category(m_ini, m_group, m_cache);
|
||||
m_cache_valid = true;
|
||||
|
||||
if (m_cache.end() != m_cache.find(&drv))
|
||||
return true;
|
||||
|
||||
if (m_include_clones)
|
||||
{
|
||||
int const found(driver_list::find(drv.parent));
|
||||
return m_cache.end() != m_cache.find(&driver_list::driver(found));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
class menu_configure : public menu
|
||||
{
|
||||
public:
|
||||
menu_configure(
|
||||
mame_ui_manager &mui,
|
||||
render_container &container,
|
||||
category_machine_filter &parent,
|
||||
std::function<void (machine_filter &filter)> &&handler)
|
||||
: menu(mui, container)
|
||||
, m_parent(parent)
|
||||
, m_handler(std::move(handler))
|
||||
, m_state(std::make_unique<std::pair<unsigned, bool> []>(mame_machine_manager::instance()->inifile().get_file_count()))
|
||||
, m_ini(parent.m_ini)
|
||||
{
|
||||
inifile_manager const &mgr(mame_machine_manager::instance()->inifile());
|
||||
for (size_t i = 0; mgr.get_file_count() > i; ++i)
|
||||
{
|
||||
m_state[i].first = (m_ini == i) ? m_parent.m_group : 0U;
|
||||
m_state[i].second = (m_ini == i) ? m_parent.m_include_clones : include_clones_default(mgr.get_file_name(i));
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~menu_configure() override
|
||||
{
|
||||
bool const valid(mame_machine_manager::instance()->inifile().get_file_count() > m_ini);
|
||||
unsigned const group(valid ? m_state[m_ini].first : 0);
|
||||
if ((m_ini != m_parent.m_ini) || (group != m_parent.m_group))
|
||||
{
|
||||
m_parent.m_cache.clear();
|
||||
m_parent.m_cache_valid = false;
|
||||
}
|
||||
m_parent.m_ini = m_ini;
|
||||
m_parent.m_group = group;
|
||||
m_parent.m_include_clones = valid ? m_state[m_ini].second : false;
|
||||
m_parent.set_adjust_text();
|
||||
m_handler(m_parent);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override
|
||||
{
|
||||
char const *const text[] = { _("Select category:") };
|
||||
draw_text_box(
|
||||
std::begin(text), std::end(text),
|
||||
x, x2, y - top, y - UI_BOX_TB_BORDER,
|
||||
ui::text_layout::CENTER, ui::text_layout::NEVER, false,
|
||||
UI_TEXT_COLOR, UI_GREEN_COLOR, 1.0f);
|
||||
}
|
||||
|
||||
private:
|
||||
enum : uintptr_t
|
||||
{
|
||||
INI_FILE = 1,
|
||||
SYSTEM_GROUP,
|
||||
INCLUDE_CLONES
|
||||
};
|
||||
|
||||
virtual void populate(float &customtop, float &custombottom) override;
|
||||
virtual void handle() override;
|
||||
|
||||
category_machine_filter &m_parent;
|
||||
std::function<void (machine_filter &)> m_handler;
|
||||
std::unique_ptr<std::pair<unsigned, bool> []> const m_state;
|
||||
unsigned m_ini;
|
||||
};
|
||||
|
||||
void set_adjust_text()
|
||||
{
|
||||
inifile_manager const &mgr(mame_machine_manager::instance()->inifile());
|
||||
unsigned const filecnt(mgr.get_file_count());
|
||||
if (!filecnt)
|
||||
{
|
||||
m_adjust_text = _("[no category INI files]");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ini = std::min(m_ini, filecnt - 1);
|
||||
unsigned const groupcnt(mgr.get_category_count(m_ini));
|
||||
if (!groupcnt)
|
||||
{
|
||||
m_adjust_text = _("[no groups in INI file]");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_group = std::min(m_group, groupcnt - 1);
|
||||
m_adjust_text = util::string_format("%s/%s", mgr.get_file_name(m_ini), mgr.get_category_name(m_ini, m_group));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool include_clones_default(std::string const &name)
|
||||
{
|
||||
return !core_stricmp(name.c_str(), "category.ini") || !core_stricmp(name.c_str(), "alltime.ini");
|
||||
}
|
||||
|
||||
unsigned m_ini, m_group;
|
||||
bool m_include_clones;
|
||||
std::string m_adjust_text;
|
||||
mutable std::unordered_set<game_driver const *> m_cache;
|
||||
mutable bool m_cache_valid;
|
||||
};
|
||||
|
||||
void category_machine_filter::show_ui(mame_ui_manager &mui, render_container &container, std::function<void (machine_filter &)> &&handler)
|
||||
{
|
||||
menu::stack_push<menu_configure>(mui, container, *this, std::move(handler));
|
||||
}
|
||||
|
||||
|
||||
void category_machine_filter::menu_configure::populate(float &customtop, float &custombottom)
|
||||
{
|
||||
inifile_manager const &mgr(mame_machine_manager::instance()->inifile());
|
||||
unsigned const filecnt(mgr.get_file_count());
|
||||
if (!filecnt)
|
||||
{
|
||||
item_append(_("No category INI files found"), "", FLAG_DISABLE, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ini = std::min(m_ini, filecnt - 1);
|
||||
item_append(_("File"), mgr.get_file_name(m_ini), get_arrow_flags(0U, filecnt - 1, m_ini), reinterpret_cast<void *>(INI_FILE));
|
||||
unsigned const groupcnt(mgr.get_category_count(m_ini));
|
||||
if (!groupcnt)
|
||||
{
|
||||
item_append(_("No groups found in category file"), "", FLAG_DISABLE, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_state[m_ini].first = std::min(m_state[m_ini].first, groupcnt - 1);
|
||||
item_append(_("Group"), mgr.get_category_name(m_ini, m_state[m_ini].first), get_arrow_flags(0U, groupcnt - 1, m_state[m_ini].first), reinterpret_cast<void *>(SYSTEM_GROUP));
|
||||
item_append(_("Include clones"), m_state[m_ini].second ? _("Yes") : _("No"), m_state[m_ini].second ? FLAG_LEFT_ARROW : FLAG_RIGHT_ARROW, reinterpret_cast<void *>(INCLUDE_CLONES));
|
||||
}
|
||||
}
|
||||
item_append(menu_item_type::SEPARATOR);
|
||||
customtop = ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
|
||||
}
|
||||
|
||||
void category_machine_filter::menu_configure::handle()
|
||||
{
|
||||
const event *menu_event = process(PROCESS_LR_REPEAT);
|
||||
if (menu_event && menu_event->itemref)
|
||||
{
|
||||
bool changed(false);
|
||||
uintptr_t const ref(reinterpret_cast<uintptr_t>(menu_event->itemref));
|
||||
inifile_manager const &mgr(mame_machine_manager::instance()->inifile());
|
||||
switch (menu_event->iptkey)
|
||||
{
|
||||
case IPT_UI_LEFT:
|
||||
if ((INI_FILE == ref) && m_ini)
|
||||
{
|
||||
--m_ini;
|
||||
changed = true;
|
||||
}
|
||||
else if ((SYSTEM_GROUP == ref) && m_state[m_ini].first)
|
||||
{
|
||||
--m_state[m_ini].first;
|
||||
changed = true;
|
||||
}
|
||||
else if ((INCLUDE_CLONES == ref) && m_state[m_ini].second)
|
||||
{
|
||||
m_state[m_ini].second = false;
|
||||
changed = true;
|
||||
}
|
||||
break;
|
||||
case IPT_UI_RIGHT:
|
||||
if ((INI_FILE == ref) && (mgr.get_file_count() > (m_ini + 1)))
|
||||
{
|
||||
++m_ini;
|
||||
changed = true;
|
||||
}
|
||||
else if ((SYSTEM_GROUP == ref) && (mgr.get_category_count(m_ini) > (m_state[m_ini].first + 1)))
|
||||
{
|
||||
++m_state[m_ini].first;
|
||||
changed = true;
|
||||
}
|
||||
else if ((INCLUDE_CLONES == ref) && !m_state[m_ini].second)
|
||||
{
|
||||
m_state[m_ini].second = true;
|
||||
changed = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case IPT_UI_SELECT:
|
||||
if (INI_FILE == ref)
|
||||
{
|
||||
std::vector<std::string> choices;
|
||||
choices.reserve(mgr.get_file_count());
|
||||
for (size_t i = 0; mgr.get_file_count() > i; ++i)
|
||||
choices.emplace_back(mgr.get_file_name(i));
|
||||
menu::stack_push<menu_selector>(
|
||||
ui(),
|
||||
container(),
|
||||
std::move(choices),
|
||||
m_ini,
|
||||
[this] (int selection)
|
||||
{
|
||||
if (selection != m_ini)
|
||||
{
|
||||
m_ini = selection;
|
||||
reset(reset_options::REMEMBER_REF);
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (SYSTEM_GROUP == ref)
|
||||
{
|
||||
std::vector<std::string> choices;
|
||||
choices.reserve(mgr.get_category_count(m_ini));
|
||||
for (size_t i = 0; mgr.get_category_count(m_ini) > i; ++i)
|
||||
choices.emplace_back(mgr.get_category_name(m_ini, i));
|
||||
menu::stack_push<menu_selector>(
|
||||
ui(),
|
||||
container(),
|
||||
std::move(choices),
|
||||
m_state[m_ini].first,
|
||||
[this] (int selection)
|
||||
{
|
||||
if (selection != m_state[m_ini].first)
|
||||
{
|
||||
m_state[m_ini].first = selection;
|
||||
reset(reset_options::REMEMBER_REF);
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (INCLUDE_CLONES == ref)
|
||||
{
|
||||
m_state[m_ini].second = !m_state[m_ini].second;
|
||||
reset(reset_options::REMEMBER_REF);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// rebuild if anything changed
|
||||
if (changed)
|
||||
reset(reset_options::REMEMBER_REF);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// composite machine filter
|
||||
//-------------------------------------------------
|
||||
@ -787,8 +1126,8 @@ using favorite_machine_filter = inclusive_machine_filter_impl<machine_filt
|
||||
class custom_machine_filter : public composite_filter_impl_base<custom_machine_filter, machine_filter, machine_filter::CUSTOM>
|
||||
{
|
||||
public:
|
||||
custom_machine_filter(char const *value, emu_file *file, unsigned indent) :
|
||||
composite_filter_impl_base<custom_machine_filter, machine_filter, machine_filter::CUSTOM>()
|
||||
custom_machine_filter(char const *value, emu_file *file, unsigned indent)
|
||||
: composite_filter_impl_base<custom_machine_filter, machine_filter, machine_filter::CUSTOM>()
|
||||
{
|
||||
populate(value, file, indent);
|
||||
}
|
||||
@ -798,7 +1137,7 @@ public:
|
||||
|
||||
static bool type_allowed(unsigned pos, type n)
|
||||
{
|
||||
return (FIRST <= n) && (LAST >= n) && (ALL != n) && (AVAILABLE != n) && (UNAVAILABLE != n) && (CATEGORY != n) && (FAVORITE != n) && (CUSTOM != n);
|
||||
return (FIRST <= n) && (LAST >= n) && (ALL != n) && (AVAILABLE != n) && (UNAVAILABLE != n) && (FAVORITE != n) && (CUSTOM != n);
|
||||
}
|
||||
|
||||
static bool types_contradictory(type n, type m)
|
||||
@ -835,7 +1174,7 @@ public:
|
||||
|
||||
static bool is_inclusion(type n)
|
||||
{
|
||||
return (MANUFACTURER == n) || (YEAR == n);
|
||||
return (CATEGORY == n) || (MANUFACTURER == n) || (YEAR == n);
|
||||
}
|
||||
};
|
||||
|
||||
@ -893,8 +1232,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(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)
|
||||
{
|
||||
}
|
||||
|
||||
@ -905,9 +1244,9 @@ 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(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)
|
||||
{
|
||||
}
|
||||
|
||||
@ -958,9 +1297,9 @@ 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(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)
|
||||
{
|
||||
}
|
||||
|
||||
@ -983,8 +1322,8 @@ private:
|
||||
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(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)
|
||||
{
|
||||
}
|
||||
|
||||
@ -995,8 +1334,8 @@ 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(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)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1012,9 +1351,9 @@ 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) :
|
||||
composite_filter_impl_base<custom_software_filter, software_filter, software_filter::CUSTOM>(),
|
||||
m_data(data)
|
||||
custom_software_filter(s_filter 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)
|
||||
{
|
||||
populate(value, file, indent);
|
||||
}
|
||||
@ -1089,7 +1428,7 @@ machine_filter::ptr machine_filter::create(type n, char const *value, emu_file *
|
||||
case NOT_MECHANICAL:
|
||||
return std::make_unique<not_mechanical_machine_filter>(value, file, indent);
|
||||
case CATEGORY:
|
||||
break;
|
||||
return std::make_unique<category_machine_filter>(value, file, indent);
|
||||
case FAVORITE:
|
||||
return std::make_unique<favorite_machine_filter>(value, file, indent);
|
||||
case BIOS:
|
||||
@ -1125,7 +1464,8 @@ machine_filter::ptr machine_filter::create(type n, char const *value, emu_file *
|
||||
machine_filter::ptr machine_filter::create(emu_file &file, unsigned indent)
|
||||
{
|
||||
char buffer[MAX_CHAR_INFO];
|
||||
file.gets(buffer, ARRAY_LENGTH(buffer));
|
||||
if (!file.gets(buffer, ARRAY_LENGTH(buffer)))
|
||||
return nullptr;
|
||||
|
||||
// split it into a key/value or bail
|
||||
std::string key(buffer);
|
||||
@ -1230,7 +1570,8 @@ software_filter::ptr software_filter::create(type n, s_filter const &data, char
|
||||
software_filter::ptr software_filter::create(emu_file &file, s_filter const &data, unsigned indent)
|
||||
{
|
||||
char buffer[MAX_CHAR_INFO];
|
||||
file.gets(buffer, ARRAY_LENGTH(buffer));
|
||||
if (!file.gets(buffer, ARRAY_LENGTH(buffer)))
|
||||
return nullptr;
|
||||
|
||||
// split it into a key/value or bail
|
||||
std::string key(buffer);
|
||||
|
@ -272,11 +272,9 @@ enum
|
||||
HOVER_RPANEL_ARROW,
|
||||
HOVER_LPANEL_ARROW,
|
||||
HOVER_FILTER_FIRST,
|
||||
HOVER_FILTER_LAST = (HOVER_FILTER_FIRST) + ui::machine_filter::COUNT,
|
||||
HOVER_SW_FILTER_FIRST,
|
||||
HOVER_SW_FILTER_LAST = (HOVER_SW_FILTER_FIRST) + ui::software_filter::COUNT,
|
||||
HOVER_FILTER_LAST = HOVER_FILTER_FIRST + std::max<unsigned>(ui::machine_filter::COUNT, ui::software_filter::COUNT),
|
||||
HOVER_RP_FIRST,
|
||||
HOVER_RP_LAST = (HOVER_RP_FIRST) + 1 + RP_LAST,
|
||||
HOVER_RP_LAST = HOVER_RP_FIRST + 1 + RP_LAST,
|
||||
HOVER_INFO_TEXT
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user