PatchAddEdit.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. // Copyright 2008 Dolphin Emulator Project
  2. // Licensed under GPLv2+
  3. // Refer to the license.txt file included.
  4. #include <string>
  5. #include <vector>
  6. #include <wx/arrstr.h>
  7. #include <wx/button.h>
  8. #include <wx/dialog.h>
  9. #include <wx/gbsizer.h>
  10. #include <wx/msgdlg.h>
  11. #include <wx/radiobox.h>
  12. #include <wx/sizer.h>
  13. #include <wx/spinbutt.h>
  14. #include <wx/statbox.h>
  15. #include <wx/stattext.h>
  16. #include <wx/textctrl.h>
  17. #include "Common/CommonTypes.h"
  18. #include "Core/PatchEngine.h"
  19. #include "DolphinWX/PatchAddEdit.h"
  20. #include "DolphinWX/WxUtils.h"
  21. CPatchAddEdit::CPatchAddEdit(int _selection, std::vector<PatchEngine::Patch>* _onFrame, wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& position, const wxSize& size, long style)
  22. : wxDialog(parent, id, title, position, size, style)
  23. , onFrame(_onFrame)
  24. , selection(_selection)
  25. {
  26. CreateGUIControls(selection);
  27. Bind(wxEVT_BUTTON, &CPatchAddEdit::SavePatchData, this, wxID_OK);
  28. }
  29. CPatchAddEdit::~CPatchAddEdit()
  30. {
  31. }
  32. void CPatchAddEdit::CreateGUIControls(int _selection)
  33. {
  34. wxString currentName = _("<Insert name here>");
  35. if (_selection == -1)
  36. {
  37. tempEntries.clear();
  38. tempEntries.emplace_back(PatchEngine::PATCH_8BIT, 0x00000000, 0x00000000);
  39. }
  40. else
  41. {
  42. currentName = StrToWxStr(onFrame->at(_selection).name);
  43. tempEntries = onFrame->at(_selection).entries;
  44. }
  45. itCurEntry = tempEntries.begin();
  46. wxBoxSizer* sEditPatch = new wxBoxSizer(wxVERTICAL);
  47. wxStaticText* EditPatchNameText = new wxStaticText(this, wxID_ANY, _("Name:"));
  48. EditPatchName = new wxTextCtrl(this, wxID_ANY);
  49. EditPatchName->SetValue(currentName);
  50. wxStaticText* EditPatchOffsetText = new wxStaticText(this, wxID_ANY, _("Offset:"));
  51. EditPatchOffset = new wxTextCtrl(this, wxID_ANY);
  52. EditPatchOffset->SetValue(wxString::Format("%08X", tempEntries.at(0).address));
  53. EntrySelection = new wxSpinButton(this);
  54. EntrySelection->Bind(wxEVT_SPIN, &CPatchAddEdit::ChangeEntry, this);
  55. EntrySelection->SetRange(0, (int)tempEntries.size() - 1);
  56. EntrySelection->SetValue((int)tempEntries.size() - 1);
  57. wxArrayString wxArrayStringFor_EditPatchType;
  58. for (int i = 0; i < 3; ++i)
  59. wxArrayStringFor_EditPatchType.Add(StrToWxStr(PatchEngine::PatchTypeStrings[i]));
  60. EditPatchType = new wxRadioBox(this, wxID_ANY, _("Type"), wxDefaultPosition, wxDefaultSize, wxArrayStringFor_EditPatchType, 3, wxRA_SPECIFY_COLS);
  61. EditPatchType->SetSelection((int)tempEntries.at(0).type);
  62. wxStaticText* EditPatchValueText = new wxStaticText(this, wxID_ANY, _("Value:"));
  63. EditPatchValue = new wxTextCtrl(this, wxID_ANY);
  64. EditPatchValue->SetValue(wxString::Format("%0*X", PatchEngine::GetPatchTypeCharLength(tempEntries.at(0).type), tempEntries.at(0).value));
  65. EntryAdd = new wxButton(this, wxID_ANY, _("Add"));
  66. EntryAdd->Bind(wxEVT_BUTTON, &CPatchAddEdit::AddEntry, this);
  67. EntryRemove = new wxButton(this, wxID_ANY, _("Remove"));
  68. EntryRemove->Bind(wxEVT_BUTTON, &CPatchAddEdit::RemoveEntry, this);
  69. if ((int)tempEntries.size() <= 1)
  70. EntryRemove->Disable();
  71. wxBoxSizer* sEditPatchName = new wxBoxSizer(wxHORIZONTAL);
  72. sEditPatchName->Add(EditPatchNameText, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
  73. sEditPatchName->Add(EditPatchName, 1, wxEXPAND | wxALL, 5);
  74. sEditPatch->Add(sEditPatchName, 0, wxEXPAND);
  75. sbEntry = new wxStaticBoxSizer(wxVERTICAL, this, wxString::Format(_("Entry 1/%d"), (int)tempEntries.size()));
  76. currentItem = 1;
  77. wxGridBagSizer* sgEntry = new wxGridBagSizer(0, 0);
  78. sgEntry->Add(EditPatchType, wxGBPosition(0, 0), wxGBSpan(1, 2), wxEXPAND | wxALL, 5);
  79. sgEntry->Add(EditPatchOffsetText, wxGBPosition(1, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL | wxALL, 5);
  80. sgEntry->Add(EditPatchOffset, wxGBPosition(1, 1), wxGBSpan(1, 1), wxEXPAND | wxALL, 5);
  81. sgEntry->Add(EditPatchValueText, wxGBPosition(2, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL | wxALL, 5);
  82. sgEntry->Add(EditPatchValue, wxGBPosition(2, 1), wxGBSpan(1, 1), wxEXPAND | wxALL, 5);
  83. sgEntry->Add(EntrySelection, wxGBPosition(0, 2), wxGBSpan(3, 1), wxEXPAND | wxALL, 5);
  84. sgEntry->AddGrowableCol(1);
  85. wxBoxSizer* sEntryAddRemove = new wxBoxSizer(wxHORIZONTAL);
  86. sEntryAddRemove->Add(EntryAdd, 0, wxALL, 5);
  87. sEntryAddRemove->Add(EntryRemove, 0, wxALL, 5);
  88. sbEntry->Add(sgEntry, 0, wxEXPAND);
  89. sbEntry->Add(sEntryAddRemove, 0, wxEXPAND);
  90. sEditPatch->Add(sbEntry, 0, wxEXPAND | wxALL, 5);
  91. sEditPatch->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
  92. SetSizerAndFit(sEditPatch);
  93. SetFocus();
  94. }
  95. void CPatchAddEdit::ChangeEntry(wxSpinEvent& event)
  96. {
  97. if (!UpdateTempEntryData(itCurEntry))
  98. return;
  99. itCurEntry = tempEntries.end() - event.GetPosition() - 1;
  100. currentItem = (int)tempEntries.size() - event.GetPosition();
  101. UpdateEntryCtrls(*itCurEntry);
  102. }
  103. void CPatchAddEdit::SavePatchData(wxCommandEvent& event)
  104. {
  105. if (!UpdateTempEntryData(itCurEntry))
  106. return;
  107. if (selection == -1)
  108. {
  109. PatchEngine::Patch newPatch;
  110. newPatch.name = WxStrToStr(EditPatchName->GetValue());
  111. newPatch.entries = tempEntries;
  112. newPatch.active = true;
  113. onFrame->push_back(newPatch);
  114. }
  115. else
  116. {
  117. onFrame->at(selection).name = WxStrToStr(EditPatchName->GetValue());
  118. onFrame->at(selection).entries = tempEntries;
  119. }
  120. AcceptAndClose();
  121. event.Skip();
  122. }
  123. void CPatchAddEdit::AddEntry(wxCommandEvent& event)
  124. {
  125. if (!UpdateTempEntryData(itCurEntry))
  126. return;
  127. PatchEngine::PatchEntry peEmptyEntry(PatchEngine::PATCH_8BIT, 0x00000000, 0x00000000);
  128. ++itCurEntry;
  129. currentItem++;
  130. itCurEntry = tempEntries.insert(itCurEntry, peEmptyEntry);
  131. EntrySelection->SetRange(EntrySelection->GetMin(), EntrySelection->GetMax() + 1);
  132. UpdateEntryCtrls(*itCurEntry);
  133. EntryRemove->Enable();
  134. EntrySelection->Enable();
  135. }
  136. void CPatchAddEdit::RemoveEntry(wxCommandEvent& event)
  137. {
  138. itCurEntry = tempEntries.erase(itCurEntry);
  139. if (itCurEntry != tempEntries.begin())
  140. {
  141. --itCurEntry;
  142. currentItem--;
  143. }
  144. else
  145. {
  146. EntrySelection->SetValue(EntrySelection->GetValue() - 1);
  147. }
  148. EntrySelection->SetRange(EntrySelection->GetMin(), EntrySelection->GetMax() - 1);
  149. UpdateEntryCtrls(*itCurEntry);
  150. if ((int)tempEntries.size() <= 1)
  151. {
  152. EntryRemove->Disable();
  153. EntrySelection->Disable();
  154. }
  155. }
  156. void CPatchAddEdit::UpdateEntryCtrls(PatchEngine::PatchEntry pE)
  157. {
  158. sbEntry->GetStaticBox()->SetLabel(wxString::Format(_("Entry %d/%d"), currentItem,
  159. (int)tempEntries.size()));
  160. EditPatchOffset->SetValue(wxString::Format("%08X", pE.address));
  161. EditPatchType->SetSelection(pE.type);
  162. EditPatchValue->SetValue(wxString::Format("%0*X",
  163. PatchEngine::GetPatchTypeCharLength(pE.type), pE.value));
  164. }
  165. bool CPatchAddEdit::UpdateTempEntryData(std::vector<PatchEngine::PatchEntry>::iterator iterEntry)
  166. {
  167. unsigned long value;
  168. bool parsed_ok = true;
  169. if (EditPatchOffset->GetValue().ToULong(&value, 16))
  170. (*iterEntry).address = value;
  171. else
  172. parsed_ok = false;
  173. PatchEngine::PatchType tempType =
  174. (*iterEntry).type = (PatchEngine::PatchType)EditPatchType->GetSelection();
  175. if (EditPatchValue->GetValue().ToULong(&value, 16))
  176. {
  177. (*iterEntry).value = value;
  178. if (tempType == PatchEngine::PATCH_8BIT && value > 0xff)
  179. parsed_ok = false;
  180. else if (tempType == PatchEngine::PATCH_16BIT && value > 0xffff)
  181. parsed_ok = false;
  182. }
  183. else
  184. {
  185. parsed_ok = false;
  186. }
  187. if (!parsed_ok)
  188. {
  189. wxMessageBox(_("Unable to create patch from given values.\nEntry not modified."), _("Error"));
  190. }
  191. return parsed_ok;
  192. }