Fix Win32 build
[lsnes.git] / src / platform / wxwidgets / dumpmenu.cpp
blob2cac400f20e54d61f218a18fc71f3e54f0198a28
1 #include <wx/wx.h>
2 #include <wx/event.h>
3 #include <wx/control.h>
4 #include <wx/combobox.h>
5 #include <wx/statline.h>
7 #include "core/advdumper.hpp"
8 #include "core/dispatch.hpp"
9 #include "core/instance.hpp"
10 #include "core/project.hpp"
11 #include "core/ui-services.hpp"
13 #include "platform/wxwidgets/menu_dump.hpp"
14 #include "platform/wxwidgets/platform.hpp"
16 struct dumper_info
18 dumper_factory_base* instance;
19 std::string name;
20 bool active;
21 std::map<std::string, std::string> modes;
24 namespace
26 struct dumper_menu_struct
28 int end_wxid;
29 wxMenuItem* end_item;
30 std::map<int, std::string> start_wxids;
31 std::map<int, wxMenuItem*> start_items;
32 wxMenuItem* sep;
34 std::map<std::string, dumper_menu_struct> menustructure;
35 std::string last_processed;
36 bool first;
40 class dumper_menu_monitor : public master_dumper::notifier
42 public:
43 dumper_menu_monitor(dumper_menu* dmenu)
45 linked = dmenu;
48 ~dumper_menu_monitor() throw()
52 void dumpers_updated() throw()
54 runuifun([this]() { if(this->linked) this->linked->update(); });
56 void dump_status_change() throw()
58 dumpers_updated();
60 private:
61 dumper_menu* linked;
64 dumper_menu::dumper_menu(wxWindow* win, emulator_instance& _inst, int wxid_low, int wxid_high)
65 : inst(_inst)
67 CHECK_UI_THREAD;
68 pwin = win;
69 win->Connect(wxid_low, wxid_high, wxEVT_COMMAND_MENU_SELECTED,
70 wxCommandEventHandler(dumper_menu::on_select), NULL, this);
71 wxid_range_low = wxid_low;
72 wxid_range_high = wxid_high;
73 monitor = new dumper_menu_monitor(this);
74 inst.mdumper->add_notifier(*monitor);
75 update();
78 dumper_menu::~dumper_menu()
80 inst.mdumper->drop_notifier(*monitor);
81 delete monitor;
84 void dumper_menu::on_select(wxCommandEvent& e)
86 CHECK_UI_THREAD;
87 int id = e.GetId();
88 if(id < wxid_range_low || id > wxid_range_high)
89 return;
90 for(auto i : menustructure) {
91 dumper_factory_base* t = existing_dumpers[i.first].factory;
92 if(i.second.end_wxid == id) {
93 UI_end_dump(inst, *t);
94 return;
96 if(i.second.start_wxids.count(id)) {
97 //Execute start of dump operation.
98 std::string mode = i.second.start_wxids[id];
99 unsigned d = t->mode_details(mode);
100 std::string prefix;
101 if((d & dumper_factory_base::target_type_mask) == dumper_factory_base::target_type_file) {
102 wxFileDialog* d = new wxFileDialog(pwin, wxT("Choose file"),
103 towxstring(UI_get_project_otherpath(inst)), wxT(""), wxT("*.*"),
104 wxFD_SAVE);
105 std::string modext = t->mode_extension(mode);
106 d->SetWildcard(towxstring(modext + " files|*." + modext));
107 auto p = inst.project->get();
108 if(p)
109 d->SetFilename(towxstring(p->prefix + "." + modext));
110 if(d->ShowModal() == wxID_OK)
111 prefix = tostdstring(d->GetPath());
112 d->Destroy();
113 } else if((d & dumper_factory_base::target_type_mask) ==
114 dumper_factory_base::target_type_prefix) {
115 wxFileDialog* d = new wxFileDialog(pwin, wxT("Choose prefix"),
116 towxstring(UI_get_project_otherpath(inst)), wxT(""), wxT("*.*"),
117 wxFD_SAVE);
118 auto p = inst.project->get();
119 if(p)
120 d->SetFilename(towxstring(p->prefix));
121 if(d->ShowModal() == wxID_OK)
122 prefix = tostdstring(d->GetPath());
123 d->Destroy();
124 } else if((d & dumper_factory_base::target_type_mask) ==
125 dumper_factory_base::target_type_special) {
126 try {
127 prefix = pick_text(pwin, "Choose target", "Enter target to dump to", "");
128 } catch(...) {
129 return;
131 } else {
132 wxMessageBox(wxT("Unsupported target type"), _T("Dumper error"), wxICON_EXCLAMATION |
133 wxOK, pwin);
134 return;
136 if(prefix == "")
137 return;
138 try {
139 UI_start_dump(inst, *t, mode, prefix);
140 } catch(std::exception& e) {
141 show_exception(this->pwin, "Error starting dump", "", e);
143 return;
148 void dumper_menu::update()
150 CHECK_UI_THREAD;
151 dumper_information dinfo = UI_get_dumpers(inst);
152 //Destroy all old entries.
153 for(auto i : menustructure) {
154 struct dumper_menu_struct& m = i.second;
155 if(m.end_item)
156 Remove(m.end_item);
157 for(auto mi : m.start_items)
158 Remove(mi.second);
159 if(m.sep)
160 Remove(m.sep);
162 //And create new ones.
163 int id = wxid_range_low;
164 first = true;
165 menustructure.clear();
166 for(auto i : dinfo.dumpers) {
167 if(!first)
168 menustructure[last_processed].sep = AppendSeparator();
169 last_processed = i.first;
170 first = false;
171 menustructure[i.first].end_item = NULL;
172 menustructure[i.first].end_wxid = wxID_ANY;
173 if(!i.second.active) {
174 if(i.second.modes.empty()) {
175 menustructure[i.first].start_items[id] = Append(id, towxstring("Dump " +
176 i.second.name + "..."));
177 menustructure[i.first].start_wxids[id++] = "";
179 for(auto j : i.second.modes) {
180 menustructure[i.first].start_items[id] = Append(id, towxstring("Dump " +
181 i.second.name + " (" + j.second + ")..."));
182 menustructure[i.first].start_wxids[id++] = j.first;
184 } else {
185 menustructure[i.first].end_item = Append(id, towxstring("End " + i.second.name));
186 menustructure[i.first].end_wxid = id++;
189 existing_dumpers = dinfo.dumpers;