Camtech075

FEditor Text Editor edit

Nov 9th, 2011
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.87 KB | None | 0 0
  1. /*
  2. * FE Editor - GBA Fire Emblem (U) ROM editor
  3. *
  4. * Copyright (C) 2008-2011 Hextator,
  5. * hextator (AIM) [email protected] (MSN)
  6. *
  7. * Major thanks to Zahlman (AIM/MSN: [email protected]) for optimization,
  8. * organization and modularity improvements.
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 3
  12. * as published by the Free Software Foundation
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22. *
  23. * <Description> This class provides a dialog with a text area and other
  24. * appropriate controls for easy modification of the games' scripts
  25. */
  26.  
  27. /* MODIFIED BY CAMTECH075 OF SERENESFOREST -
  28. *
  29. * Changed refresh method to apply changes automatically.
  30. * Removed lines 120-135 (well, commented them out, at least)
  31. * Added "applyChanges" override method at line 306
  32. */
  33.  
  34. package FEditorAdvance;
  35.  
  36. import java.awt.event.ActionListener;
  37. import java.awt.event.ActionEvent;
  38. import java.io.FileWriter;
  39. import java.io.File;
  40. import java.util.Scanner;
  41. import javax.swing.BorderFactory;
  42. import javax.swing.JCheckBox;
  43. import javax.swing.JLabel;
  44. import javax.swing.JScrollPane;
  45. import javax.swing.JTextArea;
  46. import javax.swing.JTextField;
  47. import javax.swing.JPanel;
  48. //import javax.swing.JButton;
  49. import Controls.TablePanel;
  50. import Controls.Process;
  51. import Controls.ProcessComponent;
  52. import Model.Game;
  53. import Model.TextArray;
  54. import Model.Util;
  55.  
  56. public class TextEditor extends Editor<TextArray> {
  57. private TablePanel<TextArray> tablePanel;
  58.  
  59. private JTextArea inputArea;
  60. private JCheckBox regExChkBox;
  61.  
  62. public TextEditor(View view) {
  63. super(view);
  64.  
  65. inputArea = new JTextArea(8, 16);
  66. inputArea.setLineWrap(true);
  67. inputArea.setWrapStyleWord(true);
  68. JScrollPane inputPane = new JScrollPane(inputArea);
  69. inputPane.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 5));
  70. // Don't limit the size of this!
  71. add(inputPane);
  72.  
  73. // FIXME: This should use TextArray.maxSize(), but there is
  74. // no instance available yet.
  75. tablePanel = new TablePanel<TextArray>(this, 0x1, 0xFFFF, 0);
  76. tablePanel.setMaximumSize(tablePanel.getPreferredSize());
  77. add(tablePanel);
  78.  
  79. JPanel findPanel = new JPanel();
  80. findPanel.add(new JLabel("Input text to find:"));
  81. final JTextField findField = new JTextField(32);
  82. findPanel.add(findField);
  83. findPanel.setMaximumSize(findPanel.getPreferredSize());
  84. add(findPanel);
  85.  
  86. JPanel replacePanel = new JPanel();
  87. replacePanel.add(new JLabel("Input text to replace:"));
  88. final JTextField replaceField = new JTextField(30);
  89. replacePanel.add(replaceField);
  90. replacePanel.setMaximumSize(replacePanel.getPreferredSize());
  91. add(replacePanel);
  92.  
  93. JPanel panelA = new JPanel();
  94. addButtonToPanel(panelA, "Find", new ActionListener() {
  95. public void actionPerformed(ActionEvent a) {
  96. table.moveTo(1); find(findField.getText(), true);
  97. }
  98. });
  99. addButtonToPanel(panelA, "Find Next", new ActionListener() {
  100. public void actionPerformed(ActionEvent a) {
  101. table.next(); find(findField.getText(), true);
  102. }
  103. });
  104. addButtonToPanel(panelA, "Find Previous", new ActionListener() {
  105. public void actionPerformed(ActionEvent a) {
  106. table.prev(); find(findField.getText(), false);
  107. }
  108. });
  109. addButtonToPanel(panelA, "Replace All", new ActionListener() {
  110. public void actionPerformed(ActionEvent a) {
  111. replaceAll(findField.getText(), replaceField.getText());
  112. }
  113. });
  114. regExChkBox = new JCheckBox("Use Reg Ex?");
  115. regExChkBox.setSelected(false);
  116. panelA.add(regExChkBox);
  117. panelA.setMaximumSize(panelA.getPreferredSize());
  118. add(panelA);
  119.  
  120. JPanel panelB = new JPanel();
  121. /**
  122. *addButtonToPanel(panelB, "Apply", new ActionListener() {
  123. * public void actionPerformed(ActionEvent a) {
  124. * table.setText(inputArea.getText());
  125. * // Refresh the input area in case the text
  126. * // was modified in the process of any
  127. * // last second formatting done prior to insertion
  128. * inputArea.setText(table.getText());
  129. * }
  130. *});
  131. *addButtonToPanel(panelB, "Revert", new ActionListener() {
  132. * public void actionPerformed(ActionEvent a) {
  133. * inputArea.setText(table.getText());
  134. * }
  135. *});
  136. */
  137.  
  138. addButtonToPanel(panelB, "Dump...", new ActionListener() {
  139. public void actionPerformed(ActionEvent a) {
  140. dump();
  141. }
  142. });
  143. addButtonToPanel(panelB, "Insert...", new ActionListener() {
  144. public void actionPerformed(ActionEvent a) {
  145. insert();
  146. }
  147. });
  148. addButtonToPanel(panelB, "Quit", new ActionListener() {
  149. public void actionPerformed(ActionEvent a) {
  150. quit();
  151. }
  152. });
  153. panelB.setMaximumSize(panelB.getPreferredSize());
  154. add(panelB);
  155.  
  156. setMinimumSize(getSize());
  157. }
  158.  
  159. @Override
  160. public void setup(Game game) {
  161. table = game.textArray();
  162. // The TablePanel will call back to refresh().
  163. tablePanel.setTable(table);
  164. }
  165.  
  166. /* Hextator sez: This override is redundant and unsafe
  167. @Override
  168. public void cleanup() {
  169. tablePanel.setTable(null); // so it can be GC'd
  170. }
  171. */
  172.  
  173. @Override
  174. public void refresh() {
  175. //Camtech - I'm desperately hoping that this works the way I think it
  176. //does; that is, I'm hoping it reads the 'input index' during the call
  177. //to "getText", rather than for each spinner change.
  178. applyChanges();
  179. inputArea.setText(table.getText());
  180. }
  181.  
  182. private void find(final String toFind, final boolean forward) {
  183. if (toFind.equals("")) {
  184. java.awt.Toolkit.getDefaultToolkit().beep();
  185. return;
  186. }
  187.  
  188. final boolean useRegularExpressions = regExChkBox.isSelected();
  189.  
  190. class Finder extends ProcessComponent {
  191. public String found = null;
  192. public boolean regExError = false;
  193.  
  194. public Finder(int iterations, int weight, String description) {
  195. super(iterations, weight, description);
  196. }
  197.  
  198. protected boolean iterate(int i) {
  199. //System.out.println(Util.verboseReport("find iteration"));
  200. String entry = table.getText();
  201. boolean foundMatch;
  202. if (!useRegularExpressions)
  203. foundMatch = entry.indexOf(toFind) != -1;
  204. else {
  205. try {
  206. String[] temp = entry.split(toFind);
  207. foundMatch =
  208. temp != null
  209. && (
  210. temp.length > 1
  211. || temp.length == 0
  212. )
  213. ;
  214. } catch (Exception e) {
  215. regExError = true;
  216. return true;
  217. }
  218. }
  219. if (entry != null && foundMatch) {
  220. found = entry;
  221. return true;
  222. }
  223.  
  224. if (forward) { table.next(); }
  225. else { table.prev(); }
  226. return false;
  227. }
  228. }
  229.  
  230. final Finder f = new Finder(
  231. table.getCurrentSize(), 1, "Searching for text..."
  232. );
  233.  
  234. view.process(
  235. false, // don't show dialogs
  236. new Process(true, f) { // can cancel
  237. @Override
  238. public void finish() {
  239. if (f.found == null) {
  240. if (!f.regExError)
  241. CommonDialogs.showGenericErrorDialog(
  242. "String not found!"
  243. );
  244. else
  245. CommonDialogs.showGenericErrorDialog(
  246. "It seems your regular expression is invalid."
  247. );
  248. } else {
  249. // Synchronize the spinner with the position that was moved to
  250. // behind the scenes.
  251. tablePanel.setIndex(table.getPosition());
  252. // In turn, the tablePanel will call refresh().
  253. }
  254. }
  255. }
  256. );
  257. }
  258.  
  259. class PositionRestoringProcess extends Process {
  260. private int originalPosition;
  261. public PositionRestoringProcess(ProcessComponent component) {
  262. super(false, component); // can't cancel
  263. originalPosition = tablePanel.getIndex();
  264. }
  265.  
  266. @Override
  267. public void finish() {
  268. // The spinner hasn't changed, but the table position needs to be
  269. // reset, and text should be updated to match.
  270. tablePanel.setIndex(originalPosition);
  271. }
  272. }
  273.  
  274. private void replaceAll(final String toFind, final String replaceWith) {
  275. if (toFind.equals("")) {
  276. java.awt.Toolkit.getDefaultToolkit().beep();
  277. return;
  278. }
  279.  
  280. final boolean useRegularExpressions = regExChkBox.isSelected();
  281.  
  282. view.process(
  283. true, // show dialogs
  284. new PositionRestoringProcess(
  285. new ProcessComponent(
  286. table.getCurrentSize(), 1, "Replacing occurrences of text..."
  287. ) {
  288. protected boolean iterate(int i) {
  289. if (i == 0) { return false; }
  290. table.moveTo(i);
  291. String text = table.getText();
  292. if (text != null) {
  293. if (!useRegularExpressions)
  294. table.setText(text.replace(toFind, replaceWith));
  295. else
  296. table.setText(text.replaceAll(toFind, replaceWith));
  297. }
  298. return false;
  299. }
  300. }
  301. )
  302. );
  303. }
  304.  
  305. @Override
  306. public void applyChanges() { table.setText(inputArea.getText()); }
  307. //Camtech - I'm mostly doing things in the safest way I can think of,
  308. //as I don't understand half of this stuff anyway. And still, I'm sure
  309. //I fucked something up somewhere or other.
  310.  
  311. private void dump() {
  312. final FileWriter scriptToDump;
  313. File selectedFile = CommonDialogs.showSaveFileDialog("script dump");
  314. if (selectedFile == null) { return; }
  315.  
  316. try { scriptToDump = new FileWriter(selectedFile); }
  317. catch (Exception e) {
  318. CommonDialogs.showStreamErrorDialog();
  319. return;
  320. }
  321.  
  322. int size = table.getCurrentSize();
  323. view.process(
  324. true, // show dialogs
  325. new PositionRestoringProcess(
  326. new ProcessComponent(size, 1, "Dumping script...") {
  327. protected boolean iterate(int i) {
  328. if (i == 0) { return false; }
  329. table.moveTo(i);
  330. String text = table.getText();
  331. if (text != null) { // should be impossible for text to be null?
  332. try {
  333. scriptToDump.write(String.format(
  334. "Text of ID 0x%04X\n%s\n\n",
  335. i, table.getText()
  336. ).replaceAll("\\n", Util.newline));
  337. } catch (Exception e) {}
  338. }
  339. return false;
  340. }
  341.  
  342. @Override
  343. protected void cleanup() {
  344. try { scriptToDump.close(); }
  345. catch (Exception e) {}
  346. }
  347. }
  348. )
  349. );
  350. }
  351.  
  352. private void insert() {
  353. final Scanner scriptToInsert;
  354. File fileSelected = CommonDialogs.showOpenFileDialog("script dump");
  355. if (fileSelected == null) { return; }
  356.  
  357. try { scriptToInsert = new Scanner(fileSelected); }
  358. catch (Exception e) {
  359. CommonDialogs.showStreamErrorDialog();
  360. return;
  361. }
  362.  
  363. //int writeIndex;
  364. //String indexLine;
  365.  
  366. view.process(
  367. true, // show dialogs
  368. new PositionRestoringProcess(
  369. // We don't know how many iterations there will be, so we set up
  370. // an indeterminate process step and do the loop manually.
  371. new ProcessComponent(1, 0, "Reading script...") {
  372. protected boolean iterate(int i) {
  373. int index = 1;
  374. while (writeEntry(index++, scriptToInsert)) {}
  375. return false;
  376. }
  377.  
  378. @Override
  379. protected void cleanup() {
  380. try { scriptToInsert.close(); }
  381. catch (Exception e) {}
  382. }
  383. }
  384. )
  385. );
  386. }
  387.  
  388. // Return false when we run out of data.
  389. @SuppressWarnings("empty-statement")
  390. private boolean writeEntry(int index, Scanner source) {
  391. String indexLine = "";
  392. while (indexLine.equals("")) {
  393. if (!source.hasNextLine()) { return false; }
  394. indexLine = source.nextLine();
  395. };
  396.  
  397. try {
  398. index = Util.parseInt(
  399. indexLine.substring(indexLine.lastIndexOf(" "))
  400. ) & 0xFFFF;
  401. } catch (Exception e) { /* Use the default counter value. */ }
  402.  
  403. String outString = "";
  404. String line;
  405. do {
  406. if (!source.hasNextLine()) { return false; }
  407. line = source.nextLine();
  408. outString += line + "\n";
  409. } while (!line.endsWith("[X]"));
  410. outString = outString.trim();
  411. table.moveTo(index);
  412. table.setText(outString);
  413. return true;
  414. }
  415. }
  416.  
  417.  
Advertisement
Add Comment
Please, Sign In to add comment