diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java
index ad1ae3204..9900c433d 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java
@@ -442,6 +442,7 @@ public class Timeline {
Tag t = tags.get(i);
if (t instanceof CharacterIdTag && ((CharacterIdTag) t).getCharacterId() == oldCharacterId) {
((CharacterIdTag) t).setCharacterId(newCharacterId);
+ ((Tag) t).setModified(true);
modified = true;
}
}
diff --git a/src/com/jpexs/decompiler/flash/gui/AppDialog.java b/src/com/jpexs/decompiler/flash/gui/AppDialog.java
index 7f6496993..19b979e13 100644
--- a/src/com/jpexs/decompiler/flash/gui/AppDialog.java
+++ b/src/com/jpexs/decompiler/flash/gui/AppDialog.java
@@ -28,6 +28,12 @@ import javax.swing.JRootPane;
*/
public abstract class AppDialog extends JDialog {
+ public static final int ERROR_OPTION = -1;
+
+ public static final int OK_OPTION = 0;
+
+ public static final int CANCEL_OPTION = 1;
+
private ResourceBundle resourceBundle = ResourceBundle.getBundle(AppStrings.getResourcePath(getClass()));
public AppDialog() {
diff --git a/src/com/jpexs/decompiler/flash/gui/ComboBoxItem.java b/src/com/jpexs/decompiler/flash/gui/ComboBoxItem.java
new file mode 100644
index 000000000..618c0210f
--- /dev/null
+++ b/src/com/jpexs/decompiler/flash/gui/ComboBoxItem.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010-2015 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;
+
+/**
+ *
+ * @author JPEXS
+ */
+public class ComboBoxItem {
+
+ private String title;
+
+ private E value;
+
+ public ComboBoxItem(String title, E value) {
+ this.title = title;
+ this.value = value;
+ }
+
+ public E getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return title;
+ }
+}
diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java
index e1b22ebb4..db54b0f44 100644
--- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java
+++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java
@@ -1966,8 +1966,9 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
return;
}
if (confirmExperimental()) {
- final RenameType renameType = new RenameDialog().display();
- if (renameType != null) {
+ RenameDialog renameDialog = new RenameDialog();
+ if (renameDialog.showRenameDialog() == AppDialog.OK_OPTION) {
+ final RenameType renameType = renameDialog.getRenameType();
Main.startWork(translate("work.renaming.identifiers") + "...");
new CancellableWorker() {
@Override
@@ -2686,14 +2687,13 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
previewPanel.setImageReplaceButtonVisible(false);
/*if (treeItem instanceof Tag) {
- Tag tag = (Tag) treeItem;
- Set needed = new HashSet<>();
- tag.getNeededCharactersDeep(needed);
- String neededStr = Helper.joinStrings(needed, ", ");
- // todo: it would be usefule to show this information on the UI
- System.out.println("Needed characters: " + neededStr);
- }*/
-
+ Tag tag = (Tag) treeItem;
+ Set needed = new HashSet<>();
+ tag.getNeededCharactersDeep(needed);
+ String neededStr = Helper.joinStrings(needed, ", ");
+ // todo: it would be usefule to show this information on the UI
+ System.out.println("Needed characters: " + neededStr);
+ }*/
boolean internalViewer = isInternalFlashViewerSelected();
if (treeItem instanceof HeaderItem) {
diff --git a/src/com/jpexs/decompiler/flash/gui/RenameDialog.java b/src/com/jpexs/decompiler/flash/gui/RenameDialog.java
index 3c1d4ba1e..6fb8204b9 100644
--- a/src/com/jpexs/decompiler/flash/gui/RenameDialog.java
+++ b/src/com/jpexs/decompiler/flash/gui/RenameDialog.java
@@ -21,7 +21,6 @@ import com.jpexs.decompiler.flash.configuration.Configuration;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
@@ -34,11 +33,7 @@ import javax.swing.JRadioButton;
*
* @author JPEXS
*/
-public class RenameDialog extends AppDialog implements ActionListener {
-
- private static final String ACTION_OK = "OK";
-
- private static final String ACTION_CANCEL = "CANCEL";
+public class RenameDialog extends AppDialog {
private final JRadioButton typeNumberRadioButton = new JRadioButton(translate("rename.type.typenumber"));
@@ -48,17 +43,7 @@ public class RenameDialog extends AppDialog implements ActionListener {
private final JButton cancelButton = new JButton(translate("button.cancel"));
- private boolean confirmed = false;
-
- public RenameType getRenameType() {
- if (!isConfirmed()) {
- return null;
- }
- if (typeNumberRadioButton.isSelected()) {
- return RenameType.TYPENUMBER;
- }
- return RenameType.RANDOMWORD;
- }
+ private int result = ERROR_OPTION;
public RenameDialog() {
setSize(300, 150);
@@ -76,14 +61,15 @@ public class RenameDialog extends AppDialog implements ActionListener {
setLayout(new BorderLayout());
add(new JLabel(translate("rename.type")), BorderLayout.NORTH);
add(pan, BorderLayout.CENTER);
+
JPanel panButtons = new JPanel(new FlowLayout());
+ okButton.addActionListener(this::okButtonActionPerformed);
+ cancelButton.addActionListener(this::cancelButtonActionPerformed);
panButtons.add(okButton);
- okButton.setActionCommand(ACTION_OK);
- okButton.addActionListener(this);
panButtons.add(cancelButton);
- cancelButton.setActionCommand(ACTION_CANCEL);
- cancelButton.addActionListener(this);
+
add(panButtons, BorderLayout.SOUTH);
+
setModalityType(ModalityType.APPLICATION_MODAL);
View.setWindowIcon(this);
setTitle(translate("dialog.title"));
@@ -95,32 +81,37 @@ public class RenameDialog extends AppDialog implements ActionListener {
@Override
public void setVisible(boolean b) {
if (b) {
- confirmed = false;
+ result = ERROR_OPTION;
}
+
super.setVisible(b);
}
- @Override
- public void actionPerformed(ActionEvent e) {
- switch (e.getActionCommand()) {
- case ACTION_OK:
- confirmed = true;
- Configuration.lastRenameType.set((Integer) (getRenameType() == RenameType.TYPENUMBER ? 1 : 2));
- setVisible(false);
- break;
- case ACTION_CANCEL:
- confirmed = false;
- setVisible(false);
- break;
+ private void okButtonActionPerformed(ActionEvent evt) {
+ result = OK_OPTION;
+ Configuration.lastRenameType.set((Integer) (getRenameType() == RenameType.TYPENUMBER ? 1 : 2));
+ setVisible(false);
+ }
+
+ private void cancelButtonActionPerformed(ActionEvent evt) {
+ result = CANCEL_OPTION;
+ setVisible(false);
+ }
+
+ public RenameType getRenameType() {
+ if (result == ERROR_OPTION) {
+ return null;
}
+
+ if (typeNumberRadioButton.isSelected()) {
+ return RenameType.TYPENUMBER;
+ }
+
+ return RenameType.RANDOMWORD;
}
- public boolean isConfirmed() {
- return confirmed;
- }
-
- public RenameType display() {
+ public int showRenameDialog() {
setVisible(true);
- return getRenameType();
+ return result;
}
}
diff --git a/src/com/jpexs/decompiler/flash/gui/ReplaceCharacterDialog.java b/src/com/jpexs/decompiler/flash/gui/ReplaceCharacterDialog.java
new file mode 100644
index 000000000..32ca5f6b3
--- /dev/null
+++ b/src/com/jpexs/decompiler/flash/gui/ReplaceCharacterDialog.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2010-2015 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 com.jpexs.decompiler.flash.SWF;
+import static com.jpexs.decompiler.flash.gui.AppDialog.ERROR_OPTION;
+import com.jpexs.decompiler.flash.tags.base.CharacterTag;
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.util.Map;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+/**
+ *
+ * @author JPEXS
+ */
+public class ReplaceCharacterDialog extends AppDialog {
+
+ private final JButton okButton = new JButton(translate("button.ok"));
+
+ private final JButton cancelButton = new JButton(translate("button.cancel"));
+
+ private final JComboBox> charactersComboBox = new JComboBox<>();
+
+ private int result = ERROR_OPTION;
+
+ public ReplaceCharacterDialog() {
+ setSize(400, 150);
+ setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
+ setLayout(new BorderLayout());
+ add(new JLabel(translate("replace.width")), BorderLayout.NORTH);
+
+ charactersComboBox.setPreferredSize(new Dimension(400, charactersComboBox.getPreferredSize().height));
+ add(charactersComboBox, BorderLayout.CENTER);
+
+ JPanel panButtons = new JPanel(new FlowLayout());
+ okButton.addActionListener(this::okButtonActionPerformed);
+ cancelButton.addActionListener(this::cancelButtonActionPerformed);
+ panButtons.add(okButton);
+ panButtons.add(cancelButton);
+
+ add(panButtons, BorderLayout.SOUTH);
+
+ setModalityType(ModalityType.APPLICATION_MODAL);
+ View.setWindowIcon(this);
+ setTitle(translate("dialog.title"));
+ getRootPane().setDefaultButton(okButton);
+ pack();
+ View.centerScreen(this);
+ }
+
+ private void okButtonActionPerformed(ActionEvent evt) {
+ result = OK_OPTION;
+ setVisible(false);
+ }
+
+ private void cancelButtonActionPerformed(ActionEvent evt) {
+ result = CANCEL_OPTION;
+ setVisible(false);
+ }
+
+ public Integer getCharacterId() {
+ if (result == ERROR_OPTION) {
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ ComboBoxItem item = (ComboBoxItem) charactersComboBox.getSelectedItem();
+ return item.getValue();
+ }
+
+ public int showDialog(SWF swf, int selectedCharacterId) {
+ Map characters = swf.getCharacters();
+ for (Integer key : characters.keySet()) {
+ CharacterTag character = characters.get(key);
+ int characterId = character.getCharacterId();
+ if (characterId != selectedCharacterId) {
+ charactersComboBox.addItem(new ComboBoxItem<>(character.getName(), characterId));
+ }
+ }
+
+ setVisible(true);
+ return result;
+ }
+}
diff --git a/src/com/jpexs/decompiler/flash/gui/helpers/CheckResources.java b/src/com/jpexs/decompiler/flash/gui/helpers/CheckResources.java
index 43c853a0a..afce68a58 100644
--- a/src/com/jpexs/decompiler/flash/gui/helpers/CheckResources.java
+++ b/src/com/jpexs/decompiler/flash/gui/helpers/CheckResources.java
@@ -31,6 +31,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.ReplaceCharacterDialog;
import com.jpexs.decompiler.flash.gui.ReplaceTraceDialog;
import com.jpexs.decompiler.flash.gui.SearchDialog;
import com.jpexs.decompiler.flash.gui.SearchResultsDialog;
@@ -73,6 +74,7 @@ public class CheckResources {
ModeFrame.class,
NewVersionDialog.class,
RenameDialog.class,
+ ReplaceCharacterDialog.class,
ReplaceTraceDialog.class,
SearchDialog.class,
SearchResultsDialog.class,
diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties
index 61ca4db19..3bfa3e4d3 100644
--- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties
+++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties
@@ -582,3 +582,4 @@ text.toggleCase = Toggle case
preview.loop = Loop
menu.file.import.script = Import script
contextmenu.copyTagWithDependencies = Copy tag with dependencies to
+button.replaceWithTag = Replace with other character tag
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 75709f475..cf9157f80 100644
--- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties
+++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties
@@ -581,3 +581,4 @@ text.toggleCase = Kis- nagybet\u0171 v\u00e1ltoztat\u00e1s
preview.loop = Ism\u00e9tl\u00e9s
menu.file.import.script = Szkript import\u00e1l\u00e1sa
contextmenu.copyTagWithDependencies = M\u00e1sol\u00e1s ide f\u00fcgg\u0151s\u00e9gekkel
+button.replaceWithTag = Csere m\u00e1sik karakter tagre
diff --git a/src/com/jpexs/decompiler/flash/gui/locales/ReplaceCharacterDialog.properties b/src/com/jpexs/decompiler/flash/gui/locales/ReplaceCharacterDialog.properties
new file mode 100644
index 000000000..450c09291
--- /dev/null
+++ b/src/com/jpexs/decompiler/flash/gui/locales/ReplaceCharacterDialog.properties
@@ -0,0 +1,20 @@
+# Copyright (C) 2010-2015 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 .
+
+dialog.title = Replace character tag
+replace.width = Replace with:
+
+button.ok = OK
+button.cancel = Cancel
diff --git a/src/com/jpexs/decompiler/flash/gui/locales/ReplaceCharacterDialog_hu.properties b/src/com/jpexs/decompiler/flash/gui/locales/ReplaceCharacterDialog_hu.properties
new file mode 100644
index 000000000..e072a83a3
--- /dev/null
+++ b/src/com/jpexs/decompiler/flash/gui/locales/ReplaceCharacterDialog_hu.properties
@@ -0,0 +1,20 @@
+# Copyright (C) 2010-2015 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 .
+
+dialog.title = Karakter tag cser\u00e9je
+replace.width = Csere a k\u00f6vetkez\u0151vel:
+
+button.ok = OK
+button.cancel = M\u00e9gse
diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java
index 41ab0e4fe..4d12328a3 100644
--- a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java
+++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java
@@ -17,9 +17,11 @@
package com.jpexs.decompiler.flash.gui.tagtree;
import com.jpexs.decompiler.flash.SWF;
+import com.jpexs.decompiler.flash.gui.AppDialog;
import com.jpexs.decompiler.flash.gui.Main;
import com.jpexs.decompiler.flash.gui.MainFrameRibbonMenu;
import com.jpexs.decompiler.flash.gui.MainPanel;
+import com.jpexs.decompiler.flash.gui.ReplaceCharacterDialog;
import com.jpexs.decompiler.flash.gui.View;
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
import com.jpexs.decompiler.flash.tags.DefineSoundTag;
@@ -83,6 +85,8 @@ public class TagTreeContextMenu extends JPopupMenu {
private JMenuItem replaceMenuItem;
+ private JMenuItem replaceWithTagMenuItem;
+
private JMenuItem rawEditMenuItem;
private JMenuItem jumpToCharacterMenuItem;
@@ -138,14 +142,16 @@ public class TagTreeContextMenu extends JPopupMenu {
replaceMenuItem.addActionListener(mainPanel);
add(replaceMenuItem);
+ replaceWithTagMenuItem = new JMenuItem(mainPanel.translate("button.replaceWithTag"));
+ replaceWithTagMenuItem.addActionListener(this::replaceWithTagActionPerformed);
+ add(replaceWithTagMenuItem);
+
rawEditMenuItem = new JMenuItem(mainPanel.translate("contextmenu.rawEdit"));
rawEditMenuItem.addActionListener(this::rawEditActionPerformed);
- rawEditMenuItem.setVisible(false);
add(rawEditMenuItem);
jumpToCharacterMenuItem = new JMenuItem(mainPanel.translate("contextmenu.jumpToCharacter"));
jumpToCharacterMenuItem.addActionListener(this::jumpToCharacterActionPerformed);
- jumpToCharacterMenuItem.setVisible(false);
add(jumpToCharacterMenuItem);
exportJavaSourceMenuItem = new JMenuItem(mainPanel.translate("contextmenu.exportJavaSource"));
@@ -295,6 +301,7 @@ public class TagTreeContextMenu extends JPopupMenu {
undoTagMenuItem.setVisible(allSelectedIsTag);
exportSelectionMenuItem.setEnabled(tagTree.hasExportableNodes());
replaceMenuItem.setVisible(false);
+ replaceWithTagMenuItem.setVisible(false);
rawEditMenuItem.setVisible(false);
jumpToCharacterMenuItem.setVisible(false);
exportJavaSourceMenuItem.setVisible(allSelectedIsSwf);
@@ -312,6 +319,10 @@ public class TagTreeContextMenu extends JPopupMenu {
if (singleSelect) {
final TreeItem firstItem = items.get(0);
+ if (firstItem instanceof CharacterTag) {
+ replaceWithTagMenuItem.setVisible(true);
+ }
+
// replace
if (firstItem instanceof ImageTag && ((ImageTag) firstItem).importSupported()) {
replaceMenuItem.setVisible(true);
@@ -452,10 +463,10 @@ public class TagTreeContextMenu extends JPopupMenu {
logger.log(Level.WARNING, "Target SWF already contained chatacter tag with id = {0} => id changed to {1}", new Object[]{characterId, newCharacterId});
return newCharacterId;
}
-
+
return characterId;
}
-
+
return -1;
}
@@ -523,7 +534,7 @@ public class TagTreeContextMenu extends JPopupMenu {
for (Integer characterId : needed) {
neededList.add(characterId);
}
-
+
// first add dependencies in reverse order
for (int i = neededList.size() - 1; i >= 0; i--) {
int characterId = neededList.get(i);
@@ -556,7 +567,7 @@ public class TagTreeContextMenu extends JPopupMenu {
int newCharacterId = chechUniqueCharacterId(copyTag);
changedCharacterIds.put(oldCharacterId, newCharacterId);
}
-
+
targetSwf.updateCharacters();
targetSwf.getCharacters(); // force rebuild character id cache
copyTag.setModified(true);
@@ -595,6 +606,32 @@ public class TagTreeContextMenu extends JPopupMenu {
mainPanel.loadFromBinaryTag(binaryDatas);
}
+ private void replaceWithTagActionPerformed(ActionEvent evt) {
+ TreeItem itemr = tagTree.getCurrentTreeItem();
+ if (itemr == null) {
+ return;
+ }
+
+ SWF swf = itemr.getSwf();
+ CharacterTag characterTag = (CharacterTag) itemr;
+ int characterId = characterTag.getCharacterId();
+ ReplaceCharacterDialog replaceCharacterDialog = new ReplaceCharacterDialog();
+ if (replaceCharacterDialog.showDialog(swf, characterId) == AppDialog.OK_OPTION) {
+ int newCharacterId = replaceCharacterDialog.getCharacterId();
+ CharacterTag newCharacter = swf.getCharacter(newCharacterId);
+ newCharacter.setCharacterId(characterId);
+ characterTag.setCharacterId(newCharacterId);
+ newCharacter.setModified(true);
+ characterTag.setModified(true);
+
+ swf.assignExportNamesToSymbols();
+ swf.assignClassesToSymbols();
+ swf.clearImageCache();
+ swf.updateCharacters();
+ mainPanel.refreshTree(swf);
+ }
+ }
+
private void rawEditActionPerformed(ActionEvent evt) {
TreeItem itemr = tagTree.getCurrentTreeItem();
if (itemr == null) {