Make various instance stuff to take references to other instance objs
[lsnes.git] / src / platform / wxwidgets / dumpmenu.cpp
blobf64a5954096501c76b3e0dbc1750a083e8404fe7
1 #include "core/advdumper.hpp"
2 #include "core/dispatch.hpp"
3 #include "core/project.hpp"
5 #include "platform/wxwidgets/menu_dump.hpp"
6 #include "platform/wxwidgets/platform.hpp"
8 struct dumper_info
10 adv_dumper* instance;
11 std::string name;
12 bool active;
13 std::map<std::string, std::string> modes;
16 namespace
18 std::map<std::string, dumper_info> existing_dumpers;
20 struct dumper_menu_struct
22 int end_wxid;
23 wxMenuItem* end_item;
24 std::map<int, std::string> start_wxids;
25 std::map<int, wxMenuItem*> start_items;
26 wxMenuItem* sep;
28 std::map<std::string, dumper_menu_struct> menustructure;
29 std::string last_processed;
30 bool first;
32 void update_dumperinfo(std::map<std::string, dumper_info>& new_dumpers, adv_dumper* d)
34 struct dumper_info inf;
35 inf.instance = d;
36 inf.name = d->name();
37 std::set<std::string> mset = d->list_submodes();
38 for(auto i : mset)
39 inf.modes[i] = d->modename(i);
40 inf.active = d->busy();
41 new_dumpers[d->id()] = inf;
45 class dumper_menu_monitor : public information_dispatch
47 public:
48 dumper_menu_monitor(dumper_menu* dmenu)
49 : information_dispatch("wxwidgets-dumpmenu")
51 linked = dmenu;
54 ~dumper_menu_monitor() throw()
58 void on_dumper_update()
60 new_dumpers.clear();
61 std::set<adv_dumper*> dset = adv_dumper::get_dumper_set();
62 for(auto i : dset)
63 update_dumperinfo(new_dumpers, i);
64 runuifun([this]() { if(this->linked) this->linked->update(this->new_dumpers); });
66 private:
67 dumper_menu* linked;
68 std::map<std::string, dumper_info> new_dumpers;
73 dumper_menu::dumper_menu(wxWindow* win, int wxid_low, int wxid_high)
75 pwin = win;
76 win->Connect(wxid_low, wxid_high, wxEVT_COMMAND_MENU_SELECTED,
77 wxCommandEventHandler(dumper_menu::on_select), NULL, this);
78 wxid_range_low = wxid_low;
79 wxid_range_high = wxid_high;
80 monitor = new dumper_menu_monitor(this);
81 std::map<std::string, dumper_info> new_dumpers;
82 lsnes_instance.iqueue.run([&new_dumpers]() {
83 std::set<adv_dumper*> dset = adv_dumper::get_dumper_set();
84 for(auto i : dset)
85 update_dumperinfo(new_dumpers, i);
86 });
87 update(new_dumpers);
90 dumper_menu::~dumper_menu()
92 delete monitor;
95 void dumper_menu::on_select(wxCommandEvent& e)
97 int id = e.GetId();
98 if(id < wxid_range_low || id > wxid_range_high)
99 return;
100 for(auto i : menustructure) {
101 std::string error_str;
102 adv_dumper* t = existing_dumpers[i.first].instance;
103 if(i.second.end_wxid == id) {
104 //Execute end of dump operation.
105 lsnes_instance.iqueue.run([t, &error_str]() {
106 try {
107 t->end();
108 } catch(std::exception& e) {
109 error_str = e.what();
110 }});
111 if(error_str != "")
112 wxMessageBox(towxstring(error_str), _T("Error ending dump"),
113 wxICON_EXCLAMATION | wxOK, pwin);
114 return;
116 if(i.second.start_wxids.count(id)) {
117 //Execute start of dump operation.
118 std::string mode = i.second.start_wxids[id];
119 unsigned d = t->mode_details(mode);
120 std::string prefix;
121 if((d & adv_dumper::target_type_mask) == adv_dumper::target_type_file) {
122 wxFileDialog* d = new wxFileDialog(pwin, wxT("Choose file"),
123 towxstring(lsnes_instance.project.otherpath()), wxT(""), wxT("*.*"),
124 wxFD_SAVE);
125 std::string modext = t->mode_extension(mode);
126 d->SetWildcard(towxstring(modext + " files|*." + modext));
127 auto p = lsnes_instance.project.get();
128 if(p)
129 d->SetFilename(towxstring(p->prefix + "." + modext));
130 if(d->ShowModal() == wxID_OK)
131 prefix = tostdstring(d->GetPath());
132 d->Destroy();
133 } else if((d & adv_dumper::target_type_mask) == adv_dumper::target_type_prefix) {
134 wxFileDialog* d = new wxFileDialog(pwin, wxT("Choose prefix"),
135 towxstring(lsnes_instance.project.otherpath()), wxT(""), wxT("*.*"),
136 wxFD_SAVE);
137 auto p = lsnes_instance.project.get();
138 if(p)
139 d->SetFilename(towxstring(p->prefix));
140 if(d->ShowModal() == wxID_OK)
141 prefix = tostdstring(d->GetPath());
142 d->Destroy();
143 } else if((d & adv_dumper::target_type_mask) == adv_dumper::target_type_special) {
144 try {
145 prefix = pick_text(pwin, "Choose target", "Enter target to dump to", "");
146 } catch(...) {
147 return;
149 } else {
150 wxMessageBox(wxT("Unsupported target type"), _T("Dumper error"), wxICON_EXCLAMATION |
151 wxOK, pwin);
152 return;
154 if(prefix == "")
155 return;
156 lsnes_instance.iqueue.run([t, mode, prefix, &error_str]() {
157 try {
158 t->start(mode, prefix);
159 } catch(std::exception& e) {
160 error_str = e.what();
161 }});
162 if(error_str != "")
163 wxMessageBox(towxstring(error_str), _T("Error starting dump"), wxICON_EXCLAMATION |
164 wxOK, pwin);
165 return;
170 void dumper_menu::update(const std::map<std::string, dumper_info>& new_dumpers)
172 //Destroy all old entries.
173 for(auto i : menustructure) {
174 struct dumper_menu_struct& m = i.second;
175 if(m.end_item)
176 Remove(m.end_item);
177 for(auto mi : m.start_items)
178 Remove(mi.second);
179 if(m.sep)
180 Remove(m.sep);
182 //And create new ones.
183 int id = wxid_range_low;
184 first = true;
185 menustructure.clear();
186 for(auto i : new_dumpers) {
187 if(!first)
188 menustructure[last_processed].sep = AppendSeparator();
189 last_processed = i.first;
190 first = false;
191 menustructure[i.first].end_item = NULL;
192 menustructure[i.first].end_wxid = wxID_ANY;
193 if(!i.second.active) {
194 if(i.second.modes.empty()) {
195 menustructure[i.first].start_items[id] = Append(id, towxstring("Dump " +
196 i.second.name + "..."));
197 menustructure[i.first].start_wxids[id++] = "";
199 for(auto j : i.second.modes) {
200 menustructure[i.first].start_items[id] = Append(id, towxstring("Dump " +
201 i.second.name + " (" + j.second + ")..."));
202 menustructure[i.first].start_wxids[id++] = j.first;
204 } else {
205 menustructure[i.first].end_item = Append(id, towxstring("End " + i.second.name));
206 menustructure[i.first].end_wxid = id++;
209 existing_dumpers = new_dumpers;