diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java b/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java index f576ba33f..9b0b600f3 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java @@ -155,9 +155,18 @@ public abstract class MainFrameMenu { mainFrame.getPanel().exportFla(swf); } - protected boolean search(boolean searhInText) { + protected boolean search(boolean searchInText) { if (swf != null) { - mainFrame.getPanel().searchInActionScriptOrText(searhInText); + mainFrame.getPanel().searchInActionScriptOrText(searchInText); + return true; + } + + return false; + } + + protected boolean replace() { + if (swf != null) { + mainFrame.getPanel().replaceText(); return true; } diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java index 571fb1548..bb161d5c5 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java @@ -74,6 +74,7 @@ public class MainFrameRibbonMenu extends MainFrameMenu implements ActionListener private static final String ACTION_PARALLEL_SPEED_UP = "PARALLELSPEEDUP"; private static final String ACTION_INTERNAL_VIEWER_SWITCH = "INTERNALVIEWERSWITCH"; private static final String ACTION_SEARCH = "SEARCH"; + private static final String ACTION_REPLACE = "REPLACE"; private static final String ACTION_TIMELINE = "TIMELINE"; private static final String ACTION_AUTO_DEOBFUSCATE = "AUTODEOBFUSCATE"; private static final String ACTION_EXIT = "EXIT"; @@ -139,6 +140,7 @@ public class MainFrameRibbonMenu extends MainFrameMenu implements ActionListener private JCommandButton globalRenameCommandButton; private JCommandButton deobfuscationCommandButton; private JCommandButton searchCommandButton; + private JCommandButton replaceCommandButton; private JCommandToggleButton timeLineToggleButton; private CommandToggleButtonGroup timeLineToggleGroup; private JCommandButton gotoDocumentClassCommandButton; @@ -404,6 +406,10 @@ public class MainFrameRibbonMenu extends MainFrameMenu implements ActionListener searchCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.search")), View.getResizableIcon("search32")); assignListener(searchCommandButton, ACTION_SEARCH); + // todo: change icon + replaceCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.replace")), View.getResizableIcon("replace32")); + assignListener(replaceCommandButton, ACTION_REPLACE); + timeLineToggleButton = new JCommandToggleButton(fixCommandTitle(translate("menu.tools.timeline")), View.getResizableIcon("timeline32")); assignListener(timeLineToggleButton, ACTION_TIMELINE); @@ -423,6 +429,7 @@ public class MainFrameRibbonMenu extends MainFrameMenu implements ActionListener assignListener(loadCacheCommandButton, ACTION_LOAD_CACHE); toolsBand.addCommandButton(searchCommandButton, RibbonElementPriority.TOP); + toolsBand.addCommandButton(replaceCommandButton, RibbonElementPriority.TOP); toolsBand.addCommandButton(timeLineToggleButton, RibbonElementPriority.TOP); toolsBand.addCommandButton(gotoDocumentClassCommandButton, RibbonElementPriority.TOP); toolsBand.addCommandButton(proxyCommandButton, RibbonElementPriority.MEDIUM); @@ -630,6 +637,7 @@ public class MainFrameRibbonMenu extends MainFrameMenu implements ActionListener globalRenameCommandButton.setEnabled(swfLoaded); deobfuscationCommandButton.setEnabled(swfLoaded); searchCommandButton.setEnabled(swfLoaded); + replaceCommandButton.setEnabled(swfLoaded); timeLineToggleButton.setEnabled(swfLoaded); gotoDocumentClassCommandButton.setEnabled(hasAbc); @@ -759,6 +767,9 @@ public class MainFrameRibbonMenu extends MainFrameMenu implements ActionListener case ACTION_SEARCH: search(false); break; + case ACTION_REPLACE: + replace(); + break; case ACTION_TIMELINE: timeLineToggleGroup.setSelected(timeLineToggleButton, timeLineToggleGroup.getSelected() == timeLineToggleButton); if (timeLineToggleGroup.getSelected() == timeLineToggleButton) { diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index a41dc532e..b82dc45da 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -233,6 +233,8 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec private AbortRetryIgnoreHandler errorHandler = new GuiAbortRetryIgnoreHandler(); private CancellableWorker setSourceWorker; public TreeItem oldItem; + private SearchDialog searchDialog; + private SearchDialog replaceDialog; public static final String ACTION_SELECT_BKCOLOR = "SELECTCOLOR"; public static final String ACTION_REPLACE = "REPLACE"; @@ -858,7 +860,6 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec public boolean confirmExperimental() { return View.showConfirmDialog(null, translate("message.confirm.experimental"), translate("message.warning"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.OK_OPTION; } - private SearchDialog searchDialog; public List exportSelection(AbortRetryIgnoreHandler handler, String selFile, ExportDialog export) throws IOException { @@ -1102,12 +1103,12 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec } } - public void searchInActionScriptOrText(boolean searhInText) { + public void searchInActionScriptOrText(boolean searchInText) { if (searchDialog == null) { - searchDialog = new SearchDialog(getMainFrame().getWindow()); + searchDialog = new SearchDialog(getMainFrame().getWindow(), false); } - if (searhInText) { + if (searchInText) { searchDialog.searchInTextsRadioButton.setSelected(true); } else { searchDialog.searchInASRadioButton.setSelected(true); @@ -1163,6 +1164,36 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec } } + public void replaceText() { + if (replaceDialog == null) { + replaceDialog = new SearchDialog(getMainFrame().getWindow(), true); + } + + replaceDialog.setVisible(true); + if (replaceDialog.result) { + final String txt = replaceDialog.searchField.getText(); + if (!txt.isEmpty()) { + final SWF swf = getCurrentSwf(); + + new CancellableWorker() { + @Override + protected Void doInBackground() throws Exception { + boolean found = false; + if (searchText(txt, replaceDialog.ignoreCaseCheckBox.isSelected(), replaceDialog.regexpCheckBox.isSelected(), swf)) { + found = true; + } + + if (!found) { + View.showMessageDialog(null, translate("message.search.notfound").replace("%searchtext%", txt), translate("message.search.notfound.title"), JOptionPane.INFORMATION_MESSAGE); + } + + return null; + } + }.execute(); + } + } + } + private boolean searchText(String txt, boolean ignoreCase, boolean regexp, SWF swf) { if ((txt != null) && (!txt.isEmpty())) { SearchPanel textSearchPanel = previewPanel.getTextPanel().getSearchPanel(); diff --git a/src/com/jpexs/decompiler/flash/gui/NewVersionDialog.java b/src/com/jpexs/decompiler/flash/gui/NewVersionDialog.java index 39fbc7720..9e05a899d 100644 --- a/src/com/jpexs/decompiler/flash/gui/NewVersionDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/NewVersionDialog.java @@ -140,7 +140,7 @@ public class NewVersionDialog extends AppDialog implements ActionListener { @Override public void actionPerformed(ActionEvent e) { - if (e.getActionCommand() == ACTION_OK) { + if (e.getActionCommand().equals(ACTION_OK)) { String url; if (latestVersion.updateLink != null) { url = latestVersion.updateLink; diff --git a/src/com/jpexs/decompiler/flash/gui/ReplaceDialog.java b/src/com/jpexs/decompiler/flash/gui/ReplaceDialog.java new file mode 100644 index 000000000..5809856f6 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/gui/ReplaceDialog.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.gui; + +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Image; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; +import javax.swing.BoxLayout; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JTextField; + +/** + * + * @author JPEXS + */ +public class ReplaceDialog extends AppDialog implements ActionListener { + + private static final String ACTION_OK = "OK"; + private static final String ACTION_CANCEL = "CANCEL"; + + public JTextField searchField = new MyTextField(); + public JCheckBox ignoreCaseCheckBox = new JCheckBox(translate("checkbox.ignorecase")); + //public JCheckBox regexpCheckBox = new JCheckBox(translate("checkbox.regexp")); + public boolean result = false; + + public ReplaceDialog(Window owner) { + super(owner); + setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE); + ignoreCaseCheckBox.setSelected(true); + Container cnt = getContentPane(); + setSize(400, 150); + cnt.setLayout(new BoxLayout(cnt, BoxLayout.PAGE_AXIS)); + JPanel panButtons = new JPanel(new FlowLayout()); + JButton okButton = new JButton(translate("button.ok")); + okButton.setActionCommand(ACTION_OK); + okButton.addActionListener(this); + JButton cancelButton = new JButton(translate("button.cancel")); + cancelButton.setActionCommand(ACTION_CANCEL); + cancelButton.addActionListener(this); + panButtons.add(okButton); + panButtons.add(cancelButton); + JPanel panField = new JPanel(new FlowLayout()); + searchField.setPreferredSize(new Dimension(250, searchField.getPreferredSize().height)); + panField.add(new JLabel(translate("label.searchtext"))); + panField.add(searchField); + cnt.add(panField); + + JPanel checkPanel = new JPanel(new FlowLayout()); + checkPanel.add(ignoreCaseCheckBox); + //checkPanel.add(regexpCheckBox); + cnt.add(checkPanel); + + cnt.add(panButtons); + getRootPane().setDefaultButton(okButton); + View.centerScreen(this); + //View.setWindowIcon(this); + setIconImage(View.loadImage("search16")); + setTitle(translate("dialog.title")); + setModalityType(ModalityType.APPLICATION_MODAL); + pack(); + List images = new ArrayList<>(); + images.add(View.loadImage("search16")); + images.add(View.loadImage("search32")); + setIconImages(images); + } + + @Override + public void setVisible(boolean b) { + if (b) { + result = false; + searchField.requestFocusInWindow(); + } + super.setVisible(b); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getActionCommand().equals(ACTION_OK)) { + /*if (regexpCheckBox.isSelected()) { + try { + Pattern pat = Pattern.compile(searchField.getText()); + } catch (PatternSyntaxException ex) { + View.showMessageDialog(null, translate("error.invalidregexp"), translate("error"), JOptionPane.ERROR_MESSAGE); + return; + } + }*/ + result = true; + } else { + result = false; + } + setVisible(false); + } +} diff --git a/src/com/jpexs/decompiler/flash/gui/SearchDialog.java b/src/com/jpexs/decompiler/flash/gui/SearchDialog.java index 26e18142d..87e5fab59 100644 --- a/src/com/jpexs/decompiler/flash/gui/SearchDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/SearchDialog.java @@ -48,13 +48,14 @@ public class SearchDialog extends AppDialog implements ActionListener { private static final String ACTION_CANCEL = "CANCEL"; public JTextField searchField = new MyTextField(); + public JTextField replaceField = new MyTextField(); public JCheckBox ignoreCaseCheckBox = new JCheckBox(translate("checkbox.ignorecase")); public JCheckBox regexpCheckBox = new JCheckBox(translate("checkbox.regexp")); public JRadioButton searchInASRadioButton = new JRadioButton(translate("checkbox.searchAS")); public JRadioButton searchInTextsRadioButton = new JRadioButton(translate("checkbox.searchText")); public boolean result = false; - public SearchDialog(Window owner) { + public SearchDialog(Window owner, boolean replace) { super(owner); setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE); ignoreCaseCheckBox.setSelected(true); @@ -75,34 +76,44 @@ public class SearchDialog extends AppDialog implements ActionListener { panField.add(new JLabel(translate("label.searchtext"))); panField.add(searchField); cnt.add(panField); + + if (replace) { + panField = new JPanel(new FlowLayout()); + replaceField.setPreferredSize(new Dimension(250, replaceField.getPreferredSize().height)); + panField.add(new JLabel(translate("label.replacementtext"))); + panField.add(replaceField); + cnt.add(panField); + } JPanel checkPanel = new JPanel(new FlowLayout()); checkPanel.add(ignoreCaseCheckBox); checkPanel.add(regexpCheckBox); cnt.add(checkPanel); - ButtonGroup group = new ButtonGroup(); - group.add(searchInASRadioButton); - group.add(searchInTextsRadioButton); + if (!replace) { + ButtonGroup group = new ButtonGroup(); + group.add(searchInASRadioButton); + group.add(searchInTextsRadioButton); - JPanel rbPanel = new JPanel(new FlowLayout()); - searchInASRadioButton.setSelected(true); - searchInTextsRadioButton.setSelected(false); - rbPanel.add(searchInASRadioButton); - rbPanel.add(searchInTextsRadioButton); - cnt.add(rbPanel); + JPanel rbPanel = new JPanel(new FlowLayout()); + searchInASRadioButton.setSelected(true); + searchInTextsRadioButton.setSelected(false); + rbPanel.add(searchInASRadioButton); + rbPanel.add(searchInTextsRadioButton); + cnt.add(rbPanel); + } cnt.add(panButtons); getRootPane().setDefaultButton(okButton); View.centerScreen(this); //View.setWindowIcon(this); - setIconImage(View.loadImage("search16")); - setTitle(translate("dialog.title")); + setIconImage(View.loadImage(replace ? "replace16" : "search16")); + setTitle(replace ? translate("dialog.title.replace") : translate("dialog.title")); setModalityType(ModalityType.APPLICATION_MODAL); pack(); List images = new ArrayList<>(); - images.add(View.loadImage("search16")); - images.add(View.loadImage("search32")); + images.add(View.loadImage(replace ? "replace16" : "search16")); + images.add(View.loadImage(replace ? "replace32" : "search32")); setIconImages(images); } @@ -117,7 +128,7 @@ public class SearchDialog extends AppDialog implements ActionListener { @Override public void actionPerformed(ActionEvent e) { - if (e.getActionCommand() == ACTION_OK) { + if (e.getActionCommand().equals(ACTION_OK)) { if (regexpCheckBox.isSelected()) { try { Pattern pat = Pattern.compile(searchField.getText()); diff --git a/src/com/jpexs/decompiler/flash/gui/abc/MethodCodePanel.java b/src/com/jpexs/decompiler/flash/gui/abc/MethodCodePanel.java index d6ff0f702..4f7f5c503 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/MethodCodePanel.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/MethodCodePanel.java @@ -140,7 +140,7 @@ public class MethodCodePanel extends JPanel implements ActionListener { break; case ACTION_HEX: case ACTION_HEX_ONLY: - if (e.getActionCommand() == ACTION_HEX) { + if (e.getActionCommand().equals(ACTION_HEX)) { hexOnlyButton.setSelected(false); } else { hexButton.setSelected(false); diff --git a/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java b/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java index fad374874..d582f1886 100644 --- a/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java @@ -726,7 +726,7 @@ public class ActionPanel extends JPanel implements ActionListener, SearchListene break; case ACTION_HEX: case ACTION_HEX_ONLY: - if (e.getActionCommand() == ACTION_HEX) { + if (e.getActionCommand().equals(ACTION_HEX)) { hexOnlyButton.setSelected(false); } else { hexButton.setSelected(false); diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/replace16.png b/src/com/jpexs/decompiler/flash/gui/graphics/replace16.png new file mode 100644 index 000000000..d2a99e558 Binary files /dev/null and b/src/com/jpexs/decompiler/flash/gui/graphics/replace16.png differ diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/replace32.png b/src/com/jpexs/decompiler/flash/gui/graphics/replace32.png new file mode 100644 index 000000000..5bdfcb1a9 Binary files /dev/null and b/src/com/jpexs/decompiler/flash/gui/graphics/replace32.png differ diff --git a/src/com/jpexs/decompiler/flash/gui/helpers/CheckResources.java b/src/com/jpexs/decompiler/flash/gui/helpers/CheckResources.java index 64f78c2d0..f0d179e29 100644 --- a/src/com/jpexs/decompiler/flash/gui/helpers/CheckResources.java +++ b/src/com/jpexs/decompiler/flash/gui/helpers/CheckResources.java @@ -30,6 +30,7 @@ import com.jpexs.decompiler.flash.gui.MainFrame; import com.jpexs.decompiler.flash.gui.ModeFrame; import com.jpexs.decompiler.flash.gui.NewVersionDialog; import com.jpexs.decompiler.flash.gui.RenameDialog; +import com.jpexs.decompiler.flash.gui.ReplaceDialog; import com.jpexs.decompiler.flash.gui.SearchDialog; import com.jpexs.decompiler.flash.gui.SearchResultsDialog; import com.jpexs.decompiler.flash.gui.SelectLanguageDialog; @@ -70,6 +71,7 @@ public class CheckResources { NewVersionDialog.class, RenameDialog.class, SearchDialog.class, + ReplaceDialog.class, SearchResultsDialog.class, SelectLanguageDialog.class, ProxyFrame.class, diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index dea2fddfb..3959ba114 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -543,3 +543,5 @@ error.text.invalid.continue = Invalid text: %text% on line %line%. Do you want t contextmenu.copyTag = Copy tag to fit = fit button.setAdvanceValues = Set advance values + +menu.tools.replace = Text Replace diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties index 8ce2c0981..980a4311e 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties @@ -543,3 +543,5 @@ error.text.invalid.continue = Hib\u00e1s sz\u00f6veg: %text% a %line%. sorban. F contextmenu.copyTag = M\u00e1sol\u00e1s ide fit = kit\u00f6lt button.setAdvanceValues = Halad\u00e1si \u00e9rt\u00e9kek be\u00e1ll\u00edt\u00e1sa + +menu.tools.replace = Sz\u00f6veg csere diff --git a/src/com/jpexs/decompiler/flash/gui/locales/SearchDialog.properties b/src/com/jpexs/decompiler/flash/gui/locales/SearchDialog.properties index b993c32db..fb24ab880 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/SearchDialog.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/SearchDialog.properties @@ -17,8 +17,10 @@ checkbox.regexp = Regular expression button.ok = OK button.cancel = Cancel label.searchtext = Search text: +label.replacementtext = Replacement text: #dialog.title = ActionScript search dialog.title = Text search +dialog.title.replace = Text replace error = Error error.invalidregexp = Invalid pattern diff --git a/src/com/jpexs/decompiler/flash/gui/locales/SearchDialog_hu.properties b/src/com/jpexs/decompiler/flash/gui/locales/SearchDialog_hu.properties index e9034ff4a..5cdad0348 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/SearchDialog_hu.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/SearchDialog_hu.properties @@ -17,8 +17,10 @@ checkbox.regexp = Regul\u00e1ris kifejez\u00e9s button.ok = OK button.cancel = M\u00e9gse label.searchtext = Keresett sz\u00f6veg: +label.replacementtext = Csere sz\u00f6veg: #dialog.title = ActionScript keres\u00e9s dialog.title = Sz\u00f6veg keres\u00e9s +dialog.title.replace = Sz\u00f6veg csere error = Hiba error.invalidregexp = \u00c9rv\u00e9nytelen minta