Make various instance stuff to take references to other instance objs
[lsnes.git] / src / platform / wxwidgets / editor-subtitles.cpp
blob57be51d74c81d466347697e10a38bbebe25ef5f1
1 #include "core/subtitles.hpp"
2 #include "core/instance.hpp"
3 #include "core/moviedata.hpp"
5 #include "platform/wxwidgets/platform.hpp"
7 #include <wx/wx.h>
8 #include <wx/event.h>
9 #include <wx/control.h>
10 #include <wx/combobox.h>
11 #include <wx/radiobut.h>
13 #include "library/string.hpp"
14 #include "core/dispatch.hpp"
15 #include "core/subtitles.hpp"
17 namespace
19 struct subdata
21 uint64_t first;
22 uint64_t last;
23 std::string text;
27 class wxeditor_subtitles : public wxFrame
29 public:
30 wxeditor_subtitles(wxWindow* parent);
31 ~wxeditor_subtitles() throw();
32 bool ShouldPreventAppExit() const;
33 void on_change(wxCommandEvent& e);
34 void on_add(wxCommandEvent& e);
35 void on_edit(wxCommandEvent& e);
36 void on_delete(wxCommandEvent& e);
37 void on_close(wxCommandEvent& e);
38 void on_wclose(wxCloseEvent& e);
39 void refresh();
40 private:
41 bool closing;
42 wxListBox* subs;
43 wxTextCtrl* subtext;
44 wxButton* add;
45 wxButton* edit;
46 wxButton* _delete;
47 wxButton* close;
48 std::map<int, subdata> subtexts;
49 struct dispatch::target<> subchange;
52 namespace
55 class wxeditor_subtitles_subtitle : public wxDialog
57 public:
58 wxeditor_subtitles_subtitle(wxWindow* parent, subdata d);
59 void on_change(wxCommandEvent& e);
60 void on_cancel(wxCommandEvent& e);
61 void on_ok(wxCommandEvent& e);
62 subdata get_result();
63 private:
64 wxTextCtrl* first;
65 wxTextCtrl* last;
66 wxTextCtrl* text;
67 wxButton* ok;
68 wxButton* cancel;
71 wxeditor_subtitles_subtitle::wxeditor_subtitles_subtitle(wxWindow* parent, subdata d)
72 : wxDialog(parent, wxID_ANY, wxT("lsnes: Edit subtitle"), wxDefaultPosition, wxSize(-1, -1))
74 Centre();
75 wxFlexGridSizer* top_s = new wxFlexGridSizer(2, 1, 0, 0);
76 SetSizer(top_s);
78 wxFlexGridSizer* data_s = new wxFlexGridSizer(3, 2, 0, 0);
79 data_s->Add(new wxStaticText(this, wxID_ANY, wxT("First frame:")));
80 data_s->Add(first = new wxTextCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(200, -1)));
81 data_s->Add(new wxStaticText(this, wxID_ANY, wxT("Last frame:")));
82 data_s->Add(last = new wxTextCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(200, -1)));
83 data_s->Add(new wxStaticText(this, wxID_ANY, wxT("Text:")));
84 data_s->Add(text = new wxTextCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(400, -1)));
85 top_s->Add(data_s, 1, wxGROW);
87 first->Connect(wxEVT_COMMAND_TEXT_UPDATED,
88 wxCommandEventHandler(wxeditor_subtitles_subtitle::on_change), NULL, this);
89 last->Connect(wxEVT_COMMAND_TEXT_UPDATED,
90 wxCommandEventHandler(wxeditor_subtitles_subtitle::on_change), NULL, this);
91 text->Connect(wxEVT_COMMAND_TEXT_UPDATED,
92 wxCommandEventHandler(wxeditor_subtitles_subtitle::on_change), NULL, this);
94 wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL);
95 pbutton_s->AddStretchSpacer();
96 pbutton_s->Add(ok = new wxButton(this, wxID_ANY, wxT("OK")), 0, wxGROW);
97 pbutton_s->Add(cancel = new wxButton(this, wxID_ANY, wxT("Cancel")), 0, wxGROW);
98 ok->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(wxeditor_subtitles_subtitle::on_ok),
99 NULL, this);
100 cancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
101 wxCommandEventHandler(wxeditor_subtitles_subtitle::on_cancel), NULL, this);
102 top_s->Add(pbutton_s, 0, wxGROW);
104 pbutton_s->SetSizeHints(this);
105 top_s->SetSizeHints(this);
107 first->SetValue(towxstring((stringfmt() << d.first).str()));
108 last->SetValue(towxstring((stringfmt() << d.last).str()));
109 text->SetValue(towxstring(d.text));
110 Fit();
113 void wxeditor_subtitles_subtitle::on_change(wxCommandEvent& e)
115 bool valid = true;
116 std::string _first = tostdstring(first->GetValue());
117 std::string _last = tostdstring(last->GetValue());
118 std::string _text = tostdstring(text->GetValue());
119 valid = valid && regex_match("[0-9]{1,19}", _first);
120 valid = valid && regex_match("[0-9]{1,19}", _last);
121 valid = valid && (_text != "");
122 ok->Enable(valid);
125 void wxeditor_subtitles_subtitle::on_cancel(wxCommandEvent& e)
127 EndModal(wxID_CANCEL);
130 void wxeditor_subtitles_subtitle::on_ok(wxCommandEvent& e)
132 EndModal(wxID_OK);
135 subdata wxeditor_subtitles_subtitle::get_result()
137 subdata d;
138 d.first = parse_value<uint64_t>(tostdstring(first->GetValue()));
139 d.last = parse_value<uint64_t>(tostdstring(last->GetValue()));
140 d.text = tostdstring(text->GetValue());
141 return d;
144 bool edit_subtext(wxWindow* w, struct subdata& d)
146 bool res = false;
147 wxeditor_subtitles_subtitle* editor = NULL;
148 try {
149 editor = new wxeditor_subtitles_subtitle(w, d);
150 int ret = editor->ShowModal();
151 if(ret == wxID_OK) {
152 d = editor->get_result();
153 res = true;
155 } catch(...) {
156 return false;
158 if(editor)
159 editor->Destroy();
160 return res;
165 wxeditor_subtitles::wxeditor_subtitles(wxWindow* parent)
166 : wxFrame(NULL, wxID_ANY, wxT("lsnes: Edit subtitles"), wxDefaultPosition, wxSize(-1, -1))
168 closing = false;
169 Centre();
170 wxFlexGridSizer* top_s = new wxFlexGridSizer(2, 1, 0, 0);
171 SetSizer(top_s);
173 //TODO: Apppropriate controls.
174 top_s->Add(subs = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxSize(300, 400), 0, NULL,
175 wxLB_SINGLE), 1, wxGROW);
176 subs->Connect(wxEVT_COMMAND_LISTBOX_SELECTED,
177 wxCommandEventHandler(wxeditor_subtitles::on_change), NULL, this);
179 wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL);
180 pbutton_s->AddStretchSpacer();
181 pbutton_s->Add(add = new wxButton(this, wxID_ANY, wxT("Add")), 0, wxGROW);
182 pbutton_s->Add(edit = new wxButton(this, wxID_ANY, wxT("Edit")), 0, wxGROW);
183 pbutton_s->Add(_delete = new wxButton(this, wxID_ANY, wxT("Delete")), 0, wxGROW);
184 pbutton_s->Add(close = new wxButton(this, wxID_ANY, wxT("Close")), 0, wxGROW);
185 add->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(wxeditor_subtitles::on_add), NULL, this);
186 edit->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(wxeditor_subtitles::on_edit), NULL, this);
187 _delete->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(wxeditor_subtitles::on_delete), NULL,
188 this);
189 close->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(wxeditor_subtitles::on_close), NULL, this);
190 top_s->Add(pbutton_s, 0, wxGROW);
192 pbutton_s->SetSizeHints(this);
193 top_s->SetSizeHints(this);
194 Fit();
195 subchange.set(notify_subtitle_change, [this]() { runuifun([this]() -> void { this->refresh(); }); });
196 refresh();
199 wxeditor_subtitles::~wxeditor_subtitles() throw()
203 bool wxeditor_subtitles::ShouldPreventAppExit() const
205 return false;
208 void wxeditor_subtitles::on_close(wxCommandEvent& e)
210 closing = true;
211 Destroy();
214 void wxeditor_subtitles::on_wclose(wxCloseEvent& e)
216 closing = true;
219 void wxeditor_subtitles::refresh()
221 if(closing)
222 return;
223 std::map<std::pair<uint64_t, uint64_t>, std::string> _subtitles;
224 lsnes_instance.iqueue.run([&_subtitles]() -> void {
225 auto keys = lsnes_instance.subtitles.get_all();
226 for(auto i : keys)
227 _subtitles[i] = lsnes_instance.subtitles.get(i.first, i.second);
229 int sel = subs->GetSelection();
230 bool found = (subtexts.count(sel) != 0);
231 subdata matching = subtexts[sel];
232 subs->Clear();
233 unsigned num = 0;
234 subtexts.clear();
235 for(auto i : _subtitles) {
236 subdata newdata;
237 newdata.first = i.first.first;
238 newdata.last = i.first.second;
239 newdata.text = i.second;
240 subtexts[num++] = newdata;
241 std::string s = (stringfmt() << i.first.first << "-" << i.first.second << ": " << i.second).str();
242 subs->Append(towxstring(s));
244 for(size_t i = 0; i < subs->GetCount(); i++)
245 if(subtexts[i].first == matching.first && subtexts[i].last == matching.last)
246 subs->SetSelection(i);
247 if(subs->GetSelection() == wxNOT_FOUND && sel < (ssize_t)subs->GetCount())
248 subs->SetSelection(sel);
249 sel = subs->GetSelection();
250 found = (subtexts.count(sel) != 0);
251 edit->Enable(found);
252 _delete->Enable(found);
255 void wxeditor_subtitles::on_change(wxCommandEvent& e)
257 if(closing)
258 return;
259 int sel = subs->GetSelection();
260 bool found = (subtexts.count(sel) != 0);
261 edit->Enable(found);
262 _delete->Enable(found);
265 void wxeditor_subtitles::on_add(wxCommandEvent& e)
267 if(closing)
268 return;
269 subdata t;
270 t.first = 0;
271 t.last = 0;
272 t.text = "";
273 if(edit_subtext(this, t))
274 lsnes_instance.subtitles.set(t.first, t.last, t.text);
277 void wxeditor_subtitles::on_edit(wxCommandEvent& e)
279 if(closing)
280 return;
281 int sel = subs->GetSelection();
282 if(!subtexts.count(sel))
283 return;
284 auto t = subtexts[sel];
285 auto old = t;
286 if(edit_subtext(this, t)) {
287 lsnes_instance.subtitles.set(old.first, old.last, "");
288 lsnes_instance.subtitles.set(t.first, t.last, t.text);
292 void wxeditor_subtitles::on_delete(wxCommandEvent& e)
294 if(closing)
295 return;
296 int sel = subs->GetSelection();
297 if(!subtexts.count(sel))
298 return;
299 auto t = subtexts[sel];
300 lsnes_instance.subtitles.set(t.first, t.last, "");
303 void wxeditor_subtitles_display(wxWindow* parent)
305 wxFrame* editor;
306 if(!lsnes_instance.mlogic) {
307 show_message_ok(parent, "No movie", "Can't edit authors of nonexistent movie", wxICON_EXCLAMATION);
308 return;
310 try {
311 editor = new wxeditor_subtitles(parent);
312 editor->Show();
313 } catch(...) {