From 00a4404045d28beef129d027dc9eaae33ab44703 Mon Sep 17 00:00:00 2001 From: EmptyChaos Date: Sat, 23 Jul 2016 01:05:04 +0000 Subject: CheatManager/ISOProperties: Refactor ActionReplay tabs as a class Refactor Action Replay code into its own class like Gecko Codes. --- Source/Core/DolphinWX/Cheats/CheatsWindow.cpp | 118 ++++++++++---------------- 1 file changed, 43 insertions(+), 75 deletions(-) (limited to 'Source/Core/DolphinWX/Cheats/CheatsWindow.cpp') diff --git a/Source/Core/DolphinWX/Cheats/CheatsWindow.cpp b/Source/Core/DolphinWX/Cheats/CheatsWindow.cpp index ef96aaa601..a6c6bad730 100644 --- a/Source/Core/DolphinWX/Cheats/CheatsWindow.cpp +++ b/Source/Core/DolphinWX/Cheats/CheatsWindow.cpp @@ -32,6 +32,7 @@ #include "Core/Core.h" #include "Core/GeckoCode.h" #include "Core/GeckoCodeConfig.h" +#include "DolphinWX/Cheats/ActionReplayCodesPanel.h" #include "DolphinWX/Cheats/CheatSearchTab.h" #include "DolphinWX/Cheats/CheatsWindow.h" #include "DolphinWX/Cheats/CreateCodeDialog.h" @@ -58,7 +59,7 @@ wxCheatsWindow::wxCheatsWindow(wxWindow* const parent) // load codes UpdateGUI(); - wxTheApp->Bind(DOLPHIN_EVT_LOCAL_INI_CHANGED, &wxCheatsWindow::OnEvent_CheatsList_Update, this); + wxTheApp->Bind(DOLPHIN_EVT_LOCAL_INI_CHANGED, &wxCheatsWindow::OnLocalGameIniModified, this); SetSize(wxSize(-1, 600)); Center(); @@ -77,31 +78,16 @@ void wxCheatsWindow::Init_ChildControls() // --- Tabs --- // Cheats List Tab - m_tab_cheats = new wxPanel(m_notebook_main, wxID_ANY); + wxPanel* tab_cheats = new wxPanel(m_notebook_main, wxID_ANY); - m_checklistbox_cheats_list = new wxCheckListBox(m_tab_cheats, wxID_ANY, wxDefaultPosition, - wxSize(300, 0), 0, nullptr, wxLB_HSCROLL); - m_checklistbox_cheats_list->Bind(wxEVT_LISTBOX, &wxCheatsWindow::OnEvent_CheatsList_ItemSelected, - this); - - m_label_code_name = new wxStaticText(m_tab_cheats, wxID_ANY, _("Name: "), wxDefaultPosition, - wxDefaultSize, wxST_NO_AUTORESIZE); - m_groupbox_info = new wxStaticBox(m_tab_cheats, wxID_ANY, _("Code Info")); - - m_label_num_codes = new wxStaticText(m_tab_cheats, wxID_ANY, _("Number Of Codes: ")); - m_listbox_codes_list = new wxListBox(m_tab_cheats, wxID_ANY, wxDefaultPosition, wxSize(120, 150), - 0, nullptr, wxLB_HSCROLL); - - wxStaticBoxSizer* sGroupBoxInfo = new wxStaticBoxSizer(m_groupbox_info, wxVERTICAL); - sGroupBoxInfo->Add(m_label_code_name, 0, wxEXPAND | wxALL, 5); - sGroupBoxInfo->Add(m_label_num_codes, 0, wxALL, 5); - sGroupBoxInfo->Add(m_listbox_codes_list, 1, wxALL, 5); + m_ar_codes_panel = + new ActionReplayCodesPanel(tab_cheats, ActionReplayCodesPanel::STYLE_SIDE_PANEL | + ActionReplayCodesPanel::STYLE_MODIFY_BUTTONS); wxBoxSizer* sizer_tab_cheats = new wxBoxSizer(wxHORIZONTAL); - sizer_tab_cheats->Add(m_checklistbox_cheats_list, 1, wxEXPAND | wxTOP | wxBOTTOM | wxLEFT, 10); - sizer_tab_cheats->Add(sGroupBoxInfo, 0, wxALIGN_LEFT | wxEXPAND | wxALL, 5); + sizer_tab_cheats->Add(m_ar_codes_panel, 1, wxEXPAND | wxALL, 5); - m_tab_cheats->SetSizerAndFit(sizer_tab_cheats); + tab_cheats->SetSizerAndFit(sizer_tab_cheats); // Cheat Search Tab wxPanel* const tab_cheat_search = new CheatSearchTab(m_notebook_main); @@ -134,7 +120,7 @@ void wxCheatsWindow::Init_ChildControls() m_tab_log->SetSizerAndFit(sTabLog); // Add Tabs to Notebook - m_notebook_main->AddPage(m_tab_cheats, _("AR Codes")); + m_notebook_main->AddPage(tab_cheats, _("AR Codes")); m_geckocode_panel = new Gecko::CodeConfigPanel(m_notebook_main); m_notebook_main->AddPage(m_geckocode_panel, _("Gecko Codes")); m_notebook_main->AddPage(tab_cheat_search, _("Cheat Search")); @@ -193,21 +179,17 @@ void wxCheatsWindow::UpdateGUI() void wxCheatsWindow::Load_ARCodes() { - m_checklistbox_cheats_list->Clear(); - if (!Core::IsRunning()) + { + m_ar_codes_panel->Clear(); + m_ar_codes_panel->Disable(); return; - - m_checklistbox_cheats_list->Freeze(); - for (auto& code : ActionReplay::LoadCodes(m_gameini_default, m_gameini_local)) + } + else if (!m_ar_codes_panel->IsEnabled()) { - CodeData* cd = new CodeData(); - cd->code = std::move(code); - int index = m_checklistbox_cheats_list->Append( - wxCheckListBox::EscapeMnemonics(StrToWxStr(cd->code.name)), cd); - m_checklistbox_cheats_list->Check(index, cd->code.active); + m_ar_codes_panel->Enable(); } - m_checklistbox_cheats_list->Thaw(); + m_ar_codes_panel->LoadCodes(m_gameini_default, m_gameini_local); } void wxCheatsWindow::Load_GeckoCodes() @@ -220,36 +202,10 @@ void wxCheatsWindow::OnNewARCodeCreated(wxCommandEvent& ev) { auto code = static_cast(ev.GetClientData()); ActionReplay::AddCode(*code); - - CodeData* cd = new CodeData(); - cd->code = *code; - int idx = m_checklistbox_cheats_list->Append( - wxCheckListBox::EscapeMnemonics(StrToWxStr(code->name)), cd); - m_checklistbox_cheats_list->Check(idx, code->active); + m_ar_codes_panel->AppendNewCode(*code); } -void wxCheatsWindow::OnEvent_CheatsList_ItemSelected(wxCommandEvent& event) -{ - CodeData* cd = static_cast(event.GetClientObject()); - - m_label_code_name->SetLabelText(_("Name: ") + StrToWxStr(cd->code.name)); - m_label_code_name->Wrap(m_label_code_name->GetSize().GetWidth()); - m_label_code_name->InvalidateBestSize(); - m_label_num_codes->SetLabelText( - wxString::Format("%s%zu", _("Number Of Codes: "), cd->code.ops.size())); - - m_listbox_codes_list->Freeze(); - m_listbox_codes_list->Clear(); - for (const ActionReplay::AREntry& entry : cd->code.ops) - { - m_listbox_codes_list->Append(wxString::Format("%08x %08x", entry.cmd_addr, entry.value)); - } - m_listbox_codes_list->Thaw(); - - m_tab_cheats->Layout(); -} - -void wxCheatsWindow::OnEvent_CheatsList_Update(wxCommandEvent& ev) +void wxCheatsWindow::OnLocalGameIniModified(wxCommandEvent& ev) { ev.Skip(); if (WxStrToStr(ev.GetString()) != m_game_id) @@ -264,18 +220,8 @@ void wxCheatsWindow::OnEvent_CheatsList_Update(wxCommandEvent& ev) void wxCheatsWindow::OnEvent_ApplyChanges_Press(wxCommandEvent& ev) { - // Convert embedded metadata back into ARCode vector and update active states - std::vector code_vec; - code_vec.reserve(m_checklistbox_cheats_list->GetCount()); - for (unsigned int i = 0; i < m_checklistbox_cheats_list->GetCount(); ++i) - { - CodeData* cd = static_cast(m_checklistbox_cheats_list->GetClientObject(i)); - cd->code.active = m_checklistbox_cheats_list->IsChecked(i); - code_vec.push_back(cd->code); - } - // Apply Action Replay code changes - ActionReplay::ApplyCodes(code_vec); + ActionReplay::ApplyCodes(m_ar_codes_panel->GetCodes()); // Apply Gecko Code changes Gecko::SetActiveCodes(m_geckocode_panel->GetCodes()); @@ -283,7 +229,7 @@ void wxCheatsWindow::OnEvent_ApplyChanges_Press(wxCommandEvent& ev) // Save gameini, with changed codes if (m_gameini_local_path.size()) { - ActionReplay::SaveCodes(&m_gameini_local, code_vec); + m_ar_codes_panel->SaveCodes(&m_gameini_local); Gecko::SaveCodes(m_gameini_local, m_geckocode_panel->GetCodes()); m_gameini_local.Save(m_gameini_local_path); @@ -302,9 +248,31 @@ void wxCheatsWindow::OnEvent_ButtonUpdateLog_Press(wxCommandEvent& WXUNUSED(even wxBeginBusyCursor(); m_textctrl_log->Freeze(); m_textctrl_log->Clear(); + // This horrible mess is because the Windows Textbox Widget suffers from + // a Shlemiel The Painter problem where it keeps allocating new memory each + // time some text is appended then memcpys to the new buffer. This happens + // for every single line resulting in the operation taking minutes instead of + // seconds. + // Why not just append all of the text all at once? Microsoft decided that it + // would be clever to accept as much text as will fit in the internal buffer + // then silently discard the rest. We have to iteratively append the text over + // and over until the internal buffer becomes big enough to hold all of it. + // (wxWidgets should have hidden this platform detail but it sucks) + wxString super_string; + super_string.reserve(1024 * 1024); for (const std::string& text : ActionReplay::GetSelfLog()) { - m_textctrl_log->AppendText(StrToWxStr(text)); + super_string.append(StrToWxStr(text)); + } + while (!super_string.empty()) + { + // Read "GetLastPosition" as "Size", there's no size function. + wxTextPos start = m_textctrl_log->GetLastPosition(); + m_textctrl_log->AppendText(super_string); + wxTextPos end = m_textctrl_log->GetLastPosition(); + if (start == end) + break; + super_string.erase(0, end - start); } m_textctrl_log->Thaw(); wxEndBusyCursor(); -- cgit v1.2.3