summaryrefslogtreecommitdiffstatshomepage
path: root/src/frontend/mame/ui/dirmenu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/mame/ui/dirmenu.cpp')
-rw-r--r--src/frontend/mame/ui/dirmenu.cpp770
1 files changed, 434 insertions, 336 deletions
diff --git a/src/frontend/mame/ui/dirmenu.cpp b/src/frontend/mame/ui/dirmenu.cpp
index 50afe928561..083dfbeba79 100644
--- a/src/frontend/mame/ui/dirmenu.cpp
+++ b/src/frontend/mame/ui/dirmenu.cpp
@@ -9,513 +9,611 @@
*********************************************************************/
#include "emu.h"
+#include "ui/dirmenu.h"
#include "ui/ui.h"
-#include "ui/dirmenu.h"
#include "ui/utils.h"
-#include "ui/optsmenu.h"
#include "emuopts.h"
+#include "fileio.h"
#include "mame.h"
+#include "util/corestr.h"
+#include "util/path.h"
+
+#include <locale>
+
namespace ui {
-static int ADDING = 1;
-static int CHANGE = 2;
+
+namespace {
struct folders_entry
{
const char *name;
const char *option;
- const int action;
};
-static const folders_entry s_folders[] =
+const folders_entry f_folders[] =
{
- { __("ROMs"), OPTION_MEDIAPATH, ADDING },
- { __("Software Media"), OPTION_SWPATH, CHANGE },
- { __("UI"), OPTION_UI_PATH, CHANGE },
- { __("Language"), OPTION_LANGUAGEPATH, CHANGE },
- { __("Samples"), OPTION_SAMPLEPATH, ADDING },
- { __("DATs"), OPTION_HISTORY_PATH, ADDING },
- { __("INIs"), OPTION_INIPATH, ADDING },
- { __("Category INIs"), OPTION_CATEGORYINI_PATH, CHANGE },
- { __("Icons"), OPTION_ICONS_PATH, ADDING },
- { __("Cheats"), OPTION_CHEATPATH, ADDING },
- { __("Snapshots"), OPTION_SNAPSHOT_DIRECTORY, ADDING },
- { __("Cabinets"), OPTION_CABINETS_PATH, ADDING },
- { __("Flyers"), OPTION_FLYERS_PATH, ADDING },
- { __("Titles"), OPTION_TITLES_PATH, ADDING },
- { __("Ends"), OPTION_ENDS_PATH, ADDING },
- { __("PCBs"), OPTION_PCBS_PATH, ADDING },
- { __("Marquees"), OPTION_MARQUEES_PATH, ADDING },
- { __("Controls Panels"), OPTION_CPANELS_PATH, ADDING },
- { __("Crosshairs"), OPTION_CROSSHAIRPATH, ADDING },
- { __("Artworks"), OPTION_ARTPATH, ADDING },
- { __("Bosses"), OPTION_BOSSES_PATH, ADDING },
- { __("Artworks Preview"), OPTION_ARTPREV_PATH, ADDING },
- { __("Select"), OPTION_SELECT_PATH, ADDING },
- { __("GameOver"), OPTION_GAMEOVER_PATH, ADDING },
- { __("HowTo"), OPTION_HOWTO_PATH, ADDING },
- { __("Logos"), OPTION_LOGOS_PATH, ADDING },
- { __("Scores"), OPTION_SCORES_PATH, ADDING },
- { __("Versus"), OPTION_VERSUS_PATH, ADDING },
- { __("Covers"), OPTION_COVER_PATH, ADDING }
+ { N_p("path-option", "ROMs"), OPTION_MEDIAPATH },
+ { N_p("path-option", "Software Media"), OPTION_SWPATH },
+ { N_p("path-option", "Sound Samples"), OPTION_SAMPLEPATH },
+ { N_p("path-option", "Artwork"), OPTION_ARTPATH },
+ { N_p("path-option", "Crosshairs"), OPTION_CROSSHAIRPATH },
+ { N_p("path-option", "Cheat Files"), OPTION_CHEATPATH },
+ { N_p("path-option", "Plugins"), OPTION_PLUGINSPATH },
+ { N_p("path-option", "UI Translations"), OPTION_LANGUAGEPATH },
+ { N_p("path-option", "Software Lists"), OPTION_HASHPATH },
+ { N_p("path-option", "INIs"), OPTION_INIPATH },
+ { N_p("path-option", "UI Settings"), OPTION_UI_PATH },
+ { N_p("path-option", "Plugin Data"), OPTION_PLUGINDATAPATH },
+ { N_p("path-option", "DATs"), OPTION_HISTORY_PATH },
+ { N_p("path-option", "Category INIs"), OPTION_CATEGORYINI_PATH },
+ { N_p("path-option", "Snapshots"), OPTION_SNAPSHOT_DIRECTORY },
+ { N_p("path-option", "Icons"), OPTION_ICONS_PATH },
+ { N_p("path-option", "Control Panels"), OPTION_CPANELS_PATH },
+ { N_p("path-option", "Cabinets"), OPTION_CABINETS_PATH },
+ { N_p("path-option", "Marquees"), OPTION_MARQUEES_PATH },
+ { N_p("path-option", "PCBs"), OPTION_PCBS_PATH },
+ { N_p("path-option", "Flyers"), OPTION_FLYERS_PATH },
+ { N_p("path-option", "Title Screens"), OPTION_TITLES_PATH },
+ { N_p("path-option", "Game Endings"), OPTION_ENDS_PATH },
+ { N_p("path-option", "Bosses"), OPTION_BOSSES_PATH },
+ { N_p("path-option", "Artwork Previews"), OPTION_ARTPREV_PATH },
+ { N_p("path-option", "Select"), OPTION_SELECT_PATH },
+ { N_p("path-option", "Game Over Screens"), OPTION_GAMEOVER_PATH },
+ { N_p("path-option", "HowTo"), OPTION_HOWTO_PATH },
+ { N_p("path-option", "Logos"), OPTION_LOGOS_PATH },
+ { N_p("path-option", "Scores"), OPTION_SCORES_PATH },
+ { N_p("path-option", "Versus"), OPTION_VERSUS_PATH },
+ { N_p("path-option", "Covers"), OPTION_COVER_PATH }
};
/**************************************************
- MENU DIRECTORY
+ MENU REMOVE FOLDER
**************************************************/
-//-------------------------------------------------
-// ctor / dtor
-//-------------------------------------------------
-
-menu_directory::menu_directory(mame_ui_manager &mui, render_container &container) : menu(mui, container)
-{
-}
-menu_directory::~menu_directory()
+class menu_remove_folder : public menu
{
- ui().save_ui_options();
- ui_globals::reset = true;
-}
+public:
+ menu_remove_folder(mame_ui_manager &mui, render_container &container, int ref);
-//-------------------------------------------------
-// handle
-//-------------------------------------------------
+private:
+ virtual void populate() override;
+ virtual bool handle(event const *ev) override;
-void menu_directory::handle()
-{
- // process the menu
- const event *menu_event = process(0);
-
- if (menu_event != nullptr && menu_event->itemref != nullptr && menu_event->iptkey == IPT_UI_SELECT)
- menu::stack_push<menu_display_actual>(ui(), container(), selected_index());
-}
+ std::string m_searchpath;
+ int const m_ref;
+ std::vector<std::string> m_folders;
+};
//-------------------------------------------------
-// populate
+// ctor / dtor
//-------------------------------------------------
-void menu_directory::populate(float &customtop, float &custombottom)
+menu_remove_folder::menu_remove_folder(mame_ui_manager &mui, render_container &container, int ref)
+ : menu(mui, container)
+ , m_ref(ref)
{
- for (auto & elem : s_folders)
- item_append(_(elem.name), "", 0, (void *)(uintptr_t)elem.action);
+ set_heading(util::string_format(_("Remove %1$s Folder"), _("path-option", f_folders[m_ref].name)));
- item_append(menu_item_type::SEPARATOR);
- customtop = ui().get_line_height() + 3.0f * ui().box_tb_border();
+ if (mui.options().exists(f_folders[m_ref].option))
+ m_searchpath.assign(mui.options().value(f_folders[m_ref].option));
+ else
+ m_searchpath.assign(mui.machine().options().value(f_folders[m_ref].option));
+
+ path_iterator path(m_searchpath);
+ std::string curpath;
+ while (path.next(curpath))
+ m_folders.push_back(curpath);
}
//-------------------------------------------------
-// perform our special rendering
+// handle
//-------------------------------------------------
-void menu_directory::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+bool menu_remove_folder::handle(event const *ev)
{
- char const *const toptext[] = { _("Folders Setup") };
- draw_text_box(
- std::begin(toptext), std::end(toptext),
- origx1, origx2, origy1 - top, origy1 - ui().box_tb_border(),
- ui::text_layout::CENTER, ui::text_layout::TRUNCATE, false,
- ui().colors().text_color(), UI_GREEN_COLOR, 1.0f);
-}
+ // process the menu
+ if (ev && ev->itemref && ev->iptkey == IPT_UI_SELECT)
+ {
+ std::string tmppath, error_string;
+ m_folders.erase(m_folders.begin() + selected_index());
+ for (int x = 0; x < m_folders.size(); ++x)
+ {
+ tmppath.append(m_folders[x]);
+ if (x < m_folders.size() - 1)
+ tmppath.append(";");
+ }
-/**************************************************
- MENU DISPLAY PATH
-**************************************************/
-//-------------------------------------------------
-// ctor / dtor
-//-------------------------------------------------
+ if (ui().options().exists(f_folders[m_ref].option))
+ ui().options().set_value(f_folders[m_ref].option, tmppath, OPTION_PRIORITY_CMDLINE);
+ else if (machine().options().value(f_folders[m_ref].option) != tmppath)
+ machine().options().set_value(f_folders[m_ref].option, tmppath, OPTION_PRIORITY_CMDLINE);
-menu_display_actual::menu_display_actual(mame_ui_manager &mui, render_container &container, int ref)
- : menu(mui, container), m_ref(ref)
-{
-}
+ reset_parent(reset_options::REMEMBER_REF);
+ stack_pop();
+ }
-menu_display_actual::~menu_display_actual()
-{
+ return false;
}
//-------------------------------------------------
-// handle
+// populate menu
//-------------------------------------------------
-void menu_display_actual::handle()
+void menu_remove_folder::populate()
{
- // process the menu
- const event *menu_event = process(0);
- if (menu_event != nullptr && menu_event->itemref != nullptr && menu_event->iptkey == IPT_UI_SELECT)
- switch ((uintptr_t)menu_event->itemref)
- {
- case REMOVE:
- menu::stack_push<menu_remove_folder>(ui(), container(), m_ref);
- break;
+ int folders_count = 0;
+ for (auto & elem : m_folders)
+ item_append(elem, 0, (void *)(uintptr_t)++folders_count);
- case ADD_CHANGE:
- menu::stack_push<menu_add_change_folder>(ui(), container(), m_ref);
- break;
- }
+ item_append(menu_item_type::SEPARATOR);
}
-//-------------------------------------------------
-// populate
-//-------------------------------------------------
-void menu_display_actual::populate(float &customtop, float &custombottom)
-{
- m_heading[0] = string_format(_("Current %1$s Folders"), _(s_folders[m_ref].name));
- if (ui().options().exists(s_folders[m_ref].option))
- m_searchpath.assign(ui().options().value(s_folders[m_ref].option));
- else
- m_searchpath.assign(machine().options().value(s_folders[m_ref].option));
+/**************************************************
+ MENU ADD FOLDER
+**************************************************/
- path_iterator path(m_searchpath);
- std::string curpath;
- m_folders.clear();
- while (path.next(curpath, nullptr))
- m_folders.push_back(curpath);
+class menu_add_change_folder : public menu
+{
+public:
+ menu_add_change_folder(mame_ui_manager &mui, render_container &container, int ref, bool multipath);
- item_append((s_folders[m_ref].action == CHANGE) ? _("Change Folder") : _("Add Folder"), "", 0, (void *)ADD_CHANGE);
+protected:
+ virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override;
+ virtual void custom_render(uint32_t flags, void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
- if (m_folders.size() > 1)
- item_append(_("Remove Folder"), "", 0, (void *)REMOVE);
+ virtual bool custom_ui_back() override { return !m_search.empty(); }
- item_append(menu_item_type::SEPARATOR);
- customtop = (m_folders.size() + 1) * ui().get_line_height() + 6.0f * ui().box_tb_border();
-}
+private:
+ virtual void populate() override;
+ virtual bool handle(event const *ev) override;
-//-------------------------------------------------
-// perform our special rendering
-//-------------------------------------------------
+ void update_search();
-void menu_display_actual::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
-{
- float const lineheight(ui().get_line_height());
- float const maxwidth(draw_text_box(
- std::begin(m_folders), std::end(m_folders),
- origx1, origx2, origy1 - (3.0f * ui().box_tb_border()) - (m_folders.size() * lineheight), origy1 - ui().box_tb_border(),
- ui::text_layout::CENTER, ui::text_layout::TRUNCATE, false,
- ui().colors().text_color(), ui().colors().background_color(), 1.0f));
- draw_text_box(
- std::begin(m_heading), std::end(m_heading),
- 0.5f * (1.0f - maxwidth), 0.5f * (1.0f + maxwidth), origy1 - top, origy1 - top + lineheight + (2.0f * ui().box_tb_border()),
- ui::text_layout::CENTER, ui::text_layout::TRUNCATE, false,
- ui().colors().text_color(), UI_GREEN_COLOR, 1.0f);
-}
+ int const m_ref;
+ bool const m_multipath;
+ std::string m_current_path;
+ std::string m_search;
+ std::vector<std::string> m_folders;
+};
-/**************************************************
-MENU ADD FOLDER
-**************************************************/
//-------------------------------------------------
-// ctor / dtor
+// ctor
//-------------------------------------------------
-menu_add_change_folder::menu_add_change_folder(mame_ui_manager &mui, render_container &container, int ref) : menu(mui, container)
+menu_add_change_folder::menu_add_change_folder(mame_ui_manager &mui, render_container &container, int ref, bool multipath)
+ : menu(mui, container)
+ , m_ref(ref)
+ , m_multipath(multipath)
{
- m_ref = ref;
- m_change = (s_folders[ref].action == CHANGE);
- m_search.clear();
-
// configure the starting path
osd_get_full_path(m_current_path, ".");
std::string searchpath;
- if (mui.options().exists(s_folders[m_ref].option))
- searchpath = mui.options().value(s_folders[m_ref].option);
+ if (mui.options().exists(f_folders[m_ref].option))
+ searchpath = mui.options().value(f_folders[m_ref].option);
else
- searchpath = mui.machine().options().value(s_folders[m_ref].option);
+ searchpath = mui.machine().options().value(f_folders[m_ref].option);
path_iterator path(searchpath);
std::string curpath;
- while (path.next(curpath, nullptr))
+ while (path.next(curpath))
m_folders.push_back(curpath);
}
-menu_add_change_folder::~menu_add_change_folder()
-{
-}
-
//-------------------------------------------------
// handle
//-------------------------------------------------
-void menu_add_change_folder::handle()
+bool menu_add_change_folder::handle(event const *ev)
{
- // process the menu
- const event *menu_event = process(0);
+ if (!ev || !ev->itemref)
+ return false;
- if (menu_event != nullptr && menu_event->itemref != nullptr)
+ if (ev->iptkey == IPT_UI_SELECT)
{
- if (menu_event->iptkey == IPT_UI_SELECT)
- {
- int index = (uintptr_t)menu_event->itemref - 1;
- const menu_item &pitem = item(index);
+ assert(ev->item);
+ menu_item const &pitem = *ev->item;
- // go up to the parent path
- if (!strcmp(pitem.text.c_str(), ".."))
- {
- size_t first_sep = m_current_path.find_first_of(PATH_SEPARATOR[0]);
- size_t last_sep = m_current_path.find_last_of(PATH_SEPARATOR[0]);
- if (first_sep != last_sep)
- m_current_path.erase(++last_sep);
- }
+ // go up to the parent path
+ if (pitem.text() == "..")
+ {
+ size_t const first_sep = m_current_path.find_first_of(PATH_SEPARATOR[0]);
+ size_t const last_sep = m_current_path.find_last_of(PATH_SEPARATOR[0]);
+ m_current_path.erase(last_sep + ((first_sep == last_sep) ? 1 : 0));
+ }
+ else
+ {
+ // if isn't a drive, appends the directory
+ if (pitem.subtext() != "[DRIVE]")
+ util::path_append(m_current_path, pitem.text());
else
- {
- // if isn't a drive, appends the directory
- if (strcmp(pitem.subtext.c_str(), "[DRIVE]") != 0)
- {
- if (m_current_path[m_current_path.length() - 1] == PATH_SEPARATOR[0])
- m_current_path.append(pitem.text);
- else
- m_current_path.append(PATH_SEPARATOR).append(pitem.text);
- }
- else
- m_current_path = pitem.text;
- }
+ m_current_path = pitem.text();
+ }
- // reset the char buffer also in this case
- m_search.clear();
- reset(reset_options::SELECT_FIRST);
+ // reset the char buffer also in this case
+ m_search.clear();
+ reset(reset_options::SELECT_FIRST);
+ }
+ else if (ev->iptkey == IPT_UI_PASTE)
+ {
+ if (paste_text(m_search, uchar_is_printable))
+ {
+ update_search();
+ return true;
}
- else if (menu_event->iptkey == IPT_SPECIAL)
+ }
+ else if (ev->iptkey == IPT_SPECIAL)
+ {
+ if (ev->unichar == 0x09)
{
- bool update_selected = false;
-
- if (menu_event->unichar == 0x09)
+ // Tab key, save current path
+ std::string error_string;
+ if (!m_multipath)
{
- // Tab key, save current path
- std::string error_string;
- if (m_change)
- {
- if (ui().options().exists(s_folders[m_ref].option))
- ui().options().set_value(s_folders[m_ref].option, m_current_path, OPTION_PRIORITY_CMDLINE);
- else if (strcmp(machine().options().value(s_folders[m_ref].option), m_current_path.c_str()) != 0)
- {
- machine().options().set_value(s_folders[m_ref].option, m_current_path, OPTION_PRIORITY_CMDLINE);
- }
- }
- else
- {
- m_folders.push_back(m_current_path);
- std::string tmppath;
- for (int x = 0; x < m_folders.size(); ++x)
- {
- tmppath.append(m_folders[x]);
- if (x != m_folders.size() - 1)
- tmppath.append(";");
- }
-
- if (ui().options().exists(s_folders[m_ref].option))
- ui().options().set_value(s_folders[m_ref].option, tmppath, OPTION_PRIORITY_CMDLINE);
- else if (strcmp(machine().options().value(s_folders[m_ref].option), tmppath.c_str()) != 0)
- {
- machine().options().set_value(s_folders[m_ref].option, tmppath, OPTION_PRIORITY_CMDLINE);
- }
- }
-
- reset_parent(reset_options::SELECT_FIRST);
- stack_pop();
+ if (ui().options().exists(f_folders[m_ref].option))
+ ui().options().set_value(f_folders[m_ref].option, m_current_path, OPTION_PRIORITY_CMDLINE);
+ else if (machine().options().value(f_folders[m_ref].option) != m_current_path)
+ machine().options().set_value(f_folders[m_ref].option, m_current_path, OPTION_PRIORITY_CMDLINE);
}
else
{
- // if it's any other key and we're not maxed out, update
- update_selected = input_character(m_search, menu_event->unichar, uchar_is_printable);
- }
-
- // check for entries which matches our search buffer
- if (update_selected)
- {
- const int cur_selected = selected_index();
- int entry, bestmatch = 0;
-
- // from current item to the end
- for (entry = cur_selected; entry < item_count(); entry++)
- if (item(entry).ref != nullptr && !m_search.empty())
- {
- int match = 0;
- for (int i = 0; i < m_search.size() + 1; i++)
- {
- if (core_strnicmp(item(entry).text.c_str(), m_search.data(), i) == 0)
- match = i;
- }
-
- if (match > bestmatch)
- {
- bestmatch = match;
- set_selected_index(entry);
- }
- }
-
- // and from the first item to current one
- for (entry = 0; entry < cur_selected; entry++)
+ m_folders.push_back(m_current_path);
+ std::string tmppath;
+ for (int x = 0; x < m_folders.size(); ++x)
{
- if (item(entry).ref != nullptr && !m_search.empty())
- {
- int match = 0;
- for (int i = 0; i < m_search.size() + 1; i++)
- {
- if (core_strnicmp(item(entry).text.c_str(), m_search.data(), i) == 0)
- match = i;
- }
-
- if (match > bestmatch)
- {
- bestmatch = match;
- set_selected_index(entry);
- }
- }
+ tmppath.append(m_folders[x]);
+ if (x != m_folders.size() - 1)
+ tmppath.append(";");
}
- centre_selection();
+
+ if (ui().options().exists(f_folders[m_ref].option))
+ ui().options().set_value(f_folders[m_ref].option, tmppath, OPTION_PRIORITY_CMDLINE);
+ else if (machine().options().value(f_folders[m_ref].option) != tmppath)
+ machine().options().set_value(f_folders[m_ref].option, tmppath, OPTION_PRIORITY_CMDLINE);
}
+
+ reset_parent(reset_options::SELECT_FIRST);
+ stack_pop();
}
- else if (menu_event->iptkey == IPT_UI_CANCEL)
+ else if (input_character(m_search, ev->unichar, uchar_is_printable))
{
- // reset the char buffer also in this case
- m_search.clear();
+ // if it's any other key and we're not maxed out, update
+ update_search();
+ return true;
}
}
+ else if (ev->iptkey == IPT_UI_CANCEL)
+ {
+ // reset the char buffer also in this case
+ m_search.clear();
+ return true;
+ }
+
+ return false;
}
//-------------------------------------------------
// populate
//-------------------------------------------------
-void menu_add_change_folder::populate(float &customtop, float &custombottom)
+void menu_add_change_folder::populate()
{
- // open a path
- const char *volume_name = nullptr;
- file_enumerator path(m_current_path.c_str());
- const osd::directory::entry *dirent;
int folders_count = 0;
// add the drives
- for (int i = 0; (volume_name = osd_get_volume_name(i)) != nullptr; ++i)
+ for (std::string const &volume_name : osd_get_volume_names())
item_append(volume_name, "[DRIVE]", 0, (void *)(uintptr_t)++folders_count);
- // add the directories
+ // get subdirectories
+ std::vector<std::string> dirnames;
+ file_enumerator path(m_current_path);
+ const osd::directory::entry *dirent;
while ((dirent = path.next()) != nullptr)
{
- if (dirent->type == osd::directory::entry::entry_type::DIR && strcmp(dirent->name, ".") != 0)
- item_append(dirent->name, "[DIR]", 0, (void *)(uintptr_t)++folders_count);
+ if ((osd::directory::entry::entry_type::DIR == dirent->type) && strcmp(dirent->name, "."))
+ dirnames.emplace_back(dirent->name);
}
+ // sort
+ std::locale const lcl;
+ std::collate<wchar_t> const &coll = std::use_facet<std::collate<wchar_t> >(lcl);
+ std::sort(
+ dirnames.begin(),
+ dirnames.end(),
+ [&coll] (std::string const &x, std::string const &y)
+ {
+ std::wstring const xw = wstring_from_utf8(x);
+ std::wstring const yw = wstring_from_utf8(y);
+ return coll.compare(xw.data(), xw.data() + xw.size(), yw.data(), yw.data() + yw.size()) < 0;
+ });
+
+ // add to menu
+ for (std::string const &name : dirnames)
+ item_append(name, "[DIR]", 0, (void *)(uintptr_t)++folders_count);
+
item_append(menu_item_type::SEPARATOR);
+}
+
+//-------------------------------------------------
+// recompute metrics
+//-------------------------------------------------
+
+void menu_add_change_folder::recompute_metrics(uint32_t width, uint32_t height, float aspect)
+{
+ menu::recompute_metrics(width, height, aspect);
// configure the custom rendering
- customtop = 2.0f * ui().get_line_height() + 3.0f * ui().box_tb_border();
- custombottom = 1.0f * ui().get_line_height() + 3.0f * ui().box_tb_border();
+ set_custom_space(2.0f * line_height() + 3.0f * tb_border(), 1.0f * line_height() + 3.0f * tb_border());
}
//-------------------------------------------------
// perform our special rendering
//-------------------------------------------------
-void menu_add_change_folder::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+void menu_add_change_folder::custom_render(uint32_t flags, void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
{
std::string const toptext[] = {
util::string_format(
- m_change ? _("Change %1$s Folder - Search: %2$s_") : _("Add %1$s Folder - Search: %2$s_"),
- _(s_folders[m_ref].name),
+ m_multipath ? _("Add %1$s Folder - Search: %2$s_") : _("Change %1$s Folder - Search: %2$s_"),
+ _("path-option", f_folders[m_ref].name),
m_search),
m_current_path };
draw_text_box(
std::begin(toptext), std::end(toptext),
- origx1, origx2, origy1 - top, origy1 - ui().box_tb_border(),
- ui::text_layout::CENTER, ui::text_layout::NEVER, false,
- ui().colors().text_color(), UI_GREEN_COLOR, 1.0f);
+ origx1, origx2, origy1 - top, origy1 - tb_border(),
+ text_layout::text_justify::CENTER, text_layout::word_wrapping::NEVER, false,
+ ui().colors().text_color(), UI_GREEN_COLOR);
// bottom text
char const *const bottomtext[] = { _("Press TAB to set") };
draw_text_box(
std::begin(bottomtext), std::end(bottomtext),
- origx1, origx2, origy2 + ui().box_tb_border(), origy2 + bottom,
- ui::text_layout::CENTER, ui::text_layout::TRUNCATE, false,
- ui().colors().text_color(), UI_RED_COLOR, 1.0f);
+ origx1, origx2, origy2 + tb_border(), origy2 + bottom,
+ text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false,
+ ui().colors().text_color(), ui().colors().background_color());
}
-/**************************************************
- MENU REMOVE FOLDER
-**************************************************/
//-------------------------------------------------
-// ctor / dtor
+// update search
//-------------------------------------------------
-menu_remove_folder::menu_remove_folder(mame_ui_manager &mui, render_container &container, int ref) : menu(mui, container)
+void menu_add_change_folder::update_search()
{
- m_ref = ref;
- if (mui.options().exists(s_folders[m_ref].option))
- m_searchpath.assign(mui.options().value(s_folders[m_ref].option));
- else
- m_searchpath.assign(mui.machine().options().value(s_folders[m_ref].option));
+ // check for entries which matches our search buffer
+ const int cur_selected = selected_index();
+ int entry, bestmatch = 0;
- path_iterator path(m_searchpath);
- std::string curpath;
- while (path.next(curpath, nullptr))
- m_folders.push_back(curpath);
+ // from current item to the end
+ for (entry = cur_selected; entry < item_count(); entry++)
+ if (item(entry).ref() && !m_search.empty())
+ {
+ int match = 0;
+ for (int i = 0; i < m_search.size() + 1; i++)
+ {
+ if (core_strnicmp(item(entry).text().c_str(), m_search.data(), i) == 0)
+ match = i;
+ }
+
+ if (match > bestmatch)
+ {
+ bestmatch = match;
+ set_selected_index(entry);
+ }
+ }
+
+ // and from the first item to current one
+ for (entry = 0; entry < cur_selected; entry++)
+ {
+ if (item(entry).ref() && !m_search.empty())
+ {
+ int match = 0;
+ for (int i = 0; i < m_search.size() + 1; i++)
+ {
+ if (core_strnicmp(item(entry).text().c_str(), m_search.data(), i) == 0)
+ match = i;
+ }
+
+ if (match > bestmatch)
+ {
+ bestmatch = match;
+ set_selected_index(entry);
+ }
+ }
+ }
+ centre_selection();
}
-menu_remove_folder::~menu_remove_folder()
+
+/**************************************************
+ MENU DISPLAY PATH
+**************************************************/
+
+class menu_display_actual : public menu
+{
+public:
+ menu_display_actual(mame_ui_manager &mui, render_container &container, int selectedref)
+ : menu(mui, container)
+ , m_ref(selectedref)
+ , m_multipath(is_multipath(f_folders[selectedref].option))
+ , m_heading{ util::string_format(m_multipath ? _("%1$s Folders") : _("%1$s Folder"), _("path-option", f_folders[selectedref].name)) }
+ {
+ }
+
+protected:
+ virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override;
+ virtual void custom_render(uint32_t flags, void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+private:
+ enum
+ {
+ ADD_CHANGE = 1,
+ REMOVE,
+ };
+
+ virtual void populate() override;
+ virtual bool handle(event const *ev) override;
+
+ bool is_multipath(std::string_view folder) const;
+
+ int const m_ref;
+ bool const m_multipath;
+ std::string const m_heading[1];
+ std::string m_searchpath;
+ std::vector<std::string> m_folders;
+};
+
+//-------------------------------------------------
+// is_multipath
+//-------------------------------------------------
+
+bool menu_display_actual::is_multipath(std::string_view folder) const
{
+ auto option = ui().options().get_entry(folder);
+ if (!option)
+ option = machine().options().get_entry(folder);
+ assert(option);
+
+ return option->type() == core_options::option_type::MULTIPATH;
}
//-------------------------------------------------
// handle
//-------------------------------------------------
-void menu_remove_folder::handle()
+bool menu_display_actual::handle(event const *ev)
{
- // process the menu
- const event *menu_event = process(0);
- if (menu_event != nullptr && menu_event->itemref != nullptr && menu_event->iptkey == IPT_UI_SELECT)
+ if (ev && ev->itemref && ev->iptkey == IPT_UI_SELECT)
{
- std::string tmppath, error_string;
- m_folders.erase(m_folders.begin() + selected_index());
- for (int x = 0; x < m_folders.size(); ++x)
+ switch ((uintptr_t)ev->itemref)
{
- tmppath.append(m_folders[x]);
- if (x < m_folders.size() - 1)
- tmppath.append(";");
- }
+ case REMOVE:
+ menu::stack_push<menu_remove_folder>(ui(), container(), m_ref);
+ break;
- if (ui().options().exists(s_folders[m_ref].option))
- ui().options().set_value(s_folders[m_ref].option, tmppath, OPTION_PRIORITY_CMDLINE);
- else if (strcmp(machine().options().value(s_folders[m_ref].option),tmppath.c_str())!=0)
- {
- machine().options().set_value(s_folders[m_ref].option, tmppath, OPTION_PRIORITY_CMDLINE);
+ case ADD_CHANGE:
+ menu::stack_push<menu_add_change_folder>(ui(), container(), m_ref, m_multipath);
+ break;
}
-
- reset_parent(reset_options::REMEMBER_REF);
- stack_pop();
}
+
+ return false;
}
//-------------------------------------------------
-// populate menu
+// populate
//-------------------------------------------------
-void menu_remove_folder::populate(float &customtop, float &custombottom)
+void menu_display_actual::populate()
{
- int folders_count = 0;
- for (auto & elem : m_folders)
- item_append(elem, "", 0, (void *)(uintptr_t)++folders_count);
+ auto const &folder = f_folders[m_ref];
+ auto option = ui().options().get_entry(folder.option);
+ if (!option)
+ option = machine().options().get_entry(folder.option);
+ assert(option);
+
+ m_searchpath.assign(option->value());
+
+ m_folders.clear();
+ if (m_multipath)
+ {
+ path_iterator path(m_searchpath);
+ std::string curpath;
+ while (path.next(curpath))
+ m_folders.push_back(curpath);
+
+ item_append(_("Add Folder"), 0, (void *)ADD_CHANGE);
+ if (m_folders.size() > 1)
+ item_append(_("Remove Folder"), 0, (void *)REMOVE);
+ }
+ else
+ {
+ m_folders.push_back(m_searchpath);
+ item_append(_("Change Folder"), 0, (void *)ADD_CHANGE);
+ }
item_append(menu_item_type::SEPARATOR);
- customtop = ui().get_line_height() + 3.0f * ui().box_tb_border();
+
+ set_custom_space((m_folders.size() + 1) * line_height() + 6.0f * tb_border(), 0.0f);
+}
+
+//-------------------------------------------------
+// recompute metrics
+//-------------------------------------------------
+
+void menu_display_actual::recompute_metrics(uint32_t width, uint32_t height, float aspect)
+{
+ menu::recompute_metrics(width, height, aspect);
+
+ set_custom_space((m_folders.size() + 1) * line_height() + 6.0f * tb_border(), 0.0f);
}
//-------------------------------------------------
// perform our special rendering
//-------------------------------------------------
-void menu_remove_folder::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+void menu_display_actual::custom_render(uint32_t flags, void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
{
- std::string const toptext[] = {string_format(_("Remove %1$s Folder"), _(s_folders[m_ref].name)) };
+ float const maxwidth(draw_text_box(
+ std::begin(m_folders), std::end(m_folders),
+ origx1, origx2, origy1 - (3.0f * tb_border()) - (m_folders.size() * line_height()), origy1 - tb_border(),
+ text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false,
+ ui().colors().text_color(), ui().colors().background_color()));
draw_text_box(
- std::begin(toptext), std::end(toptext),
- origx1, origx2, origy1 - top, origy1 - ui().box_tb_border(),
- ui::text_layout::CENTER, ui::text_layout::TRUNCATE, false,
- ui().colors().text_color(), UI_GREEN_COLOR, 1.0f);
+ std::begin(m_heading), std::end(m_heading),
+ 0.5f * (1.0f - maxwidth), 0.5f * (1.0f + maxwidth), origy1 - top, origy1 - top + line_height() + (2.0f * tb_border()),
+ text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false,
+ ui().colors().text_color(), UI_GREEN_COLOR);
+}
+
+} // anonymous namespace
+
+
+/**************************************************
+ MENU DIRECTORY
+**************************************************/
+//-------------------------------------------------
+// ctor / dtor
+//-------------------------------------------------
+
+menu_directory::menu_directory(mame_ui_manager &mui, render_container &container) : menu(mui, container)
+{
+ set_heading(_("Configure Folders"));
+}
+
+menu_directory::~menu_directory()
+{
+ ui().save_ui_options();
+ ui_globals::reset = true;
+}
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+bool menu_directory::handle(event const *ev)
+{
+ if (ev && ev->itemref && ev->iptkey == IPT_UI_SELECT)
+ menu::stack_push<menu_display_actual>(ui(), container(), selected_index());
+
+ return false;
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void menu_directory::populate()
+{
+ for (auto & elem : f_folders)
+ item_append(_("path-option", elem.name), 0, this); // need a non-null reference pointer - value is immaterial
+
+ item_append(menu_item_type::SEPARATOR);
}
} // namespace ui