Split cases for prefix and special for dumper targets
[lsnes.git] / src / platform / wxwidgets / dumpmenu.cpp
blob53fbff54c5f21fd4f4c11491d13489a9cdd269ba
1 #include "core/advdumper.hpp"
2 #include "core/dispatch.hpp"
4 #include "platform/wxwidgets/menu_dump.hpp"
5 #include "platform/wxwidgets/platform.hpp"
7 struct dumper_info
9 adv_dumper* instance;
10 std::string name;
11 bool active;
12 std::map<std::string, std::string> modes;
15 namespace
17 std::map<std::string, dumper_info> existing_dumpers;
19 struct dumper_menu_struct
21 int end_wxid;
22 wxMenuItem* end_item;
23 std::map<int, std::string> start_wxids;
24 std::map<int, wxMenuItem*> start_items;
25 wxMenuItem* sep;
27 std::map<std::string, dumper_menu_struct> menustructure;
28 std::string last_processed;
29 bool first;
31 void update_dumperinfo(std::map<std::string, dumper_info>& new_dumpers, adv_dumper* d)
33 struct dumper_info inf;
34 inf.instance = d;
35 inf.name = d->name();
36 std::set<std::string> mset = d->list_submodes();
37 for(auto i : mset)
38 inf.modes[i] = d->modename(i);
39 inf.active = d->busy();
40 new_dumpers[d->id()] = inf;
44 class dumper_menu_monitor : public information_dispatch
46 public:
47 dumper_menu_monitor(dumper_menu* dmenu)
48 : information_dispatch("wxwidgets-dumpmenu")
50 linked = dmenu;
53 ~dumper_menu_monitor()
57 void on_dumper_update()
59 std::map<std::string, dumper_info> new_dumpers;
60 std::set<adv_dumper*> dset = adv_dumper::get_dumper_set();
61 for(auto i : dset)
62 update_dumperinfo(new_dumpers, i);
63 runuifun([linked, new_dumpers]() { if(linked) linked->update(new_dumpers); });
65 private:
66 dumper_menu* linked;
71 dumper_menu::dumper_menu(wxWindow* win, int wxid_low, int wxid_high)
73 pwin = win;
74 win->Connect(wxid_low, wxid_high, wxEVT_COMMAND_MENU_SELECTED,
75 wxCommandEventHandler(dumper_menu::on_select), NULL, this);
76 wxid_range_low = wxid_low;
77 wxid_range_high = wxid_high;
78 monitor = new dumper_menu_monitor(this);
79 std::map<std::string, dumper_info> new_dumpers;
80 runemufn([&new_dumpers]() {
81 std::set<adv_dumper*> dset = adv_dumper::get_dumper_set();
82 for(auto i : dset)
83 update_dumperinfo(new_dumpers, i);
84 });
85 update(new_dumpers);
88 dumper_menu::~dumper_menu()
90 delete monitor;
93 void dumper_menu::on_select(wxCommandEvent& e)
95 int id = e.GetId();
96 if(id < wxid_range_low || id > wxid_range_high)
97 return;
98 for(auto i : menustructure) {
99 std::string error_str;
100 adv_dumper* t = existing_dumpers[i.first].instance;
101 if(i.second.end_wxid == id) {
102 //Execute end of dump operation.
103 runemufn([t, &error_str]() {
104 try {
105 t->end();
106 } catch(std::exception& e) {
107 error_str = e.what();
108 }});
109 if(error_str != "")
110 wxMessageBox(towxstring(error_str), _T("Error ending dump"), wxICON_EXCLAMATION | wxOK,
111 pwin);
112 return;
114 if(i.second.start_wxids.count(id)) {
115 //Execute start of dump operation.
116 std::string mode = i.second.start_wxids[id];
117 unsigned d = t->mode_details(mode);
118 std::string prefix;
119 if((d & adv_dumper::target_type_mask) == adv_dumper::target_type_file) {
120 wxFileDialog* d = new wxFileDialog(pwin, wxT("Choose file"), wxT("."));
121 if(d->ShowModal() == wxID_OK)
122 prefix = tostdstring(d->GetPath());
123 d->Destroy();
124 } else if((d & adv_dumper::target_type_mask) == adv_dumper::target_type_prefix) {
125 wxFileDialog* d = new wxFileDialog(pwin, wxT("Choose prefix"), wxT("."));
126 if(d->ShowModal() == wxID_OK)
127 prefix = tostdstring(d->GetPath());
128 d->Destroy();
129 } else if((d & adv_dumper::target_type_mask) == adv_dumper::target_type_special) {
130 try {
131 prefix = pick_text(pwin, "Choose target", "Enter target to dump to", "");
132 } catch(...) {
133 return;
135 } else {
136 wxMessageBox(wxT("Unsupported target type"), _T("Dumper error"), wxICON_EXCLAMATION |
137 wxOK, pwin);
138 return;
140 if(prefix == "")
141 return;
142 runemufn([t, mode, prefix, &error_str]() {
143 try {
144 t->start(mode, prefix);
145 } catch(std::exception& e) {
146 error_str = e.what();
147 }});
148 if(error_str != "")
149 wxMessageBox(towxstring(error_str), _T("Error starting dump"), wxICON_EXCLAMATION |
150 wxOK, pwin);
151 return;
156 void dumper_menu::update(const std::map<std::string, dumper_info>& new_dumpers)
158 //Destroy all old entries.
159 for(auto i : menustructure) {
160 struct dumper_menu_struct& m = i.second;
161 if(m.end_item)
162 Remove(m.end_item);
163 for(auto mi : m.start_items)
164 Remove(mi.second);
165 if(m.sep)
166 Remove(m.sep);
168 //And create new ones.
169 int id = wxid_range_low;
170 first = true;
171 menustructure.clear();
172 for(auto i : new_dumpers) {
173 if(!first)
174 menustructure[last_processed].sep = AppendSeparator();
175 last_processed = i.first;
176 first = false;
177 menustructure[i.first].end_item = NULL;
178 menustructure[i.first].end_wxid = wxID_ANY;
179 if(!i.second.active) {
180 if(i.second.modes.empty()) {
181 menustructure[i.first].start_items[id] = Append(id, towxstring("Dump " +
182 i.second.name + "..."));
183 menustructure[i.first].start_wxids[id++] = "";
185 for(auto j : i.second.modes) {
186 menustructure[i.first].start_items[id] = Append(id, towxstring("Dump " +
187 i.second.name + " (" + j.second + ")..."));
188 menustructure[i.first].start_wxids[id++] = j.first;
190 } else {
191 menustructure[i.first].end_item = Append(id, towxstring("End " + i.second.name));
192 menustructure[i.first].end_wxid = id++;
195 existing_dumpers = new_dumpers;