trunk contents moved to root

This commit is contained in:
Jindra Petřík
2014-05-10 20:50:57 +02:00
parent 1b851e66a8
commit 199a4d0c2b
2296 changed files with 0 additions and 0 deletions
@@ -0,0 +1,165 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.ApplicationInfo;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
/**
*
* @author JPEXS
*/
public class AboutDialog extends AppDialog {
private static final String[] CONTRIBUTORS = new String[]{
"Paolo Cancedda",
"Capasha",
"focus",
"honfika",
"Krock",
"Laurent LOUVET",
"MaGiC",
"pepka",
"poxyran",
"Rtsjx"};
private static final String AUTHOR = "JPEXS";
public AboutDialog() {
setDefaultCloseOperation(HIDE_ON_CLOSE);
setSize(new Dimension(300, 320));
setTitle(translate("dialog.title"));
Container cnt = getContentPane();
JPanel cp = new JPanel();
cp.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
cnt.setLayout(new BorderLayout());
cnt.add(cp, BorderLayout.CENTER);
cp.setLayout(new BoxLayout(cp, BoxLayout.Y_AXIS));
JPanel appNamePanel = new JPanel(new FlowLayout());
JLabel jpLabel = new JLabel("JPEXS");
jpLabel.setAlignmentX(0.5f);
jpLabel.setForeground(new Color(0, 0, 160));
jpLabel.setFont(new Font("Tahoma", Font.BOLD, 25));
jpLabel.setHorizontalAlignment(SwingConstants.CENTER);
appNamePanel.add(jpLabel);
JLabel ffLabel = new JLabel("Free Flash");
ffLabel.setAlignmentX(0.5f);
ffLabel.setFont(new Font("Tahoma", Font.BOLD, 25));
ffLabel.setHorizontalAlignment(SwingConstants.CENTER);
appNamePanel.add(ffLabel);
JLabel decLabel = new JLabel("Decompiler");
decLabel.setAlignmentX(0.5f);
decLabel.setForeground(Color.red);
decLabel.setFont(new Font("Tahoma", Font.BOLD, 25));
decLabel.setHorizontalAlignment(SwingConstants.CENTER);
appNamePanel.add(decLabel);
appNamePanel.setAlignmentX(0.5f);
cp.add(appNamePanel);
JLabel verLabel = new JLabel(translate("version") + " " + ApplicationInfo.version);
verLabel.setAlignmentX(0.5f);
//verLabel.setPreferredSize(new Dimension(300, 15));
verLabel.setFont(new Font("Tahoma", Font.BOLD, 15));
verLabel.setHorizontalAlignment(SwingConstants.CENTER);
cp.add(verLabel);
JLabel byLabel = new JLabel(translate("by"));
byLabel.setAlignmentX(0.5f);
byLabel.setHorizontalAlignment(SwingConstants.CENTER);
cp.add(byLabel);
JLabel authorLabel = new JLabel(AUTHOR);
authorLabel.setAlignmentX(0.5f);
authorLabel.setForeground(new Color(0, 0, 160));
authorLabel.setFont(new Font("Tahoma", Font.BOLD, 20));
//jpexsLabel.setPreferredSize(new Dimension(300, 25));
authorLabel.setHorizontalAlignment(SwingConstants.CENTER);
cp.add(authorLabel);
JLabel dateLabel = new JLabel("2010-2014");
dateLabel.setAlignmentX(0.5f);
//dateLabel.setPreferredSize(new Dimension(300, 10));
dateLabel.setHorizontalAlignment(SwingConstants.CENTER);
cp.add(dateLabel);
JLabel transAuthorLabel = new JLabel(translate("translation.author.label"));
transAuthorLabel.setAlignmentX(0.5f);
//transAuthorLabel.setPreferredSize(new Dimension(300, 20));
transAuthorLabel.setHorizontalAlignment(SwingConstants.CENTER);
JLabel transAuthor = new JLabel(translate("translation.author"));
transAuthor.setAlignmentX(0.5f);
//transAuthor.setPreferredSize(new Dimension(300, 20));
transAuthor.setHorizontalAlignment(SwingConstants.CENTER);
cp.add(transAuthorLabel);
cp.add(transAuthor);
JLabel contributorsLabel = new JLabel(translate("contributors"));
contributorsLabel.setAlignmentX(0.5f);
contributorsLabel.setHorizontalAlignment(SwingConstants.CENTER);
contributorsLabel.setFont(contributorsLabel.getFont().deriveFont(Font.BOLD));
cp.add(contributorsLabel);
for (String c : CONTRIBUTORS) {
JLabel contributorLabel = new JLabel(c);
contributorLabel.setAlignmentX(0.5f);
contributorLabel.setHorizontalAlignment(SwingConstants.CENTER);
cp.add(contributorLabel);
}
cp.add(Box.createVerticalStrut(10));
LinkLabel wwwLabel = new LinkLabel(ApplicationInfo.PROJECT_PAGE);
wwwLabel.setAlignmentX(0.5f);
wwwLabel.setForeground(Color.blue);
//wwwLabel.setPreferredSize(new Dimension(300, 25));
wwwLabel.setHorizontalAlignment(SwingConstants.CENTER);
cp.add(wwwLabel);
cp.add(Box.createVerticalStrut(10));
JButton okButton = new JButton(translate("button.ok"));
okButton.setAlignmentX(0.5f);
cp.add(okButton);
okButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
setVisible(false);
}
});
getRootPane().setDefaultButton(okButton);
setModal(true);
View.centerScreen(this);
View.setWindowIcon(this);
setResizable(false);
pack();
}
}
@@ -0,0 +1,41 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
*
* @author JPEXS
*/
public class ActionRedirector implements ActionListener {
ActionListener target;
String actionCommand;
public ActionRedirector(ActionListener target, String actionCommand) {
this.target = target;
this.actionCommand = actionCommand;
}
@Override
public void actionPerformed(ActionEvent e) {
e = new ActionEvent(e.getSource(), e.getID(), actionCommand);
target.actionPerformed(e);
}
}
@@ -0,0 +1,367 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.AppStrings;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.configuration.ConfigurationCategory;
import com.jpexs.decompiler.flash.configuration.ConfigurationItem;
import com.jpexs.decompiler.flash.gui.helpers.SpringUtilities;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.SpringLayout;
import javax.swing.table.DefaultTableModel;
/**
*
* @author JPEXS
*/
public class AdvancedSettingsDialog extends AppDialog implements ActionListener {
private Map<String, Component> componentsMap = new HashMap<>();
/**
* Creates new form AdvancedSettingsDialog
*/
public AdvancedSettingsDialog() {
initComponents();
View.centerScreen(this);
View.setWindowIcon(this);
//configurationTable.setCellEditor(configurationTable.getDefaultEditor(null));
pack();
}
private DefaultTableModel getModel() {
return new javax.swing.table.DefaultTableModel(
new Object[][]{},
new String[]{
translate("advancedSettings.columns.name"),
translate("advancedSettings.columns.value"),
translate("advancedSettings.columns.description")
}
) {
Class[] types = new Class[]{
String.class, Object.class, String.class
};
boolean[] canEdit = new boolean[]{
false, true, false
};
@Override
public Class getColumnClass(int columnIndex) {
return types[columnIndex];
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return canEdit[columnIndex];
}
};
}
private void initComponents() {
okButton = new JButton();
cancelButton = new JButton();
resetButton = new JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setTitle(translate("advancedSettings.dialog.title"));
setModal(true);
setPreferredSize(new java.awt.Dimension(800, 500));
okButton.setText(AppStrings.translate("button.ok"));
okButton.addActionListener(this);
okButton.setActionCommand("OK");
cancelButton.setText(AppStrings.translate("button.cancel"));
cancelButton.addActionListener(this);
cancelButton.setActionCommand("CANCEL");
resetButton.setText(AppStrings.translate("button.reset"));
resetButton.addActionListener(this);
resetButton.setActionCommand("RESET");
Container cnt = getContentPane();
cnt.setLayout(new BorderLayout());
//cnt.add(new JScrollPane(configurationTable),BorderLayout.CENTER);
JPanel buttonsPanel = new JPanel(new BorderLayout());
JPanel buttonsLeftPanel = new JPanel(new FlowLayout());
buttonsLeftPanel.add(resetButton, BorderLayout.WEST);
buttonsPanel.add(buttonsLeftPanel, BorderLayout.WEST);
JPanel buttonsRightPanel = new JPanel(new FlowLayout());
buttonsRightPanel.add(cancelButton);
buttonsRightPanel.add(okButton);
buttonsPanel.add(buttonsRightPanel, BorderLayout.EAST);
cnt.add(buttonsPanel, BorderLayout.SOUTH);
Map<String, Field> fields = Configuration.getConfigurationFields();
String[] keys = new String[fields.size()];
keys = fields.keySet().toArray(keys);
Arrays.sort(keys);
Map<String, Map<String, Field>> categorized = new HashMap<>();
for (String name : keys) {
Field field = fields.get(name);
ConfigurationCategory cat = field.getAnnotation(ConfigurationCategory.class);
String scat = cat == null?"other":cat.value();
if (!categorized.containsKey(scat)) {
categorized.put(scat, new HashMap<String, Field>());
}
categorized.get(scat).put(name, field);
}
JTabbedPane tabPane = new JTabbedPane();
Map<String,Component> tabs=new HashMap<>();
for (String cat : categorized.keySet()) {
JPanel configPanel = new JPanel(new SpringLayout());
for (String name : categorized.get(cat).keySet()) {
Field field = categorized.get(cat).get(name);
String locName = translate("config.name." + name);
try {
ConfigurationItem item = (ConfigurationItem) field.get(null);
ParameterizedType listType = (ParameterizedType) field.getGenericType();
Class itemType = (Class<?>) listType.getActualTypeArguments()[0];
/*String description = Configuration.getDescription(field);
if (description == null) {
description = "";
}*/
String description = translate("config.description." + name);
Object defaultValue = Configuration.getDefaultValue(field);
if (defaultValue != null) {
description += " (" + translate("default") + ": " + defaultValue + ")";
}
//model.addRow(new Object[]{locName, item.get(), description});
JLabel l = new JLabel(locName, JLabel.TRAILING);
l.setToolTipText(description);
configPanel.add(l);
Component c = null;
if ((itemType == String.class) || (itemType == Integer.class) || (itemType == Long.class) || (itemType == Double.class) || (itemType == Float.class) || (itemType == Calendar.class)) {
JTextField tf = new JTextField();
Object val = item.get();
if (val == null) {
val = "";
}
if (itemType == Calendar.class) {
tf.setText(new SimpleDateFormat().format(((Calendar) item.get()).getTime()));
} else {
tf.setText(val.toString());
}
tf.setToolTipText(description);
tf.setMaximumSize(new Dimension(Integer.MAX_VALUE,tf.getPreferredSize().height));
c = tf;
}
if (itemType == Boolean.class) {
JCheckBox cb = new JCheckBox();
cb.setSelected((Boolean) item.get());
cb.setToolTipText(description);
c = cb;
}
componentsMap.put(name, c);
l.setLabelFor(c);
configPanel.add(c);
} catch (IllegalArgumentException | IllegalAccessException ex) {
// Reflection exceptions. This should never happen
throw new Error(ex.getMessage());
}
}
SpringUtilities.makeCompactGrid(configPanel,
categorized.get(cat).size(), 2, //rows, cols
6, 6, //initX, initY
6, 6); //xPad, yPad
tabs.put(cat,new JScrollPane(configPanel));
}
String catOrder[] = new String[]{"ui","display","decompilation","script","format","export","limit","update","debug","other"};
for(String cat:catOrder){
if(!tabs.containsKey(cat)){
continue;
}
tabPane.add(translate("config.group.name."+cat),tabs.get(cat));
tabPane.setToolTipTextAt(tabPane.getTabCount()-1, translate("config.group.description."+cat));
}
cnt.add(tabPane, BorderLayout.CENTER);
pack();
}
private void showRestartConfirmDialod() {
if (View.showConfirmDialog(this, translate("advancedSettings.restartConfirmation"), AppStrings.translate("message.warning"), JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
View.execInEventDispatchLater(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(AdvancedSettingsDialog.class.getName()).log(Level.SEVERE, null, ex);
}
SelectLanguageDialog.reloadUi();
}
});
}
}
private JButton cancelButton;
private JButton okButton;
private JButton resetButton;
//private EachRowRendererEditor configurationTable;
@Override
@SuppressWarnings("unchecked")
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case "OK":
boolean modified = false;
Map<String, Field> fields = Configuration.getConfigurationFields();
Map<String, Object> values = new HashMap<>();
for (String name : fields.keySet()) {
Component c = componentsMap.get(name);
Object value = null;
ParameterizedType listType = (ParameterizedType) fields.get(name).getGenericType();
Class itemType = (Class<?>) listType.getActualTypeArguments()[0];
if (itemType == String.class) {
value = ((JTextField) c).getText();
}
if (itemType == Boolean.class) {
value = ((JCheckBox) c).isSelected();
}
if (itemType == Calendar.class) {
Calendar cal = Calendar.getInstance();
try {
cal.setTime(new SimpleDateFormat().parse(((JTextField) c).getText()));
} catch (ParseException ex) {
c.requestFocusInWindow();
return;
}
value = cal;
}
try {
if (itemType == Integer.class) {
value = Integer.parseInt(((JTextField) c).getText());
}
if (itemType == Long.class) {
value = Long.parseLong(((JTextField) c).getText());
}
if (itemType == Double.class) {
value = Double.parseDouble(((JTextField) c).getText());
}
if (itemType == Float.class) {
value = Float.parseFloat(((JTextField) c).getText());
}
} catch (NumberFormatException nfe) {
if (!((JTextField) c).getText().equals("")) {
c.requestFocusInWindow();
return;
}//else null
}
values.put(name, value);
}
for (String name : fields.keySet()) {
Component c = componentsMap.get(name);
Object value = values.get(name);
Field field = fields.get(name);
ConfigurationItem item = null;
try {
item = (ConfigurationItem) field.get(null);
} catch (IllegalArgumentException | IllegalAccessException ex) {
// Reflection exceptions. This should never happen
throw new Error(ex.getMessage());
}
if (item.get() != null && !item.get().equals(value)) {
item.set(value);
modified = true;
}
}
Configuration.saveConfig();
setVisible(false);
if (modified) {
showRestartConfirmDialod();
}
break;
case "CANCEL":
setVisible(false);
break;
case "RESET":
Map<String, Field> rfields = Configuration.getConfigurationFields();
for (Entry<String, Field> entry : rfields.entrySet()) {
String name = entry.getKey();
Field field = entry.getValue();
try {
ConfigurationItem item = (ConfigurationItem) field.get(null);
item.unset();
} catch (IllegalArgumentException | IllegalAccessException ex) {
// Reflection exceptions. This should never happen
throw new Error(ex.getMessage());
}
}
Configuration.saveConfig();
setVisible(false);
showRestartConfirmDialod();
break;
}
}
}
@@ -0,0 +1,47 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.AppStrings;
import com.jpexs.decompiler.flash.configuration.Configuration;
import java.util.ResourceBundle;
import javax.swing.JDialog;
import javax.swing.JRootPane;
/**
*
* @author JPEXS
*/
public abstract class AppDialog extends JDialog {
private ResourceBundle resourceBundle = ResourceBundle.getBundle(AppStrings.getResourcePath(getClass()));
public AppDialog() {
View.installEscapeCloseOperation(this);
if (Configuration.useRibbonInterface.get()) {
getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
}
}
public String translate(String key) {
return resourceBundle.getString(key);
}
public void updateLanguage() {
resourceBundle = ResourceBundle.getBundle(AppStrings.getResourcePath(getClass()));
}
}
@@ -0,0 +1,46 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.AppStrings;
import java.util.ResourceBundle;
import javax.swing.JFrame;
/**
*
* @author JPEXS
*/
public abstract class AppFrame extends JFrame {
private ResourceBundle resourceBundle;
public AppFrame() {
if (getClass().equals(MainFrameClassic.class)) {
resourceBundle = ResourceBundle.getBundle(AppStrings.getResourcePath(MainFrame.class));
} else {
resourceBundle = ResourceBundle.getBundle(AppStrings.getResourcePath(getClass()));
}
}
public String translate(String key) {
return resourceBundle.getString(key);
}
public void updateLanguage() {
resourceBundle = ResourceBundle.getBundle(AppStrings.getResourcePath(getClass()));
}
}
@@ -0,0 +1,42 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.AppStrings;
import java.util.ResourceBundle;
import org.pushingpixels.flamingo.api.ribbon.JRibbonFrame;
/**
*
* @author JPEXS
*/
public abstract class AppRibbonFrame extends JRibbonFrame {
private final ResourceBundle resourceBundle;
public AppRibbonFrame() {
if (getClass().equals(MainFrameRibbon.class)) {
resourceBundle = ResourceBundle.getBundle(AppStrings.getResourcePath(MainFrame.class));
} else {
resourceBundle = ResourceBundle.getBundle(AppStrings.getResourcePath(getClass()));
}
}
public String translate(String key) {
return resourceBundle.getString(key);
}
}
@@ -0,0 +1,83 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.gui.abc.LineMarkedEditorPane;
import com.jpexs.helpers.Helper;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
/**
*
* @author JPEXS
*/
public final class BinaryPanel extends JPanel implements ComponentListener {
public LineMarkedEditorPane hexEditor = new LineMarkedEditorPane();
private byte[] data;
public BinaryPanel() {
super(new BorderLayout());
add(new JScrollPane(hexEditor), BorderLayout.CENTER);
JPanel bottomPanel = new JPanel(new BorderLayout());
JPanel buttonsPanel = new JPanel(new FlowLayout());
bottomPanel.add(buttonsPanel, BorderLayout.EAST);
add(bottomPanel, BorderLayout.SOUTH);
addComponentListener(this);
}
public void setBinaryData(byte[] data) {
this.data = data;
hexEditor.setEditable(false);
if (data != null) {
int widthInChars = getWidth() / 7 - 3 - 11; // -3: scrollbar, -11: address in hex format
int blockCount = widthInChars / 34;
hexEditor.setFont(new Font("Monospaced", Font.PLAIN, hexEditor.getFont().getSize()));
hexEditor.setContentType("text/plain");
int limit = Configuration.binaryDataDisplayLimit.get();
hexEditor.setText(Helper.byteArrayToHex(data, blockCount * 8, limit));
hexEditor.setCaretPosition(0);
} else {
hexEditor.setText("");
}
}
@Override
public void componentResized(ComponentEvent e) {
setBinaryData(data);
}
@Override
public void componentMoved(ComponentEvent ce) {
}
@Override
public void componentShown(ComponentEvent ce) {
}
@Override
public void componentHidden(ComponentEvent ce) {
}
}
@@ -0,0 +1,88 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import javax.swing.JButton;
import javax.swing.JPanel;
/**
*
* @author JPEXS
*/
public class ButtonsPanel extends JPanel {
private ComponentListener listener;
public ButtonsPanel() {
super(new FlowLayout());
listener = new ComponentListener() {
@Override
public void componentResized(ComponentEvent e) {
}
@Override
public void componentMoved(ComponentEvent e) {
}
@Override
public void componentShown(ComponentEvent e) {
updateVisibility();
}
@Override
public void componentHidden(ComponentEvent e) {
updateVisibility();
}
};
this.addContainerListener(new ContainerListener() {
@Override
public void componentAdded(ContainerEvent e) {
e.getComponent().addComponentListener(listener);
}
@Override
public void componentRemoved(ContainerEvent e) {
e.getComponent().removeComponentListener(listener);
}
});
}
private void updateVisibility() {
// hide button panel when no button is visible
boolean visible = false;
for (Component component : getComponents()) {
if (component instanceof JButton) {
JButton button = (JButton) component;
if (button.isVisible()) {
visible = true;
}
}
}
setVisible(visible);
}
}
@@ -0,0 +1,65 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import javax.swing.JTable;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
/**
*
* @author JPEXS
*/
public class EachRowRendererEditor extends JTable {
private static final long serialVersionUID = 1L;
private Class editingClass;
@Override
public TableCellRenderer getCellRenderer(int row, int column) {
editingClass = null;
int modelColumn = convertColumnIndexToModel(column);
if (modelColumn == 1) {
Object value = getModel().getValueAt(row, modelColumn);
Class rowClass = value == null ? String.class : value.getClass();
return getDefaultRenderer(rowClass);
} else {
return super.getCellRenderer(row, column);
}
}
@Override
public TableCellEditor getCellEditor(int row, int column) {
editingClass = null;
int modelColumn = convertColumnIndexToModel(column);
if (modelColumn == 1) {
Object value = getModel().getValueAt(row, modelColumn);
editingClass = value == null ? String.class : value.getClass();
return getDefaultEditor(editingClass);
} else {
return super.getCellEditor(row, column);
}
}
// This method is also invoked by the editor when the value in the editor
// component is saved in the TableModel. The class was saved when the
// editor was invoked so the proper class can be created.
@Override
public Class getColumnClass(int column) {
return editingClass != null ? editingClass : super.getColumnClass(column);
}
}
@@ -0,0 +1,314 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JToggleButton;
import javax.swing.SwingUtilities;
/**
*
* @author JPEXS
*/
public class ErrorLogFrame extends AppFrame {
private static ErrorLogFrame instance;
private final JPanel logView = new JPanel();
private JPanel logViewInner = new JPanel();
private final Handler handler;
private final ImageIcon expandIcon;
private final ImageIcon collapseIcon;
private ErrorState errorState = ErrorState.NO_ERROR;
public Handler getHandler() {
return handler;
}
public static ErrorLogFrame getInstance() {
if (instance == null) {
instance = new ErrorLogFrame();
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
Logger logger = Logger.getLogger("");
logger.addHandler(instance.getHandler());
}
});
}
return instance;
}
public static ErrorLogFrame createNewInstance() {
if (instance != null) {
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
Logger logger = Logger.getLogger("");
logger.removeHandler(instance.getHandler());
}
});
instance.setVisible(false);
instance.dispose();
instance = null;
}
return getInstance();
}
public ErrorState getErrorState() {
return errorState;
}
public ErrorLogFrame() {
setTitle(translate("dialog.title"));
setSize(700, 400);
setBackground(Color.white);
View.centerScreen(this);
View.setWindowIcon(this);
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
Container cnt = getContentPane();
cnt.setLayout(new BorderLayout());
logView.setBackground(Color.white);
logView.setLayout(new BorderLayout());
cnt.setBackground(Color.white);
logViewInner.setLayout(new BoxLayout(logViewInner, BoxLayout.Y_AXIS));
logView.add(logViewInner, BorderLayout.NORTH);
JPanel buttonsPanel = new JPanel(new FlowLayout());
JButton clearButton = new JButton(translate("clear"));
clearButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
logViewInner.removeAll();
Main.clearLogFile();
revalidate();
repaint();
}
});
buttonsPanel.add(clearButton);
expandIcon = View.getIcon("expand16");
collapseIcon = View.getIcon("collapse16");
cnt.add(buttonsPanel, BorderLayout.SOUTH);
cnt.add(new JScrollPane(logView), BorderLayout.CENTER);
handler = new Handler() {
SimpleFormatter formatter = new SimpleFormatter();
@Override
public void publish(LogRecord record) {
if (getLevel().intValue() <= record.getLevel().intValue()) {
log(record.getLevel(), formatter.formatMessage(record), record.getThrown());
}
}
@Override
public void flush() {
}
@Override
public void close() throws SecurityException {
}
};
handler.setLevel(Level.WARNING);
}
public void clearErrorState() {
errorState = ErrorState.NO_ERROR;
MainFrame mainFrame = Main.getMainFrame();
if (mainFrame != null) {
mainFrame.getPanel().setErrorState(errorState);
}
}
private void notifyMainFrame(Level level) {
boolean stateChanged = false;
if (level.intValue() >= Level.SEVERE.intValue()) {
if (errorState != ErrorState.ERROR) {
errorState = ErrorState.ERROR;
stateChanged = true;
}
} else if (level.intValue() >= Level.WARNING.intValue()) {
if (errorState != ErrorState.ERROR && errorState != ErrorState.WARNING) {
errorState = ErrorState.WARNING;
stateChanged = true;
}
} else if (level.intValue() >= Level.INFO.intValue()) {
if (errorState == ErrorState.NO_ERROR) {
errorState = ErrorState.INFO;
stateChanged = true;
}
}
if (stateChanged) {
MainFrame mainFrame = Main.getMainFrame();
if (mainFrame != null) {
mainFrame.getPanel().setErrorState(errorState);
}
}
}
private void log(final Level level, final String msg, final String detail) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
notifyMainFrame(level);
JPanel pan = new JPanel();
pan.setBackground(Color.white);
pan.setLayout(new BoxLayout(pan, BoxLayout.Y_AXIS));
JComponent detailComponent;
if (detail == null) {
detailComponent = null;
} else {
final JTextArea detailTextArea = new JTextArea(detail);
detailTextArea.setEditable(false);
detailTextArea.setOpaque(false);
detailTextArea.setFont(new JLabel().getFont());
detailTextArea.setBackground(Color.white);
detailComponent = detailTextArea;
}
JPanel header = new JPanel();
header.setLayout(new BoxLayout(header, BoxLayout.X_AXIS));
header.setBackground(Color.white);
SimpleDateFormat format = new SimpleDateFormat("dd/MM/YYYY HH:mm:ss");
final String dateStr = format.format(new Date());
JToggleButton copyButton = new JToggleButton(View.getIcon("copy16"));
copyButton.setFocusPainted(false);
copyButton.setBorderPainted(false);
copyButton.setFocusable(false);
copyButton.setContentAreaFilled(false);
copyButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
copyButton.setMargin(new Insets(2, 2, 2, 2));
copyButton.setToolTipText(translate("copy"));
copyButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
StringSelection stringSelection = new StringSelection(dateStr + " " + level.toString() + " " + msg + "\r\n" + detail);
clipboard.setContents(stringSelection, null);
}
});
final JToggleButton expandButton = new JToggleButton(collapseIcon);
expandButton.setFocusPainted(false);
expandButton.setBorderPainted(false);
expandButton.setFocusable(false);
expandButton.setContentAreaFilled(false);
expandButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
expandButton.setMargin(new Insets(2, 2, 2, 2));
expandButton.setToolTipText(translate("details"));
final JScrollPane scrollPane;
if (detailComponent != null) {
scrollPane = new JScrollPane(detailComponent);
scrollPane.setAlignmentX(0f);
} else {
scrollPane = null;
}
if (detailComponent != null) {
expandButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
expandButton.setIcon(expandButton.isSelected() ? expandIcon : collapseIcon);
scrollPane.setVisible(expandButton.isSelected());
revalidate();
repaint();
}
});
}
if (detailComponent != null) {
header.add(expandButton);
}
JLabel dateLabel = new JLabel(dateStr);
dateLabel.setPreferredSize(new Dimension(200, (int) dateLabel.getPreferredSize().getHeight()));
dateLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
header.add(dateLabel);
JLabel levelLabel = new JLabel(level.getName());
levelLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
header.add(levelLabel);
JTextArea msgLabel = new JTextArea(msg);
msgLabel.setEditable(false);
msgLabel.setOpaque(false);
msgLabel.setFont(levelLabel.getFont());
msgLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
header.add(msgLabel);
header.setAlignmentX(0f);
header.add(copyButton);
pan.add(header);
if (detailComponent != null) {
pan.add(scrollPane);
scrollPane.setVisible(false);
}
pan.setAlignmentX(0f);
logViewInner.add(pan);
revalidate();
repaint();
}
});
}
public void log(Level level, String msg) {
log(level, msg, (String) null);
}
public void log(Level level, String msg, Throwable ex) {
StringWriter sw = new StringWriter();
if (ex != null) {
ex.printStackTrace(new PrintWriter(sw));
}
log(level, msg, sw.toString());
}
}
@@ -0,0 +1,26 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
/**
*
* @author JPEXS
*/
public enum ErrorState {
NO_ERROR, INFO, WARNING, ERROR
}
@@ -0,0 +1,252 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.abc.ScriptPack;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.BinaryDataExportMode;
import com.jpexs.decompiler.flash.exporters.modes.FontExportMode;
import com.jpexs.decompiler.flash.exporters.modes.FramesExportMode;
import com.jpexs.decompiler.flash.exporters.modes.ImageExportMode;
import com.jpexs.decompiler.flash.exporters.modes.MorphShapeExportMode;
import com.jpexs.decompiler.flash.exporters.modes.MovieExportMode;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.exporters.modes.ShapeExportMode;
import com.jpexs.decompiler.flash.exporters.modes.SoundExportMode;
import com.jpexs.decompiler.flash.exporters.modes.TextExportMode;
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag;
import com.jpexs.decompiler.flash.tags.base.FontTag;
import com.jpexs.decompiler.flash.tags.base.ImageTag;
import com.jpexs.decompiler.flash.tags.base.MorphShapeTag;
import com.jpexs.decompiler.flash.tags.base.ShapeTag;
import com.jpexs.decompiler.flash.tags.base.SoundTag;
import com.jpexs.decompiler.flash.tags.base.TextTag;
import com.jpexs.decompiler.flash.treeitems.FrameNodeItem;
import com.jpexs.decompiler.flash.treenodes.TreeNode;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Arrays;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
/**
*
* @author JPEXS
*/
public class ExportDialog extends AppDialog {
boolean cancelled = false;
String[] optionNames = {
"shapes",
"texts",
"images",
"movies",
"sounds",
"scripts",
"binaryData",
"frames",
"fonts",
"morphshapes"
};
//Display options only when these classes found
Class[][] objClasses = {
{ShapeTag.class},
{TextTag.class},
{ImageTag.class},
{DefineVideoStreamTag.class},
{SoundTag.class},
{TreeNode.class, ScriptPack.class},
{DefineBinaryDataTag.class},
{FrameNodeItem.class},
{FontTag.class},
{MorphShapeTag.class}
};
//Enum classes for values
Class[] optionClasses = {
ShapeExportMode.class,
TextExportMode.class,
ImageExportMode.class,
MovieExportMode.class,
SoundExportMode.class,
ScriptExportMode.class,
BinaryDataExportMode.class,
FramesExportMode.class,
FontExportMode.class,
MorphShapeExportMode.class
};
private final JComboBox[] combos;
public <E> E getValue(Class<E> option) {
for (int i = 0; i < optionClasses.length; i++) {
if (option == optionClasses[i]) {
E values[] = option.getEnumConstants();
return values[combos[i].getSelectedIndex()];
}
}
return null;
}
private void saveConfig() {
String cfg = "";
for (int i = 0; i < optionNames.length; i++) {
int selIndex = combos[i].getSelectedIndex();
Class c = optionClasses[i];
Object vals[] = c.getEnumConstants();
String key = optionNames[i] + "." + vals[selIndex].toString().toLowerCase();
if (i > 0) {
cfg += ",";
}
cfg += key;
}
Configuration.lastSelectedExportFormats.set(cfg);
}
public ExportDialog(List<Object> exportables) {
setTitle(translate("dialog.title"));
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
cancelled = true;
}
});
Container cnt = getContentPane();
cnt.setLayout(new BorderLayout());
JPanel comboPanel = new JPanel(null);
combos = new JComboBox[optionNames.length];
JLabel[] labels = new JLabel[optionNames.length];
int labWidth = 0;
for (int i = 0; i < optionNames.length; i++) {
labels[i] = new JLabel(optionNames[i]);
if (labels[i].getPreferredSize().width > labWidth) {
labWidth = labels[i].getPreferredSize().width;
}
}
String exportFormatsStr = Configuration.lastSelectedExportFormats.get();
if ("".equals(exportFormatsStr)) {
exportFormatsStr = null;
}
String exportFormatsArr[] = new String[0];
if (exportFormatsStr != null) {
if (exportFormatsStr.contains(",")) {
exportFormatsArr = exportFormatsStr.split(",");
} else {
exportFormatsArr = new String[]{exportFormatsStr};
}
}
List<String> exportFormats = Arrays.asList(exportFormatsArr);
int comboWidth = 200;
int top = 10;
for (int i = 0; i < optionNames.length; i++) {
Class c = optionClasses[i];
Object vals[] = c.getEnumConstants();
String names[] = new String[vals.length];
int itemIndex = -1;
for (int j = 0; j < vals.length; j++) {
String key = optionNames[i] + "." + vals[j].toString().toLowerCase();
if (exportFormats.contains(key)) {
itemIndex = j;
}
names[j] = translate(key);
}
combos[i] = new JComboBox<>(names);
if (itemIndex > -1) {
combos[i].setSelectedIndex(itemIndex);
}
combos[i].setBounds(10 + labWidth + 10, top, comboWidth, combos[i].getPreferredSize().height);
boolean exportableExists = false;
if (exportables == null) {
exportableExists = true;
} else {
for (Object e : exportables) {
for (int j = 0; j < objClasses[i].length; j++) {
if (objClasses[i][j].isInstance(e)) {
exportableExists = true;
}
}
}
}
if (!exportableExists) {
continue;
}
JLabel lab = new JLabel(translate(optionNames[i]));
lab.setBounds(10, top, lab.getPreferredSize().width, lab.getPreferredSize().height);
comboPanel.add(lab);
comboPanel.add(combos[i]);
top += combos[i].getHeight();
}
Dimension dim = new Dimension(10 + labWidth + 10 + comboWidth + 10, top + 10);
comboPanel.setMinimumSize(dim);
comboPanel.setPreferredSize(dim);
cnt.add(comboPanel, BorderLayout.CENTER);
JPanel buttonsPanel = new JPanel(new FlowLayout());
JButton okButton = new JButton(translate("button.ok"));
okButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
saveConfig();
setVisible(false);
}
});
JButton cancelButton = new JButton(translate("button.cancel"));
cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
cancelled = true;
setVisible(false);
}
});
buttonsPanel.add(okButton);
buttonsPanel.add(cancelButton);
cnt.add(buttonsPanel, BorderLayout.SOUTH);
pack();
//setSize(245, top + getInsets().top);
View.centerScreen(this);
View.setWindowIcon(this);
getRootPane().setDefaultButton(okButton);
setModal(true);
}
@Override
public void setVisible(boolean b) {
if (b) {
cancelled = false;
}
super.setVisible(b);
}
}
@@ -0,0 +1,28 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
/**
*
* @author JPEXS
*/
public class FlashUnsupportedException extends RuntimeException {
public FlashUnsupportedException() {
super("Flash Unsupported");
}
}
@@ -0,0 +1,220 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.AppStrings;
import com.jpexs.decompiler.flash.tags.base.FontTag;
import com.jpexs.decompiler.flash.tags.font.CharacterRanges;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Set;
import java.util.TreeSet;
import java.util.Vector;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
/**
*
* @author JPEXS
*/
public class FontEmbedDialog extends AppDialog implements ActionListener {
private static final String ACTION_OK = "OK";
private static final String ACTION_CANCEL = "CANCEL";
private static final int SAMPLE_MAX_LENGTH = 50;
private final JComboBox<String> sourceFont;
private final JCheckBox[] rangeCheckboxes;
private final String rangeNames[];
private final JLabel[] rangeSamples;
private final JTextField individualCharsField;
private boolean result = false;
private JLabel individialSample;
private final int style;
public String getSelectedFont() {
return sourceFont.getSelectedItem().toString();
}
public Set<Integer> getSelectedChars() {
Set<Integer> chars = new TreeSet<>();
Font f = new Font(getSelectedFont(), style, new JLabel().getFont().getSize());
for (int i = 0; i < rangeCheckboxes.length; i++) {
if (rangeCheckboxes[i].isSelected()) {
int codes[] = CharacterRanges.rangeCodes(i);
for (int c : codes) {
if (f.canDisplay(c)) {
chars.add(c);
}
}
}
}
String indStr = individualCharsField.getText();
for (int i = 0; i < indStr.length(); i++) {
if (f.canDisplay(indStr.codePointAt(i))) {
chars.add(indStr.codePointAt(i));
}
}
return chars;
}
public FontEmbedDialog(String selectedFont, String selectedChars, int style) {
setSize(900, 600);
this.style = style;
setDefaultCloseOperation(HIDE_ON_CLOSE);
setTitle(translate("dialog.title"));
Container cnt = getContentPane();
cnt.setLayout(new BoxLayout(cnt, BoxLayout.Y_AXIS));
individialSample = new JLabel();
sourceFont = new JComboBox<>(new Vector<>(FontTag.fontNames));
sourceFont.setSelectedItem(selectedFont);
cnt.add(sourceFont);
JPanel rangesPanel = new JPanel();
rangesPanel.setLayout(new BoxLayout(rangesPanel, BoxLayout.Y_AXIS));
int rc = CharacterRanges.rangeCount();
rangeCheckboxes = new JCheckBox[rc];
rangeSamples = new JLabel[rc];
rangeNames = new String[rc];
for (int i = 0; i < rc; i++) {
rangeNames[i] = CharacterRanges.rangeName(i);
rangeSamples[i] = new JLabel("");
rangeCheckboxes[i] = new JCheckBox(rangeNames[i]);
JPanel rangeRowPanel = new JPanel();
rangeRowPanel.setLayout(new BoxLayout(rangeRowPanel, BoxLayout.X_AXIS));
rangeRowPanel.add(rangeCheckboxes[i]);
rangeRowPanel.add(Box.createHorizontalGlue());
rangeRowPanel.add(rangeSamples[i]);
rangeRowPanel.setAlignmentX(0);
rangesPanel.add(rangeRowPanel);
}
cnt.add(new JScrollPane(rangesPanel));
JPanel specialPanel = new JPanel();
specialPanel.setLayout(new BoxLayout(specialPanel, BoxLayout.X_AXIS));
specialPanel.add(new JLabel(translate("label.individual")));
individualCharsField = new JTextField();
individualCharsField.setPreferredSize(new Dimension(100, individualCharsField.getPreferredSize().height));
individialSample = new JLabel();
specialPanel.add(individualCharsField);
cnt.add(specialPanel);
cnt.add(individialSample);
JPanel buttonsPanel = new JPanel(new FlowLayout());
JButton okButton = new JButton(AppStrings.translate("button.ok"));
okButton.setActionCommand(ACTION_OK);
okButton.addActionListener(this);
JButton cancelButton = new JButton(AppStrings.translate("button.cancel"));
cancelButton.setActionCommand(ACTION_CANCEL);
cancelButton.addActionListener(this);
buttonsPanel.add(okButton);
buttonsPanel.add(cancelButton);
cnt.add(buttonsPanel);
View.setWindowIcon(this);
View.centerScreen(this);
setModalityType(ModalityType.APPLICATION_MODAL);
individualCharsField.setText(selectedChars);
getRootPane().setDefaultButton(okButton);
sourceFont.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
updateCheckboxes();
}
});
updateCheckboxes();
individualCharsField.addKeyListener(new KeyAdapter() {
@Override
public void keyTyped(KeyEvent e) {
updateIndividual();
}
});
}
private void updateIndividual() {
String chars = individualCharsField.getText();
Font f = new Font(getSelectedFont(), style, new JLabel().getFont().getSize());
String visibleChars = "";
for (int i = 0; i < chars.length(); i++) {
if (f.canDisplay(chars.codePointAt(i))) {
visibleChars += "" + chars.charAt(i);
}
}
individialSample.setText(visibleChars);
}
private void updateCheckboxes() {
String fontStr = sourceFont.getSelectedItem().toString();
Font f = new Font(fontStr, style, new JLabel().getFont().getSize());
int rc = CharacterRanges.rangeCount();
for (int i = 0; i < rc; i++) {
rangeNames[i] = CharacterRanges.rangeName(i);
int codes[] = CharacterRanges.rangeCodes(i);
int avail = 0;
String sample = "";
for (int c = 0; c < codes.length; c++) {
if (f.canDisplay(codes[c])) {
if (avail < SAMPLE_MAX_LENGTH) {
sample += "" + (char) codes[c];
}
avail++;
}
}
rangeSamples[i].setText(sample);
rangeSamples[i].setFont(f);
rangeCheckboxes[i].setText(translate("range.description").replace("%available%", "" + avail).replace("%name%", rangeNames[i]).replace("%total%", "" + codes.length));
}
individialSample.setFont(f);
updateIndividual();
}
@Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case ACTION_OK:
result = true;
setVisible(false);
break;
case ACTION_CANCEL:
result = false;
setVisible(false);
break;
}
}
public boolean display() {
result = false;
setVisible(true);
return result;
}
}
@@ -0,0 +1,591 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.8" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<Events>
<EventHandler event="componentResized" listener="java.awt.event.ComponentListener" parameters="java.awt.event.ComponentEvent" handler="formComponentResized"/>
</Events>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" alignment="0" pref="473" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" alignment="0" pref="415" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<Properties>
<Property name="horizontalScrollBarPolicy" type="int" value="31"/>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel2">
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="463" max="32767" attributes="0"/>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jPanel1" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel11" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="fontSelection" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel10" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="fontAddCharactersField" min="-2" pref="150" max="-2" attributes="0"/>
</Group>
<Component id="fontEmbedButton" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Component id="buttonEdit" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="buttonSave" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="buttonCancel" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="100" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="fontAddCharsButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="updateTextsCheckBox" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="buttonPreviewFont" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="315" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="415" max="32767" attributes="0"/>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jPanel1" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel10" alignment="3" max="32767" attributes="0"/>
<Component id="fontAddCharactersField" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="fontAddCharsButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="updateTextsCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel11" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="fontSelection" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="buttonPreviewFont" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="fontEmbedButton" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="78" max="32767" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="buttonEdit" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="buttonSave" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="buttonCancel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel1">
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="font.name" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="23" weightX="0.0" weightY="1.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JLabel" name="fontNameLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="value.unknown" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[250, 14]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[250, 14]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[250, 14]"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="0" insetsRight="6" anchor="23" weightX="1.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JLabel" name="jLabel2">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="fontName.name" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="8" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="23" weightX="0.0" weightY="1.0"/>
</Constraint>
</Constraints>
</Component>
<Container class="javax.swing.JScrollPane" name="fontDisplayNameScrollPane">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="null"/>
</Property>
<Property name="horizontalScrollBarPolicy" type="int" value="31"/>
<Property name="horizontalScrollBar" type="javax.swing.JScrollBar" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="null"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="0" insetsRight="6" anchor="23" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextArea" name="fontDisplayNameTextArea">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="columns" type="int" value="20"/>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new JLabel().getFont()" type="code"/>
</Property>
<Property name="lineWrap" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="value.unknown" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
<Property name="wrapStyleWord" type="boolean" value="true"/>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[250, 16]"/>
</Property>
<Property name="opaque" type="boolean" value="false"/>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JLabel" name="jLabel3">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="fontName.copyright" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="23" weightX="0.0" weightY="1.0"/>
</Constraint>
</Constraints>
</Component>
<Container class="javax.swing.JScrollPane" name="fontCopyrightScrollPane">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="null"/>
</Property>
<Property name="horizontalScrollBarPolicy" type="int" value="31"/>
<Property name="horizontalScrollBar" type="javax.swing.JScrollBar" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="null"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="2" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="0" insetsRight="6" anchor="23" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextArea" name="fontCopyrightTextArea">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="columns" type="int" value="20"/>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new JLabel().getFont()" type="code"/>
</Property>
<Property name="lineWrap" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="value.unknown" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
<Property name="wrapStyleWord" type="boolean" value="true"/>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[250, 16]"/>
</Property>
<Property name="opaque" type="boolean" value="false"/>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JLabel" name="jLabel4">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="font.isbold" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="23" weightX="0.0" weightY="1.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JCheckBox" name="fontIsBoldCheckBox">
<Properties>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="0" insetsRight="6" anchor="23" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JLabel" name="jLabel5">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="font.isitalic" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="4" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="23" weightX="0.0" weightY="1.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JCheckBox" name="fontIsItalicCheckBox">
<Properties>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="4" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="0" insetsRight="6" anchor="23" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JLabel" name="jLabel6">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="font.ascent" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="5" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="23" weightX="0.0" weightY="1.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JLabel" name="fontAscentLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="value.unknown" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="5" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="0" insetsRight="6" anchor="23" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JLabel" name="jLabel7">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="font.descent" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="6" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="23" weightX="0.0" weightY="1.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JLabel" name="fontDescentLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="value.unknown" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="6" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="0" insetsRight="6" anchor="23" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JLabel" name="jLabel8">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="font.leading" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="7" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="23" weightX="0.0" weightY="1.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JLabel" name="fontLeadingLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="value.unknown" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="7" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="0" insetsRight="6" anchor="23" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JLabel" name="jLabel9">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="font.characters" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="8" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="23" weightX="0.0" weightY="1.0"/>
</Constraint>
</Constraints>
</Component>
<Container class="javax.swing.JScrollPane" name="fontCharactersScrollPane">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="null"/>
</Property>
<Property name="horizontalScrollBarPolicy" type="int" value="31"/>
<Property name="horizontalScrollBar" type="javax.swing.JScrollBar" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="null"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="8" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="0" insetsRight="6" anchor="23" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextArea" name="fontCharactersTextArea">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="columns" type="int" value="20"/>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new JLabel().getFont()" type="code"/>
</Property>
<Property name="lineWrap" type="boolean" value="true"/>
<Property name="wrapStyleWord" type="boolean" value="true"/>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[250, 16]"/>
</Property>
<Property name="opaque" type="boolean" value="false"/>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
<Component class="javax.swing.JLabel" name="jLabel10">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="font.characters.add" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
</Component>
<Component class="javax.swing.JTextField" name="fontAddCharactersField">
</Component>
<Component class="javax.swing.JButton" name="fontAddCharsButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="button.ok" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="fontAddCharsButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="updateTextsCheckBox">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="font.updateTexts" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel11">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="font.source" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JComboBox" name="fontSelection">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="getModel()" type="code"/>
</Property>
<Property name="selectedItem" type="java.lang.Object" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="FontTag.defaultFontName" type="code"/>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="fontSelectionItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="fontEmbedButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="button.font.embed" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="fontEmbedButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="buttonEdit">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/com/jpexs/decompiler/flash/gui/graphics/edit16.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="button.edit" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonEditActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="buttonSave">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/com/jpexs/decompiler/flash/gui/graphics/save16.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="button.save" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonSaveActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="buttonCancel">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/com/jpexs/decompiler/flash/gui/graphics/cancel16.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="button.cancel" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonCancelActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="buttonPreviewFont">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="button.preview" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonPreviewFontActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Form>
@@ -0,0 +1,679 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.tags.DefineFontNameTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.FontTag;
import com.jpexs.decompiler.flash.tags.base.TextTag;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
import java.awt.Font;
import java.util.Set;
import java.util.TreeSet;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
/**
*
* @author JPEXS
*/
public class FontPanel extends javax.swing.JPanel {
private final MainPanel mainPanel;
private FontTag fontTag;
/**
* Creates new form FontPanel
*
* @param mainPanel
*/
public FontPanel(MainPanel mainPanel) {
this.mainPanel = mainPanel;
initComponents();
}
public FontTag getFontTag() {
return fontTag;
}
public void clear() {
fontTag = null;
}
private ComboBoxModel<String> getModel() {
return new DefaultComboBoxModel<>(FontTag.fontNamesArray);
}
private void setEditable(boolean editable) {
if (editable) {
buttonEdit.setVisible(false);
buttonSave.setVisible(true);
buttonCancel.setVisible(true);
if (fontTag.isBoldEditable()) {
fontIsBoldCheckBox.setEnabled(true);
}
if (fontTag.isItalicEditable()) {
fontIsItalicCheckBox.setEnabled(true);
}
} else {
buttonEdit.setVisible(true);
buttonSave.setVisible(false);
buttonCancel.setVisible(false);
fontIsBoldCheckBox.setEnabled(false);
fontIsItalicCheckBox.setEnabled(false);
}
}
private String translate(String key) {
return mainPanel.translate(key);
}
private void fontAddChars(FontTag ft, Set<Integer> selChars, String selFont) {
FontTag f = (FontTag) mainPanel.tagTree.getCurrentTreeItem();
SWF swf = ft.getSwf();
String oldchars = f.getCharacters(swf.tags);
for (int ic : selChars) {
char c = (char) ic;
if (oldchars.indexOf((int) c) == -1) {
Font font = new Font(selFont, f.getFontStyle(), 1024);
if (!font.canDisplay(c)) {
View.showMessageDialog(null, translate("error.font.nocharacter").replace("%char%", "" + c), translate("error"), JOptionPane.ERROR_MESSAGE);
return;
}
}
}
String[] yesno = new String[]{translate("button.yes"), translate("button.no"), translate("button.yes.all"), translate("button.no.all")};
boolean yestoall = false;
boolean notoall = false;
for (int ic : selChars) {
char c = (char) ic;
if (oldchars.indexOf((int) c) > -1) {
int opt; //yes
if (!(yestoall || notoall)) {
opt = View.showOptionDialog(null, translate("message.font.add.exists").replace("%char%", "" + c), translate("message.warning"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, yesno, translate("button.yes"));
if (opt == 2) {
yestoall = true;
}
if (opt == 3) {
notoall = true;
}
}
if (yestoall) {
opt = 0; //yes
} else if (notoall) {
opt = 1; //no
} else {
opt = 1;
}
if (opt == 1) {
continue;
}
}
f.addCharacter(c, fontSelection.getSelectedItem().toString());
oldchars += c;
}
int fontId = ft.getFontId();
if (updateTextsCheckBox.isSelected()) {
for (Tag tag : swf.tags) {
if (tag instanceof TextTag) {
TextTag textTag = (TextTag) tag;
if (textTag.getFontIds().contains(fontId)) {
String text = textTag.getFormattedText();
mainPanel.saveText(textTag, text, null);
}
}
}
}
ft.setModified(true);
SWF.clearImageCache();
}
public void showFontTag(FontTag ft) {
SWF swf = ft.getSwf();
fontTag = ft;
DefineFontNameTag fontNameTag = null;
for (Tag tag : swf.tags) {
if (tag instanceof DefineFontNameTag) {
DefineFontNameTag dfnt = (DefineFontNameTag) tag;
if (dfnt.fontId == ft.getFontId()) {
fontNameTag = dfnt;
}
}
}
fontNameLabel.setText(ft.getFontName());
if (fontNameTag != null) {
fontDisplayNameTextArea.setText(fontNameTag.fontName);
fontCopyrightTextArea.setText(fontNameTag.fontCopyright);
}
fontIsBoldCheckBox.setSelected(ft.isBold());
fontIsItalicCheckBox.setSelected(ft.isItalic());
fontDescentLabel.setText(ft.getDescent() == -1 ? translate("value.unknown") : "" + ft.getDescent());
fontAscentLabel.setText(ft.getAscent() == -1 ? translate("value.unknown") : "" + ft.getAscent());
fontLeadingLabel.setText(ft.getLeading() == -1 ? translate("value.unknown") : "" + ft.getLeading());
String chars = ft.getCharacters(swf.tags);
fontCharactersTextArea.setText(chars);
String key = swf.getShortFileName() + "_" + ft.getFontId() + "_" + ft.getFontName();
if (swf.sourceFontsMap.containsKey(ft.getFontId())) {
fontSelection.setSelectedItem(swf.sourceFontsMap.get(ft.getFontId()));
} else if (Configuration.getFontPairs().containsKey(key)) {
fontSelection.setSelectedItem(Configuration.getFontPairs().get(key));
} else if (Configuration.getFontPairs().containsKey(ft.getFontName())) {
fontSelection.setSelectedItem(Configuration.getFontPairs().get(ft.getFontName()));
} else {
fontSelection.setSelectedItem(FontTag.findInstalledFontName(ft.getFontName()));
}
setEditable(false);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
java.awt.GridBagConstraints gridBagConstraints;
jScrollPane1 = new javax.swing.JScrollPane();
jPanel2 = new javax.swing.JPanel();
jPanel1 = new javax.swing.JPanel();
javax.swing.JLabel jLabel1 = new javax.swing.JLabel();
fontNameLabel = new javax.swing.JLabel();
javax.swing.JLabel jLabel2 = new javax.swing.JLabel();
javax.swing.JScrollPane fontDisplayNameScrollPane = new javax.swing.JScrollPane();
fontDisplayNameTextArea = new javax.swing.JTextArea();
javax.swing.JLabel jLabel3 = new javax.swing.JLabel();
javax.swing.JScrollPane fontCopyrightScrollPane = new javax.swing.JScrollPane();
fontCopyrightTextArea = new javax.swing.JTextArea();
javax.swing.JLabel jLabel4 = new javax.swing.JLabel();
fontIsBoldCheckBox = new javax.swing.JCheckBox();
javax.swing.JLabel jLabel5 = new javax.swing.JLabel();
fontIsItalicCheckBox = new javax.swing.JCheckBox();
javax.swing.JLabel jLabel6 = new javax.swing.JLabel();
fontAscentLabel = new javax.swing.JLabel();
javax.swing.JLabel jLabel7 = new javax.swing.JLabel();
fontDescentLabel = new javax.swing.JLabel();
javax.swing.JLabel jLabel8 = new javax.swing.JLabel();
fontLeadingLabel = new javax.swing.JLabel();
javax.swing.JLabel jLabel9 = new javax.swing.JLabel();
fontCharactersScrollPane = new javax.swing.JScrollPane();
fontCharactersTextArea = new javax.swing.JTextArea();
javax.swing.JLabel jLabel10 = new javax.swing.JLabel();
fontAddCharactersField = new javax.swing.JTextField();
fontAddCharsButton = new javax.swing.JButton();
updateTextsCheckBox = new javax.swing.JCheckBox();
jLabel11 = new javax.swing.JLabel();
fontSelection = new javax.swing.JComboBox();
fontEmbedButton = new javax.swing.JButton();
buttonEdit = new javax.swing.JButton();
buttonSave = new javax.swing.JButton();
buttonCancel = new javax.swing.JButton();
buttonPreviewFont = new javax.swing.JButton();
addComponentListener(new java.awt.event.ComponentAdapter() {
public void componentResized(java.awt.event.ComponentEvent evt) {
formComponentResized(evt);
}
});
jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
jPanel1.setLayout(new java.awt.GridBagLayout());
java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("com/jpexs/decompiler/flash/gui/locales/MainFrame"); // NOI18N
jLabel1.setText(bundle.getString("font.name")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
gridBagConstraints.weighty = 1.0;
jPanel1.add(jLabel1, gridBagConstraints);
fontNameLabel.setText(bundle.getString("value.unknown")); // NOI18N
fontNameLabel.setMaximumSize(new java.awt.Dimension(250, 14));
fontNameLabel.setMinimumSize(new java.awt.Dimension(250, 14));
fontNameLabel.setPreferredSize(new java.awt.Dimension(250, 14));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 6);
jPanel1.add(fontNameLabel, gridBagConstraints);
jLabel2.setText(bundle.getString("fontName.name")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.ipadx = 8;
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
gridBagConstraints.weighty = 1.0;
jPanel1.add(jLabel2, gridBagConstraints);
fontDisplayNameScrollPane.setBorder(null);
fontDisplayNameScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
fontDisplayNameScrollPane.setHorizontalScrollBar(null);
fontDisplayNameTextArea.setEditable(false);
fontDisplayNameTextArea.setColumns(20);
fontDisplayNameTextArea.setFont(new JLabel().getFont());
fontDisplayNameTextArea.setLineWrap(true);
fontDisplayNameTextArea.setText(bundle.getString("value.unknown")); // NOI18N
fontDisplayNameTextArea.setWrapStyleWord(true);
fontDisplayNameTextArea.setMinimumSize(new java.awt.Dimension(250, 16));
fontDisplayNameTextArea.setOpaque(false);
fontDisplayNameScrollPane.setViewportView(fontDisplayNameTextArea);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 6);
jPanel1.add(fontDisplayNameScrollPane, gridBagConstraints);
jLabel3.setText(bundle.getString("fontName.copyright")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
gridBagConstraints.weighty = 1.0;
jPanel1.add(jLabel3, gridBagConstraints);
fontCopyrightScrollPane.setBorder(null);
fontCopyrightScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
fontCopyrightScrollPane.setHorizontalScrollBar(null);
fontCopyrightTextArea.setEditable(false);
fontCopyrightTextArea.setColumns(20);
fontCopyrightTextArea.setFont(new JLabel().getFont());
fontCopyrightTextArea.setLineWrap(true);
fontCopyrightTextArea.setText(bundle.getString("value.unknown")); // NOI18N
fontCopyrightTextArea.setWrapStyleWord(true);
fontCopyrightTextArea.setMinimumSize(new java.awt.Dimension(250, 16));
fontCopyrightTextArea.setOpaque(false);
fontCopyrightScrollPane.setViewportView(fontCopyrightTextArea);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 6);
jPanel1.add(fontCopyrightScrollPane, gridBagConstraints);
jLabel4.setText(bundle.getString("font.isbold")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 3;
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
gridBagConstraints.weighty = 1.0;
jPanel1.add(jLabel4, gridBagConstraints);
fontIsBoldCheckBox.setEnabled(false);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 3;
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 6);
jPanel1.add(fontIsBoldCheckBox, gridBagConstraints);
jLabel5.setText(bundle.getString("font.isitalic")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 4;
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
gridBagConstraints.weighty = 1.0;
jPanel1.add(jLabel5, gridBagConstraints);
fontIsItalicCheckBox.setEnabled(false);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 4;
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 6);
jPanel1.add(fontIsItalicCheckBox, gridBagConstraints);
jLabel6.setText(bundle.getString("font.ascent")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 5;
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
gridBagConstraints.weighty = 1.0;
jPanel1.add(jLabel6, gridBagConstraints);
fontAscentLabel.setText(bundle.getString("value.unknown")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 5;
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 6);
jPanel1.add(fontAscentLabel, gridBagConstraints);
jLabel7.setText(bundle.getString("font.descent")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 6;
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
gridBagConstraints.weighty = 1.0;
jPanel1.add(jLabel7, gridBagConstraints);
fontDescentLabel.setText(bundle.getString("value.unknown")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 6;
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 6);
jPanel1.add(fontDescentLabel, gridBagConstraints);
jLabel8.setText(bundle.getString("font.leading")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 7;
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
gridBagConstraints.weighty = 1.0;
jPanel1.add(jLabel8, gridBagConstraints);
fontLeadingLabel.setText(bundle.getString("value.unknown")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 7;
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 6);
jPanel1.add(fontLeadingLabel, gridBagConstraints);
jLabel9.setText(bundle.getString("font.characters")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 8;
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
gridBagConstraints.weighty = 1.0;
jPanel1.add(jLabel9, gridBagConstraints);
fontCharactersScrollPane.setBorder(null);
fontCharactersScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
fontCharactersScrollPane.setHorizontalScrollBar(null);
fontCharactersTextArea.setEditable(false);
fontCharactersTextArea.setColumns(20);
fontCharactersTextArea.setFont(new JLabel().getFont());
fontCharactersTextArea.setLineWrap(true);
fontCharactersTextArea.setWrapStyleWord(true);
fontCharactersTextArea.setMinimumSize(new java.awt.Dimension(250, 16));
fontCharactersTextArea.setOpaque(false);
fontCharactersScrollPane.setViewportView(fontCharactersTextArea);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 8;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 6);
jPanel1.add(fontCharactersScrollPane, gridBagConstraints);
jLabel10.setText(bundle.getString("font.characters.add")); // NOI18N
fontAddCharsButton.setText(bundle.getString("button.ok")); // NOI18N
fontAddCharsButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
fontAddCharsButtonActionPerformed(evt);
}
});
updateTextsCheckBox.setText(bundle.getString("font.updateTexts")); // NOI18N
jLabel11.setText(bundle.getString("font.source")); // NOI18N
fontSelection.setModel(getModel());
fontSelection.setSelectedItem(FontTag.defaultFontName);
fontSelection.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
fontSelectionItemStateChanged(evt);
}
});
fontEmbedButton.setText(bundle.getString("button.font.embed")); // NOI18N
fontEmbedButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
fontEmbedButtonActionPerformed(evt);
}
});
buttonEdit.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jpexs/decompiler/flash/gui/graphics/edit16.png"))); // NOI18N
buttonEdit.setText(bundle.getString("button.edit")); // NOI18N
buttonEdit.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
buttonEditActionPerformed(evt);
}
});
buttonSave.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jpexs/decompiler/flash/gui/graphics/save16.png"))); // NOI18N
buttonSave.setText(bundle.getString("button.save")); // NOI18N
buttonSave.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
buttonSaveActionPerformed(evt);
}
});
buttonCancel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jpexs/decompiler/flash/gui/graphics/cancel16.png"))); // NOI18N
buttonCancel.setText(bundle.getString("button.cancel")); // NOI18N
buttonCancel.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
buttonCancelActionPerformed(evt);
}
});
buttonPreviewFont.setText(bundle.getString("button.preview")); // NOI18N
buttonPreviewFont.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
buttonPreviewFontActionPerformed(evt);
}
});
javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
jPanel2.setLayout(jPanel2Layout);
jPanel2Layout.setHorizontalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 463, Short.MAX_VALUE)
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanel2Layout.createSequentialGroup()
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addComponent(jLabel11)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(fontSelection, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(jPanel2Layout.createSequentialGroup()
.addComponent(jLabel10)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(fontAddCharactersField, javax.swing.GroupLayout.PREFERRED_SIZE, 150, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(fontEmbedButton))
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(jPanel2Layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(buttonEdit)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(buttonSave)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(buttonCancel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 100, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(jPanel2Layout.createSequentialGroup()
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addComponent(fontAddCharsButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(updateTextsCheckBox))
.addComponent(buttonPreviewFont))
.addGap(315, 315, 315)))
.addContainerGap()))
);
jPanel2Layout.setVerticalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 415, Short.MAX_VALUE)
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel10, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(fontAddCharactersField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(fontAddCharsButton)
.addComponent(updateTextsCheckBox))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel11)
.addComponent(fontSelection, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(buttonPreviewFont)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(fontEmbedButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 78, Short.MAX_VALUE)
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(buttonEdit)
.addComponent(buttonSave)
.addComponent(buttonCancel))
.addContainerGap()))
);
jScrollPane1.setViewportView(jPanel2);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 473, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 415, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents
private void fontAddCharsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fontAddCharsButtonActionPerformed
String newchars = fontAddCharactersField.getText();
TreeItem item = mainPanel.tagTree.getCurrentTreeItem();
if (item instanceof FontTag) {
Set<Integer> selChars = new TreeSet<>();
for (int c = 0; c < newchars.length(); c++) {
selChars.add(newchars.codePointAt(c));
}
fontAddChars((FontTag) item, selChars, fontSelection.getSelectedItem().toString());
fontAddCharactersField.setText("");
mainPanel.reload(true);
}
}//GEN-LAST:event_fontAddCharsButtonActionPerformed
private void fontEmbedButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fontEmbedButtonActionPerformed
TreeItem item = mainPanel.tagTree.getCurrentTreeItem();
if (item instanceof FontTag) {
FontTag fontTag = (FontTag) item;
FontEmbedDialog fed = new FontEmbedDialog(fontSelection.getSelectedItem().toString(), fontAddCharactersField.getText(), fontTag.getFontStyle());
if (fed.display()) {
Set<Integer> selChars = fed.getSelectedChars();
if (!selChars.isEmpty()) {
String selFont = fed.getSelectedFont();
fontSelection.setSelectedItem(selFont);
fontAddChars(fontTag, selChars, selFont);
fontAddCharactersField.setText("");
mainPanel.reload(true);
}
}
}
}//GEN-LAST:event_fontEmbedButtonActionPerformed
private void fontSelectionItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_fontSelectionItemStateChanged
TreeItem item = mainPanel.tagTree.getCurrentTreeItem();
if (item instanceof FontTag) {
FontTag f = (FontTag) item;
SWF swf = f.getSwf();
String selectedSystemFont = (String) fontSelection.getSelectedItem();
swf.sourceFontsMap.put(f.getFontId(), selectedSystemFont);
Configuration.addFontPair(swf.getShortFileName(), f.getFontId(), f.getFontName(), selectedSystemFont);
}
}//GEN-LAST:event_fontSelectionItemStateChanged
private void buttonEditActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonEditActionPerformed
setEditable(true);
}//GEN-LAST:event_buttonEditActionPerformed
private void buttonSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonSaveActionPerformed
if (fontTag.isBoldEditable()) {
fontTag.setBold(fontIsBoldCheckBox.isSelected());
}
if (fontTag.isItalicEditable()) {
fontTag.setItalic(fontIsItalicCheckBox.isSelected());
}
setEditable(false);
}//GEN-LAST:event_buttonSaveActionPerformed
private void buttonCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonCancelActionPerformed
showFontTag(fontTag);
setEditable(false);
}//GEN-LAST:event_buttonCancelActionPerformed
private void buttonPreviewFontActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonPreviewFontActionPerformed
String selectedSystemFont = (String) fontSelection.getSelectedItem();
new FontPreviewDialog(null, true, new Font(selectedSystemFont, fontTag.getFontStyle(), 1024)).setVisible(true);
}//GEN-LAST:event_buttonPreviewFontActionPerformed
private void formComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_formComponentResized
jPanel1.updateUI();
}//GEN-LAST:event_formComponentResized
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton buttonCancel;
private javax.swing.JButton buttonEdit;
private javax.swing.JButton buttonPreviewFont;
private javax.swing.JButton buttonSave;
private javax.swing.JTextField fontAddCharactersField;
private javax.swing.JButton fontAddCharsButton;
private javax.swing.JLabel fontAscentLabel;
private javax.swing.JScrollPane fontCharactersScrollPane;
private javax.swing.JTextArea fontCharactersTextArea;
private javax.swing.JTextArea fontCopyrightTextArea;
private javax.swing.JLabel fontDescentLabel;
private javax.swing.JTextArea fontDisplayNameTextArea;
private javax.swing.JButton fontEmbedButton;
private javax.swing.JCheckBox fontIsBoldCheckBox;
private javax.swing.JCheckBox fontIsItalicCheckBox;
private javax.swing.JLabel fontLeadingLabel;
private javax.swing.JLabel fontNameLabel;
private javax.swing.JComboBox fontSelection;
private javax.swing.JLabel jLabel11;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JCheckBox updateTextsCheckBox;
// End of variables declaration//GEN-END:variables
}
@@ -0,0 +1,268 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.3" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
<Properties>
<Property name="defaultCloseOperation" type="int" value="2"/>
<Property name="title" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/FontPreviewDialog.properties" key="fontPreview.dialog.title" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
<Property name="iconImage" type="java.awt.Image" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="default"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[1024, 512]"/>
</Property>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
</SyntheticProperties>
<Events>
<EventHandler event="componentMoved" listener="java.awt.event.ComponentListener" parameters="java.awt.event.ComponentEvent" handler="formComponentMoved"/>
<EventHandler event="componentResized" listener="java.awt.event.ComponentListener" parameters="java.awt.event.ComponentEvent" handler="formComponentResized"/>
</Events>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="comboBoxSampleTexts" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="labelFontName" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="519" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
<Component id="jScrollPane1" alignment="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="comboBoxSampleTexts" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="labelFontName" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="431" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel1">
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
<Component id="jLabel3" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabel4" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabel5" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabel6" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabel7" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabel8" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="labelSample72" min="-2" max="-2" attributes="0"/>
<Component id="labelSample18" min="-2" max="-2" attributes="0"/>
<Component id="labelSample12" min="-2" max="-2" attributes="0"/>
<Component id="labelSample24" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="labelSample36" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="labelSample48" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="labelSample60" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="692" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="labelSample12" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel2" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="labelSample18" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel3" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="labelSample24" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel4" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="labelSample36" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel5" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="labelSample48" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel6" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="labelSample60" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel7" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="labelSample72" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel8" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="labelSample72">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="72" style="0"/>
</Property>
<Property name="text" type="java.lang.String" value="---"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="labelSample60">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="60" style="0"/>
</Property>
<Property name="text" type="java.lang.String" value="---"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="labelSample12">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="12" style="0"/>
</Property>
<Property name="text" type="java.lang.String" value="---"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="labelSample24">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="24" style="0"/>
</Property>
<Property name="text" type="java.lang.String" value="---"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="labelSample48">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="48" style="0"/>
</Property>
<Property name="text" type="java.lang.String" value="---"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="labelSample36">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="36" style="0"/>
</Property>
<Property name="text" type="java.lang.String" value="---"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="labelSample18">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="18" style="0"/>
</Property>
<Property name="text" type="java.lang.String" value="---"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel2">
<Properties>
<Property name="text" type="java.lang.String" value="12"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel3">
<Properties>
<Property name="text" type="java.lang.String" value="18"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel4">
<Properties>
<Property name="text" type="java.lang.String" value="24"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel5">
<Properties>
<Property name="text" type="java.lang.String" value="36"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel6">
<Properties>
<Property name="text" type="java.lang.String" value="48"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel7">
<Properties>
<Property name="text" type="java.lang.String" value="60"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel8">
<Properties>
<Property name="text" type="java.lang.String" value="72"/>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
<Component class="javax.swing.JComboBox" name="comboBoxSampleTexts">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="getModel()" type="code"/>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="comboBoxSampleTextsItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jpexs/decompiler/flash/gui/locales/MainFrame.properties" key="font.name" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="labelFontName">
<Properties>
<Property name="text" type="java.lang.String" value="-"/>
</Properties>
</Component>
</SubComponents>
</Form>
@@ -0,0 +1,315 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.helpers.utf8.Utf8Helper;
import java.awt.Font;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
/**
*
* @author JPEXS
*/
public class FontPreviewDialog extends AppDialog {
/**
* Creates new form FontPreviewDialog
*
* @param parent
* @param font
* @param modal
*/
public FontPreviewDialog(java.awt.Frame parent, boolean modal, Font font) {
super();
setModal(true);
initComponents();
View.setWindowIcon(this);
labelSample12.setFont(font.deriveFont(Font.PLAIN, 12));
labelSample18.setFont(font.deriveFont(Font.PLAIN, 18));
labelSample24.setFont(font.deriveFont(Font.PLAIN, 24));
labelSample36.setFont(font.deriveFont(Font.PLAIN, 36));
labelSample48.setFont(font.deriveFont(Font.PLAIN, 48));
labelSample60.setFont(font.deriveFont(Font.PLAIN, 60));
labelSample72.setFont(font.deriveFont(Font.PLAIN, 72));
comboBoxSampleTexts.setSelectedIndex(Configuration.guiFontPreviewSampleText.get(0));
if (Configuration.guiFontPreviewWidth.hasValue()) {
int width = Configuration.guiFontPreviewWidth.get();
int height = Configuration.guiFontPreviewHeight.get();
setSize(width, height);
}
if (Configuration.guiFontPreviewPosX.hasValue()) {
int posX = Configuration.guiFontPreviewPosX.get();
int posY = Configuration.guiFontPreviewPosY.get();
setLocation(posX, posY);
}
setText((String) comboBoxSampleTexts.getSelectedItem());
labelFontName.setText(font.getFontName());
}
private void setText(String text) {
labelSample12.setText(text);
labelSample18.setText(text);
labelSample24.setText(text);
labelSample36.setText(text);
labelSample48.setText(text);
labelSample60.setText(text);
labelSample72.setText(text);
}
private ComboBoxModel<String> getModel() {
List<String> sampleTexts = new ArrayList<>();
BufferedReader br = new BufferedReader(new InputStreamReader(FontPreviewDialog.class.getResourceAsStream("/com/jpexs/decompiler/flash/tags/font/font_preview_samples.txt"), Utf8Helper.charset));
String s;
try {
while ((s = br.readLine()) != null) {
sampleTexts.add(s);
}
} catch (IOException ex) {
Logger.getLogger(FontPreviewDialog.class.getName()).log(Level.SEVERE, "Cannot read font preview dialog sample texts", ex);
}
return new DefaultComboBoxModel<>(sampleTexts.toArray(new String[sampleTexts.size()]));
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
jPanel1 = new javax.swing.JPanel();
labelSample72 = new javax.swing.JLabel();
labelSample60 = new javax.swing.JLabel();
labelSample12 = new javax.swing.JLabel();
labelSample24 = new javax.swing.JLabel();
labelSample48 = new javax.swing.JLabel();
labelSample36 = new javax.swing.JLabel();
labelSample18 = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel();
jLabel3 = new javax.swing.JLabel();
jLabel4 = new javax.swing.JLabel();
jLabel5 = new javax.swing.JLabel();
jLabel6 = new javax.swing.JLabel();
jLabel7 = new javax.swing.JLabel();
jLabel8 = new javax.swing.JLabel();
comboBoxSampleTexts = new javax.swing.JComboBox();
jLabel1 = new javax.swing.JLabel();
labelFontName = new javax.swing.JLabel();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("com/jpexs/decompiler/flash/gui/locales/FontPreviewDialog"); // NOI18N
setTitle(bundle.getString("fontPreview.dialog.title")); // NOI18N
setPreferredSize(new java.awt.Dimension(1024, 512));
addComponentListener(new java.awt.event.ComponentAdapter() {
public void componentMoved(java.awt.event.ComponentEvent evt) {
formComponentMoved(evt);
}
public void componentResized(java.awt.event.ComponentEvent evt) {
formComponentResized(evt);
}
});
labelSample72.setFont(new java.awt.Font("Tahoma", 0, 72)); // NOI18N
labelSample72.setText("---");
labelSample60.setFont(new java.awt.Font("Tahoma", 0, 60)); // NOI18N
labelSample60.setText("---");
labelSample12.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
labelSample12.setText("---");
labelSample24.setFont(new java.awt.Font("Tahoma", 0, 24)); // NOI18N
labelSample24.setText("---");
labelSample48.setFont(new java.awt.Font("Tahoma", 0, 48)); // NOI18N
labelSample48.setText("---");
labelSample36.setFont(new java.awt.Font("Tahoma", 0, 36)); // NOI18N
labelSample36.setText("---");
labelSample18.setFont(new java.awt.Font("Tahoma", 0, 18)); // NOI18N
labelSample18.setText("---");
jLabel2.setText("12");
jLabel3.setText("18");
jLabel4.setText("24");
jLabel5.setText("36");
jLabel6.setText("48");
jLabel7.setText("60");
jLabel8.setText("72");
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel2)
.addComponent(jLabel3)
.addComponent(jLabel4)
.addComponent(jLabel5)
.addComponent(jLabel6)
.addComponent(jLabel7)
.addComponent(jLabel8))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(labelSample72)
.addComponent(labelSample18)
.addComponent(labelSample12)
.addComponent(labelSample24)
.addComponent(labelSample36)
.addComponent(labelSample48)
.addComponent(labelSample60))
.addContainerGap(692, Short.MAX_VALUE))
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(labelSample12)
.addComponent(jLabel2))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(labelSample18)
.addComponent(jLabel3))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(labelSample24)
.addComponent(jLabel4))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(labelSample36)
.addComponent(jLabel5))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(labelSample48)
.addComponent(jLabel6))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(labelSample60)
.addComponent(jLabel7))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(labelSample72)
.addComponent(jLabel8))
.addContainerGap())
);
jScrollPane1.setViewportView(jPanel1);
comboBoxSampleTexts.setModel(getModel());
comboBoxSampleTexts.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
comboBoxSampleTextsItemStateChanged(evt);
}
});
java.util.ResourceBundle bundle1 = java.util.ResourceBundle.getBundle("com/jpexs/decompiler/flash/gui/locales/MainFrame"); // NOI18N
jLabel1.setText(bundle1.getString("font.name")); // NOI18N
labelFontName.setText("-");
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(comboBoxSampleTexts, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(labelFontName)
.addGap(519, 519, 519)))
.addContainerGap())
.addComponent(jScrollPane1)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addComponent(comboBoxSampleTexts, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel1)
.addComponent(labelFontName))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 431, Short.MAX_VALUE))
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void comboBoxSampleTextsItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_comboBoxSampleTextsItemStateChanged
Configuration.guiFontPreviewSampleText.set(comboBoxSampleTexts.getSelectedIndex());
setText((String) comboBoxSampleTexts.getSelectedItem());
}//GEN-LAST:event_comboBoxSampleTextsItemStateChanged
private void formComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_formComponentResized
Configuration.guiFontPreviewWidth.set(getWidth());
Configuration.guiFontPreviewHeight.set(getHeight());
}//GEN-LAST:event_formComponentResized
private void formComponentMoved(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_formComponentMoved
Configuration.guiFontPreviewPosX.set(getX());
Configuration.guiFontPreviewPosY.set(getY());
}//GEN-LAST:event_formComponentMoved
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JComboBox comboBoxSampleTexts;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
private javax.swing.JLabel jLabel5;
private javax.swing.JLabel jLabel6;
private javax.swing.JLabel jLabel7;
private javax.swing.JLabel jLabel8;
private javax.swing.JPanel jPanel1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JLabel labelFontName;
private javax.swing.JLabel labelSample12;
private javax.swing.JLabel labelSample18;
private javax.swing.JLabel labelSample24;
private javax.swing.JLabel labelSample36;
private javax.swing.JLabel labelSample48;
private javax.swing.JLabel labelSample60;
private javax.swing.JLabel labelSample72;
// End of variables declaration//GEN-END:variables
}
@@ -0,0 +1,588 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.gui.generictageditors.BooleanEditor;
import com.jpexs.decompiler.flash.gui.generictageditors.ChangeListener;
import com.jpexs.decompiler.flash.gui.generictageditors.ColorEditor;
import com.jpexs.decompiler.flash.gui.generictageditors.GenericTagEditor;
import com.jpexs.decompiler.flash.gui.generictageditors.NumberEditor;
import com.jpexs.decompiler.flash.gui.generictageditors.ReflectionTools;
import com.jpexs.decompiler.flash.gui.generictageditors.StringEditor;
import com.jpexs.decompiler.flash.gui.helpers.SpringUtilities;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.types.ARGB;
import com.jpexs.decompiler.flash.types.RGB;
import com.jpexs.decompiler.flash.types.RGBA;
import com.jpexs.decompiler.flash.types.annotations.Calculated;
import com.jpexs.decompiler.flash.types.annotations.Conditional;
import com.jpexs.decompiler.flash.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.annotations.Multiline;
import com.jpexs.decompiler.flash.types.annotations.Optional;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.decompiler.flash.types.annotations.parser.ConditionEvaluator;
import com.jpexs.decompiler.flash.types.annotations.parser.ParseException;
import com.jpexs.helpers.Helper;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.SpringLayout;
/**
* Old Generic Tag editor
*
* @author JPEXS
*/
public class GenericTagPanel extends JPanel implements ChangeListener {
private final JEditorPane genericTagPropertiesEditorPane;
private final JPanel genericTagPropertiesEditPanel;
private final JScrollPane genericTagPropertiesEditorPaneScrollPanel;
private final JScrollPane genericTagPropertiesEditPanelScrollPanel;
private Tag tag;
private Tag editedTag;
private List<String> keys = new ArrayList<>();
private Map<String, GenericTagEditor> editors = new HashMap<>();
private Map<String, Component> labels = new HashMap<>();
private Map<String, Component> types = new HashMap<>();
private Map<String, List<Field>> fieldPaths = new HashMap<>();
private Map<String, List<Integer>> fieldIndices = new HashMap<>();
private HeaderLabel hdr;
private Set<String> addKeys = new HashSet<>();
private Map<String, Component> addButtons = new HashMap<>();
private Map<String, Component> removeButtons = new HashMap<>();
public GenericTagPanel() {
super(new BorderLayout());
hdr = new HeaderLabel("");
add(hdr, BorderLayout.NORTH);
genericTagPropertiesEditorPane = new JEditorPane() {
@Override
public boolean getScrollableTracksViewportWidth() {
return true;
}
};
genericTagPropertiesEditorPane.setEditable(false);
genericTagPropertiesEditorPaneScrollPanel = new JScrollPane(genericTagPropertiesEditorPane);
add(genericTagPropertiesEditorPaneScrollPanel, BorderLayout.CENTER);
genericTagPropertiesEditPanel = new JPanel();
genericTagPropertiesEditPanel.setLayout(new SpringLayout());
JPanel edPanel = new JPanel(new BorderLayout());
edPanel.add(genericTagPropertiesEditPanel, BorderLayout.NORTH);
genericTagPropertiesEditPanelScrollPanel = new JScrollPane(edPanel);
}
public void clear() {
editors.clear();
fieldPaths.clear();
fieldIndices.clear();
labels.clear();
types.clear();
keys.clear();
addKeys.clear();
addButtons.clear();
removeButtons.clear();
genericTagPropertiesEditPanel.removeAll();
genericTagPropertiesEditPanel.setSize(0, 0);
}
public void setEditMode(boolean edit, Tag tag) {
if (tag == null) {
tag = this.tag;
}
this.tag = tag;
this.editedTag = Helper.deepCopy(tag);
generateEditControls(editedTag, !edit);
if (edit) {
remove(genericTagPropertiesEditorPaneScrollPanel);
add(genericTagPropertiesEditPanelScrollPanel, BorderLayout.CENTER);
} else {
genericTagPropertiesEditPanel.removeAll();
genericTagPropertiesEditPanel.setSize(0, 0);
remove(genericTagPropertiesEditPanelScrollPanel);
add(genericTagPropertiesEditorPaneScrollPanel, BorderLayout.CENTER);
setTagText(this.tag);
}
revalidate();
repaint();
}
private void setTagText(Tag tag) {
clear();
generateEditControls(tag, true);
String val = "";
for (String key : keys) {
GenericTagEditor ed = editors.get(key);
if (((Component) ed).isVisible()) {
val += key + " : " + ed.getReadOnlyValue() + "<br>";
}
}
//HTML for colors:
val = "<html>" + val + "</html>";
genericTagPropertiesEditorPane.setContentType("text/html");
genericTagPropertiesEditorPane.setText(val);
genericTagPropertiesEditorPane.setCaretPosition(0);
hdr.setText(tag.toString());
}
private void generateEditControls(Tag tag, boolean readonly) {
clear();
generateEditControlsRecursive(tag, "", new ArrayList<Field>(), new ArrayList<Integer>(), readonly);
change(null);
}
private void relayout(int propCount) {
//Lay out the panel.
SpringUtilities.makeCompactGrid(genericTagPropertiesEditPanel,
propCount, 3, //rows, cols
6, 6, //initX, initY
6, 6); //xPad, yPad
revalidate();
repaint();
}
private int generateEditControlsRecursive(final Object obj, String parent, List<Field> parentFields, List<Integer> parentIndices, boolean readonly) {
if (obj == null) {
return 0;
}
Field[] fields = obj.getClass().getDeclaredFields();
int propCount = 0;
for (final Field field : fields) {
try {
if (Modifier.isStatic(field.getModifiers())) {
continue;
}
field.setAccessible(true);
String name = parent + field.getName();
final Object value = field.get(obj);
if (List.class.isAssignableFrom(field.getType())) {
if (value != null) {
int i = 0;
for (Object obj1 : (Iterable) value) {
final String subname = name + "[" + i + "]";
propCount += addEditor(subname, obj, field, i, obj1.getClass(), obj1, parentFields, parentIndices, readonly);
final int fi = i;
i++;
JButton removeButton = new JButton(View.getIcon("close16"));
removeButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
removeItem(obj, field, fi);
}
});
removeButtons.put(subname, removeButton);
}
}
} else if (field.getType().isArray()) {
if (value != null) {
for (int i = 0; i < Array.getLength(value); i++) {
Object item = Array.get(value, i);
String subname = name + "[" + i + "]";
propCount += addEditor(subname, obj, field, i, item.getClass(), item, parentFields, parentIndices, readonly);
final int fi = i;
JButton removeButton = new JButton(View.getIcon("close16"));
removeButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
removeItem(obj, field, fi);
}
});
removeButtons.put(subname, removeButton);
}
}
} else {
propCount += addEditor(name, obj, field, 0, field.getType(), value, parentFields, parentIndices, readonly);
}
if (ReflectionTools.needsIndex(field) && !readonly && !field.getName().equals("clipActionRecords")) { //No clip actions, sorry
JButton addButton = new JButton(View.getIcon("add16"));
addButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
addItem(obj, field);
}
});
name += "[]";
List<Field> parList = new ArrayList<>(parentFields);
parList.add(field);
fieldPaths.put(name, parList);
List<Integer> parIndices = new ArrayList<>(parentIndices);
parIndices.add(0);
fieldIndices.put(name, parIndices);
addRow(name, addButton, field);
addKeys.add(name);
addButtons.put(name, addButton);
}
} catch (IllegalArgumentException | IllegalAccessException ex) {
Logger.getLogger(GenericTagPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
return propCount;
}
private void removeItem(Object obj, Field field, int index) {
final JScrollBar sb = genericTagPropertiesEditPanelScrollPanel.getVerticalScrollBar();
final int val = sb.getValue(); //save scroll top
SWFType swfType = field.getAnnotation(SWFType.class);
if (swfType != null && !swfType.countField().isEmpty()) { //Fields with same countField must be removed from too
Field fields[] = obj.getClass().getDeclaredFields();
for (int f = 0; f < fields.length; f++) {
SWFType fieldSwfType = fields[f].getAnnotation(SWFType.class);
if (fieldSwfType != null && fieldSwfType.countField().equals(swfType.countField())) {
ReflectionTools.removeFromField(obj, fields[f], index);
}
}
try {
//If countField exists, decrement, otherwise do nothing
Field countField = obj.getClass().getDeclaredField(swfType.countField());
if (countField != null) {
int cnt = countField.getInt(obj);
cnt--;
countField.setInt(obj, cnt);
}
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
//ignored
}
} else {
ReflectionTools.removeFromField(obj, field, index);
}
generateEditControls(editedTag, false);
//Restore scroll top after some time. TODO: Handle this better. I don't know how :-(.
new Thread() {
@Override
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
Logger.getLogger(GenericTagPanel.class.getName()).log(Level.SEVERE, null, ex);
}
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
genericTagPropertiesEditPanelScrollPanel.getVerticalScrollBar().setValue(val);
}
});
}
}.start();
revalidate();
repaint();
}
private void addItem(Object obj, Field field) {
final JScrollBar sb = genericTagPropertiesEditPanelScrollPanel.getVerticalScrollBar();
final int val = sb.getValue(); //save scroll top
SWFType swfType = field.getAnnotation(SWFType.class);
if (swfType != null && !swfType.countField().isEmpty()) { //Fields with same countField must be enlarged too
Field fields[] = obj.getClass().getDeclaredFields();
for (int f = 0; f < fields.length; f++) {
SWFType fieldSwfType = fields[f].getAnnotation(SWFType.class);
if (fieldSwfType != null && fieldSwfType.countField().equals(swfType.countField())) {
ReflectionTools.addToField(obj, fields[f], ReflectionTools.getFieldSubSize(obj, fields[f]), true);
}
}
try {
//If countField exists, increment, otherwise do nothing
Field countField = obj.getClass().getDeclaredField(swfType.countField());
if (countField != null) {
int cnt = countField.getInt(obj);
cnt++;
countField.setInt(obj, cnt);
}
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
//ignored
}
} else {
ReflectionTools.addToField(obj, field, ReflectionTools.getFieldSubSize(obj, field), true);
}
generateEditControls(editedTag, false);
//Restore scroll top after some time. TODO: Handle this better. I don't know how :-(.
new Thread() {
@Override
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
Logger.getLogger(GenericTagPanel.class.getName()).log(Level.SEVERE, null, ex);
}
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
genericTagPropertiesEditPanelScrollPanel.getVerticalScrollBar().setValue(val);
}
});
}
}.start();
revalidate();
repaint();
}
private int addEditor(String name, Object obj, Field field, int index, Class<?> type, Object value, List<Field> parentList, List<Integer> parentIndices, boolean readonly) throws IllegalArgumentException, IllegalAccessException {
Calculated calculated = field.getAnnotation(Calculated.class);
if (calculated != null) {
return 0;
}
List<Field> parList = new ArrayList<>(parentList);
parList.add(field);
List<Integer> parIndices = new ArrayList<>(parentIndices);
parIndices.add(index);
Internal inter = field.getAnnotation(Internal.class);
if (inter != null) {
return 0;
}
SWFType swfType = field.getAnnotation(SWFType.class);
Multiline multiline = field.getAnnotation(Multiline.class);
Component editor;
if (type.equals(int.class) || type.equals(Integer.class)
|| type.equals(short.class) || type.equals(Short.class)
|| type.equals(long.class) || type.equals(Long.class)
|| type.equals(double.class) || type.equals(Double.class)
|| type.equals(float.class) || type.equals(Float.class)) {
editor = new NumberEditor(name, obj, field, index, type, swfType);
} else if (type.equals(boolean.class) || type.equals(Boolean.class)) {
editor = new BooleanEditor(name, obj, field, index, type);
} else if (type.equals(String.class)) {
editor = new StringEditor(name, obj, field, index, type, multiline != null);
} else if (type.equals(RGB.class) || type.equals(RGBA.class) || type.equals(ARGB.class)) {
editor = new ColorEditor(name, obj, field, index, type);
} else {
if (value == null) {
if (readonly) {
return 0;
}
Optional opt = field.getAnnotation(Optional.class);
if (opt == null) {
try {
value = ReflectionTools.newInstanceOf(field.getType());
field.set(obj, value);
} catch (InstantiationException | IllegalAccessException ex) {
Logger.getLogger(GenericTagPanel.class.getName()).log(Level.SEVERE, null, ex);
return 0;
}
} else {
return 0;
}
}
return generateEditControlsRecursive(value, name + ".", parList, parIndices, readonly);
}
if (editor instanceof GenericTagEditor) {
GenericTagEditor ce = (GenericTagEditor) editor;
ce.addChangeListener(this);
editors.put(name, ce);
fieldPaths.put(name, parList);
fieldIndices.put(name, parIndices);
addRow(name, editor, field);
}
return 1;
}
private void addRow(String name, Component editor, Field field) {
JLabel label = new JLabel(name + ":", JLabel.TRAILING);
label.setVerticalAlignment(JLabel.TOP);
genericTagPropertiesEditPanel.add(label);
label.setLabelFor(editor);
labels.put(name, label);
genericTagPropertiesEditPanel.add(editor);
JLabel typeLabel = new JLabel(swfTypeToString(field.getAnnotation(SWFType.class)), JLabel.TRAILING);
typeLabel.setVerticalAlignment(JLabel.TOP);
genericTagPropertiesEditPanel.add(typeLabel);
types.put(name, typeLabel);
keys.add(name);
}
public String swfTypeToString(SWFType swfType) {
if (swfType == null) {
return null;
}
String result = swfType.value().toString();
if (swfType.count() > 0) {
result += "[" + swfType.count();
if (swfType.countAdd() > 0) {
result += " + " + swfType.countAdd();
}
result += "]";
} else if (!swfType.countField().isEmpty()) {
result += "[" + swfType.countField();
if (swfType.countAdd() > 0) {
result += " + " + swfType.countAdd();
}
result += "]";
}
return result;
}
private void assignTag(Tag t, Tag assigned) {
if (t.getClass() != assigned.getClass()) {
return;
}
for (Field f : t.getClass().getDeclaredFields()) {
if ((f.getModifiers() & Modifier.FINAL) == Modifier.FINAL) {
continue;
}
if ((f.getModifiers() & Modifier.STATIC) == Modifier.STATIC) {
continue;
}
try {
f.set(t, f.get(assigned));
} catch (IllegalArgumentException | IllegalAccessException ex) {
Logger.getLogger(GenericTagPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public void save() {
for (Object component : genericTagPropertiesEditPanel.getComponents()) {
if (component instanceof GenericTagEditor) {
((GenericTagEditor) component).save();
}
}
SWF swf = tag.getSwf();
assignTag(tag, editedTag);
tag.setModified(true);
tag.setSwf(swf);
setTagText(tag);
}
public Tag getTag() {
return tag;
}
@Override
public void change(GenericTagEditor ed) {
for (String key : editors.keySet()) {
GenericTagEditor dependentEditor = editors.get(key);
Component dependentLabel = labels.get(key);
Component dependentTypeLabel = types.get(key);
List<Field> path = fieldPaths.get(key);
List<Integer> indices = fieldIndices.get(key);
String p = "";
boolean conditionMet = true;
for (int i = 0; i < path.size(); i++) {
Field f = path.get(i);
int index = indices.get(i);
String par = p;
if (!p.isEmpty()) {
p += ".";
}
p += f.getName();
if (ReflectionTools.needsIndex(f)) {
p += "[" + index + "]";
}
Conditional cond = f.getAnnotation(Conditional.class);
if (cond != null) {
ConditionEvaluator ev = new ConditionEvaluator(cond);
try {
Set<String> fieldNames = ev.getFields();
Map<String, Boolean> fields = new HashMap<>();
for (String fld : fieldNames) {
String ckey = "";
if (!par.isEmpty()) {
ckey = par + ".";
}
ckey += fld;
if (editors.containsKey(ckey)) {
GenericTagEditor editor = editors.get(ckey);
Object val = editor.getChangedValue();
fields.put(fld, true);
if (val instanceof Boolean) {
fields.put(fld, (Boolean) val);
}
}
}
boolean ok = ev.eval(fields);
if (conditionMet) {
conditionMet = ok;
}
((Component) dependentEditor).setVisible(conditionMet);
dependentLabel.setVisible(conditionMet);
dependentTypeLabel.setVisible(conditionMet);
} catch (ParseException ex) {
Logger.getLogger(GenericTagPanel.class.getName()).log(Level.SEVERE, "Invalid condition", ex);
}
}
if (!conditionMet) {
break;
}
}
}
genericTagPropertiesEditPanel.removeAll();
genericTagPropertiesEditPanel.setSize(0, 0);
int propCount = 0;
for (String key : keys) {
Component dependentEditor = null;
if (addKeys.contains(key)) {
dependentEditor = addButtons.get(key);
} else if (removeButtons.containsKey(key)) { //It's array/list, add remove button
JPanel editRemPanel = new JPanel(new BorderLayout());
editRemPanel.add((Component) editors.get(key), BorderLayout.CENTER);
editRemPanel.add(removeButtons.get(key), BorderLayout.EAST);
dependentEditor = editRemPanel;
} else {
dependentEditor = (Component) editors.get(key);
}
Component dependentLabel = labels.get(key);
Component dependentTypeLabel = types.get(key);
if (dependentEditor.isVisible()) {
genericTagPropertiesEditPanel.add(dependentLabel);
genericTagPropertiesEditPanel.add(((Component) dependentEditor));
genericTagPropertiesEditPanel.add(dependentTypeLabel);
propCount++;
}
}
/*genericTagPropertiesEditPanel.add(new JPanel());
genericTagPropertiesEditPanel.add(new JPanel());
genericTagPropertiesEditPanel.add(new JPanel());*/
relayout(propCount /*+ 1*/);
}
}
@@ -0,0 +1,896 @@
/*
* Copyright (C) 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.AppStrings;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.gui.generictageditors.BooleanEditor;
import com.jpexs.decompiler.flash.gui.generictageditors.ColorEditor;
import com.jpexs.decompiler.flash.gui.generictageditors.GenericTagEditor;
import com.jpexs.decompiler.flash.gui.generictageditors.NumberEditor;
import com.jpexs.decompiler.flash.gui.generictageditors.ReflectionTools;
import com.jpexs.decompiler.flash.gui.generictageditors.StringEditor;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.types.ARGB;
import com.jpexs.decompiler.flash.types.BasicType;
import com.jpexs.decompiler.flash.types.RGB;
import com.jpexs.decompiler.flash.types.RGBA;
import com.jpexs.decompiler.flash.types.annotations.Conditional;
import com.jpexs.decompiler.flash.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.annotations.Multiline;
import com.jpexs.decompiler.flash.types.annotations.SWFArray;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.decompiler.flash.types.annotations.parser.ConditionEvaluator;
import com.jpexs.decompiler.flash.types.annotations.parser.ParseException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.EventObject;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractCellEditor;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeModelListener;
import javax.swing.plaf.basic.BasicLabelUI;
import javax.swing.plaf.basic.BasicTreeUI;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellEditor;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
/**
*
* @author JPEXS
*/
public class GenericTagTreePanel extends GenericTagPanel {
private JTree tree;
private Tag editedTag;
private class MyTree extends JTree {
public MyTree() {
setBackground(Color.white);
setUI(new BasicTreeUI() {
@Override
public void paint(Graphics g, JComponent c) {
setHashColor(Color.gray);
super.paint(g, c);
}
});
setCellRenderer(new MyTreeCellRenderer());
setCellEditor(new MyTreeCellEditor(this));
setInvokesStopCellEditing(true);
}
}
private class MyTreeCellEditor extends AbstractCellEditor implements TreeCellEditor {
private GenericTagEditor editor = null;
private final JTree tree;
private FieldNode fnode;
public MyTreeCellEditor(JTree tree) {
this.tree = tree;
}
@Override
public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) {
if (value instanceof FieldNode) {
fnode = (FieldNode) value;
Field field = fnode.field;
int index = fnode.index;
Object obj = fnode.obj;
Class<?> type;
try {
type = ReflectionTools.getValue(obj, field, index).getClass();
} catch (IllegalArgumentException | IllegalAccessException ex) {
ex.printStackTrace();
return null;
}
SWFType swfType = field.getAnnotation(SWFType.class);
Multiline multiline = field.getAnnotation(Multiline.class);
if (type.equals(int.class) || type.equals(Integer.class)
|| type.equals(short.class) || type.equals(Short.class)
|| type.equals(long.class) || type.equals(Long.class)
|| type.equals(double.class) || type.equals(Double.class)
|| type.equals(float.class) || type.equals(Float.class)) {
editor = new NumberEditor(field.getName(), obj, field, index, type, swfType);
} else if (type.equals(boolean.class) || type.equals(Boolean.class)) {
editor = new BooleanEditor(field.getName(), obj, field, index, type);
} else if (type.equals(String.class)) {
editor = new StringEditor(field.getName(), obj, field, index, type, multiline != null);
} else if (type.equals(RGB.class) || type.equals(RGBA.class) || type.equals(ARGB.class)) {
editor = new ColorEditor(field.getName(), obj, field, index, type);
}
JPanel pan = new JPanel();
FlowLayout fl = new FlowLayout(FlowLayout.LEFT, 0, 0);
fl.setAlignOnBaseline(true);
pan.setLayout(fl);
JLabel nameLabel = new JLabel(fnode.getNameType() + " = ") {
@Override
public BaselineResizeBehavior getBaselineResizeBehavior() {
return Component.BaselineResizeBehavior.CONSTANT_ASCENT;
}
@Override
public int getBaseline(int width, int height) {
return 0;
}
};
pan.setBackground(Color.white);
nameLabel.setSize(nameLabel.getWidth(), ((Component) editor).getHeight());
nameLabel.setAlignmentY(TOP_ALIGNMENT);
((JComponent) editor).setAlignmentY(TOP_ALIGNMENT);
pan.add(nameLabel);
pan.add((Component) editor);
pan.setPreferredSize(new Dimension((int) nameLabel.getPreferredSize().getWidth() + 5 + (int) ((Component) editor).getPreferredSize().getWidth(), (int) ((Component) editor).getPreferredSize().getHeight()));
return pan;
}
return null;
}
@Override
public Object getCellEditorValue() {
return editor.getChangedValue();
}
@Override
public boolean isCellEditable(EventObject e) {
if (!(e instanceof MouseEvent)) {
return false;
}
MouseEvent me = (MouseEvent) e;
TreePath path = tree.getPathForLocation(me.getX(), me.getY());
if (path == null) {
return false;
}
Object obj = path.getLastPathComponent();
boolean ret = super.isCellEditable(e)
&& path != null && (tree.getModel().isLeaf(obj));
return ret;
}
@Override
public boolean stopCellEditing() {
super.stopCellEditing();
/*List<FieldNode> depends = ((MyTreeModel) tree.getModel()).getDependentFields(fnode);
boolean dep = false;
if (!depends.isEmpty()) {
dep = true;
} */
editor.save();
((MyTreeModel) tree.getModel()).vchanged(tree.getSelectionPath());
refreshTree();
return true;
}
}
public GenericTagTreePanel() {
setLayout(new BorderLayout());
tree = new MyTree();
add(new JScrollPane(tree), BorderLayout.CENTER);
tree.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (!tree.isEditable()) {
return;
}
int selRow = tree.getRowForLocation(e.getX(), e.getY());
TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
if (selRow != -1 && selPath != null) {
if (e.getClickCount() == 1) {
if (e.getButton() == MouseEvent.BUTTON3) { //right click
Object selObject = selPath.getLastPathComponent();
if (selObject instanceof FieldNode) {
final FieldNode fnode = (FieldNode) selObject;
SWFArray swfArray = fnode.field.getAnnotation(SWFArray.class);
String itemStr = "";
if (swfArray != null) {
itemStr = swfArray.value();
}
if (itemStr.isEmpty()) {
itemStr = AppStrings.translate("generictag.array.item");
}
if (ReflectionTools.needsIndex(fnode.field)) {
boolean canAdd = true;
if (!ReflectionTools.canAddToField(fnode.obj, fnode.field)) {
canAdd = false;
}
JPopupMenu p = new JPopupMenu();
JMenuItem mi;
mi = new JMenuItem(AppStrings.translate("generictag.array.insertbeginning").replace("%item%", itemStr));
mi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
addItem(fnode.obj, fnode.field, 0);
}
});
if (!canAdd) {
mi.setEnabled(false);
}
p.add(mi);
if (fnode.index > -1) {
mi = new JMenuItem(AppStrings.translate("generictag.array.insertbefore").replace("%item%", itemStr));
mi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
addItem(fnode.obj, fnode.field, fnode.index);
}
});
if (!canAdd) {
mi.setEnabled(false);
}
p.add(mi);
mi = new JMenuItem(AppStrings.translate("generictag.array.remove").replace("%item%", itemStr));
mi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
removeItem(fnode.obj, fnode.field, fnode.index);
}
});
p.add(mi);
mi = new JMenuItem(AppStrings.translate("generictag.array.insertafter").replace("%item%", itemStr));
mi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
addItem(fnode.obj, fnode.field, fnode.index + 1);
}
});
if (!canAdd) {
mi.setEnabled(false);
}
p.add(mi);
}
mi = new JMenuItem(AppStrings.translate("generictag.array.insertend").replace("%item%", itemStr));
mi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
addItem(fnode.obj, fnode.field, ReflectionTools.getFieldSubSize(fnode.obj, fnode.field));
}
});
if (!canAdd) {
mi.setEnabled(false);
}
p.add(mi);
//}
p.show(tree, e.getX(), e.getY());
}
}
}
} else if (e.getClickCount() == 2) {
//myDoubleClick(selRow, selPath);
}
}
}
});
}
private Tag tag;
public class MyTreeCellRenderer extends DefaultTreeCellRenderer {
@Override
public Component getTreeCellRendererComponent(
JTree tree,
Object value,
boolean sel,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus) {
super.getTreeCellRendererComponent(
tree, value, sel,
expanded, leaf, row,
hasFocus);
setUI(new BasicLabelUI());
setOpaque(false);
setBackgroundNonSelectionColor(Color.white);
return this;
}
}
@Override
public void clear() {
}
private static class FieldNode extends DefaultMutableTreeNode {
private Object obj;
private Field field;
private int index;
public FieldNode(Object obj, Field field, int index) {
this.obj = obj;
this.field = field;
this.index = index;
}
@Override
public void setUserObject(Object userObject) {
}
/*
*/
@Override
public String toString() {
String valStr = "";
if (ReflectionTools.needsIndex(field) && (index == -1)) {
valStr += "";
} else if (hasEditor(obj, field, index)) {
Object val = getValue();
Color color = null;
String colorAdd = "";
if (val instanceof RGB) { //Note: Can be RGBA too
color = ((RGB) val).toColor();
}
if (val instanceof ARGB) {
color = ((ARGB) val).toColor();
}
if (color != null) {
colorAdd = "<cite style=\"color:rgb(" + color.getRed() + "," + color.getGreen() + "," + color.getBlue() + ");\">●</cite> ";
}
valStr += " = " + colorAdd + val.toString();
}
return "<html>" + getNameType() + valStr + "</html>";
}
public String getType() {
SWFType swfType = field.getAnnotation(SWFType.class);
SWFArray swfArray = field.getAnnotation(SWFArray.class);
String typeStr = null;
if ((swfType != null || swfArray != null) && !(ReflectionTools.needsIndex(field) && (index > -1))) {
Class<?> type = field.getType();
if (ReflectionTools.needsIndex(field)) {
type = ReflectionTools.getFieldSubType(obj, field);
}
typeStr = swfTypeToString(type, swfType, swfArray);
}
return typeStr;
}
public String getNameType() {
String typeStr = getType();
return getName() + (typeStr != null ? " : " + typeStr : "");
}
public String getName() {
SWFArray swfArray = field.getAnnotation(SWFArray.class);
String name = "";
if (swfArray != null) {
name = swfArray.value();
}
return (index > -1 ? name + "[" + index + "]" : field.getName());
}
public Object getValue() {
try {
if (ReflectionTools.needsIndex(field) && (index == -1)) {
return obj;
}
Object val = ReflectionTools.getValue(obj, field, index);
if (val == null) {
try {
val = ReflectionTools.newInstanceOf(field.getType());
ReflectionTools.setValue(obj, field, index, val);
} catch (InstantiationException | IllegalAccessException ex) {
Logger.getLogger(GenericTagPanel.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
return val;
} catch (IllegalArgumentException | IllegalAccessException ex) {
return null;
}
}
@Override
public int hashCode() {
int hash = 7;
hash = 11 * hash + Objects.hashCode(this.obj);
hash = 11 * hash + Objects.hashCode(this.field);
hash = 11 * hash + this.index;
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final FieldNode other = (FieldNode) obj;
if (!Objects.equals(this.obj, other.obj)) {
return false;
}
if (!Objects.equals(this.field, other.field)) {
return false;
}
if (this.index != other.index) {
return false;
}
return true;
}
}
private static class MyTreeModel extends DefaultTreeModel {
private final Object mtroot;
private final List<TreeModelListener> listeners = new ArrayList<>();
private final Map<String, Object> nodeCache = new HashMap<>();
// it is much faster to store the reverse mappings, too
private final Map<Object, String> nodeCacheReverse = new HashMap<>();
private Object getNodeByPath(String path) {
if (nodeCache.containsKey(path)) {
return nodeCache.get(path);
}
return null;
}
public String getNodePathName(Object find) {
if (nodeCacheReverse.containsKey(find)) {
return nodeCacheReverse.get(find);
}
return null;
}
public List<FieldNode> getDependentFields(FieldNode fnode) {
List<FieldNode> ret = new ArrayList<>();
getDependentFields(getNodePathName(fnode), mtroot.getClass().getSimpleName(), mtroot, ret);
return ret;
}
public void getDependentFields(String dependence, String currentPath, Object node, List<FieldNode> ret) {
if (node instanceof FieldNode) {
FieldNode fnode = (FieldNode) node;
Conditional cond = fnode.field.getAnnotation(Conditional.class);
if (cond != null) {
ConditionEvaluator ev = new ConditionEvaluator(cond);
String parentPath = currentPath.indexOf('.') == -1 ? "" : currentPath.substring(0, currentPath.lastIndexOf('.'));
try {
for (String cname : ev.getFields()) {
String fullParh = parentPath + "." + cname;
if (fullParh.equals(dependence)) {
ret.add(fnode);
break;
}
}
} catch (ParseException ex) {
Logger.getLogger(GenericTagTreePanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
int count = getChildCount(node);
for (int i = 0; i < count; i++) {
FieldNode f = (FieldNode) getChild(node, i);
getDependentFields(dependence, currentPath + "." + f.getName(), f, ret);
}
}
public MyTreeModel(Tag root) {
super(new DefaultMutableTreeNode(root));
this.mtroot = root;
buildCache(root, "");
}
private void buildCache(Object obj, String parentPath) {
if (!"".equals(parentPath)) {
parentPath += ".";
}
if (obj instanceof FieldNode) {
FieldNode fn = (FieldNode) obj;
parentPath += fn.getName();
} else {
parentPath += obj.getClass().getSimpleName();
}
nodeCache.put(parentPath, obj);
nodeCacheReverse.put(obj, parentPath);
int count = getChildCount(obj, false);
for (int i = 0; i < count; i++) {
buildCache(getChild(obj, i, false), parentPath);
}
}
@Override
public Object getRoot() {
return mtroot;
}
private Object getChild(Object parent, int index, boolean limited) {
if (parent == mtroot) {
return new FieldNode(mtroot, filterFields(this, mtroot.getClass().getSimpleName(), mtroot.getClass(), limited).get(index), -1);
}
FieldNode fnode = (FieldNode) parent;
Field field = fnode.field;
if (ReflectionTools.needsIndex(field) && (fnode.index == -1)) { //Arrays ot Lists
return new FieldNode(fnode.obj, field, index);
}
parent = fnode.getValue();
return new FieldNode(parent, filterFields(this, getNodePathName(fnode), parent.getClass(), limited).get(index), -1);
}
@Override
public Object getChild(Object parent, int index) {
return getChild(parent, index, true);
}
@Override
public int getChildCount(Object parent) {
return getChildCount(parent, true);
}
private int getChildCount(Object parent, boolean limited) {
if (parent == mtroot) {
return filterFields(this, mtroot.getClass().getSimpleName(), mtroot.getClass(), limited).size();
}
FieldNode fnode = (FieldNode) parent;
if (isLeaf(fnode)) {
return 0;
}
Field field = fnode.field;
if (ReflectionTools.needsIndex(field) && (fnode.index == -1)) { //Arrays or Lists
try {
if (field.get(fnode.obj) == null) {
// todo: instanciate the (Array)List or Array to allow adding items to it
return 0;
}
} catch (IllegalArgumentException | IllegalAccessException ex) {
return 0;
}
return ReflectionTools.getFieldSubSize(fnode.obj, field);
}
parent = fnode.getValue();
return filterFields(this, getNodePathName(fnode), parent.getClass(), limited).size();
}
@Override
public boolean isLeaf(Object node) {
if (node == mtroot) {
return false;
}
FieldNode fnode = (FieldNode) node;
Field field = fnode.field;
if (ReflectionTools.needsIndex(field) && fnode.index == -1) {
return false;
}
boolean r = hasEditor(fnode.obj, field, fnode.index);
return r;
}
public void vchanged(TreePath path) {
fireTreeNodesChanged(this, path.getPath(), null, null);
}
@Override
public int getIndexOfChild(Object parent, Object child) {
int cnt = getChildCount(parent);
for (int i = 0; i < cnt; i++) {
if (getChild(parent, i).equals(child)) {
return i;
}
}
return -1;
}
}
private TreeModel getModel() {
return new MyTreeModel(editedTag);
}
@Override
public void setEditMode(boolean edit, Tag tag) {
if (tag == null) {
tag = this.tag;
}
this.tag = tag;
SWF swf = tag.getSwf();
try {
this.editedTag = SWFInputStream.resolveTag(swf, tag, 0, false, true, swf.gfx);
} catch (InterruptedException ex) {
}
tree.setEditable(edit);
if (!edit) {
tree.stopEditing();
}
refreshTree();
}
@Override
public void save() {
tree.stopEditing();
SWF swf = tag.getSwf();
assignTag(tag, editedTag);
tag.setModified(true);
tag.setSwf(swf);
}
private void assignTag(Tag t, Tag assigned) {
if (t.getClass() != assigned.getClass()) {
return;
}
for (Field f : getAvailableFields(t.getClass())) {
try {
f.set(t, f.get(assigned));
} catch (IllegalArgumentException | IllegalAccessException ex) {
Logger.getLogger(GenericTagPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
@Override
public Tag getTag() {
return tag;
}
public static String swfArrayToString(SWFArray swfArray) {
String result = "";
if (swfArray == null) {
return result;
}
if (swfArray.count() > 0) {
result += "[" + swfArray.count() + "]";
} else if (!swfArray.countField().isEmpty()) {
result += "[" + swfArray.countField() + "]";
}
return result;
}
public static String swfTypeToString(Class<?> type, SWFType swfType, SWFArray swfArray) {
String stype = type.getSimpleName();
if (swfType == null) {
return stype + swfArrayToString(swfArray);
}
String result = swfType.value().toString();
if (swfType.value() == BasicType.OTHER) {
result = stype;
}
if (swfType.count() > 0) {
result += "[" + swfType.count();
if (swfType.countAdd() > 0) {
result += " + " + swfType.countAdd();
}
result += "]";
} else if (!swfType.countField().isEmpty()) {
result += "[" + swfType.countField();
if (swfType.countAdd() > 0) {
result += " + " + swfType.countAdd();
}
result += "]";
}
return result + swfArrayToString(swfArray);
}
private static boolean hasEditor(Object obj, Field field, int index) {
if (ReflectionTools.needsIndex(field) && index == -1) {
return false;
}
Class<?> type;
try {
Object val = ReflectionTools.getValue(obj, field, index);
if (val == null) {
return false;
}
type = val.getClass();
} catch (IllegalArgumentException | IllegalAccessException ex) {
return false;
}
SWFType swfType = field.getAnnotation(SWFType.class);
Multiline multiline = field.getAnnotation(Multiline.class);
if (type.equals(int.class) || type.equals(Integer.class)
|| type.equals(short.class) || type.equals(Short.class)
|| type.equals(long.class) || type.equals(Long.class)
|| type.equals(double.class) || type.equals(Double.class)
|| type.equals(float.class) || type.equals(Float.class)) {
return true;
} else if (type.equals(boolean.class) || type.equals(Boolean.class)) {
return true;
} else if (type.equals(String.class)) {
return true;
} else if (type.equals(RGB.class) || type.equals(RGBA.class) || type.equals(ARGB.class)) {
return true;
} else {
return false;
}
}
private static List<Field> filterFields(MyTreeModel mod, String parentPath, Class<?> cls, boolean limited) {
List<Field> ret = new ArrayList<>();
List<Field> fields = getAvailableFields(cls);
for (Field f : fields) {
if (limited) {
Conditional cond = f.getAnnotation(Conditional.class);
if (cond != null) {
ConditionEvaluator ev = new ConditionEvaluator(cond);
try {
Map<String, Boolean> fieldMap = new HashMap<>();
for (String sf : ev.getFields()) {
String fulldf = parentPath + "." + sf;
FieldNode condnode = (FieldNode) (mod).getNodeByPath(fulldf);
if (condnode != null) {
fieldMap.put(sf, (Boolean) ReflectionTools.getValue(condnode.obj, condnode.field, condnode.index));
} else {
fieldMap.put(sf, true);
}
}
if (!ev.eval(fieldMap)) {
continue;
}
} catch (ParseException | IllegalArgumentException | IllegalAccessException ex) {
Logger.getLogger(GenericTagTreePanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
ret.add(f);
}
return ret;
}
private static List<Field> getAvailableFields(Class<?> cls) {
List<Field> ret = new ArrayList<>();
Field fields[] = cls.getFields();
for (Field f : fields) {
if (Modifier.isStatic(f.getModifiers())) {
continue;
}
f.setAccessible(true);
Internal inter = f.getAnnotation(Internal.class);
if (inter != null) {
continue;
}
ret.add(f);
}
return ret;
}
private void addItem(Object obj, Field field, int index) {
SWFArray swfArray = field.getAnnotation(SWFArray.class);
if (swfArray != null && !swfArray.countField().isEmpty()) { //Fields with same countField must be enlarged too
Field fields[] = obj.getClass().getDeclaredFields();
List<Integer> sameFlds = new ArrayList<>();
for (int f = 0; f < fields.length; f++) {
SWFArray fieldSwfArray = fields[f].getAnnotation(SWFArray.class);
if (fieldSwfArray != null && fieldSwfArray.countField().equals(swfArray.countField())) {
sameFlds.add(f);
if (!ReflectionTools.canAddToField(obj, fields[f])) {
JOptionPane.showMessageDialog(this, "This field is abstract, cannot be instantiated, sorry."); //TODO!!!
return;
}
}
}
for (int f : sameFlds) {
ReflectionTools.addToField(obj, fields[f], index, true);
}
try {
//If countField exists, increment, otherwise do nothing
Field countField = obj.getClass().getDeclaredField(swfArray.countField());
if (countField != null) {
int cnt = countField.getInt(obj);
cnt++;
countField.setInt(obj, cnt);
}
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
//ignored
}
} else {
if (!ReflectionTools.canAddToField(obj, field)) {
JOptionPane.showMessageDialog(this, "This field is abstract, cannot be instantiated, sorry."); //TODO!!!
return;
}
ReflectionTools.addToField(obj, field, index, true);
}
refreshTree();
}
public void refreshTree() {
View.refreshTree(tree, getModel());
revalidate();
repaint();
}
private void removeItem(Object obj, Field field, int index) {
SWFArray swfArray = field.getAnnotation(SWFArray.class);
if (swfArray != null && !swfArray.countField().isEmpty()) { //Fields with same countField must be removed from too
Field fields[] = obj.getClass().getDeclaredFields();
for (int f = 0; f < fields.length; f++) {
SWFArray fieldSwfArray = fields[f].getAnnotation(SWFArray.class);
if (fieldSwfArray != null && fieldSwfArray.countField().equals(swfArray.countField())) {
ReflectionTools.removeFromField(obj, fields[f], index);
}
}
try {
//If countField exists, decrement, otherwise do nothing
Field countField = obj.getClass().getDeclaredField(swfArray.countField());
if (countField != null) {
int cnt = countField.getInt(obj);
cnt--;
countField.setInt(obj, cnt);
}
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
//ignored
}
} else {
ReflectionTools.removeFromField(obj, field, index);
}
refreshTree();
}
}
@@ -0,0 +1,334 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.graph.Graph;
import com.jpexs.decompiler.graph.GraphPart;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
/**
*
* @author JPEXS
*/
public class GraphFrame extends AppFrame {
private class GraphPanel extends JPanel {
private static final int SPACE_VERTICAL = 16;
private static final int SPACE_HORIZONTAL = 10;
private static final int SPACE_BACKLINKS = 5;
private static final int BLOCK_WIDTH = 200;
private static final int BLOCK_HEIGHT = 20;
private final HashMap<GraphPart, Point> partPos = new HashMap<>();
private final Point size;
private int backLinksLeft = 0;
private int backLinksRight = 0;
private final GraphPart head;
public GraphPanel(Graph graph) throws InterruptedException {
graph.init(null);
size = getPartPositions(head = graph.heads.get(0), SPACE_VERTICAL + SPACE_VERTICAL + BLOCK_HEIGHT / 2, getPartWidth(graph.heads.get(0), new HashSet<GraphPart>()) * (BLOCK_WIDTH + SPACE_HORIZONTAL) / 2 - SPACE_HORIZONTAL, partPos, true);
backLinksLeft = 1;
backLinksRight = 1;
for (GraphPart part : partPos.keySet()) {
Point p = partPos.get(part);
for (GraphPart n : part.nextParts) {
Point npos = partPos.get(n);
if (npos.y < p.y) {
if (p.x > size.x / 2) {
backLinksRight++;
} else {
backLinksLeft++;
}
}
}
}
size.x += 2 * SPACE_BACKLINKS + backLinksLeft * SPACE_BACKLINKS + backLinksRight * SPACE_BACKLINKS;
setPreferredSize(new Dimension(size.x, size.y));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
/*g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);*/
g2.setColor(Color.black);
int startX = SPACE_BACKLINKS + backLinksLeft * SPACE_BACKLINKS;
int blLeft = 0;
int blRight = 0;
for (GraphPart part : partPos.keySet()) {
Point p = partPos.get(part);
g2.setColor(Color.white);
g2.fillRect(startX + p.x - BLOCK_WIDTH / 2, p.y - BLOCK_HEIGHT / 2, BLOCK_WIDTH, BLOCK_HEIGHT);
g2.setColor(Color.black);
g2.drawRect(startX + p.x - BLOCK_WIDTH / 2, p.y - BLOCK_HEIGHT / 2, BLOCK_WIDTH, BLOCK_HEIGHT);
g2.drawString(part.toString(), startX + p.x - g2.getFontMetrics().stringWidth(part.toString()) / 2, p.y + g2.getFontMetrics().getHeight() / 2);
}
Point hp = partPos.get(head);
drawArrow(g2, startX + hp.x, hp.y - BLOCK_HEIGHT / 2 - SPACE_VERTICAL, startX + hp.x, hp.y - BLOCK_HEIGHT / 2);
for (GraphPart part : partPos.keySet()) {
Point p = partPos.get(part);
for (int n = 0; n < part.nextParts.size(); n++) {
boolean isIf = part.nextParts.size() == 2;
if (isIf) {
if (n == 0) {
g2.setColor(new Color(0, 0x80, 0));
} else {
g2.setColor(Color.red);
}
} else {
g2.setColor(Color.black);
}
Point npos = partPos.get(part.nextParts.get(n));
if (npos.y < p.y) {
int sidex = startX;
if (p.x > size.x / 2) {
blRight++;
sidex = size.x - backLinksRight * SPACE_BACKLINKS;
sidex += SPACE_BACKLINKS + SPACE_BACKLINKS * blRight;
} else {
blLeft++;
sidex -= SPACE_BACKLINKS + SPACE_BACKLINKS * blLeft;
}
g2.drawLine(startX + p.x, p.y + BLOCK_HEIGHT / 2, startX + p.x, p.y + BLOCK_HEIGHT / 2 + SPACE_VERTICAL / 2);
g2.drawLine(startX + p.x, p.y + BLOCK_HEIGHT / 2 + SPACE_VERTICAL / 2, sidex, p.y + BLOCK_HEIGHT / 2 + SPACE_VERTICAL / 2);
g2.drawLine(sidex, npos.y - BLOCK_HEIGHT / 2 - SPACE_VERTICAL / 2, sidex, p.y + BLOCK_HEIGHT / 2 + SPACE_VERTICAL / 2);
drawArrow(g2, sidex, npos.y - BLOCK_HEIGHT / 2 - SPACE_VERTICAL / 2, startX + npos.x, npos.y - BLOCK_HEIGHT / 2 - SPACE_VERTICAL / 2);
g2.drawLine(startX + npos.x, npos.y - BLOCK_HEIGHT / 2 - SPACE_VERTICAL / 2, startX + npos.x, npos.y - BLOCK_HEIGHT / 2);
} else {
drawArrow(g2, startX + p.x, p.y + BLOCK_HEIGHT / 2, startX + npos.x, npos.y - BLOCK_HEIGHT / 2 - SPACE_VERTICAL / 2);
g2.drawLine(startX + npos.x, npos.y - BLOCK_HEIGHT / 2 - SPACE_VERTICAL / 2, startX + npos.x, npos.y - BLOCK_HEIGHT / 2);
}
}
}
}
private Point getPartSubPositions(Point ret, int totalWidth, GraphPart part, int y, int x, HashMap<GraphPart, Point> used) {
if (used.containsKey(part)) {
Point p = used.get(part);
return new Point(x, y);
}
used.put(part, new Point(x, y));
if (part.nextParts.size() > 0) {
int cx = x - totalWidth / 2;
for (int p = 0; p < part.nextParts.size(); p++) {
HashSet<GraphPart> k = new HashSet<>();
k.addAll(used.keySet());
int partWidth = getPartWidth(part.nextParts.get(p), k);
int cellWidth = partWidth * (BLOCK_WIDTH + SPACE_HORIZONTAL);
Point pt = getPartPositions(part.nextParts.get(p), y + BLOCK_HEIGHT + SPACE_VERTICAL, cx + cellWidth / 2, used, false);
if (pt.x > ret.x) {
ret.x = pt.x;
}
if (pt.y > ret.y) {
ret.y = pt.y;
}
cx += cellWidth;
}
cx = x - totalWidth / 2;
for (int p = 0; p < part.nextParts.size(); p++) {
HashSet<GraphPart> k = new HashSet<>();
k.addAll(used.keySet());
int cellWidth = getPartWidth(part.nextParts.get(p), k) * (BLOCK_WIDTH + SPACE_HORIZONTAL);
HashSet<GraphPart> hs = new HashSet<>();
hs.addAll(used.keySet());
int totalWidthParts2 = getPartWidth(part.nextParts.get(p), hs);
int totalWidth2 = totalWidthParts2 * (BLOCK_WIDTH + SPACE_HORIZONTAL);
Point pt = getPartSubPositions(ret, totalWidth2, part.nextParts.get(p), y + BLOCK_HEIGHT + SPACE_VERTICAL, cx + cellWidth / 2, used);
if (pt.x > ret.x) {
ret.x = pt.x;
}
if (pt.y > ret.y) {
ret.y = pt.y;
}
cx += cellWidth;
}
}
return ret;
}
private Point getPartPositions(GraphPart part, int y, int x, HashMap<GraphPart, Point> used, boolean goSub) {
HashMap<GraphPart, Point> l = new HashMap<>();
l.putAll(used);
HashSet<GraphPart> hs = new HashSet<>();
hs.addAll(l.keySet());
int totalWidthParts = getPartWidth(part, hs);
int totalWidth = totalWidthParts * (BLOCK_WIDTH + SPACE_HORIZONTAL);
if (used.containsKey(part)) {
Point p = used.get(part);
return new Point(x, y);
}
Point ret = new Point(x - BLOCK_WIDTH / 2 - SPACE_HORIZONTAL / 2 + BLOCK_WIDTH, y + BLOCK_HEIGHT);
if (goSub) {
Point p2 = getPartSubPositions(ret, totalWidth, part, y, x, used);
if (p2.x > ret.x) {
ret.x = p2.x;
}
if (p2.y > ret.y) {
ret.y = p2.y;
}
}
return ret;
}
private int getPartHeight(GraphPart part, List<GraphPart> used) {
if (used.contains(part)) {
return 1;
}
used.add(part);
int maxH = 0;
for (int p = 0; p < part.nextParts.size(); p++) {
int h = getPartHeight(part.nextParts.get(p), used);
if (h > maxH) {
maxH = h;
}
}
return 1 + maxH;
}
private int getPartWidth(GraphPart part, HashSet<GraphPart> used) {
if (used.contains(part)) {
return 1;
}
used.add(part);
if (part.nextParts.isEmpty()) {
return 1;
}
int w = 0;
for (GraphPart subpart : part.nextParts) {
w += getPartWidth(subpart, used);
}
return w;
}
}
GraphPanel gp;
int scrollBarWidth;
int scrollBarHeight;
int frameWidthDiff;
int frameHeightDiff;
public GraphFrame(Graph graph, String name) throws InterruptedException {
setSize(500, 500);
Container cnt = getContentPane();
cnt.setLayout(new BorderLayout());
gp = new GraphPanel(graph);
setTitle(translate("graph") + " " + name);
JScrollPane scrollPane = new JScrollPane(gp);
scrollBarWidth = scrollPane.getVerticalScrollBar().getPreferredSize().width;
scrollBarHeight = scrollPane.getHorizontalScrollBar().getPreferredSize().height;
cnt.add(scrollPane, BorderLayout.CENTER);
pack();
Dimension size = getSize();
Dimension innerSize = getContentPane().getSize();
frameWidthDiff = size.width - innerSize.width;
frameHeightDiff = size.height - innerSize.height;
View.setWindowIcon(this);
}
@Override
public void setVisible(boolean b) {
super.setVisible(b);
Dimension screen = getToolkit().getScreenSize();
Dimension dim = new Dimension(0, 0);
Dimension panDim = gp.getPreferredSize();
// add some magic constants
panDim = new Dimension(panDim.width + 3, panDim.height + 2);
boolean tooHigh = false;
boolean tooWide = false;
if (panDim.width + frameWidthDiff < screen.width) {
dim.width = panDim.width;
} else {
dim.width = screen.width;
tooWide = true;
}
if (panDim.height + frameHeightDiff < screen.height) {
dim.height = panDim.height;
} else {
dim.height = screen.height;
tooHigh = true;
}
if (tooWide) {
dim.height += scrollBarHeight;
dim.height = Math.min(dim.height, screen.height);
}
if (tooHigh) {
dim.width += scrollBarWidth;
dim.width = Math.min(dim.width, screen.width);
}
setVisibleSize(dim);
View.centerScreen(this);
}
private void setVisibleSize(Dimension dim) {
setSize(new Dimension(dim.width + frameWidthDiff, dim.height + frameHeightDiff));
}
private void drawArrow(Graphics g, int x1, int y1, int x2, int y2) {
Polygon arrowHead = new Polygon();
arrowHead.addPoint(0, 0);
arrowHead.addPoint(-3, -8);
arrowHead.addPoint(3, -8);
Line2D.Double line = new Line2D.Double(x1, y1, x2, y2);
AffineTransform tx = new AffineTransform();
tx.setToIdentity();
double angle = Math.atan2(line.y2 - line.y1, line.x2 - line.x1);
tx.translate(line.x2, line.y2);
tx.rotate((angle - Math.PI / 2d));
Graphics2D g2d = (Graphics2D) g;
AffineTransform oldTransform = g2d.getTransform();
g2d.draw(line);
tx.preConcatenate(oldTransform);
g2d.setTransform(tx);
g2d.fill(arrowHead);
g2d.setTransform(oldTransform);
}
}
@@ -0,0 +1,81 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.abc.avm2.graph.AVM2Graph;
import com.jpexs.decompiler.graph.GraphPart;
import java.awt.BorderLayout;
import java.awt.Container;
import javax.swing.JTree;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
/**
*
* @author JPEXS
*/
public class GraphTreeFrame extends AppFrame {
public JTree graphTree;
public GraphTreeFrame(final AVM2Graph graph) {
setSize(400, 400);
graphTree = new JTree(new TreeModel() {
@Override
public Object getRoot() {
return graph.heads.get(0);
}
@Override
public Object getChild(Object parent, int index) {
return ((GraphPart) parent).nextParts.get(index);
}
@Override
public int getChildCount(Object parent) {
return ((GraphPart) parent).nextParts.size();
}
@Override
public boolean isLeaf(Object node) {
return getChildCount(node) == 0;
}
@Override
public void valueForPathChanged(TreePath path, Object newValue) {
}
@Override
public int getIndexOfChild(Object parent, Object child) {
return ((GraphPart) parent).nextParts.indexOf(child);
}
@Override
public void addTreeModelListener(TreeModelListener l) {
}
@Override
public void removeTreeModelListener(TreeModelListener l) {
}
});
Container cnt = getContentPane();
cnt.setLayout(new BorderLayout());
cnt.add(graphTree, BorderLayout.CENTER);
}
}
@@ -0,0 +1,43 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
import com.jpexs.decompiler.flash.AppStrings;
import javax.swing.JOptionPane;
/**
*
* @author JPEXS
*/
public class GuiAbortRetryIgnoreHandler implements AbortRetryIgnoreHandler {
@Override
public int handle(Throwable thrown) {
synchronized (GuiAbortRetryIgnoreHandler.class) {
String[] options = new String[]{AppStrings.translate("button.abort"), AppStrings.translate("button.retry"), AppStrings.translate("button.ignore")};
return View.showOptionDialog(null, AppStrings.translate("error.occured").replace("%error%", thrown.getLocalizedMessage()), AppStrings.translate("error"), JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE, null, options, "");
}
}
@Override
public AbortRetryIgnoreHandler getNewInstance() {
// there are no non-static field in this class, so return the original instance
return this;
}
}
@@ -0,0 +1,91 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.geom.GeneralPath;
import java.util.EnumSet;
import java.util.Set;
import javax.swing.JLabel;
import org.pushingpixels.substance.api.DecorationAreaType;
import org.pushingpixels.substance.api.SubstanceConstants;
import org.pushingpixels.substance.api.painter.border.StandardBorderPainter;
import org.pushingpixels.substance.api.skin.OfficeBlue2007Skin;
import org.pushingpixels.substance.internal.utils.SubstanceOutlineUtilities;
/**
*
* @author JPEXS
*/
public class HeaderLabel extends JLabel {
public HeaderLabel(String text) {
super(text);
//setBorder(BorderFactory.createRaisedBevelBorder());
/*setBorder(new Border() {
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
g.setColor(Color.gray);
g.drawLine(0, 0,width-1, 0);
g.drawLine(0, 0, 0, height-1);
g.setColor(Color.darkGray);
g.drawLine(width-1, 0, width-1, height-1);
g.drawLine(0, height-1, width-1, height-1);
}
@Override
public Insets getBorderInsets(Component c) {
return new Insets(2, 2, 2, 2);
}
@Override
public boolean isBorderOpaque() {
return false;
}
});*/
}
@Override
public void paint(Graphics g) {
g.setColor(new Color(217, 232, 251));
g.fillRect(0, 0, getWidth(), getHeight());
StandardBorderPainter borderPainter = new StandardBorderPainter();
Set<SubstanceConstants.Side> straightSides = EnumSet.of(SubstanceConstants.Side.BOTTOM);
int dy = 0;
float cornerRadius = 5f;
int borderThickness = 1;
int borderInsets = 0;
GeneralPath contourInner = borderPainter.isPaintingInnerContour() ? SubstanceOutlineUtilities.getBaseOutline(getWidth(), getHeight() + dy,
cornerRadius - borderThickness, straightSides, borderThickness + borderInsets)
: null;
GeneralPath contour = SubstanceOutlineUtilities.getBaseOutline(getWidth(),
getHeight() + dy, cornerRadius, straightSides, borderInsets);
borderPainter.paintBorder(g, this, getWidth(), getHeight() + dy,
contour, contourInner, new OfficeBlue2007Skin().getActiveColorScheme(DecorationAreaType.HEADER));
g.setColor(Color.black);
JLabel lab = new JLabel(getText(), JLabel.CENTER);
lab.setSize(getSize());
lab.paint(g);
//g.drawString(getText(), getWidth()/2-getFontMetrics(getFont()).stringWidth(getText())/2, getFont().getSize());
}
}
@@ -0,0 +1,679 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.AppStrings;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
import com.jpexs.decompiler.flash.gui.player.MediaDisplay;
import com.jpexs.decompiler.flash.tags.DefineButtonSoundTag;
import com.jpexs.decompiler.flash.tags.base.BoundedTag;
import com.jpexs.decompiler.flash.tags.base.ButtonTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.tags.base.SoundTag;
import com.jpexs.decompiler.flash.timeline.DepthState;
import com.jpexs.decompiler.flash.timeline.Timeline;
import com.jpexs.decompiler.flash.timeline.Timelined;
import com.jpexs.decompiler.flash.types.ColorTransform;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD;
import com.jpexs.helpers.SerializableImage;
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
public final class ImagePanel extends JPanel implements ActionListener, MediaDisplay {
static final String ACTION_SELECT_BKCOLOR = "SELECTCOLOR";
//private JLabel label = new JLabel();
private Timelined timelined;
private boolean stillFrame = false;
private Timer timer;
private int frame = -1;
private SWF swf;
private boolean loaded;
private int mouseButton;
private JLabel debugLabel = new JLabel("-");
private DepthState stateUnderCursor = null;
private MouseEvent lastMouseEvent = null;
private final List<SoundTagPlayer> soundPlayers = new ArrayList<>();
private final IconPanel iconPanel;
private int time = 0;
private class IconPanel extends JPanel {
private SerializableImage img;
private Rectangle rect = null;
private List<DepthState> dss;
private List<Shape> outlines;
public synchronized void setOutlines(List<DepthState> dss, List<Shape> outlines) {
this.outlines = outlines;
this.dss = dss;
}
public void setImg(SerializableImage img) {
this.img = img;
calcRect();
repaint();
}
public synchronized List<DepthState> getObjectsUnderPoint(Point p) {
List<DepthState> ret = new ArrayList<>();
for (int i = 0; i < outlines.size(); i++) {
if (outlines.get(i).contains(p)) {
ret.add(dss.get(i));
}
}
return ret;
}
public Rectangle getRect() {
return rect;
}
public Point toImagePoint(Point p) {
if (img == null) {
return null;
}
return new Point((p.x - rect.x) * img.getWidth() / rect.width, (p.y - rect.y) * img.getHeight() / rect.height);
}
private void calcRect() {
if (img != null) {
int w1 = img.getWidth();
int h1 = img.getHeight();
int w2 = getWidth();
int h2 = getHeight();
int w;
int h;
if (w1 <= w2 && h1 <= h2) {
w = w1;
h = h1;
} else {
h = h1 * w2 / w1;
if (h > h2) {
w = w1 * h2 / h1;
h = h2;
} else {
w = w2;
}
}
rect = new Rectangle(getWidth() / 2 - w / 2, getHeight() / 2 - h / 2, w, h);
} else {
rect = null;
}
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setPaint(View.transparentPaint);
g2d.fill(new Rectangle(0, 0, getWidth(), getHeight()));
g2d.setComposite(AlphaComposite.SrcOver);
g2d.setPaint(View.swfBackgroundColor);
g2d.fill(new Rectangle(0, 0, getWidth(), getHeight()));
if (img != null) {
calcRect();
g2d.setComposite(AlphaComposite.SrcOver);
g2d.drawImage(img.getBufferedImage(), rect.x, rect.y, rect.x + rect.width, rect.y + rect.height, 0, 0, img.getWidth(), img.getHeight(), null);
}
}
}
@Override
public void setBackground(Color bg) {
if (iconPanel != null) {
iconPanel.setBackground(bg);
}
super.setBackground(bg);
}
@Override
public synchronized void addMouseListener(MouseListener l) {
iconPanel.addMouseListener(l);
}
@Override
public synchronized void removeMouseListener(MouseListener l) {
iconPanel.removeMouseListener(l);
}
@Override
public synchronized void addMouseMotionListener(MouseMotionListener l) {
iconPanel.addMouseMotionListener(l);
}
@Override
public synchronized void removeMouseMotionListener(MouseMotionListener l) {
iconPanel.removeMouseMotionListener(l);
}
private void updatePos(MouseEvent e, boolean draw) {
if (e == null) {
return;
}
synchronized (iconPanel) {
lastMouseEvent = e;
boolean handCursor = false;
DepthState newStateUnderCursor = null;
if (timelined != null) {
Timeline tim = ((Timelined) timelined).getTimeline();
BoundedTag bounded = (BoundedTag) timelined;
RECT rect = bounded.getRect();
int width = rect.getWidth();
double scale = 1.0;
/*if (width > swf.displayRect.getWidth()) {
scale = (double) swf.displayRect.getWidth() / (double) width;
}*/
Matrix m = new Matrix();
m.translate(-rect.Xmin, -rect.Ymin);
m.scale(scale);
Point p = e.getPoint();
p = iconPanel.toImagePoint(p);
List<DepthState> objs = new ArrayList<>();
String ret = "";
if (p != null) {
int x = p.x;
int y = p.y;
objs = iconPanel.getObjectsUnderPoint(p);
ret += " [" + x + "," + y + "] : ";
}
boolean first = true;
for (int i = 0; i < objs.size(); i++) {
DepthState ds = objs.get(i);
if (!first) {
ret += ", ";
}
first = false;
CharacterTag c = tim.swf.characters.get(ds.characterId);
if (c instanceof ButtonTag) {
newStateUnderCursor = ds;
handCursor = true;
}
ret += c.toString();
if (timelined instanceof ButtonTag) {
handCursor = true;
}
}
if (first) {
ret += " - ";
}
debugLabel.setText(ret);
if (handCursor) {
iconPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
} else {
iconPanel.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
if (newStateUnderCursor != stateUnderCursor) {
stateUnderCursor = newStateUnderCursor;
if (draw) {
drawFrame();
}
}
}
}
}
public ImagePanel() {
super(new BorderLayout());
//iconPanel.setHorizontalAlignment(JLabel.CENTER);
setOpaque(true);
setBackground(View.DEFAULT_BACKGROUND_COLOR);
iconPanel = new IconPanel();
//labelPan.add(label, new GridBagConstraints());
add(iconPanel, BorderLayout.CENTER);
JPanel bottomPanel = new JPanel(new BorderLayout());
JPanel buttonsPanel = new JPanel(new FlowLayout());
JButton selectColorButton = new JButton(View.getIcon("color16"));
selectColorButton.addActionListener(this);
selectColorButton.setActionCommand(ACTION_SELECT_BKCOLOR);
selectColorButton.setToolTipText(AppStrings.translate("button.selectbkcolor.hint"));
buttonsPanel.add(selectColorButton);
bottomPanel.add(buttonsPanel, BorderLayout.EAST);
add(bottomPanel, BorderLayout.SOUTH);
add(debugLabel, BorderLayout.NORTH);
iconPanel.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
drawFrame();
}
@Override
public void mouseExited(MouseEvent e) {
stateUnderCursor = null;
drawFrame();
debugLabel.setText(" - ");
}
@Override
public void mousePressed(MouseEvent e) {
mouseButton = e.getButton();
updatePos(e, true);
drawFrame();
if (stateUnderCursor != null) {
ButtonTag b = (ButtonTag) swf.characters.get(stateUnderCursor.characterId);
DefineButtonSoundTag sounds = b.getSounds();
if (sounds != null && sounds.buttonSoundChar2 != 0) { //OverUpToOverDown
playSound((SoundTag) swf.characters.get(sounds.buttonSoundChar2));
}
}
}
@Override
public void mouseReleased(MouseEvent e) {
mouseButton = 0;
updatePos(e, true);
drawFrame();
if (stateUnderCursor != null) {
ButtonTag b = (ButtonTag) swf.characters.get(stateUnderCursor.characterId);
DefineButtonSoundTag sounds = b.getSounds();
if (sounds != null && sounds.buttonSoundChar3 != 0) { //OverDownToOverUp
playSound((SoundTag) swf.characters.get(sounds.buttonSoundChar3));
}
}
}
});
iconPanel.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
DepthState lastUnderCur = stateUnderCursor;
updatePos(e, true);
if (stateUnderCursor != null) {
if (lastUnderCur == null || lastUnderCur.instanceId != stateUnderCursor.instanceId) {
//New mouse entered
ButtonTag b = (ButtonTag) swf.characters.get(stateUnderCursor.characterId);
DefineButtonSoundTag sounds = b.getSounds();
if (sounds != null && sounds.buttonSoundChar1 != 0) { //IddleToOverUp
playSound((SoundTag) swf.characters.get(sounds.buttonSoundChar1));
}
}
}
if (lastUnderCur != null) {
if (stateUnderCursor == null || stateUnderCursor.instanceId != lastUnderCur.instanceId) {
//Old mouse leave
ButtonTag b = (ButtonTag) swf.characters.get(lastUnderCur.characterId);
DefineButtonSoundTag sounds = b.getSounds();
if (sounds != null && sounds.buttonSoundChar0 != 0) { //OverUpToIddle
playSound((SoundTag) swf.characters.get(sounds.buttonSoundChar0));
}
}
}
}
@Override
public void mouseDragged(MouseEvent e) {
updatePos(e, true);
}
});
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals(ACTION_SELECT_BKCOLOR)) {
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
Color newColor = JColorChooser.showDialog(null, AppStrings.translate("dialog.selectbkcolor.title"), View.swfBackgroundColor);
if (newColor != null) {
View.swfBackgroundColor = newColor;
setBackground(newColor);
repaint();
}
}
});
}
}
public void setImage(byte[] data) {
setBackground(View.swfBackgroundColor);
if (timer != null) {
timer.cancel();
}
timelined = null;
loaded = true;
try {
iconPanel.setImg(new SerializableImage(ImageIO.read(new ByteArrayInputStream(data))));
iconPanel.setOutlines(new ArrayList<DepthState>(), new ArrayList<Shape>());
} catch (IOException ex) {
Logger.getLogger(ImagePanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
public synchronized void setTimelined(final Timelined drawable, final SWF swf, int frame) {
pause();
if (drawable instanceof ButtonTag) {
frame = ButtonTag.FRAME_UP;
}
this.timelined = drawable;
this.swf = swf;
if (frame > -1) {
this.frame = frame;
this.stillFrame = true;
} else {
this.frame = 0;
this.stillFrame = false;
}
loaded = true;
if (drawable.getTimeline().frames.isEmpty()) {
iconPanel.setImg(null);
iconPanel.setOutlines(new ArrayList<DepthState>(), new ArrayList<Shape>());
return;
}
time = 0;
play();
}
public void setImage(SerializableImage image) {
setBackground(View.swfBackgroundColor);
if (timer != null) {
timer.cancel();
}
timelined = null;
loaded = true;
stillFrame = true;
iconPanel.setImg(image);
iconPanel.setOutlines(new ArrayList<DepthState>(), new ArrayList<Shape>());
}
@Override
public int getCurrentFrame() {
return frame;
}
@Override
public int getTotalFrames() {
if (timelined == null) {
return 0;
}
if (stillFrame) {
return 0;
}
return timelined.getTimeline().frames.size();
}
@Override
public void pause() {
if (timer != null) {
timer.cancel();
timer = null;
}
stopAllSounds();
}
private void stopAllSounds() {
for (int i = soundPlayers.size() - 1; i >= 0; i--) {
SoundTagPlayer pl = soundPlayers.get(i);
pl.pause();
}
soundPlayers.clear();
}
private void nextFrame() {
drawFrame();
int newframe = (frame + 1) % timelined.getTimeline().frames.size();
if (stillFrame) {
newframe = frame;
}
if (newframe != frame) {
if (newframe == 0) {
stopAllSounds();
}
frame = newframe;
time = 0;
} else {
time++;
}
}
private static SerializableImage getFrame(SWF swf, int frame, int time, Timelined drawable, DepthState stateUnderCursor, int mouseButton) {
String key = "drawable_" + frame + "_" + drawable.hashCode() + "_" + mouseButton + "_" + (stateUnderCursor == null ? "out" : stateUnderCursor.hashCode());
SerializableImage img = SWF.getFromCache(key);
if (img == null) {
if (drawable instanceof BoundedTag) {
BoundedTag bounded = (BoundedTag) drawable;
RECT rect = bounded.getRect();
if (rect == null) { //??? Why?
rect = new RECT(0, 0, 1, 1);
}
int width = rect.getWidth();
int height = rect.getHeight();
SerializableImage image = new SerializableImage((int) (width / SWF.unitDivisor) + 1,
(int) (height / SWF.unitDivisor) + 1, SerializableImage.TYPE_INT_ARGB);
image.fillTransparent();
Matrix m = new Matrix();
m.translate(-rect.Xmin, -rect.Ymin);
drawable.getTimeline().toImage(frame, time, frame, stateUnderCursor, mouseButton, image, m, new ColorTransform());
Graphics2D gg = (Graphics2D) image.getGraphics();
gg.setStroke(new BasicStroke(3));
gg.setPaint(Color.green);
gg.setTransform(AffineTransform.getTranslateInstance(0, 0));
List<DepthState> dss = new ArrayList<>();
List<Shape> os = new ArrayList<>();
/*drawable.getTimeline().getObjectsOutlines(frame, frame, stateUnderCursor, mouseButton, m, dss, os);
//gg.setTransform(AffineTransform.getTranslateInstance(0, 0));
for(Shape s:os){
gg.draw(SHAPERECORD.twipToPixelShape(s));
}*/
img = image;
}
if (drawable.getTimeline().isSingleFrame()) {
SWF.putToCache(key, img);
}
}
return img;
}
private synchronized void drawFrame() {
if (timelined == null) {
return;
}
Timeline timeline = timelined.getTimeline();
if (frame>=timeline.frames.size()) {
return;
}
getOutlines();
Matrix mat = new Matrix();
mat.translateX = swf.displayRect.Xmin;
mat.translateY = swf.displayRect.Ymin;
updatePos(lastMouseEvent, false);
SerializableImage img = getFrame(swf, frame, time, timelined, stateUnderCursor, mouseButton);
List<Integer> sounds = new ArrayList<>();
List<String> soundClasses = new ArrayList<>();
timeline.getSounds(frame, time, stateUnderCursor, mouseButton, sounds, soundClasses);
for (int cid : swf.characters.keySet()) {
CharacterTag c = swf.characters.get(cid);
for (String cls : soundClasses) {
if (cls.equals(c.getClassName())) {
sounds.add(cid);
}
}
}
for (int sndId : sounds) {
CharacterTag c = swf.characters.get(sndId);
if (c instanceof SoundTag) {
SoundTag st = (SoundTag) c;
playSound(st);
}
}
iconPanel.setImg(img);
}
private void playSound(SoundTag st) {
final SoundTagPlayer sp;
try {
sp = new SoundTagPlayer(st, 1);
synchronized (ImagePanel.class) {
soundPlayers.add(sp);
}
sp.addListener(new PlayerListener() {
@Override
public void playingFinished() {
synchronized (ImagePanel.class) {
soundPlayers.remove(sp);
}
}
});
sp.play();
} catch (LineUnavailableException | IOException | UnsupportedAudioFileException ex) {
Logger.getLogger(ImagePanel.class.getName()).log(Level.SEVERE, "Error during playing sound", ex);
}
}
private void getOutlines() {
List<DepthState> objs = new ArrayList<>();
List<Shape> outlines = new ArrayList<>();
Matrix m = new Matrix();
RECT rect = timelined.getTimeline().displayRect;
m.translate(-rect.Xmin, -rect.Ymin);
m.scale(1);
timelined.getTimeline().getObjectsOutlines(frame, time, frame, stateUnderCursor, mouseButton, m, objs, outlines);
for (int i = 0; i < outlines.size(); i++) {
outlines.set(i, SHAPERECORD.twipToPixelShape(outlines.get(i)));
}
iconPanel.setOutlines(objs, outlines);
}
public void stop() {
if (timer != null) {
timer.cancel();
timer = null;
}
}
@Override
public void play() {
pause();
if (timelined != null) {
timer = new Timer();
timer.schedule(new TimerTask() {
boolean first = true;
@Override
public void run() {
Timeline timeline = timelined.getTimeline();
if (timeline.frames.size() <= 1 && timeline.isSingleFrame()) {
if (first) {
drawFrame();
first = false;
}
} else {
nextFrame();
}
}
}, 0, 1000 / timelined.getTimeline().frameRate);
} else {
drawFrame();
}
}
@Override
public void rewind() {
frame = 0;
drawFrame();
}
@Override
public boolean isPlaying() {
if (timelined == null) {
return false;
}
if (stillFrame) {
return false;
}
return (timelined.getTimeline().frames.size() <= 1) || (timer != null);
}
@Override
public void gotoFrame(int frame) {
this.frame = frame;
drawFrame();
}
@Override
public int getFrameRate() {
if (timelined == null) {
return 1;
}
if (stillFrame) {
return 1;
}
return timelined.getTimeline().frameRate;
}
@Override
public boolean isLoaded() {
return loaded;
}
}
@@ -0,0 +1,37 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
/**
*
* @author JPEXS
*/
public class Language {
public String code;
public String name;
public Language(String code, String name) {
this.code = code;
this.name = name;
}
@Override
public String toString() {
return name;
}
}
@@ -0,0 +1,110 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.helpers.utf8.Utf8PrintWriter;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
*
* @author JPEXS
*/
public class LicenseUpdater {
public static void updateLicense() {
updateLicenseInDir(new File(".\\src\\"));
}
/**
* Script for updating license header in java files :-)
*
* @param dir Star directory (e.g. "src/")
*/
public static void updateLicenseInDir(File dir) {
int defaultStartYear = 2010;
int defaultFinalYear = 2013;
String defaultAuthor = "JPEXS";
String defaultYearStr = "" + defaultStartYear;
if (defaultFinalYear != defaultStartYear) {
defaultYearStr += "-" + defaultFinalYear;
}
String license = "/*\r\n * Copyright (C) {year} {author}\r\n * \r\n * This program is free software: you can redistribute it and/or modify\r\n * it under the terms of the GNU General Public License as published by\r\n * the Free Software Foundation, either version 3 of the License, or\r\n * (at your option) any later version.\r\n * \r\n * This program is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n * GNU General Public License for more details.\r\n * \r\n * You should have received a copy of the GNU General Public License\r\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\r\n */";
File[] files = dir.listFiles();
for (File f : files) {
if (f.isDirectory()) {
updateLicenseInDir(f);
} else {
if (f.getName().endsWith(".java")) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintWriter pw = new Utf8PrintWriter(baos);
try {
try (BufferedReader br = new BufferedReader(new FileReader(f))) {
String s;
boolean packageFound = false;
String author = defaultAuthor;
String yearStr = defaultYearStr;
while ((s = br.readLine()) != null) {
if (!packageFound) {
if (s.trim().startsWith("package")) {
packageFound = true;
pw.println(license.replace("{year}", yearStr).replace("{author}", author));
} else {
Matcher mAuthor = Pattern.compile("^.*Copyright \\(C\\) ([0-9]+)(-[0-9]+)? (.*)$").matcher(s);
if (mAuthor.matches()) {
author = mAuthor.group(3).trim();
int startYear = Integer.parseInt(mAuthor.group(1).trim());
if (startYear == defaultFinalYear) {
yearStr = "" + startYear;
} else {
yearStr = "" + startYear + "-" + defaultFinalYear;
}
if (!author.equals(defaultAuthor)) {
System.out.println("Detected nodefault author:" + author + " in " + f.getAbsolutePath());
}
}
}
}
if (packageFound) {
pw.println(s);
}
}
}
pw.close();
} catch (IOException ex) {
}
FileOutputStream fos;
try {
fos = new FileOutputStream(f);
fos.write(baos.toByteArray());
fos.close();
} catch (IOException ex) {
}
}
}
}
}
}
@@ -0,0 +1,96 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import java.awt.Cursor;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.net.URISyntaxException;
import javax.swing.JLabel;
/**
* An extension of JLabel which looks like a link and responds appropriately
* when clicked. Note that this class will only work with Swing 1.1.1 and later.
* Note that because of the way this class is implemented, getText() will not
* return correct values, user <code>getNormalText</code> instead.
*/
public class LinkLabel extends JLabel {
/**
* The normal text set by the user.
*/
private String text;
/**
* Creates a new LinkLabel with the given text.
*
* @param text
*/
public LinkLabel(String text) {
super(text);
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
enableEvents(MouseEvent.MOUSE_EVENT_MASK);
}
/**
* Sets the text of the label.
*
* @param text
*/
@Override
public void setText(String text) {
super.setText("<html><font color=\"#0000CF\"><u>" + text + "</u></font></html>");
this.text = text;
}
/**
* Returns the text set by the user.
*
* @return
*/
public String getNormalText() {
return text;
}
/**
* Processes mouse events and responds to clicks.
*
* @param evt
*/
@Override
protected void processMouseEvent(MouseEvent evt) {
super.processMouseEvent(evt);
if (evt.getID() == MouseEvent.MOUSE_CLICKED) {
clicked();
}
}
protected void clicked() {
if (java.awt.Desktop.isDesktopSupported()) {
java.awt.Desktop desktop = java.awt.Desktop.getDesktop();
try {
java.net.URI uri = new java.net.URI(getNormalText());
desktop.browse(uri);
} catch (URISyntaxException | IOException e) {
System.err.println(e.getMessage());
}
}
}
}
@@ -0,0 +1,103 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
/**
*
* @author JPEXS
*/
public class ListLayout implements LayoutManager {
private int border;
public ListLayout() {
this(5);
}
public ListLayout(int border) {
this.border = border;
}
@Override
public void addLayoutComponent(String name, Component comp) {
}
@Override
public void removeLayoutComponent(Component comp) {
}
@Override
public Dimension preferredLayoutSize(Container parent) {
int h = 0;
int maxw = 0;
Insets ins = parent.getInsets();
boolean first = true;
for (Component c : parent.getComponents()) {
if (!c.isVisible()) {
continue;
}
if (true) { //!first) {
h += border;
}
Dimension pref = c.getPreferredSize();
if (pref.width > maxw) {
maxw = pref.width;
}
h += pref.height;
first = false;
}
h += border;
maxw = (parent.getSize().width == 0 ? maxw : parent.getSize().width) - ins.left - ins.right;
return new Dimension(maxw, h);
}
@Override
public Dimension minimumLayoutSize(Container parent) {
return preferredLayoutSize(parent);
}
@Override
public void layoutContainer(Container parent) {
Dimension dim = preferredLayoutSize(parent);
int top = 0;
Insets ins = parent.getInsets();
top = ins.top;
boolean first = true;
for (Component c : parent.getComponents()) {
if (!c.isVisible()) {
continue;
}
if (!first) {
top += border;
}
Dimension pref = c.getPreferredSize();
c.setPreferredSize(new Dimension(dim.width, pref.height));
c.setMinimumSize(new Dimension(dim.width, pref.height));
c.setBounds(0, top, dim.width, pref.height);
top += pref.height;
first = false;
}
}
}
@@ -0,0 +1,291 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.browsers.cache.CacheEntry;
import com.jpexs.browsers.cache.CacheImplementation;
import com.jpexs.browsers.cache.CacheReader;
import com.jpexs.decompiler.flash.AppStrings;
import com.jpexs.decompiler.flash.SWFSourceInfo;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.helpers.Helper;
import com.jpexs.helpers.ReReadableInputStream;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingWorker;
import javax.swing.filechooser.FileFilter;
/**
*
* @author JPEXS
*/
public class LoadFromCacheFrame extends AppFrame implements ActionListener {
static final String ACTION_OPEN = "OPEN";
static final String ACTION_SAVE = "SAVE";
static final String ACTION_REFRESH = "REFRESH";
private final JList<CacheEntry> list;
private final JTextField searchField;
private List<CacheImplementation> caches;
private List<CacheEntry> entries;
private final JProgressBar progressBar;
JButton saveButton;
JButton refreshButton;
JButton openButton;
public LoadFromCacheFrame() {
setSize(900, 600);
View.setWindowIcon(this);
View.centerScreen(this);
setTitle(translate("dialog.title"));
setDefaultCloseOperation(HIDE_ON_CLOSE);
Container cnt = getContentPane();
list = new JList<>();
list.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() > 1) {
openSWF();
}
}
});
searchField = new JTextField();
searchField.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
filter();
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
});
cnt.setLayout(new BorderLayout());
cnt.add(searchField, BorderLayout.NORTH);
cnt.add(new JScrollPane(list), BorderLayout.CENTER);
JPanel bottomPanel = new JPanel();
bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.Y_AXIS));
JPanel buttonsPanel = new JPanel(new FlowLayout());
openButton = new JButton(translate("button.open"));
openButton.setActionCommand(ACTION_OPEN);
openButton.addActionListener(this);
buttonsPanel.add(openButton);
saveButton = new JButton(translate("button.save"));
saveButton.setActionCommand(ACTION_SAVE);
saveButton.addActionListener(this);
buttonsPanel.add(saveButton);
refreshButton = new JButton(translate("button.refresh"));
refreshButton.setActionCommand(ACTION_REFRESH);
refreshButton.addActionListener(this);
buttonsPanel.add(refreshButton);
JPanel browsersPanel = new JPanel(new FlowLayout());
browsersPanel.add(new JLabel(translate("supported.browsers")));
JLabel chromeLabel = new JLabel("Google Chrome", View.getIcon("chrome16"), JLabel.CENTER);
JLabel firefoxLabel = new JLabel("Mozilla Firefox*", View.getIcon("firefox16"), JLabel.CENTER);
browsersPanel.add(chromeLabel);
browsersPanel.add(firefoxLabel);
buttonsPanel.setAlignmentX(0.5f);
progressBar = new JProgressBar();
progressBar.setAlignmentX(0.5f);
progressBar.setIndeterminate(true);
bottomPanel.add(progressBar);
bottomPanel.add(buttonsPanel);
browsersPanel.setAlignmentX(0.5f);
bottomPanel.add(browsersPanel);
JLabel infoLabel = new JLabel(translate("info.closed"));
infoLabel.setAlignmentX(0.5f);
bottomPanel.add(infoLabel);
cnt.add(bottomPanel, BorderLayout.SOUTH);
progressBar.setVisible(false);
openButton.setEnabled(false);
saveButton.setEnabled(false);
java.util.List<Image> images = new ArrayList<>();
images.add(View.loadImage("loadcache16"));
images.add(View.loadImage("loadcache32"));
setIconImages(images);
refresh();
}
private void refresh() {
progressBar.setVisible(true);
openButton.setEnabled(false);
saveButton.setEnabled(false);
refreshButton.setEnabled(false);
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
if (caches == null) {
caches = new ArrayList<>();
for (String b : CacheReader.availableBrowsers()) {
caches.add(CacheReader.getBrowserCache(b));
}
} else {
for (CacheImplementation c : caches) {
c.refresh();
}
}
entries = new ArrayList<>();
for (CacheImplementation c : caches) {
List<CacheEntry> list = c.getEntries();
if (list != null) {
for (CacheEntry en : c.getEntries()) {
String contentType = en.getHeader("Content-Type");
if ("application/x-shockwave-flash".equals(contentType)) {
entries.add(en);
}
}
}
}
filter();
return null;
}
@Override
protected void done() {
openButton.setEnabled(true);
saveButton.setEnabled(true);
refreshButton.setEnabled(true);
progressBar.setVisible(false);
}
}.execute();
}
private void filter() {
String search = searchField.getText();
List<CacheEntry> filtered = new ArrayList<>();
for (CacheEntry en : entries) {
if (search.isEmpty() || en.getRequestURL().contains(search)) {
filtered.add(en);
}
}
list.setListData(new Vector<>(filtered));
}
private static String entryToFileName(CacheEntry en) {
String ret = en.getRequestURL();
//Strip parameters
if (ret.contains("?")) {
ret = ret.substring(0, ret.indexOf('?'));
}
//Strip path
if (ret.contains("/")) {
ret = ret.substring(ret.lastIndexOf('/') + 1);
}
return ret;
}
private void openSWF() {
CacheEntry en = list.getSelectedValue();
if (en != null) {
ReReadableInputStream str = new ReReadableInputStream(en.getResponseDataStream());
SWFSourceInfo sourceInfo = new SWFSourceInfo(str, null, entryToFileName(en));
Main.openFile(sourceInfo);
}
}
@Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case ACTION_REFRESH:
refresh();
break;
case ACTION_OPEN:
openSWF();
break;
case ACTION_SAVE:
List<CacheEntry> selected = list.getSelectedValuesList();
if (!selected.isEmpty()) {
JFileChooser fc = new JFileChooser();
fc.setCurrentDirectory(new File(Configuration.lastSaveDir.get()));
if (selected.size() > 1) {
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
} else {
fc.setSelectedFile(new File(Configuration.lastSaveDir.get(), entryToFileName(selected.get(0))));
fc.setFileFilter(new FileFilter() {
@Override
public boolean accept(File f) {
return (f.getName().endsWith(".swf")) || (f.isDirectory());
}
@Override
public String getDescription() {
return AppStrings.translate("filter.swf");
}
});
}
fc.setAcceptAllFileFilterUsed(false);
JFrame f = new JFrame();
View.setWindowIcon(f);
int returnVal = fc.showSaveDialog(f);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = Helper.fixDialogFile(fc.getSelectedFile());
try {
if (selected.size() == 1) {
Helper.saveStream(selected.get(0).getResponseDataStream(), file);
} else {
for (CacheEntry sel : selected) {
Helper.saveStream(sel.getResponseDataStream(), new File(file, entryToFileName(sel)));
}
}
Configuration.lastSaveDir.set(file.getParentFile().getAbsolutePath());
} catch (IOException ex) {
View.showMessageDialog(null, translate("error.file.write"));
}
}
}
break;
}
}
}
@@ -0,0 +1,463 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.AppStrings;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFSourceInfo;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.helpers.Helper;
import com.jpexs.helpers.LimitedInputStream;
import com.jpexs.helpers.PosMarkedInputStream;
import com.jpexs.helpers.ProgressListener;
import com.jpexs.helpers.ReReadableInputStream;
import com.jpexs.process.ProcessTools;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BoxLayout;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.SwingWorker;
import javax.swing.SwingWorker.StateValue;
import javax.swing.filechooser.FileFilter;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter;
/**
*
* @author petrik
*/
public class LoadFromMemoryFrame extends AppFrame implements ActionListener {
static final String ACTION_SELECT_PROCESS = "SELECTPROCESS";
static final String ACTION_REFRESH_PROCESS_LIST = "REFRESHPROCESSLIST";
static final String ACTION_OPEN_SWF = "OPENSWF";
static final String ACTION_SAVE = "SAVE";
private MainFrame mainFrame;
private List<com.jpexs.process.Process> processlist;
private List<SwfInMemory> foundIs;
private List<com.jpexs.process.Process> selProcesses;
private JList<com.jpexs.process.Process> list;
private DefaultListModel<com.jpexs.process.Process> model;
private DefaultTableModel resTableModel;
private final JTable tableRes;
private final JLabel stateLabel;
private boolean processing = false;
private final JProgressBar progress;
private class SelectProcessWorker extends SwingWorker<List<SwfInMemory>, Object> {
private final List<com.jpexs.process.Process> procs;
public SelectProcessWorker(List<com.jpexs.process.Process> procs) {
this.procs = procs;
}
@Override
protected void process(List<Object> chunks) {
for (Object s : chunks) {
if (s instanceof com.jpexs.process.Process) {
stateLabel.setText(s.toString());
}
if (s instanceof SwfInMemory) {
SwfInMemory swf = (SwfInMemory) s;
addResultRow(swf);
}
}
}
@Override
protected List<SwfInMemory> doInBackground() throws Exception {
Map<Long, InputStream> ret = new HashMap<>();
List<SwfInMemory> swfStreams = new ArrayList<>();
for (com.jpexs.process.Process proc : procs) {
publish(proc);
ret = proc.search(new ProgressListener() {
@Override
public void progress(int p) {
setProgress(p);
}
}, "CWS".getBytes(), "FWS".getBytes(), "ZWS".getBytes());
int pos = 0;
for (Long addr : ret.keySet()) {
setProgress(pos * 100 / ret.size());
pos++;
try {
PosMarkedInputStream pmi = new PosMarkedInputStream(ret.get(addr));
ReReadableInputStream is = new ReReadableInputStream(pmi);
SWF swf = new SWF(is, null, false, true);
long limit = pmi.getPos();
is.seek(0);
is = new ReReadableInputStream(new LimitedInputStream(is, limit));
if (swf.fileSize > 0 && swf.version > 0 && !swf.tags.isEmpty() && swf.version < 25/*Needs to be fixed when SWF versions reaches this value*/) {
SwfInMemory s = new SwfInMemory(is, swf.version, swf.fileSize, proc);
String p = translate("swfitem").replace("%version%", "" + swf.version).replace("%size%", "" + swf.fileSize);
publish(s);
swfStreams.add(s);
}
} catch (OutOfMemoryError ome) {
System.gc();
} catch (Exception | Error ex) {
}
}
setProgress(100);
}
if (swfStreams.isEmpty()) {
return null;
}
return swfStreams;
}
}
private void addResultRow(SwfInMemory swf) {
if (swf != null) {
com.jpexs.process.Process process = swf.process;
resTableModel.addRow(new Object[]{swf.version, swf.fileSize, process.getPid(), process.getFileName()});
} else {
String notFound = translate("notfound");
resTableModel.addRow(new Object[]{notFound, 0, "", ""});
}
}
private void refreshList() {
model.clear();
processlist = ProcessTools.listProcesses();
Collections.sort(processlist);
for (com.jpexs.process.Process p : processlist) {
model.addElement(p);
}
}
private void openSWF() {
if (foundIs == null) {
return;
}
int index = tableRes.getRowSorter().convertRowIndexToModel(tableRes.getSelectedRow());
if (index > -1) {
SwfInMemory swf = foundIs.get(index);
ReReadableInputStream str = swf.is;
try {
str.seek(0);
} catch (IOException ex) {
Logger.getLogger(LoadFromMemoryFrame.class.getName()).log(Level.SEVERE, null, ex);
return;
}
str.mark(Integer.MAX_VALUE);
SWFSourceInfo sourceInfo = new SWFSourceInfo(str, null, swf.process + " [" + (index + 1) + "]");
Main.openFile(sourceInfo);
}
}
private void selectProcess() {
if (processing) {
return;
}
selProcesses = list.getSelectedValuesList();
if (!selProcesses.isEmpty()) {
processing = true;
tableRes.setEnabled(false);
resTableModel.getDataVector().removeAllElements();
resTableModel.fireTableDataChanged();
foundIs = null;
progress.setIndeterminate(true);
progress.setString(translate("searching"));
progress.setStringPainted(true);
progress.setVisible(true);
final SelectProcessWorker wrk = new SelectProcessWorker(selProcesses);
wrk.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
switch (evt.getPropertyName()) {
case "progress":
progress.setIndeterminate(false);
progress.setStringPainted(false);
progress.setValue((Integer) evt.getNewValue());
break;
case "state":
if (((StateValue) evt.getNewValue()) == StateValue.DONE) {
try {
foundIs = wrk.get();
} catch (InterruptedException | ExecutionException ex) {
Logger.getLogger(LoadFromMemoryFrame.class.getName()).log(Level.SEVERE, null, ex);
}
if (foundIs == null) {
addResultRow(null);
}
tableRes.setEnabled(foundIs != null);
progress.setVisible(false);
processing = false;
}
}
}
});
wrk.execute();
}
}
public LoadFromMemoryFrame(final MainFrame mainFrame) {
setSize(800, 600);
//setAlwaysOnTop(true);
setTitle(translate("dialog.title"));
this.mainFrame = mainFrame;
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
if (!mainFrame.isVisible()) {
mainFrame.setVisible(true);
}
}
});
model = new DefaultListModel<>();
resTableModel = new DefaultTableModel() {
@Override
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0:
return Integer.class;
case 1:
return Integer.class;
case 2:
return String.class;
case 3:
return String.class;
}
return null;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
};
resTableModel.addColumn(translate("column.version"));
resTableModel.addColumn(translate("column.fileSize"));
resTableModel.addColumn(translate("column.pid"));
resTableModel.addColumn(translate("column.processName"));
tableRes = new JTable(resTableModel);
TableRowSorter<DefaultTableModel> sorter = new TableRowSorter<>(resTableModel);
tableRes.setRowSorter(sorter);
list = new JList<>(model);
list.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == 10) { //Enter pressed
selectProcess();
}
}
});
list.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() > 1) {
selectProcess();
}
}
});
tableRes.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() > 1) {
openSWF();
}
}
});
tableRes.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == 10) { //Enter pressed
openSWF();
}
}
});
list.setCellRenderer(new DefaultListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
JLabel label = (JLabel) super.getListCellRendererComponent(list,
value, index, isSelected, cellHasFocus);
if (value instanceof com.jpexs.process.Process) {
if (((com.jpexs.process.Process) value).getIcon() != null) {
label.setIcon(new ImageIcon(((com.jpexs.process.Process) value).getIcon()));
}
}
if (!isSelected) {
label.setBackground(Color.white);
}
return label;
}
});
refreshList();
Container cnt = getContentPane();
cnt.setLayout(new BorderLayout());
JPanel leftPanel = new JPanel(new BorderLayout());
leftPanel.add(new JScrollPane(list), BorderLayout.CENTER);
JPanel leftButtonsPanel = new JPanel(new FlowLayout());
JButton selectButton = new JButton(translate("button.select"));
selectButton.setActionCommand(ACTION_SELECT_PROCESS);
selectButton.addActionListener(this);
JButton refreshButton = new JButton(translate("button.refresh"));
refreshButton.setActionCommand(ACTION_REFRESH_PROCESS_LIST);
refreshButton.addActionListener(this);
leftButtonsPanel.add(selectButton);
leftButtonsPanel.add(refreshButton);
leftPanel.add(leftButtonsPanel, BorderLayout.SOUTH);
JPanel rightPanel = new JPanel(new BorderLayout());
rightPanel.add(new JScrollPane(tableRes), BorderLayout.CENTER);
JPanel rightButtonsPanel = new JPanel(new FlowLayout());
JButton openButton = new JButton(translate("button.open"));
openButton.setActionCommand(ACTION_OPEN_SWF);
openButton.addActionListener(this);
JButton saveButton = new JButton(translate("button.save"));
saveButton.setActionCommand(ACTION_SAVE);
saveButton.addActionListener(this);
rightButtonsPanel.add(openButton);
rightButtonsPanel.add(saveButton);
rightPanel.add(rightButtonsPanel, BorderLayout.SOUTH);
JPanel statePanel = new JPanel();
statePanel.setLayout(new BoxLayout(statePanel, BoxLayout.Y_AXIS));
stateLabel = new JLabel(translate("noprocess"));
statePanel.add(stateLabel);
progress = new JProgressBar(0, 100);
statePanel.add(progress);
progress.setVisible(false);
rightPanel.add(statePanel, BorderLayout.NORTH);
cnt.add(new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, rightPanel), BorderLayout.CENTER);
View.setWindowIcon(this);
View.centerScreen(this);
java.util.List<Image> images = new ArrayList<>();
images.add(View.loadImage("loadmemory16"));
images.add(View.loadImage("loadmemory32"));
setIconImages(images);
}
@Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case ACTION_SELECT_PROCESS:
selectProcess();
break;
case ACTION_OPEN_SWF:
openSWF();
break;
case ACTION_REFRESH_PROCESS_LIST:
refreshList();
break;
case ACTION_SAVE:
if (foundIs == null) {
return;
}
int[] selected = tableRes.getSelectedRows();
if (selected.length > 0) {
JFileChooser fc = new JFileChooser();
fc.setCurrentDirectory(new File(Configuration.lastSaveDir.get()));
if (selected.length > 1) {
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
} else {
fc.setSelectedFile(new File(Configuration.lastSaveDir.get(), "movie.swf"));
fc.setFileFilter(new FileFilter() {
@Override
public boolean accept(File f) {
return (f.getName().endsWith(".swf")) || (f.isDirectory());
}
@Override
public String getDescription() {
return AppStrings.translate("filter.swf");
}
});
}
fc.setAcceptAllFileFilterUsed(false);
JFrame f = new JFrame();
View.setWindowIcon(f);
int returnVal = fc.showSaveDialog(f);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = Helper.fixDialogFile(fc.getSelectedFile());
try {
if (selected.length == 1) {
SwfInMemory swf = foundIs.get(tableRes.getRowSorter().convertRowIndexToModel(selected[0]));
ReReadableInputStream bis = swf.is;
bis.seek(0);
Helper.saveStream(bis, file);
} else {
for (int sel : selected) {
SwfInMemory swf = foundIs.get(tableRes.getRowSorter().convertRowIndexToModel(sel));
ReReadableInputStream bis = swf.is;
bis.seek(0);
Helper.saveStream(bis, new File(file, "movie" + sel + ".swf"));
}
}
Configuration.lastSaveDir.set(file.getParentFile().getAbsolutePath());
} catch (IOException ex) {
View.showMessageDialog(null, translate("error.file.write"));
}
}
}
break;
}
}
}
@@ -0,0 +1,111 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.ApplicationInfo;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.ImageObserver;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingConstants;
/**
* Dialog showing loading of SWF file
*
* @author JPEXS
*/
public class LoadingDialog extends AppDialog implements ImageObserver {
private final JLabel detailLabel;
private LoadingPanel loadingPanel;
JProgressBar progressBar = new JProgressBar(0, 100);
public void setDetail(String d) {
detailLabel.setText(d);
detailLabel.setHorizontalAlignment(SwingConstants.CENTER);
}
public void setPercent(final int percent) {
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
progressBar.setIndeterminate(false);
progressBar.setValue(percent);
progressBar.setStringPainted(true);
}
});
}
public void hidePercent() {
progressBar.setIndeterminate(true);
progressBar.setStringPainted(false);
}
/**
* Constructor
*/
public LoadingDialog() {
setResizable(false);
setTitle(ApplicationInfo.shortApplicationVerName);
Container cntp = getContentPane();
JPanel cnt = new JPanel();
cntp.setLayout(new BorderLayout());
cntp.add(cnt);
cnt.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
cnt.setLayout(new BorderLayout());
//loadingPanel = new LoadingPanel(50, 50);
//loadingPanel.setPreferredSize(new Dimension(100, 100));
//add(loadingPanel, BorderLayout.WEST);
JPanel pan = new JPanel();
pan.setLayout(new ListLayout(5));
//pan.setPreferredSize(new Dimension(120, 150));
JLabel loadingLabel = new JLabel(translate("loadingpleasewait"));
//loadingLabel.setBounds(0, 30, 150, 20);
loadingLabel.setHorizontalAlignment(SwingConstants.CENTER);
detailLabel = new JLabel("", JLabel.CENTER);
detailLabel.setPreferredSize(new Dimension(loadingLabel.getPreferredSize()));
detailLabel.setHorizontalAlignment(SwingConstants.CENTER);
//detailLabel.setBounds(0, 45, 150, 20);
//progressBar.setBounds(0, 70, 125, 25);
pan.add(loadingLabel);
pan.add(detailLabel);
pan.add(progressBar);
cnt.add(pan, BorderLayout.CENTER);
//progressBar.setVisible(false);
progressBar.setStringPainted(true);
//progressBar.setVisible(false);
View.setWindowIcon(this);
detailLabel.setHorizontalAlignment(SwingConstants.LEFT);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
pack();
Dimension siz = getSize();
setSize(Math.max(300, 150 + getFontMetrics(new JLabel().getFont()).stringWidth(translate("loadingpleasewait"))), siz.height);
View.centerScreen(this);
}
}
@@ -0,0 +1,68 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import java.awt.Graphics;
import java.awt.Image;
import java.util.Timer;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
/**
* Panel with loading animation
*
* @author JPEXS
*/
public class LoadingPanel extends JPanel {
private int pos = 0;
private final Image animationImage;
private final int iconWidth;
private final int iconHeight;
/**
* Constructor
*
* @param iconWidth Width of displayed icon
* @param iconHeight Height of displayed icon
*/
public LoadingPanel(int iconWidth, int iconHeight) {
this.iconWidth = iconWidth;
this.iconHeight = iconHeight;
ImageIcon icon = View.getIcon("loading");
animationImage = icon.getImage();
Timer timer = new Timer();
timer.schedule(new java.util.TimerTask() {
@Override
public void run() {
pos = (pos + 1) % 12;
repaint();
}
}, 100, 100);
}
/**
* Paints component
*
* @param g Graphics to paint on
*/
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(animationImage, getWidth() / 2 - iconWidth / 2, getHeight() / 2 - iconHeight / 2, getWidth() / 2 + iconWidth / 2, getHeight() / 2 + iconHeight / 2, pos * 100, 0, (pos + 1) * 100, 100, this);
}
}
@@ -0,0 +1,69 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
/**
*
* @author JPEXS
*/
public class LogFormatter extends Formatter {
static final String lineSep = System.getProperty("line.separator");
private DateFormat dateFormat;
@Override
public String format(LogRecord record) {
StringBuilder buf = new StringBuilder(180);
if (dateFormat == null) {
dateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
}
buf.append(dateFormat.format(new Date(record.getMillis())));
buf.append(" > ");
if (record.getLevel().intValue() >= Level.WARNING.intValue()) {
buf.append(record.getLevel());
buf.append(": ");
}
buf.append(formatMessage(record));
buf.append(lineSep);
Throwable throwable = record.getThrown();
if (throwable != null) {
StringWriter sink = new StringWriter();
throwable.printStackTrace(new PrintWriter(sink, true));
buf.append(record.getSourceClassName());
buf.append(' ');
buf.append(record.getSourceMethodName());
buf.append(lineSep);
buf.append(sink.toString());
}
return buf.toString();
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,34 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
/**
*
* @author JPEXS
*/
public interface MainFrame {
public void setTitle(String string);
public String translate(String key);
public MainPanel getPanel();
public boolean isVisible();
public void setVisible(boolean b);
}
@@ -0,0 +1,121 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.gui.player.FlashPlayerPanel;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowStateListener;
import javax.swing.JFrame;
/**
*
* @author JPEXS
*/
public final class MainFrameClassic extends AppFrame implements MainFrame {
public MainPanel panel;
private MainFrameMenu mainMenu;
public MainFrameClassic() {
super();
FlashPlayerPanel flashPanel = null;
try {
flashPanel = new FlashPlayerPanel(this);
} catch (FlashUnsupportedException fue) {
}
boolean externalFlashPlayerUnavailable = flashPanel == null;
mainMenu = new MainFrameClassicMenu(this, externalFlashPlayerUnavailable);
panel = new MainPanel(this, mainMenu, flashPanel);
int w = Configuration.guiWindowWidth.get();
int h = Configuration.guiWindowHeight.get();
Dimension dim = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
if (w > dim.width) {
w = dim.width;
}
if (h > dim.height) {
h = dim.height;
}
setSize(w, h);
boolean maximizedHorizontal = Configuration.guiWindowMaximizedHorizontal.get();
boolean maximizedVertical = Configuration.guiWindowMaximizedVertical.get();
int state = 0;
if (maximizedHorizontal) {
state |= JFrame.MAXIMIZED_HORIZ;
}
if (maximizedVertical) {
state |= JFrame.MAXIMIZED_VERT;
}
setExtendedState(state);
View.setWindowIcon(this);
addWindowStateListener(new WindowStateListener() {
@Override
public void windowStateChanged(WindowEvent e) {
int state = e.getNewState();
Configuration.guiWindowMaximizedHorizontal.set((state & JFrame.MAXIMIZED_HORIZ) == JFrame.MAXIMIZED_HORIZ);
Configuration.guiWindowMaximizedVertical.set((state & JFrame.MAXIMIZED_VERT) == JFrame.MAXIMIZED_VERT);
}
});
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
int state = getExtendedState();
if ((state & JFrame.MAXIMIZED_HORIZ) == 0) {
Configuration.guiWindowWidth.set(getWidth());
}
if ((state & JFrame.MAXIMIZED_VERT) == 0) {
Configuration.guiWindowHeight.set(getHeight());
}
}
});
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
Main.exit();
}
});
java.awt.Container cnt = getContentPane();
cnt.setLayout(new BorderLayout());
cnt.add(panel);
View.centerScreen(this);
}
@Override
public void setVisible(boolean b) {
super.setVisible(b);
panel.setVisible(b);
}
@Override
public MainPanel getPanel() {
return panel;
}
}
@@ -0,0 +1,579 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.ApplicationInfo;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.console.ContextMenuTools;
import com.jpexs.decompiler.flash.gui.treenodes.SWFNode;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.helpers.Cache;
import com.sun.jna.Platform;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
/**
*
* @author JPEXS
*/
public class MainFrameClassicMenu implements MainFrameMenu, ActionListener {
static final String ACTION_RELOAD = "RELOAD";
static final String ACTION_ADVANCED_SETTINGS = "ADVANCEDSETTINGS";
static final String ACTION_LOAD_MEMORY = "LOADMEMORY";
static final String ACTION_LOAD_CACHE = "LOADCACHE";
static final String ACTION_GOTO_DOCUMENT_CLASS_ON_STARTUP = "GOTODOCUMENTCLASSONSTARTUP";
static final String ACTION_AUTO_RENAME_IDENTIFIERS = "AUTORENAMEIDENTIFIERS";
static final String ACTION_CACHE_ON_DISK = "CACHEONDISK";
static final String ACTION_SET_LANGUAGE = "SETLANGUAGE";
static final String ACTION_DISABLE_DECOMPILATION = "DISABLEDECOMPILATION";
static final String ACTION_ASSOCIATE = "ASSOCIATE";
static final String ACTION_GOTO_DOCUMENT_CLASS = "GOTODOCUMENTCLASS";
static final String ACTION_PARALLEL_SPEED_UP = "PARALLELSPEEDUP";
static final String ACTION_INTERNAL_VIEWER_SWITCH = "INTERNALVIEWERSWITCH";
static final String ACTION_SEARCH_AS = "SEARCHAS";
static final String ACTION_AUTO_DEOBFUSCATE = "AUTODEOBFUSCATE";
static final String ACTION_EXIT = "EXIT";
static final String ACTION_RENAME_ONE_IDENTIFIER = "RENAMEONEIDENTIFIER";
static final String ACTION_ABOUT = "ABOUT";
static final String ACTION_SHOW_PROXY = "SHOWPROXY";
static final String ACTION_SUB_LIMITER = "SUBLIMITER";
static final String ACTION_SAVE = "SAVE";
static final String ACTION_SAVE_AS = "SAVEAS";
static final String ACTION_SAVE_AS_EXE = "SAVEASEXE";
static final String ACTION_OPEN = "OPEN";
static final String ACTION_EXPORT_FLA = "EXPORTFLA";
public static final String ACTION_EXPORT_SEL = "EXPORTSEL";
static final String ACTION_EXPORT = "EXPORT";
static final String ACTION_CHECK_UPDATES = "CHECKUPDATES";
static final String ACTION_HELP_US = "HELPUS";
static final String ACTION_HOMEPAGE = "HOMEPAGE";
static final String ACTION_RESTORE_CONTROL_FLOW = "RESTORECONTROLFLOW";
static final String ACTION_RESTORE_CONTROL_FLOW_ALL = "RESTORECONTROLFLOWALL";
static final String ACTION_RENAME_IDENTIFIERS = "RENAMEIDENTIFIERS";
static final String ACTION_DEOBFUSCATE = "DEOBFUSCATE";
static final String ACTION_DEOBFUSCATE_ALL = "DEOBFUSCATEALL";
static final String ACTION_REMOVE_NON_SCRIPTS = "REMOVENONSCRIPTS";
static final String ACTION_REFRESH_DECOMPILED = "REFRESHDECOMPILED";
private final MainFrameClassic mainFrame;
private JCheckBoxMenuItem miAutoDeobfuscation;
private JCheckBoxMenuItem miInternalViewer;
private JCheckBoxMenuItem miParallelSpeedUp;
private JCheckBoxMenuItem miAssociate;
private JCheckBoxMenuItem miDecompile;
private JCheckBoxMenuItem miCacheDisk;
private JCheckBoxMenuItem miGotoMainClassOnStartup;
private JCheckBoxMenuItem miAutoRenameIdentifiers;
private JMenuItem saveCommandButton;
private JMenuItem saveasCommandButton;
private JMenuItem saveasexeCommandButton;
private JMenuItem exportAllCommandButton;
private JMenuItem exportFlaCommandButton;
private JMenuItem exportSelectionCommandButton;
private JMenuItem reloadCommandButton;
private JMenuItem renameinvalidCommandButton;
private JMenuItem globalrenameCommandButton;
private JMenuItem deobfuscationCommandButton;
private JMenuItem searchCommandButton;
private JMenuItem gotoDocumentClassCommandButton;
public MainFrameClassicMenu(MainFrameClassic mainFrame, boolean externalFlashPlayerUnavailable) {
this.mainFrame = mainFrame;
createMenuBar(externalFlashPlayerUnavailable);
}
@Override
public boolean isInternalFlashViewerSelected() {
return miInternalViewer.isSelected();
}
private String translate(String key) {
return mainFrame.translate(key);
}
private void assignListener(JMenuItem b, final String command) {
final MainFrameClassicMenu t = this;
b.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
t.actionPerformed(new ActionEvent(e.getSource(), 0, command));
}
});
}
private String fixCommandTitle(String title) {
if (title.length() > 2) {
if (title.charAt(1) == ' ') {
title = title.charAt(0) + "\u00A0" + title.substring(2);
}
}
return title;
}
private void createMenuBar(boolean externalFlashPlayerUnavailable) {
JMenuBar menuBar = new JMenuBar();
JMenu menuFile = new JMenu(translate("menu.file"));
JMenuItem miOpen = new JMenuItem(translate("menu.file.open"));
miOpen.setIcon(View.getIcon("open16"));
miOpen.setActionCommand(ACTION_OPEN);
miOpen.addActionListener(this);
JMenuItem miSave = new JMenuItem(translate("menu.file.save"));
miSave.setIcon(View.getIcon("save16"));
miSave.setActionCommand(ACTION_SAVE);
miSave.addActionListener(this);
JMenuItem miSaveAs = new JMenuItem(translate("menu.file.saveas"));
miSaveAs.setIcon(View.getIcon("saveas16"));
miSaveAs.setActionCommand(ACTION_SAVE_AS);
miSaveAs.addActionListener(this);
JMenuItem miSaveAsExe = new JMenuItem(translate("menu.file.saveasexe"));
miSaveAsExe.setIcon(View.getIcon("saveas16"));
miSaveAsExe.setActionCommand(ACTION_SAVE_AS_EXE);
miSaveAsExe.addActionListener(this);
JMenuItem menuExportFla = new JMenuItem(translate("menu.file.export.fla"));
menuExportFla.setActionCommand(ACTION_EXPORT_FLA);
menuExportFla.addActionListener(this);
menuExportFla.setIcon(View.getIcon("flash16"));
JMenuItem menuExportAll = new JMenuItem(translate("menu.file.export.all"));
menuExportAll.setActionCommand(ACTION_EXPORT);
menuExportAll.addActionListener(this);
JMenuItem menuExportSel = new JMenuItem(translate("menu.file.export.selection"));
menuExportSel.setActionCommand(ACTION_EXPORT_SEL);
menuExportSel.addActionListener(this);
menuExportAll.setIcon(View.getIcon("export16"));
menuExportSel.setIcon(View.getIcon("exportsel16"));
menuFile.add(miOpen);
menuFile.add(miSave);
menuFile.add(miSaveAs);
menuFile.add(miSaveAsExe);
menuFile.add(menuExportFla);
menuFile.add(menuExportAll);
menuFile.add(menuExportSel);
menuFile.addSeparator();
JMenuItem miClose = new JMenuItem(translate("menu.file.exit"));
miClose.setIcon(View.getIcon("exit16"));
miClose.setActionCommand(ACTION_EXIT);
miClose.addActionListener(this);
menuFile.add(miClose);
menuBar.add(menuFile);
JMenu menuDeobfuscation = new JMenu(translate("menu.tools.deobfuscation"));
menuDeobfuscation.setIcon(View.getIcon("deobfuscate16"));
JMenuItem miDeobfuscation = new JMenuItem(translate("menu.tools.deobfuscation.pcode"));
miDeobfuscation.setActionCommand(ACTION_DEOBFUSCATE);
miDeobfuscation.addActionListener(this);
miAutoDeobfuscation = new JCheckBoxMenuItem(translate("menu.settings.autodeobfuscation"));
miAutoDeobfuscation.setSelected(Configuration.autoDeobfuscate.get());
miAutoDeobfuscation.addActionListener(this);
miAutoDeobfuscation.setActionCommand(ACTION_AUTO_DEOBFUSCATE);
JMenuItem miRenameOneIdentifier = new JMenuItem(translate("menu.tools.deobfuscation.globalrename"));
miRenameOneIdentifier.setActionCommand(ACTION_RENAME_ONE_IDENTIFIER);
miRenameOneIdentifier.addActionListener(this);
JMenuItem miRenameIdentifiers = new JMenuItem(translate("menu.tools.deobfuscation.renameinvalid"));
miRenameIdentifiers.setActionCommand(ACTION_RENAME_IDENTIFIERS);
miRenameIdentifiers.addActionListener(this);
menuDeobfuscation.add(miRenameOneIdentifier);
menuDeobfuscation.add(miRenameIdentifiers);
menuDeobfuscation.add(miDeobfuscation);
JMenu menuTools = new JMenu(translate("menu.tools"));
JMenuItem miProxy = new JMenuItem(translate("menu.tools.proxy"));
miProxy.setActionCommand(ACTION_SHOW_PROXY);
miProxy.setIcon(View.getIcon("proxy16"));
miProxy.addActionListener(this);
JMenuItem miSearchScript = new JMenuItem(translate("menu.tools.searchas"));
miSearchScript.addActionListener(this);
miSearchScript.setActionCommand(ACTION_SEARCH_AS);
miSearchScript.setIcon(View.getIcon("search16"));
menuTools.add(miSearchScript);
miInternalViewer = new JCheckBoxMenuItem(translate("menu.settings.internalflashviewer"));
miInternalViewer.setSelected(Configuration.internalFlashViewer.get() || externalFlashPlayerUnavailable);
if (externalFlashPlayerUnavailable) {
miInternalViewer.setEnabled(false);
}
miInternalViewer.setActionCommand(ACTION_INTERNAL_VIEWER_SWITCH);
miInternalViewer.addActionListener(this);
miParallelSpeedUp = new JCheckBoxMenuItem(translate("menu.settings.parallelspeedup"));
miParallelSpeedUp.setSelected(Configuration.parallelSpeedUp.get());
miParallelSpeedUp.setActionCommand(ACTION_PARALLEL_SPEED_UP);
miParallelSpeedUp.addActionListener(this);
menuTools.add(miProxy);
menuTools.add(menuDeobfuscation);
JMenuItem miGotoDocumentClass = new JMenuItem(translate("menu.tools.gotodocumentclass"));
miGotoDocumentClass.setActionCommand(ACTION_GOTO_DOCUMENT_CLASS);
miGotoDocumentClass.addActionListener(this);
menuBar.add(menuTools);
miDecompile = new JCheckBoxMenuItem(translate("menu.settings.disabledecompilation"));
miDecompile.setSelected(!Configuration.decompile.get());
miDecompile.setActionCommand(ACTION_DISABLE_DECOMPILATION);
miDecompile.addActionListener(this);
miCacheDisk = new JCheckBoxMenuItem(translate("menu.settings.cacheOnDisk"));
miCacheDisk.setSelected(Configuration.cacheOnDisk.get());
miCacheDisk.setActionCommand(ACTION_CACHE_ON_DISK);
miCacheDisk.addActionListener(this);
miGotoMainClassOnStartup = new JCheckBoxMenuItem(translate("menu.settings.gotoMainClassOnStartup"));
miGotoMainClassOnStartup.setSelected(Configuration.gotoMainClassOnStartup.get());
miGotoMainClassOnStartup.setActionCommand(ACTION_GOTO_DOCUMENT_CLASS_ON_STARTUP);
miGotoMainClassOnStartup.addActionListener(this);
miAutoRenameIdentifiers = new JCheckBoxMenuItem(translate("menu.settings.autoRenameIdentifiers"));
miAutoRenameIdentifiers.setSelected(Configuration.autoRenameIdentifiers.get());
miAutoRenameIdentifiers.setActionCommand(ACTION_AUTO_RENAME_IDENTIFIERS);
miAutoRenameIdentifiers.addActionListener(this);
JMenu menuSettings = new JMenu(translate("menu.settings"));
menuSettings.add(miAutoDeobfuscation);
menuSettings.add(miInternalViewer);
menuSettings.add(miParallelSpeedUp);
menuSettings.add(miDecompile);
menuSettings.add(miCacheDisk);
menuSettings.add(miGotoMainClassOnStartup);
menuSettings.add(miAutoRenameIdentifiers);
miAssociate = new JCheckBoxMenuItem(translate("menu.settings.addtocontextmenu"));
miAssociate.setActionCommand(ACTION_ASSOCIATE);
miAssociate.addActionListener(this);
miAssociate.setSelected(ContextMenuTools.isAddedToContextMenu());
JMenuItem miLanguage = new JMenuItem(translate("menu.settings.language"));
miLanguage.setActionCommand(ACTION_SET_LANGUAGE);
miLanguage.addActionListener(this);
if (Platform.isWindows()) {
menuSettings.add(miAssociate);
}
menuSettings.add(miLanguage);
JMenuItem advancedSettingsCommandButton = new JMenuItem(translate("menu.advancedsettings.advancedsettings"));
advancedSettingsCommandButton.setActionCommand(ACTION_ADVANCED_SETTINGS);
advancedSettingsCommandButton.setIcon(View.getIcon("settings16"));
advancedSettingsCommandButton.addActionListener(this);
menuSettings.add(advancedSettingsCommandButton);
menuBar.add(menuSettings);
JMenu menuHelp = new JMenu(translate("menu.help"));
JMenuItem miAbout = new JMenuItem(translate("menu.help.about"));
miAbout.setIcon(View.getIcon("about16"));
miAbout.setActionCommand(ACTION_ABOUT);
miAbout.addActionListener(this);
JMenuItem miCheckUpdates = new JMenuItem(translate("menu.help.checkupdates"));
miCheckUpdates.setActionCommand(ACTION_CHECK_UPDATES);
miCheckUpdates.setIcon(View.getIcon("update16"));
miCheckUpdates.addActionListener(this);
JMenuItem miHelpUs = new JMenuItem(translate("menu.help.helpus"));
miHelpUs.setActionCommand(ACTION_HELP_US);
miHelpUs.setIcon(View.getIcon("donate16"));
miHelpUs.addActionListener(this);
JMenuItem miHomepage = new JMenuItem(translate("menu.help.homepage"));
miHomepage.setActionCommand(ACTION_HOMEPAGE);
miHomepage.setIcon(View.getIcon("homepage16"));
miHomepage.addActionListener(this);
menuHelp.add(miCheckUpdates);
menuHelp.add(miHelpUs);
menuHelp.add(miHomepage);
menuHelp.add(miAbout);
menuBar.add(menuHelp);
mainFrame.setJMenuBar(menuBar);
//if (hasAbc) {
menuTools.add(miGotoDocumentClass);
//}
}
@Override
public void updateComponents(SWF swf, List<ABCContainerTag> abcList) {
boolean swfLoaded = swf != null;
boolean hasAbc = swfLoaded && abcList != null && !abcList.isEmpty();
/*saveCommandButton.setEnabled(swfLoaded);
saveasCommandButton.setEnabled(swfLoaded);
saveasexeCommandButton.setEnabled(swfLoaded);
exportAllCommandButton.setEnabled(swfLoaded);
exportFlaCommandButton.setEnabled(swfLoaded);
exportSelectionCommandButton.setEnabled(swfLoaded);
reloadCommandButton.setEnabled(swfLoaded);
renameinvalidCommandButton.setEnabled(swfLoaded);
globalrenameCommandButton.setEnabled(swfLoaded);
deobfuscationCommandButton.setEnabled(swfLoaded);
searchCommandButton.setEnabled(swfLoaded);
gotoDocumentClassCommandButton.setEnabled(hasAbc);
deobfuscationCommandButton.setEnabled(hasAbc);*/
}
private void saveAs(SWF swf, SaveFileMode mode) {
if (Main.saveFileDialog(swf, mode)) {
swf.fileTitle = null;
mainFrame.setTitle(ApplicationInfo.applicationVerName + (Configuration.displayFileName.get() ? " - " + swf.getFileTitle() : ""));
saveCommandButton.setEnabled(mainFrame.panel.getCurrentSwf() != null);
}
}
@Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case ACTION_RELOAD:
if (View.showConfirmDialog(null, translate("message.confirm.reload"), translate("message.warning"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) {
Main.reloadApp();
}
break;
case ACTION_ADVANCED_SETTINGS:
Main.advancedSettings();
break;
case ACTION_LOAD_MEMORY:
Main.loadFromMemory();
break;
case ACTION_LOAD_CACHE:
Main.loadFromCache();
break;
case ACTION_GOTO_DOCUMENT_CLASS_ON_STARTUP:
Configuration.gotoMainClassOnStartup.set(miGotoMainClassOnStartup.isSelected());
break;
case ACTION_AUTO_RENAME_IDENTIFIERS:
Configuration.autoRenameIdentifiers.set(miAutoRenameIdentifiers.isSelected());
break;
case ACTION_CACHE_ON_DISK:
Configuration.cacheOnDisk.set(miCacheDisk.isSelected());
if (miCacheDisk.isSelected()) {
Cache.setStorageType(Cache.STORAGE_FILES);
} else {
Cache.setStorageType(Cache.STORAGE_MEMORY);
}
break;
case ACTION_SET_LANGUAGE:
new SelectLanguageDialog().display();
break;
case ACTION_DISABLE_DECOMPILATION:
Configuration.decompile.set(!miDecompile.isSelected());
mainFrame.panel.disableDecompilationChanged();
break;
case ACTION_ASSOCIATE:
if (miAssociate.isSelected() == ContextMenuTools.isAddedToContextMenu()) {
return;
}
ContextMenuTools.addToContextMenu(miAssociate.isSelected(), false);
//Update checkbox menuitem accordingly (User can cancel rights elevation)
new Timer().schedule(new TimerTask() {
@Override
public void run() {
miAssociate.setSelected(ContextMenuTools.isAddedToContextMenu());
}
}, 1000); //It takes some time registry change to apply
break;
case ACTION_GOTO_DOCUMENT_CLASS:
mainFrame.panel.gotoDocumentClass(mainFrame.panel.getCurrentSwf());
break;
case ACTION_PARALLEL_SPEED_UP:
String confStr = translate("message.confirm.parallel") + "\r\n";
if (miParallelSpeedUp.isSelected()) {
confStr += " " + translate("message.confirm.on");
} else {
confStr += " " + translate("message.confirm.off");
}
if (View.showConfirmDialog(null, confStr, translate("message.parallel"), JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) {
Configuration.parallelSpeedUp.set((Boolean) miParallelSpeedUp.isSelected());
} else {
miParallelSpeedUp.setSelected(!miParallelSpeedUp.isSelected());
}
break;
case ACTION_INTERNAL_VIEWER_SWITCH:
Configuration.internalFlashViewer.set(miInternalViewer.isSelected());
mainFrame.panel.reload(true);
break;
case ACTION_SEARCH_AS:
mainFrame.panel.searchAs();
break;
case ACTION_AUTO_DEOBFUSCATE:
if (View.showConfirmDialog(mainFrame.panel, translate("message.confirm.autodeobfuscate") + "\r\n" + (miAutoDeobfuscation.isSelected() ? translate("message.confirm.on") : translate("message.confirm.off")), translate("message.confirm"), JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) {
Configuration.autoDeobfuscate.set(miAutoDeobfuscation.isSelected());
mainFrame.panel.autoDeobfuscateChanged();
} else {
miAutoDeobfuscation.setSelected(!miAutoDeobfuscation.isSelected());
}
break;
case ACTION_EXIT:
mainFrame.panel.setVisible(false);
if (Main.proxyFrame != null) {
if (Main.proxyFrame.isVisible()) {
return;
}
}
Main.exit();
break;
}
if (Main.isWorking()) {
return;
}
switch (e.getActionCommand()) {
case ACTION_RENAME_ONE_IDENTIFIER:
mainFrame.panel.renameOneIdentifier(mainFrame.panel.getCurrentSwf());
break;
case ACTION_ABOUT:
Main.about();
break;
case ACTION_SHOW_PROXY:
Main.showProxy();
break;
case ACTION_SUB_LIMITER:
if (e.getSource() instanceof JCheckBoxMenuItem) {
Main.setSubLimiter(((JCheckBoxMenuItem) e.getSource()).getState());
}
break;
case ACTION_SAVE: {
SWF swf = mainFrame.panel.getCurrentSwf();
SWFNode snode = ((TagTreeModel)mainFrame.panel.tagTree.getModel()).getSwfNode(swf);
if(snode.binaryData!=null){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
swf.saveTo(baos);
snode.binaryData.binaryData = baos.toByteArray();
snode.binaryData.setModified(true);
} catch (IOException ex) {
Logger.getLogger(MainFrameRibbonMenu.class.getName()).log(Level.SEVERE, "Cannot save SWF", ex);
}
}
else if(swf.file == null) {
saveAs(swf, SaveFileMode.SAVEAS);
} else {
try {
Main.saveFile(swf, swf.file);
} catch (IOException ex) {
Logger.getLogger(MainFrameClassicMenu.class.getName()).log(Level.SEVERE, null, ex);
View.showMessageDialog(null, translate("error.file.save"), translate("error"), JOptionPane.ERROR_MESSAGE);
}
}
}
break;
case ACTION_SAVE_AS: {
SWF swf = mainFrame.panel.getCurrentSwf();
saveAs(swf, SaveFileMode.SAVEAS);
}
break;
case ACTION_SAVE_AS_EXE: {
SWF swf = mainFrame.panel.getCurrentSwf();
saveAs(swf, SaveFileMode.EXE);
}
break;
case ACTION_OPEN:
Main.openFileDialog();
break;
case ACTION_EXPORT_FLA:
mainFrame.panel.exportFla(mainFrame.panel.getCurrentSwf());
break;
case ACTION_EXPORT_SEL:
case ACTION_EXPORT:
boolean onlySel = e.getActionCommand().endsWith("SEL");
mainFrame.panel.export(onlySel);
break;
case ACTION_CHECK_UPDATES:
if (!Main.checkForUpdates()) {
View.showMessageDialog(null, translate("update.check.nonewversion"), translate("update.check.title"), JOptionPane.INFORMATION_MESSAGE);
}
break;
case ACTION_HELP_US:
String helpUsURL = ApplicationInfo.PROJECT_PAGE + "/help_us.html";
if (java.awt.Desktop.isDesktopSupported()) {
java.awt.Desktop desktop = java.awt.Desktop.getDesktop();
try {
java.net.URI uri = new java.net.URI(helpUsURL);
desktop.browse(uri);
} catch (URISyntaxException | IOException ex) {
}
} else {
View.showMessageDialog(null, translate("message.helpus").replace("%url%", helpUsURL));
}
break;
case ACTION_HOMEPAGE:
String homePageURL = ApplicationInfo.PROJECT_PAGE;
if (java.awt.Desktop.isDesktopSupported()) {
java.awt.Desktop desktop = java.awt.Desktop.getDesktop();
try {
java.net.URI uri = new java.net.URI(homePageURL);
desktop.browse(uri);
} catch (URISyntaxException | IOException ex) {
}
} else {
View.showMessageDialog(null, translate("message.homepage").replace("%url%", homePageURL));
}
break;
case ACTION_RESTORE_CONTROL_FLOW:
case ACTION_RESTORE_CONTROL_FLOW_ALL:
boolean all = e.getActionCommand().endsWith("ALL");
mainFrame.panel.restoreControlFlow(all);
break;
case ACTION_RENAME_IDENTIFIERS:
mainFrame.panel.renameIdentifiers(mainFrame.panel.getCurrentSwf());
break;
case ACTION_DEOBFUSCATE:
case ACTION_DEOBFUSCATE_ALL:
mainFrame.panel.deobfuscate();
break;
case ACTION_REMOVE_NON_SCRIPTS:
mainFrame.panel.removeNonScripts(mainFrame.panel.getCurrentSwf());
break;
case ACTION_REFRESH_DECOMPILED:
mainFrame.panel.refreshDecompiled();
break;
}
}
}
@@ -0,0 +1,32 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import java.util.List;
/**
*
* @author JPEXS
*/
public interface MainFrameMenu {
public boolean isInternalFlashViewerSelected();
public void updateComponents(SWF swf, List<ABCContainerTag> abcList);
}
@@ -0,0 +1,218 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.gui.player.FlashPlayerPanel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowStateListener;
import java.util.List;
import javax.swing.JFrame;
import org.pushingpixels.flamingo.api.ribbon.JRibbon;
import org.pushingpixels.flamingo.internal.ui.ribbon.appmenu.JRibbonApplicationMenuButton;
/**
*
* @author JPEXS
*/
public final class MainFrameRibbon extends AppRibbonFrame implements MainFrame {
public MainPanel panel;
private MainFrameMenu mainMenu;
public MainFrameRibbon() {
super();
FlashPlayerPanel flashPanel = null;
try {
flashPanel = new FlashPlayerPanel(this);
} catch (FlashUnsupportedException fue) {
}
Container cnt = getContentPane();
cnt.setLayout(new BorderLayout());
JRibbon ribbon = getRibbon();
cnt.add(ribbon, BorderLayout.NORTH);
boolean externalFlashPlayerUnavailable = flashPanel == null;
mainMenu = new MainFrameRibbonMenu(this, ribbon, externalFlashPlayerUnavailable);
panel = new MainPanel(this, mainMenu, flashPanel);
panel.setBackground(Color.yellow);
cnt.add(panel, BorderLayout.CENTER);
int w = Configuration.guiWindowWidth.get();
int h = Configuration.guiWindowHeight.get();
Dimension dim = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
if (w > dim.width) {
w = dim.width;
}
if (h > dim.height) {
h = dim.height;
}
setSize(w, h);
boolean maximizedHorizontal = Configuration.guiWindowMaximizedHorizontal.get();
boolean maximizedVertical = Configuration.guiWindowMaximizedVertical.get();
int state = 0;
if (maximizedHorizontal) {
state |= JFrame.MAXIMIZED_HORIZ;
}
if (maximizedVertical) {
state |= JFrame.MAXIMIZED_VERT;
}
setExtendedState(state);
View.setWindowIcon(this);
addWindowStateListener(new WindowStateListener() {
@Override
public void windowStateChanged(WindowEvent e) {
int state = e.getNewState();
Configuration.guiWindowMaximizedHorizontal.set((state & JFrame.MAXIMIZED_HORIZ) == JFrame.MAXIMIZED_HORIZ);
Configuration.guiWindowMaximizedVertical.set((state & JFrame.MAXIMIZED_VERT) == JFrame.MAXIMIZED_VERT);
}
});
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
int state = getExtendedState();
if ((state & JFrame.MAXIMIZED_HORIZ) == 0) {
Configuration.guiWindowWidth.set(getWidth());
}
if ((state & JFrame.MAXIMIZED_VERT) == 0) {
Configuration.guiWindowHeight.set(getHeight());
}
}
});
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
Main.exit();
}
});
View.centerScreen(this);
}
private static void getApplicationMenuButtons(Component comp, List<JRibbonApplicationMenuButton> ret) {
if (comp instanceof JRibbonApplicationMenuButton) {
ret.add((JRibbonApplicationMenuButton) comp);
return;
}
if (comp instanceof java.awt.Container) {
java.awt.Container cont = (java.awt.Container) comp;
for (int i = 0; i < cont.getComponentCount(); i++) {
getApplicationMenuButtons(cont.getComponent(i), ret);
}
}
}
@Override
public void setVisible(boolean b) {
super.setVisible(b);
/* final MainFrameRibbon t = this;
//TODO: Handle this better. This is awful :-(
new Timer().schedule(new TimerTask() {
@Override
public void run() {
List<JRibbonApplicationMenuButton> mbuttons = new ArrayList<>();
getApplicationMenuButtons(t, mbuttons);
if (mbuttons.size() < 2) {
//return, task will run again
return;
}
for (final JRibbonApplicationMenuButton mbutton : mbuttons) {
mbutton.setIcon(View.getResizableIcon("buttonicon_256"));
mbutton.setDisplayState(new CommandButtonDisplayState(
"My Ribbon Application Menu Button", mbutton.getSize().width) {
@Override
public CommandButtonLayoutManager createLayoutManager(
AbstractCommandButton commandButton) {
return new CommandButtonLayoutManager() {
@Override
public int getPreferredIconSize() {
return mbutton.getSize().width;
}
@Override
public CommandButtonLayoutManager.CommandButtonLayoutInfo getLayoutInfo(
AbstractCommandButton commandButton, Graphics g) {
CommandButtonLayoutManager.CommandButtonLayoutInfo result = new CommandButtonLayoutManager.CommandButtonLayoutInfo();
result.actionClickArea = new Rectangle(0, 0, 0, 0);
result.popupClickArea = new Rectangle(0, 0, commandButton
.getWidth(), commandButton.getHeight());
result.popupActionRect = new Rectangle(0, 0, 0, 0);
ResizableIcon icon = commandButton.getIcon();
icon.setDimension(new Dimension(commandButton.getWidth(), commandButton.getHeight()));
result.iconRect = new Rectangle(
0,
0,
commandButton.getWidth(), commandButton.getHeight());
result.isTextInActionArea = false;
return result;
}
@Override
public Dimension getPreferredSize(
AbstractCommandButton commandButton) {
return new Dimension(40, 40);
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
}
@Override
public Point getKeyTipAnchorCenterPoint(
AbstractCommandButton commandButton) {
// dead center
return new Point(commandButton.getWidth() / 2,
commandButton.getHeight() / 2);
}
};
}
});
MyRibbonApplicationMenuButtonUI mui = (MyRibbonApplicationMenuButtonUI) mbutton.getUI();
mui.setHoverIcon(View.getResizableIcon("buttonicon_hover_256"));
mui.setNormalIcon(View.getResizableIcon("buttonicon_256"));
mui.setClickIcon(View.getResizableIcon("buttonicon_down_256"));
mbutton.repaint();
}
cancel(); //cancel task so it does not run again
}
}, 1, 50);*/
panel.setVisible(b);
}
@Override
public MainPanel getPanel() {
return panel;
}
}
@@ -0,0 +1,804 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.ApplicationInfo;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.console.ContextMenuTools;
import com.jpexs.decompiler.flash.gui.helpers.CheckResources;
import com.jpexs.decompiler.flash.gui.treenodes.SWFNode;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.helpers.Cache;
import com.jpexs.helpers.utf8.Utf8Helper;
import com.jpexs.process.ProcessTools;
import com.sun.jna.Platform;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.ScrollPane;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JCheckBox;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import org.pushingpixels.flamingo.api.common.CommandButtonDisplayState;
import org.pushingpixels.flamingo.api.common.JCommandButton;
import org.pushingpixels.flamingo.api.common.JCommandButtonPanel;
import org.pushingpixels.flamingo.api.ribbon.JRibbon;
import org.pushingpixels.flamingo.api.ribbon.JRibbonBand;
import org.pushingpixels.flamingo.api.ribbon.JRibbonComponent;
import org.pushingpixels.flamingo.api.ribbon.RibbonApplicationMenu;
import org.pushingpixels.flamingo.api.ribbon.RibbonApplicationMenuEntryFooter;
import org.pushingpixels.flamingo.api.ribbon.RibbonApplicationMenuEntryPrimary;
import org.pushingpixels.flamingo.api.ribbon.RibbonElementPriority;
import org.pushingpixels.flamingo.api.ribbon.RibbonTask;
import org.pushingpixels.flamingo.api.ribbon.resize.BaseRibbonBandResizePolicy;
import org.pushingpixels.flamingo.api.ribbon.resize.CoreRibbonResizePolicies;
import org.pushingpixels.flamingo.api.ribbon.resize.IconRibbonBandResizePolicy;
import org.pushingpixels.flamingo.api.ribbon.resize.RibbonBandResizePolicy;
import org.pushingpixels.flamingo.internal.ui.ribbon.AbstractBandControlPanel;
/**
*
* @author JPEXS
*/
public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener {
static final String ACTION_RELOAD = "RELOAD";
static final String ACTION_ADVANCED_SETTINGS = "ADVANCEDSETTINGS";
static final String ACTION_LOAD_MEMORY = "LOADMEMORY";
static final String ACTION_LOAD_CACHE = "LOADCACHE";
static final String ACTION_GOTO_DOCUMENT_CLASS_ON_STARTUP = "GOTODOCUMENTCLASSONSTARTUP";
static final String ACTION_AUTO_RENAME_IDENTIFIERS = "AUTORENAMEIDENTIFIERS";
static final String ACTION_CACHE_ON_DISK = "CACHEONDISK";
static final String ACTION_SET_LANGUAGE = "SETLANGUAGE";
static final String ACTION_DISABLE_DECOMPILATION = "DISABLEDECOMPILATION";
static final String ACTION_ASSOCIATE = "ASSOCIATE";
static final String ACTION_GOTO_DOCUMENT_CLASS = "GOTODOCUMENTCLASS";
static final String ACTION_PARALLEL_SPEED_UP = "PARALLELSPEEDUP";
static final String ACTION_INTERNAL_VIEWER_SWITCH = "INTERNALVIEWERSWITCH";
static final String ACTION_SEARCH = "SEARCH";
static final String ACTION_TIMELINE = "TIMELINE";
static final String ACTION_AUTO_DEOBFUSCATE = "AUTODEOBFUSCATE";
static final String ACTION_EXIT = "EXIT";
static final String ACTION_RENAME_ONE_IDENTIFIER = "RENAMEONEIDENTIFIER";
static final String ACTION_ABOUT = "ABOUT";
static final String ACTION_SHOW_PROXY = "SHOWPROXY";
static final String ACTION_SUB_LIMITER = "SUBLIMITER";
static final String ACTION_SAVE = "SAVE";
static final String ACTION_SAVE_AS = "SAVEAS";
static final String ACTION_SAVE_AS_EXE = "SAVEASEXE";
static final String ACTION_OPEN = "OPEN";
static final String ACTION_CLOSE = "CLOSE";
static final String ACTION_CLOSE_ALL = "CLOSEALL";
static final String ACTION_EXPORT_FLA = "EXPORTFLA";
public static final String ACTION_EXPORT_SEL = "EXPORTSEL";
static final String ACTION_EXPORT = "EXPORT";
static final String ACTION_IMPORT_TEXT = "IMPORTTEXT";
static final String ACTION_CHECK_UPDATES = "CHECKUPDATES";
static final String ACTION_HELP_US = "HELPUS";
static final String ACTION_HOMEPAGE = "HOMEPAGE";
static final String ACTION_RESTORE_CONTROL_FLOW = "RESTORECONTROLFLOW";
static final String ACTION_RESTORE_CONTROL_FLOW_ALL = "RESTORECONTROLFLOWALL";
static final String ACTION_RENAME_IDENTIFIERS = "RENAMEIDENTIFIERS";
static final String ACTION_DEOBFUSCATE = "DEOBFUSCATE";
static final String ACTION_DEOBFUSCATE_ALL = "DEOBFUSCATEALL";
static final String ACTION_REMOVE_NON_SCRIPTS = "REMOVENONSCRIPTS";
static final String ACTION_REFRESH_DECOMPILED = "REFRESHDECOMPILED";
static final String ACTION_CLEAR_RECENT_FILES = "CLEARRECENTFILES";
static final String ACTION_CHECK_RESOURCES = "CHECKRESOURCES";
private final MainFrameRibbon mainFrame;
private JCheckBox miAutoDeobfuscation;
private JCheckBox miInternalViewer;
private JCheckBox miParallelSpeedUp;
private JCheckBox miAssociate;
private JCheckBox miDecompile;
private JCheckBox miCacheDisk;
private JCheckBox miGotoMainClassOnStartup;
private JCheckBox miAutoRenameIdentifiers;
private JCommandButton saveCommandButton;
private JCommandButton saveasCommandButton;
private JCommandButton saveasexeCommandButton;
private JCommandButton exportAllCommandButton;
private JCommandButton exportFlaCommandButton;
private JCommandButton exportSelectionCommandButton;
private JCommandButton importTextCommandButton;
private JCommandButton reloadCommandButton;
private JCommandButton renameinvalidCommandButton;
private JCommandButton globalrenameCommandButton;
private JCommandButton deobfuscationCommandButton;
private JCommandButton searchCommandButton;
private JCommandButton timeLineCommandButton;
private JCommandButton gotoDocumentClassCommandButton;
private JCommandButton clearRecentFilesCommandButton;
RibbonApplicationMenuEntryPrimary exportFlaMenu;
RibbonApplicationMenuEntryPrimary exportAllMenu;
RibbonApplicationMenuEntryPrimary exportSelMenu;
RibbonApplicationMenuEntryPrimary closeFileMenu;
RibbonApplicationMenuEntryPrimary closeAllFilesMenu;
public MainFrameRibbonMenu(MainFrameRibbon mainFrame, JRibbon ribbon, boolean externalFlashPlayerUnavailable) {
this.mainFrame = mainFrame;
ribbon.addTask(createFileRibbonTask());
ribbon.addTask(createToolsRibbonTask());
ribbon.addTask(createSettingsRibbonTask(externalFlashPlayerUnavailable));
ribbon.addTask(createHelpRibbonTask());
if (Configuration.debugMode.get()) {
ribbon.addTask(createDebugRibbonTask());
}
ribbon.setApplicationMenu(createMainMenu());
}
@Override
public boolean isInternalFlashViewerSelected() {
return miInternalViewer.isSelected();
}
private String translate(String key) {
return mainFrame.translate(key);
}
private void assignListener(JCommandButton b, final String command) {
final MainFrameRibbonMenu t = this;
b.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
t.actionPerformed(new ActionEvent(e.getSource(), 0, command));
}
});
}
private String fixCommandTitle(String title) {
if (title.length() > 2) {
if (title.charAt(1) == ' ') {
title = title.charAt(0) + "\u00A0" + title.substring(2);
}
}
return title;
}
private RibbonApplicationMenu createMainMenu() {
RibbonApplicationMenu mainMenu = new RibbonApplicationMenu();
exportFlaMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("exportfla32"), translate("menu.file.export.fla"), new ActionRedirector(this, ACTION_EXPORT_FLA), JCommandButton.CommandButtonKind.ACTION_ONLY);
exportAllMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("export32"), translate("menu.file.export.all"), new ActionRedirector(this, ACTION_EXPORT), JCommandButton.CommandButtonKind.ACTION_ONLY);
exportSelMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("exportsel32"), translate("menu.file.export.selection"), new ActionRedirector(this, ACTION_EXPORT_SEL), JCommandButton.CommandButtonKind.ACTION_ONLY);
RibbonApplicationMenuEntryPrimary checkUpdatesMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("update32"), translate("menu.help.checkupdates"), new ActionRedirector(this, ACTION_CHECK_UPDATES), JCommandButton.CommandButtonKind.ACTION_ONLY);
RibbonApplicationMenuEntryPrimary aboutMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("about32"), translate("menu.help.about"), new ActionRedirector(this, ACTION_ABOUT), JCommandButton.CommandButtonKind.ACTION_ONLY);
RibbonApplicationMenuEntryPrimary openFileMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("open32"), translate("menu.file.open"), new ActionRedirector(this, ACTION_OPEN), JCommandButton.CommandButtonKind.ACTION_AND_POPUP_MAIN_ACTION);
closeFileMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("close32"), translate("menu.file.close"), new ActionRedirector(this, ACTION_CLOSE), JCommandButton.CommandButtonKind.ACTION_ONLY);
closeAllFilesMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("close32"), translate("menu.file.closeAll"), new ActionRedirector(this, ACTION_CLOSE_ALL), JCommandButton.CommandButtonKind.ACTION_ONLY);
openFileMenu.setRolloverCallback(new RibbonApplicationMenuEntryPrimary.PrimaryRolloverCallback() {
@Override
public void menuEntryActivated(JPanel targetPanel) {
targetPanel.removeAll();
JCommandButtonPanel openHistoryPanel = new JCommandButtonPanel(CommandButtonDisplayState.MEDIUM);
String groupName = translate("menu.recentFiles");
openHistoryPanel.addButtonGroup(groupName);
List<String> recentFiles = Configuration.getRecentFiles();
int j = 0;
for (int i = recentFiles.size() - 1; i >= 0; i--) {
String path = recentFiles.get(i);
RecentFilesButton historyButton = new RecentFilesButton(j + " " + path, null);
historyButton.fileName = path;
historyButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
RecentFilesButton source = (RecentFilesButton) ae.getSource();
if (Main.openFile(source.fileName, null) == OpenFileResult.NOT_FOUND) {
if (View.showConfirmDialog(null, translate("message.confirm.recentFileNotFound"), translate("message.confirm"), JOptionPane.YES_NO_OPTION) == JOptionPane.YES_NO_OPTION) {
Configuration.removeRecentFile(source.fileName);
}
}
}
});
j++;
historyButton.setHorizontalAlignment(SwingUtilities.LEFT);
openHistoryPanel.addButtonToLastGroup(historyButton);
}
openHistoryPanel.setMaxButtonColumns(1);
targetPanel.setLayout(new BorderLayout());
targetPanel.add(openHistoryPanel, BorderLayout.CENTER);
}
});
RibbonApplicationMenuEntryFooter exitMenu = new RibbonApplicationMenuEntryFooter(View.getResizableIcon("exit32"), translate("menu.file.exit"), new ActionRedirector(this, "EXIT"));
mainMenu.addMenuEntry(openFileMenu);
mainMenu.addMenuEntry(closeFileMenu);
mainMenu.addMenuEntry(closeAllFilesMenu);
mainMenu.addMenuSeparator();
mainMenu.addMenuEntry(exportFlaMenu);
mainMenu.addMenuEntry(exportAllMenu);
mainMenu.addMenuEntry(exportSelMenu);
mainMenu.addMenuSeparator();
mainMenu.addMenuEntry(checkUpdatesMenu);
mainMenu.addMenuEntry(aboutMenu);
mainMenu.addFooterEntry(exitMenu);
mainMenu.addMenuSeparator();
return mainMenu;
}
private List<RibbonBandResizePolicy> getResizePolicies(JRibbonBand ribbonBand) {
List<RibbonBandResizePolicy> resizePolicies = new ArrayList<>();
resizePolicies.add(new CoreRibbonResizePolicies.Mirror(ribbonBand.getControlPanel()));
resizePolicies.add(new IconRibbonBandResizePolicy(ribbonBand.getControlPanel()));
return resizePolicies;
}
private List<RibbonBandResizePolicy> getIconBandResizePolicies(JRibbonBand ribbonBand) {
List<RibbonBandResizePolicy> resizePolicies = new ArrayList<>();
resizePolicies.add(new BaseRibbonBandResizePolicy<AbstractBandControlPanel>(ribbonBand.getControlPanel()) {
@Override
public int getPreferredWidth(int i, int i1) {
return 105;
}
@Override
public void install(int i, int i1) {
}
});
resizePolicies.add(new IconRibbonBandResizePolicy(ribbonBand.getControlPanel()));
return resizePolicies;
}
private RibbonTask createFileRibbonTask() {
JRibbonBand editBand = new JRibbonBand(translate("menu.general"), null);
editBand.setResizePolicies(getResizePolicies(editBand));
JCommandButton openCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.open")), View.getResizableIcon("open32"));
assignListener(openCommandButton, ACTION_OPEN);
saveCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.save")), View.getResizableIcon("save32"));
assignListener(saveCommandButton, ACTION_SAVE);
saveasCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.saveas")), View.getResizableIcon("saveas16"));
assignListener(saveasCommandButton, ACTION_SAVE_AS);
reloadCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.reload")), View.getResizableIcon("reload16"));
assignListener(reloadCommandButton, ACTION_RELOAD);
editBand.addCommandButton(openCommandButton, RibbonElementPriority.TOP);
editBand.addCommandButton(saveCommandButton, RibbonElementPriority.TOP);
editBand.addCommandButton(saveasCommandButton, RibbonElementPriority.MEDIUM);
editBand.addCommandButton(reloadCommandButton, RibbonElementPriority.MEDIUM);
JRibbonBand exportBand = new JRibbonBand(translate("menu.export"), null);
exportBand.setResizePolicies(getResizePolicies(exportBand));
exportFlaCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.export.fla")), View.getResizableIcon("exportfla32"));
assignListener(exportFlaCommandButton, ACTION_EXPORT_FLA);
exportAllCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.export.all")), View.getResizableIcon("export16"));
assignListener(exportAllCommandButton, ACTION_EXPORT);
exportSelectionCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.export.selection")), View.getResizableIcon("exportsel16"));
assignListener(exportSelectionCommandButton, ACTION_EXPORT_SEL);
saveasexeCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.saveasexe")), View.getResizableIcon("saveasexe16"));
assignListener(saveasexeCommandButton, ACTION_SAVE_AS_EXE);
exportBand.addCommandButton(exportFlaCommandButton, RibbonElementPriority.TOP);
exportBand.addCommandButton(exportAllCommandButton, RibbonElementPriority.MEDIUM);
exportBand.addCommandButton(exportSelectionCommandButton, RibbonElementPriority.MEDIUM);
exportBand.addCommandButton(saveasexeCommandButton, RibbonElementPriority.MEDIUM);
JRibbonBand importBand = new JRibbonBand(translate("menu.import"), null);
importBand.setResizePolicies(getResizePolicies(importBand));
importTextCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.import.text")), View.getResizableIcon("import32"));
assignListener(importTextCommandButton, ACTION_IMPORT_TEXT);
importBand.addCommandButton(importTextCommandButton, RibbonElementPriority.TOP);
return new RibbonTask(translate("menu.file"), editBand, exportBand, importBand);
}
private RibbonTask createToolsRibbonTask() {
//----------------------------------------- TOOLS -----------------------------------
JRibbonBand toolsBand = new JRibbonBand(translate("menu.tools"), null);
toolsBand.setResizePolicies(getResizePolicies(toolsBand));
searchCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.search")), View.getResizableIcon("search32"));
assignListener(searchCommandButton, ACTION_SEARCH);
timeLineCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.timeline")), View.getResizableIcon("timeline32"));
assignListener(timeLineCommandButton, ACTION_TIMELINE);
gotoDocumentClassCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.gotodocumentclass")), View.getResizableIcon("gotomainclass32"));
assignListener(gotoDocumentClassCommandButton, ACTION_GOTO_DOCUMENT_CLASS);
JCommandButton proxyCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.proxy")), View.getResizableIcon("proxy16"));
assignListener(proxyCommandButton, ACTION_SHOW_PROXY);
JCommandButton loadMemoryCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.searchmemory")), View.getResizableIcon("loadmemory16"));
assignListener(loadMemoryCommandButton, ACTION_LOAD_MEMORY);
JCommandButton loadCacheCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.searchcache")), View.getResizableIcon("loadcache16"));
assignListener(loadCacheCommandButton, ACTION_LOAD_CACHE);
toolsBand.addCommandButton(searchCommandButton, RibbonElementPriority.TOP);
toolsBand.addCommandButton(timeLineCommandButton, RibbonElementPriority.TOP);
toolsBand.addCommandButton(gotoDocumentClassCommandButton, RibbonElementPriority.TOP);
toolsBand.addCommandButton(proxyCommandButton, RibbonElementPriority.MEDIUM);
toolsBand.addCommandButton(loadMemoryCommandButton, RibbonElementPriority.MEDIUM);
toolsBand.addCommandButton(loadCacheCommandButton, RibbonElementPriority.MEDIUM);
if (!ProcessTools.toolsAvailable()) {
loadMemoryCommandButton.setEnabled(false);
}
JRibbonBand deobfuscationBand = new JRibbonBand(translate("menu.tools.deobfuscation"), null);
deobfuscationBand.setResizePolicies(getResizePolicies(deobfuscationBand));
deobfuscationCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.deobfuscation.pcode")), View.getResizableIcon("deobfuscate32"));
assignListener(deobfuscationCommandButton, ACTION_DEOBFUSCATE);
globalrenameCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.deobfuscation.globalrename")), View.getResizableIcon("rename16"));
assignListener(globalrenameCommandButton, ACTION_RENAME_ONE_IDENTIFIER);
renameinvalidCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.deobfuscation.renameinvalid")), View.getResizableIcon("renameall16"));
assignListener(renameinvalidCommandButton, ACTION_RENAME_IDENTIFIERS);
deobfuscationBand.addCommandButton(deobfuscationCommandButton, RibbonElementPriority.TOP);
deobfuscationBand.addCommandButton(globalrenameCommandButton, RibbonElementPriority.MEDIUM);
deobfuscationBand.addCommandButton(renameinvalidCommandButton, RibbonElementPriority.MEDIUM);
//JRibbonBand otherToolsBand = new JRibbonBand(translate("menu.tools.otherTools"), null);
//otherToolsBand.setResizePolicies(getResizePolicies(otherToolsBand));
return new RibbonTask(translate("menu.tools"), toolsBand, deobfuscationBand/*, otherToolsBand*/);
}
private RibbonTask createSettingsRibbonTask(boolean externalFlashPlayerUnavailable) {
//----------------------------------------- SETTINGS -----------------------------------
JRibbonBand settingsBand = new JRibbonBand(translate("menu.settings"), null);
settingsBand.setResizePolicies(getResizePolicies(settingsBand));
miAutoDeobfuscation = new JCheckBox(translate("menu.settings.autodeobfuscation"));
miAutoDeobfuscation.setSelected(Configuration.autoDeobfuscate.get());
miAutoDeobfuscation.addActionListener(this);
miAutoDeobfuscation.setActionCommand(ACTION_AUTO_DEOBFUSCATE);
miInternalViewer = new JCheckBox(translate("menu.settings.internalflashviewer"));
miInternalViewer.setSelected(Configuration.internalFlashViewer.get() || externalFlashPlayerUnavailable);
if (externalFlashPlayerUnavailable) {
miInternalViewer.setEnabled(false);
}
miInternalViewer.setActionCommand(ACTION_INTERNAL_VIEWER_SWITCH);
miInternalViewer.addActionListener(this);
miParallelSpeedUp = new JCheckBox(translate("menu.settings.parallelspeedup"));
miParallelSpeedUp.setSelected(Configuration.parallelSpeedUp.get());
miParallelSpeedUp.setActionCommand(ACTION_PARALLEL_SPEED_UP);
miParallelSpeedUp.addActionListener(this);
miDecompile = new JCheckBox(translate("menu.settings.disabledecompilation"));
miDecompile.setSelected(!Configuration.decompile.get());
miDecompile.setActionCommand(ACTION_DISABLE_DECOMPILATION);
miDecompile.addActionListener(this);
miAssociate = new JCheckBox(translate("menu.settings.addtocontextmenu"));
miAssociate.setActionCommand(ACTION_ASSOCIATE);
miAssociate.addActionListener(this);
miAssociate.setSelected(ContextMenuTools.isAddedToContextMenu());
miCacheDisk = new JCheckBox(translate("menu.settings.cacheOnDisk"));
miCacheDisk.setSelected(Configuration.cacheOnDisk.get());
miCacheDisk.setActionCommand(ACTION_CACHE_ON_DISK);
miCacheDisk.addActionListener(this);
miGotoMainClassOnStartup = new JCheckBox(translate("menu.settings.gotoMainClassOnStartup"));
miGotoMainClassOnStartup.setSelected(Configuration.gotoMainClassOnStartup.get());
miGotoMainClassOnStartup.setActionCommand(ACTION_GOTO_DOCUMENT_CLASS_ON_STARTUP);
miGotoMainClassOnStartup.addActionListener(this);
miAutoRenameIdentifiers = new JCheckBox(translate("menu.settings.autoRenameIdentifiers"));
miAutoRenameIdentifiers.setSelected(Configuration.autoRenameIdentifiers.get());
miAutoRenameIdentifiers.setActionCommand(ACTION_AUTO_RENAME_IDENTIFIERS);
miAutoRenameIdentifiers.addActionListener(this);
settingsBand.addRibbonComponent(new JRibbonComponent(miAutoDeobfuscation));
settingsBand.addRibbonComponent(new JRibbonComponent(miInternalViewer));
settingsBand.addRibbonComponent(new JRibbonComponent(miParallelSpeedUp));
settingsBand.addRibbonComponent(new JRibbonComponent(miDecompile));
if (Platform.isWindows()) {
settingsBand.addRibbonComponent(new JRibbonComponent(miAssociate));
}
settingsBand.addRibbonComponent(new JRibbonComponent(miCacheDisk));
settingsBand.addRibbonComponent(new JRibbonComponent(miGotoMainClassOnStartup));
settingsBand.addRibbonComponent(new JRibbonComponent(miAutoRenameIdentifiers));
JRibbonBand languageBand = new JRibbonBand(translate("menu.language"), null);
List<RibbonBandResizePolicy> languageBandResizePolicies = getIconBandResizePolicies(languageBand);
languageBand.setResizePolicies(languageBandResizePolicies);
JCommandButton setLanguageCommandButton = new JCommandButton(fixCommandTitle(translate("menu.settings.language")), View.getResizableIcon("setlanguage32"));
assignListener(setLanguageCommandButton, ACTION_SET_LANGUAGE);
languageBand.addCommandButton(setLanguageCommandButton, RibbonElementPriority.TOP);
JRibbonBand advancedSettingsBand = new JRibbonBand(translate("menu.advancedsettings.advancedsettings"), null);
advancedSettingsBand.setResizePolicies(getResizePolicies(advancedSettingsBand));
JCommandButton advancedSettingsCommandButton = new JCommandButton(fixCommandTitle(translate("menu.advancedsettings.advancedsettings")), View.getResizableIcon("settings32"));
assignListener(advancedSettingsCommandButton, ACTION_ADVANCED_SETTINGS);
advancedSettingsBand.addCommandButton(advancedSettingsCommandButton, RibbonElementPriority.TOP);
clearRecentFilesCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.otherTools.clearRecentFiles")), View.getResizableIcon("clearrecent16"));
assignListener(clearRecentFilesCommandButton, ACTION_CLEAR_RECENT_FILES);
advancedSettingsBand.addCommandButton(clearRecentFilesCommandButton, RibbonElementPriority.MEDIUM);
return new RibbonTask(translate("menu.settings"), settingsBand, languageBand, advancedSettingsBand);
}
private RibbonTask createHelpRibbonTask() {
//----------------------------------------- HELP -----------------------------------
JRibbonBand helpBand = new JRibbonBand(translate("menu.help"), null);
helpBand.setResizePolicies(getResizePolicies(helpBand));
JCommandButton checkForUpdatesCommandButton = new JCommandButton(fixCommandTitle(translate("menu.help.checkupdates")), View.getResizableIcon("update16"));
assignListener(checkForUpdatesCommandButton, ACTION_CHECK_UPDATES);
JCommandButton helpUsUpdatesCommandButton = new JCommandButton(fixCommandTitle(translate("menu.help.helpus")), View.getResizableIcon("donate32"));
assignListener(helpUsUpdatesCommandButton, ACTION_HELP_US);
JCommandButton homepageCommandButton = new JCommandButton(fixCommandTitle(translate("menu.help.homepage")), View.getResizableIcon("homepage16"));
assignListener(homepageCommandButton, ACTION_HOMEPAGE);
JCommandButton aboutCommandButton = new JCommandButton(fixCommandTitle(translate("menu.help.about")), View.getResizableIcon("about32"));
assignListener(aboutCommandButton, ACTION_ABOUT);
helpBand.addCommandButton(aboutCommandButton, RibbonElementPriority.TOP);
helpBand.addCommandButton(checkForUpdatesCommandButton, RibbonElementPriority.MEDIUM);
helpBand.addCommandButton(homepageCommandButton, RibbonElementPriority.MEDIUM);
helpBand.addCommandButton(helpUsUpdatesCommandButton, RibbonElementPriority.TOP);
return new RibbonTask(translate("menu.help"), helpBand);
}
private RibbonTask createDebugRibbonTask() {
//----------------------------------------- DEBUG -----------------------------------
JRibbonBand debugBand = new JRibbonBand("Debug", null);
debugBand.setResizePolicies(getResizePolicies(debugBand));
JCommandButton removeNonScriptsCommandButton = new JCommandButton(fixCommandTitle("Remove non scripts"), View.getResizableIcon("update16"));
assignListener(removeNonScriptsCommandButton, ACTION_REMOVE_NON_SCRIPTS);
JCommandButton refreshDecompiledCommandButton = new JCommandButton(fixCommandTitle("Refresh decompiled script"), View.getResizableIcon("update16"));
assignListener(refreshDecompiledCommandButton, ACTION_REFRESH_DECOMPILED);
JCommandButton checkResourcesCommandButton = new JCommandButton(fixCommandTitle("Check resources"), View.getResizableIcon("update16"));
assignListener(checkResourcesCommandButton, ACTION_CHECK_RESOURCES);
debugBand.addCommandButton(removeNonScriptsCommandButton, RibbonElementPriority.MEDIUM);
debugBand.addCommandButton(refreshDecompiledCommandButton, RibbonElementPriority.MEDIUM);
debugBand.addCommandButton(checkResourcesCommandButton, RibbonElementPriority.MEDIUM);
return new RibbonTask("Debug", debugBand);
}
@Override
public void updateComponents(SWF swf, List<ABCContainerTag> abcList) {
boolean swfLoaded = swf != null;
boolean hasAbc = swfLoaded && abcList != null && !abcList.isEmpty();
exportAllMenu.setEnabled(swfLoaded);
exportFlaMenu.setEnabled(swfLoaded);
exportSelMenu.setEnabled(swfLoaded);
closeFileMenu.setEnabled(swfLoaded);
closeAllFilesMenu.setEnabled(swfLoaded);
boolean isBundle = swfLoaded && (swf.swfList != null) && swf.swfList.isBundle;
saveCommandButton.setEnabled(swfLoaded && !isBundle);
saveasCommandButton.setEnabled(swfLoaded);
saveasexeCommandButton.setEnabled(swfLoaded);
exportAllCommandButton.setEnabled(swfLoaded);
exportFlaCommandButton.setEnabled(swfLoaded);
exportSelectionCommandButton.setEnabled(swfLoaded);
importTextCommandButton.setEnabled(swfLoaded);
reloadCommandButton.setEnabled(swfLoaded);
renameinvalidCommandButton.setEnabled(swfLoaded);
globalrenameCommandButton.setEnabled(swfLoaded);
deobfuscationCommandButton.setEnabled(swfLoaded);
searchCommandButton.setEnabled(swfLoaded);
timeLineCommandButton.setEnabled(swfLoaded);
gotoDocumentClassCommandButton.setEnabled(hasAbc);
deobfuscationCommandButton.setEnabled(hasAbc);
}
private void saveAs(SWF swf, SaveFileMode mode) {
if (Main.saveFileDialog(swf, mode)) {
swf.fileTitle = null;
mainFrame.setTitle(ApplicationInfo.applicationVerName + (Configuration.displayFileName.get() ? " - " + swf.getFileTitle() : ""));
saveCommandButton.setEnabled(mainFrame.panel.getCurrentSwf() != null);
}
}
private void clearModified(SWF swf) {
for (Tag tag : swf.tags) {
if (tag.isModified()) {
tag.createOriginalData();
tag.setModified(false);
}
}
}
@Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case ACTION_RELOAD:
if (View.showConfirmDialog(null, translate("message.confirm.reload"), translate("message.warning"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) {
Main.reloadApp();
}
break;
case ACTION_ADVANCED_SETTINGS:
Main.advancedSettings();
break;
case ACTION_LOAD_MEMORY:
Main.loadFromMemory();
break;
case ACTION_LOAD_CACHE:
Main.loadFromCache();
break;
case ACTION_GOTO_DOCUMENT_CLASS_ON_STARTUP:
Configuration.gotoMainClassOnStartup.set(miGotoMainClassOnStartup.isSelected());
break;
case ACTION_AUTO_RENAME_IDENTIFIERS:
Configuration.autoRenameIdentifiers.set(miAutoRenameIdentifiers.isSelected());
break;
case ACTION_CACHE_ON_DISK:
Configuration.cacheOnDisk.set(miCacheDisk.isSelected());
if (miCacheDisk.isSelected()) {
Cache.setStorageType(Cache.STORAGE_FILES);
} else {
Cache.setStorageType(Cache.STORAGE_MEMORY);
}
break;
case ACTION_SET_LANGUAGE:
new SelectLanguageDialog().display();
break;
case ACTION_DISABLE_DECOMPILATION:
Configuration.decompile.set(!miDecompile.isSelected());
mainFrame.panel.disableDecompilationChanged();
break;
case ACTION_ASSOCIATE:
if (miAssociate.isSelected() == ContextMenuTools.isAddedToContextMenu()) {
return;
}
ContextMenuTools.addToContextMenu(miAssociate.isSelected(), false);
//Update checkbox menuitem accordingly (User can cancel rights elevation)
new Timer().schedule(new TimerTask() {
@Override
public void run() {
miAssociate.setSelected(ContextMenuTools.isAddedToContextMenu());
}
}, 1000); //It takes some time registry change to apply
break;
case ACTION_GOTO_DOCUMENT_CLASS:
mainFrame.panel.gotoDocumentClass(mainFrame.panel.getCurrentSwf());
break;
case ACTION_PARALLEL_SPEED_UP:
String confStr = translate("message.confirm.parallel") + "\r\n";
if (miParallelSpeedUp.isSelected()) {
confStr += " " + translate("message.confirm.on");
} else {
confStr += " " + translate("message.confirm.off");
}
if (View.showConfirmDialog(null, confStr, translate("message.parallel"), JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) {
Configuration.parallelSpeedUp.set((Boolean) miParallelSpeedUp.isSelected());
} else {
miParallelSpeedUp.setSelected(!miParallelSpeedUp.isSelected());
}
break;
case ACTION_INTERNAL_VIEWER_SWITCH:
Configuration.internalFlashViewer.set(miInternalViewer.isSelected());
mainFrame.panel.reload(true);
break;
case ACTION_SEARCH:
mainFrame.panel.searchAs();
break;
case ACTION_TIMELINE:
mainFrame.panel.timeline();
break;
case ACTION_AUTO_DEOBFUSCATE:
if (View.showConfirmDialog(mainFrame.panel, translate("message.confirm.autodeobfuscate") + "\r\n" + (miAutoDeobfuscation.isSelected() ? translate("message.confirm.on") : translate("message.confirm.off")), translate("message.confirm"), JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) {
Configuration.autoDeobfuscate.set(miAutoDeobfuscation.isSelected());
mainFrame.panel.autoDeobfuscateChanged();
} else {
miAutoDeobfuscation.setSelected(!miAutoDeobfuscation.isSelected());
}
break;
case ACTION_CLEAR_RECENT_FILES:
Configuration.recentFiles.set(null);
break;
case ACTION_EXIT:
mainFrame.panel.setVisible(false);
if (Main.proxyFrame != null) {
if (Main.proxyFrame.isVisible()) {
return;
}
}
Main.exit();
break;
}
if (Main.isWorking()) {
return;
}
switch (e.getActionCommand()) {
case ACTION_RENAME_ONE_IDENTIFIER:
mainFrame.panel.renameOneIdentifier(mainFrame.panel.getCurrentSwf());
break;
case ACTION_ABOUT:
Main.about();
break;
case ACTION_SHOW_PROXY:
Main.showProxy();
break;
case ACTION_SUB_LIMITER:
if (e.getSource() instanceof JCheckBoxMenuItem) {
Main.setSubLimiter(((JCheckBoxMenuItem) e.getSource()).getState());
}
break;
case ACTION_SAVE: {
SWF swf = mainFrame.panel.getCurrentSwf();
SWFNode snode = ((TagTreeModel)mainFrame.panel.tagTree.getModel()).getSwfNode(swf);
if(snode.binaryData!=null){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
swf.saveTo(baos);
snode.binaryData.binaryData = baos.toByteArray();
snode.binaryData.setModified(true);
} catch (IOException ex) {
Logger.getLogger(MainFrameRibbonMenu.class.getName()).log(Level.SEVERE, "Cannot save SWF", ex);
}
}
else if (swf.file == null) {
saveAs(swf, SaveFileMode.SAVEAS);
} else {
try {
Main.saveFile(swf, swf.file);
} catch (IOException ex) {
Logger.getLogger(MainFrameRibbonMenu.class.getName()).log(Level.SEVERE, null, ex);
View.showMessageDialog(null, translate("error.file.save"), translate("error"), JOptionPane.ERROR_MESSAGE);
}
}
clearModified(swf);
}
break;
case ACTION_SAVE_AS: {
SWF swf = mainFrame.panel.getCurrentSwf();
saveAs(swf, SaveFileMode.SAVEAS);
clearModified(swf);
}
break;
case ACTION_SAVE_AS_EXE: {
SWF swf = mainFrame.panel.getCurrentSwf();
saveAs(swf, SaveFileMode.EXE);
}
break;
case ACTION_OPEN:
Main.openFileDialog();
break;
case ACTION_CLOSE:
Main.closeFile(mainFrame.panel.getCurrentSwfList());
break;
case ACTION_CLOSE_ALL:
Main.closeAll();
break;
case ACTION_EXPORT_FLA:
mainFrame.panel.exportFla(mainFrame.panel.getCurrentSwf());
break;
case ACTION_IMPORT_TEXT:
mainFrame.panel.importText(mainFrame.panel.getCurrentSwf());
break;
case ACTION_EXPORT_SEL:
case ACTION_EXPORT:
boolean onlySel = e.getActionCommand().endsWith("SEL");
mainFrame.panel.export(onlySel);
break;
case ACTION_CHECK_UPDATES:
if (!Main.checkForUpdates()) {
View.showMessageDialog(null, translate("update.check.nonewversion"), translate("update.check.title"), JOptionPane.INFORMATION_MESSAGE);
}
break;
case ACTION_HELP_US:
String helpUsURL = ApplicationInfo.PROJECT_PAGE + "/help_us.html";
if (java.awt.Desktop.isDesktopSupported()) {
java.awt.Desktop desktop = java.awt.Desktop.getDesktop();
try {
java.net.URI uri = new java.net.URI(helpUsURL);
desktop.browse(uri);
} catch (URISyntaxException | IOException ex) {
}
} else {
View.showMessageDialog(null, translate("message.helpus").replace("%url%", helpUsURL));
}
break;
case ACTION_HOMEPAGE:
String homePageURL = ApplicationInfo.PROJECT_PAGE;
if (java.awt.Desktop.isDesktopSupported()) {
java.awt.Desktop desktop = java.awt.Desktop.getDesktop();
try {
java.net.URI uri = new java.net.URI(homePageURL);
desktop.browse(uri);
} catch (URISyntaxException | IOException ex) {
}
} else {
View.showMessageDialog(null, translate("message.homepage").replace("%url%", homePageURL));
}
break;
case ACTION_RESTORE_CONTROL_FLOW:
case ACTION_RESTORE_CONTROL_FLOW_ALL:
boolean all = e.getActionCommand().endsWith("ALL");
mainFrame.panel.restoreControlFlow(all);
break;
case ACTION_RENAME_IDENTIFIERS:
mainFrame.panel.renameIdentifiers(mainFrame.panel.getCurrentSwf());
break;
case ACTION_DEOBFUSCATE:
case ACTION_DEOBFUSCATE_ALL:
mainFrame.panel.deobfuscate();
break;
case ACTION_REMOVE_NON_SCRIPTS:
mainFrame.panel.removeNonScripts(mainFrame.panel.getCurrentSwf());
break;
case ACTION_REFRESH_DECOMPILED:
mainFrame.panel.refreshDecompiled();
break;
case ACTION_CHECK_RESOURCES:
ByteArrayOutputStream os = new ByteArrayOutputStream();
PrintStream stream = new PrintStream(os);
CheckResources.checkResources(stream);
final String str = new String(os.toByteArray(), Utf8Helper.charset);
JDialog dialog = new JDialog() {
@Override
public void setVisible(boolean bln) {
setSize(new Dimension(800, 600));
Container cnt = getContentPane();
cnt.setLayout(new BorderLayout());
ScrollPane scrollPane = new ScrollPane();
JEditorPane editor = new JEditorPane();
editor.setEditable(false);
editor.setText(str);
scrollPane.add(editor);
this.add(scrollPane, BorderLayout.CENTER);
this.setModal(true);
View.centerScreen(this);
super.setVisible(bln);
}
};
dialog.setVisible(true);
break;
}
}
}
@@ -0,0 +1,188 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.helpers.CancellableWorker;
import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.BevelBorder;
/**
*
* @author JPEXS
*/
public class MainFrameStatusPanel extends JPanel implements ActionListener {
static final String ACTION_SHOW_ERROR_LOG = "SHOWERRORLOG";
private final MainPanel mainPanel;
private final LoadingPanel loadingPanel = new LoadingPanel(20, 20);
private final JLabel statusLabel = new JLabel("");
private final JButton cancelButton = new JButton();
private JButton errorNotificationButton;
private Icon currentIcon;
private Timer blinkTimer;
private int blinkPos;
private CancellableWorker currentWorker;
public MainFrameStatusPanel(MainPanel mainPanel) {
this.mainPanel = mainPanel;
createStatusPanel();
}
private void createStatusPanel() {
JPanel statusLeftPanel = new JPanel();
statusLeftPanel.setLayout(new BoxLayout(statusLeftPanel, BoxLayout.X_AXIS));
loadingPanel.setPreferredSize(new Dimension(30, 30));
// todo: this button is a little bit ugly in the UI. Maybe it can be changed to an icon (as in NetBeans)
cancelButton.setText(translate("button.cancel"));
cancelButton.setPreferredSize(new Dimension(100, 30));
cancelButton.setBorderPainted(false);
cancelButton.setOpaque(false);
cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (currentWorker != null) {
currentWorker.cancel(true);
}
}
});
statusLeftPanel.add(loadingPanel);
statusLeftPanel.add(statusLabel);
statusLeftPanel.add(cancelButton);
setPreferredSize(new Dimension(1, 30));
setBorder(new BevelBorder(BevelBorder.LOWERED));
setLayout(new BorderLayout());
add(statusLeftPanel, BorderLayout.WEST);
errorNotificationButton = new JButton("");
errorNotificationButton.setIcon(View.getIcon("okay16"));
errorNotificationButton.setBorderPainted(false);
errorNotificationButton.setFocusPainted(false);
errorNotificationButton.setContentAreaFilled(false);
errorNotificationButton.setMargin(new Insets(2, 2, 2, 2));
errorNotificationButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
errorNotificationButton.setActionCommand(ACTION_SHOW_ERROR_LOG);
errorNotificationButton.addActionListener(this);
errorNotificationButton.setToolTipText(translate("errors.none"));
add(errorNotificationButton, BorderLayout.EAST);
loadingPanel.setVisible(false);
cancelButton.setVisible(false);
}
@Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case ACTION_SHOW_ERROR_LOG:
Main.displayErrorFrame();
break;
}
}
private String translate(String key) {
return mainPanel.translate(key);
}
public void setStatus(String s) {
statusLabel.setText(s);
}
public void setWorkStatus(String s, CancellableWorker worker) {
if (s.isEmpty()) {
loadingPanel.setVisible(false);
} else {
loadingPanel.setVisible(true);
}
statusLabel.setText(s);
currentWorker = worker;
cancelButton.setVisible(worker != null);
}
public void setErrorState(ErrorState errorState) {
if (errorNotificationButton == null) {
// todo: honfika
// why null?
return;
}
switch (errorState) {
case NO_ERROR:
currentIcon = View.getIcon("okay16");
errorNotificationButton.setToolTipText(translate("errors.none"));
blinkPos = 0;
break;
case INFO:
currentIcon = View.getIcon("information16");
errorNotificationButton.setToolTipText(translate("errors.info"));
break;
case WARNING:
currentIcon = View.getIcon("warning16");
errorNotificationButton.setToolTipText(translate("errors.warning"));
break;
case ERROR:
currentIcon = View.getIcon("error16");
errorNotificationButton.setToolTipText(translate("errors.present"));
break;
}
errorNotificationButton.setIcon(currentIcon);
if (errorState != ErrorState.NO_ERROR) {
if (blinkTimer != null) {
blinkTimer.cancel();
}
blinkTimer = new Timer();
blinkTimer.schedule(new TimerTask() {
@Override
public void run() {
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
blinkPos++;
if ((blinkPos % 2) == 0 || (blinkPos >= 4)) {
errorNotificationButton.setIcon(currentIcon);
} else {
errorNotificationButton.setIcon(null);
errorNotificationButton.setSize(16, 16);
}
}
});
if (blinkPos >= 4) {
cancel();
}
}
}, 500, 500);
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,102 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.ApplicationInfo;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JLabel;
/**
* Frame with selection on application startServer
*
* @author JPEXS
*/
public class ModeFrame extends AppFrame implements ActionListener {
static final String ACTION_OPEN = "OPEN";
static final String ACTION_PROXY = "PROXY";
static final String ACTION_EXIT = "EXIT";
private final JButton openButton = new JButton(translate("button.open"));
private final JButton proxyButton = new JButton(translate("button.proxy"));
private final JButton exitButton = new JButton(translate("button.exit"));
/**
* Constructor
*/
public ModeFrame() {
setSize(350, 200);
openButton.addActionListener(this);
openButton.setActionCommand(ACTION_OPEN);
openButton.setIcon(View.getIcon("open32"));
proxyButton.addActionListener(this);
proxyButton.setActionCommand(ACTION_PROXY);
proxyButton.setIcon(View.getIcon("proxy32"));
exitButton.addActionListener(this);
exitButton.setActionCommand(ACTION_EXIT);
exitButton.setIcon(View.getIcon("exit32"));
setResizable(false);
Container cont = getContentPane();
cont.setLayout(new GridLayout(4, 1));
JLabel logoLabel = new JLabel();
logoLabel.setIcon(View.getIcon("logo"));
cont.add(logoLabel);
cont.add(openButton);
cont.add(proxyButton);
cont.add(exitButton);
View.centerScreen(this);
View.setWindowIcon(this);
setTitle(ApplicationInfo.shortApplicationVerName);
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
Main.exit();
}
});
}
/**
* Method handling actions from buttons
*
* @param e event
*/
@Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case ACTION_OPEN:
setVisible(false);
if (!Main.openFileDialog()) {
setVisible(true);
}
break;
case ACTION_PROXY:
setVisible(false);
Main.showProxy();
break;
case ACTION_EXIT:
setVisible(false);
Main.exit();
break;
}
}
}
@@ -0,0 +1,95 @@
/*
* Copyright (C) 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;
import javax.swing.plaf.ComponentUI;
import org.pushingpixels.flamingo.api.common.JCommandButton;
import org.pushingpixels.flamingo.api.common.popup.JCommandPopupMenu;
import org.pushingpixels.flamingo.api.common.popup.JPopupPanel;
import org.pushingpixels.flamingo.api.common.popup.PopupPanelManager;
import org.pushingpixels.substance.flamingo.common.ui.SubstanceCommandButtonUI;
/**
*
* Own CommandButtonUI because original Flamingo UI throws Exception in some cases
*
* @author JPEXS
*/
public class MyCommandButtonUI extends SubstanceCommandButtonUI{
public static ComponentUI createUI(JComponent comp) {
return new MyCommandButtonUI((JCommandButton)comp);
}
public MyCommandButtonUI(JCommandButton jcb) {
super(jcb);
}
@Override
protected void installListeners() {
super.installListeners();
this.commandButton.removeActionListener(this.disposePopupsActionListener);
this.disposePopupsActionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(commandButton == null){ //Added by JPEXS
return;
}
boolean toDismiss = !Boolean.TRUE.equals(commandButton
.getClientProperty(DONT_DISPOSE_POPUPS));
if (toDismiss) {
JCommandPopupMenu menu = (JCommandPopupMenu) SwingUtilities
.getAncestorOfClass(JCommandPopupMenu.class,
commandButton);
if (menu != null) {
toDismiss = menu.isToDismissOnChildClick();
}
}
if (toDismiss) {
if (SwingUtilities.getAncestorOfClass(JPopupPanel.class,
commandButton) != null) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// command button may be cleared if the
// button click resulted in LAF switch
if (commandButton != null) {
// clear the active states
commandButton.getActionModel().setPressed(
false);
commandButton.getActionModel().setRollover(
false);
commandButton.getActionModel().setArmed(
false);
}
}
});
}
PopupPanelManager.defaultManager().hidePopups(null);
}
}
};
this.commandButton.addActionListener(disposePopupsActionListener);
}
}
@@ -0,0 +1,31 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import java.text.Format;
import javax.swing.JFormattedTextField;
/**
*
* @author JPEXS
*/
public class MyFormattedTextField extends JFormattedTextField {
public MyFormattedTextField(Format format) {
super(format);
}
}
@@ -0,0 +1,93 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import javax.swing.CellRendererPane;
import javax.swing.JComponent;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.ComponentUI;
import org.pushingpixels.substance.internal.ui.SubstanceProgressBarUI;
import org.pushingpixels.substance.internal.utils.SubstanceCoreUtilities;
/**
*
* @author JPEXS
*/
public class MyProgressBarUI extends SubstanceProgressBarUI {
private final class MySubstanceChangeListener implements ChangeListener {
@Override
public void stateChanged(ChangeEvent e) {
SubstanceCoreUtilities.testComponentStateChangeThreadingViolation(progressBar);
if (displayTimeline != null) { //Main Change - this should be first
//displayTimeline.abort();
}
int currValue = progressBar.getValue();
int span = progressBar.getMaximum() - progressBar.getMinimum();
int barRectWidth = progressBar.getWidth() - 2 * margin;
int barRectHeight = progressBar.getHeight() - 2 * margin;
int totalPixels = (progressBar.getOrientation() == JProgressBar.HORIZONTAL) ? barRectWidth
: barRectHeight;
int pixelDelta = (span <= 0) ? 0 : (currValue - displayedValue)
* totalPixels / span;
/*displayTimeline = new Timeline(progressBar);
displayTimeline.addPropertyToInterpolate(Timeline
.<Integer>property("displayedValue").from(displayedValue)
.to(currValue).setWith(new TimelinePropertyBuilder.PropertySetter<Integer>() {
@Override
public void set(Object obj, String fieldName,
Integer value) {
displayedValue = value;
progressBar.repaint();
}
}));
displayTimeline.setEase(new Spline(0.4f));
AnimationConfigurationManager.getInstance().configureTimeline(
displayTimeline);*/
boolean isInCellRenderer = (SwingUtilities.getAncestorOfClass(
CellRendererPane.class, progressBar) != null);
if (false) {//currValue > 0 && !isInCellRenderer && Math.abs(pixelDelta) > 5) {
displayTimeline.play();
} else {
displayedValue = currValue;
progressBar.repaint();
}
}
}
public static ComponentUI createUI(JComponent comp) {
SubstanceCoreUtilities.testComponentCreationThreadingViolation(comp);
return new MyProgressBarUI();
}
@Override
protected void installListeners() {
super.installListeners();
this.progressBar.removeChangeListener(substanceValueChangeListener);
this.substanceValueChangeListener = new MySubstanceChangeListener();
this.progressBar.addChangeListener(this.substanceValueChangeListener);
}
}
@@ -0,0 +1,95 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Map;
import javax.swing.Icon;
import org.pushingpixels.flamingo.internal.utils.FlamingoUtilities;
/**
*
* @author JPEXS
*/
public class MyResizableIcon implements Icon {
protected BufferedImage originalImage;
protected Map<String, BufferedImage> cachedImages = new HashMap<>();
public MyResizableIcon(BufferedImage originalImage) {
this.originalImage = originalImage;
width = originalImage.getWidth();
height = originalImage.getHeight();
}
protected int width;
protected int height;
protected BufferedImage image;
public void setDimension(Dimension dim) {
setIconSize(dim.width, dim.height);
}
public void setIconSize(int renderWidth, int renderHeight) {
width = renderWidth;
height = renderHeight;
String key = renderWidth + ":" + renderHeight;
if (this.cachedImages.containsKey(key)) {
image = this.cachedImages.get(key);
return;
}
BufferedImage result = originalImage;
float scaleX = (float) originalImage.getWidth()
/ (float) renderWidth;
float scaleY = (float) originalImage.getHeight()
/ (float) renderHeight;
float scale = Math.max(scaleX, scaleY);
if (scale > 1.0f) {
int finalWidth = (int) (originalImage.getWidth() / scale);
result = FlamingoUtilities.createThumbnail(originalImage,
finalWidth);
}
cachedImages.put(renderWidth + ":" + renderHeight, result);
image = result;
}
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
if (image != null) {
int dx = (this.width - image.getWidth()) / 2;
int dy = (this.height - image.getHeight()) / 2;
g.drawImage(image, x + dx, y + dy, null);
}
}
@Override
public int getIconWidth() {
return width;
}
@Override
public int getIconHeight() {
return height;
}
}
@@ -0,0 +1,232 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import org.pushingpixels.flamingo.api.common.model.PopupButtonModel;
import org.pushingpixels.flamingo.internal.ui.ribbon.appmenu.BasicRibbonApplicationMenuButtonUI;
import org.pushingpixels.flamingo.internal.ui.ribbon.appmenu.JRibbonApplicationMenuButton;
import org.pushingpixels.lafwidget.animation.effects.GhostingListener;
import org.pushingpixels.substance.flamingo.common.ui.ActionPopupTransitionAwareUI;
import org.pushingpixels.substance.flamingo.utils.CommandButtonVisualStateTracker;
import org.pushingpixels.substance.internal.animation.StateTransitionTracker;
/**
* UI for {@link JRibbonApplicationMenuButton} components in <b>Substance</b>
* look and feel.
*
* @author Kirill Grouchnikov
*/
/**
*
* @author JPEXS
*/
public class MyRibbonApplicationMenuButtonUI extends BasicRibbonApplicationMenuButtonUI implements
ActionPopupTransitionAwareUI {
private MyResizableIcon hoverIcon = null;
private MyResizableIcon clickIcon = null;
private MyResizableIcon normalIcon = null;
private final boolean buttonResized = false;
public MyResizableIcon getClickIcon() {
return clickIcon;
}
public MyRibbonApplicationMenuButtonUI() {
super();
hoverIcon = View.getMyResizableIcon("buttonicon_hover_256");
normalIcon = View.getMyResizableIcon("buttonicon_256");
clickIcon = View.getMyResizableIcon("buttonicon_down_256");
}
/**
* Model change listener for ghost image effects.
*/
private GhostingListener substanceModelChangeListener;
/**
* Tracker for visual state transitions.
*/
protected CommandButtonVisualStateTracker substanceVisualStateTracker;
public static ComponentUI createUI(JComponent c) {
return new MyRibbonApplicationMenuButtonUI();
}
/*
* (non-Javadoc)
*
* @see org.jvnet.flamingo.common.ui.BasicCommandButtonUI#installListeners()
*/
@Override
protected void installListeners() {
super.installListeners();
this.substanceVisualStateTracker = new CommandButtonVisualStateTracker();
this.substanceVisualStateTracker.installListeners(this.commandButton);
this.substanceModelChangeListener = new GhostingListener(
this.commandButton, this.commandButton.getActionModel());
this.substanceModelChangeListener.registerListeners();
}
/*
* (non-Javadoc)
*
* @see
* org.jvnet.flamingo.common.ui.BasicCommandButtonUI#uninstallListeners()
*/
@Override
protected void uninstallListeners() {
this.substanceVisualStateTracker.uninstallListeners(this.commandButton);
this.substanceVisualStateTracker = null;
this.substanceModelChangeListener.unregisterListeners();
this.substanceModelChangeListener = null;
super.uninstallListeners();
}
private void updateIcons(JComponent c) {
Dimension dim = c.getPreferredSize();
hoverIcon.setDimension(dim);
clickIcon.setDimension(dim);
normalIcon.setDimension(dim);
}
/*
* (non-Javadoc)
*
* @see javax.swing.plaf.basic.BasicButtonUI#paint(java.awt.Graphics,
* javax.swing.JComponent)
*/
@Override
public void paint(Graphics g, JComponent c) {
JRibbonApplicationMenuButton b = (JRibbonApplicationMenuButton) c;
updateIcons(c);
this.layoutInfo = this.layoutManager.getLayoutInfo(this.commandButton, g);
commandButton.putClientProperty("icon.bounds", layoutInfo.iconRect);
Graphics2D g2d = (Graphics2D) g.create();
// Paint the icon
Icon icon = getCurrentIcon(b);
if (icon != null) {
paintButtonIcon(g2d);
}
g2d.dispose();
}
private Icon getCurrentIcon(JRibbonApplicationMenuButton button) {
PopupButtonModel mod = button.getPopupModel();
if (mod.isPopupShowing()) {
if (clickIcon != null) {
return clickIcon;
}
}
if (mod.isRollover()) {
if (hoverIcon != null) {
return hoverIcon;
}
}
if (normalIcon != null) {
return normalIcon;
}
return button.getIcon();
}
/*
* (non-Javadoc)
*
* @see
* org.jvnet.flamingo.common.ui.BasicCommandButtonUI#paintButtonIcon(java
* .awt.Graphics, java.awt.Rectangle)
*/
protected void paintButtonIcon(Graphics g) {
Icon regular = getCurrentIcon(this.applicationMenuButton);
if (regular == null) {
return;
}
if (regular != null) {
Graphics2D g2d = (Graphics2D) g.create();
regular.paintIcon(this.applicationMenuButton, g2d, 0, 0);
g2d.dispose();
}
}
/*
* (non-Javadoc)
*
* @see
* org.jvnet.flamingo.ribbon.ui.appmenu.BasicRibbonApplicationMenuButtonUI
* #update(java.awt.Graphics, javax.swing.JComponent)
*/
@Override
public void update(Graphics g, JComponent c) {
this.paint(g, c);
}
/*
* (non-Javadoc)
*
* @see
* org.jvnet.substance.SubstanceButtonUI#contains(javax.swing.JComponent,
* int, int)
*/
@Override
public boolean contains(JComponent c, int x, int y) {
// allow clicking anywhere in the area (around the button
// round outline as well) to activate the button.
return (x >= 0) && (x < c.getWidth()) && (y >= 0)
&& (y < c.getHeight());
}
@Override
public StateTransitionTracker getActionTransitionTracker() {
return this.substanceVisualStateTracker
.getActionStateTransitionTracker();
}
@Override
public StateTransitionTracker getPopupTransitionTracker() {
return this.substanceVisualStateTracker
.getPopupStateTransitionTracker();
}
@Override
public StateTransitionTracker getTransitionTracker() {
return this.substanceVisualStateTracker
.getPopupStateTransitionTracker();
}
@Override
public boolean isInside(MouseEvent me) {
return true;
}
}
@@ -0,0 +1,167 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import java.awt.BasicStroke;
import java.awt.Component;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import javax.swing.CellRendererPane;
import javax.swing.JComponent;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.plaf.ComponentUI;
import org.pushingpixels.flamingo.internal.ui.ribbon.appmenu.BasicRibbonApplicationMenuPopupPanelUI;
import org.pushingpixels.flamingo.internal.ui.ribbon.appmenu.JRibbonApplicationMenuButton;
import org.pushingpixels.substance.api.ColorSchemeAssociationKind;
import org.pushingpixels.substance.api.ComponentState;
import org.pushingpixels.substance.api.SubstanceColorScheme;
import org.pushingpixels.substance.internal.painter.HighlightPainterUtils;
import org.pushingpixels.substance.internal.utils.SubstanceColorSchemeUtilities;
import org.pushingpixels.substance.internal.utils.SubstanceSizeUtils;
import org.pushingpixels.substance.internal.utils.border.SubstanceBorder;
/**
*
* @author JPEXS
*/
public class MyRibbonApplicationMenuPopupPanelUI extends BasicRibbonApplicationMenuPopupPanelUI {
public static ComponentUI createUI(JComponent c) {
return new MyRibbonApplicationMenuPopupPanelUI();
}
@Override
protected void installComponents() {
super.installComponents();
Border newBorder = new CompoundBorder(new SubstanceBorder(new Insets(2,
2, 2, 2)), new Border() {
@Override
public boolean isBorderOpaque() {
return true;
}
@Override
public Insets getBorderInsets(Component c) {
return new Insets(18, 0, 0, 0);
}
@Override
public void paintBorder(Component c, Graphics g, int x, int y,
int width, int height) {
SubstanceColorScheme bgFillScheme = SubstanceColorSchemeUtilities
.getColorScheme(c,
ColorSchemeAssociationKind.HIGHLIGHT,
ComponentState.ENABLED);
SubstanceColorScheme bgBorderScheme = SubstanceColorSchemeUtilities
.getColorScheme(c,
ColorSchemeAssociationKind.HIGHLIGHT_BORDER,
ComponentState.ENABLED);
HighlightPainterUtils.paintHighlight(g, null, c, new Rectangle(
x, y, width, height), 0.0f, null, bgFillScheme,
bgBorderScheme);
// draw the application menu button
JRibbonApplicationMenuButton rendererButton = new JRibbonApplicationMenuButton(
applicationMenuPopupPanel.getAppMenuButton()
.getRibbon());
JRibbonApplicationMenuButton appMenuButton = applicationMenuPopupPanel
.getAppMenuButton();
rendererButton.applyComponentOrientation(appMenuButton
.getComponentOrientation());
rendererButton.setPopupKeyTip(appMenuButton.getPopupKeyTip());
rendererButton.getPopupModel().setPopupShowing(true);
rendererButton.setDisplayState(appMenuButton.getDisplayState());
rendererButton.getPopupModel().setRollover(false);
rendererButton.getPopupModel().setPressed(true);
rendererButton.getPopupModel().setArmed(true);
CellRendererPane buttonRendererPane = new CellRendererPane();
Point buttonLoc = appMenuButton.getLocationOnScreen();
Point panelLoc = c.getLocationOnScreen();
buttonRendererPane.setBounds(panelLoc.x - buttonLoc.x,
panelLoc.y - buttonLoc.y, appMenuButton.getWidth(),
appMenuButton.getHeight());
buttonRendererPane.paintComponent(g, rendererButton,
(Container) c, -panelLoc.x + buttonLoc.x, -panelLoc.y
+ buttonLoc.y, appMenuButton.getWidth(),
appMenuButton.getHeight(), true);
/*g.setColor(Color.red);
g.fillRect(0, 0, width,height);*/
}
});
this.applicationMenuPopupPanel.setBorder(newBorder);
this.panelLevel2.setBorder(new Border() {
@Override
public Insets getBorderInsets(Component c) {
boolean ltr = c.getComponentOrientation().isLeftToRight();
return new Insets(0, ltr ? 1 : 0, 0, ltr ? 0 : 1);
}
@Override
public boolean isBorderOpaque() {
return true;
}
@Override
public void paintBorder(Component c, Graphics g, int x, int y,
int width, int height) {
int componentFontSize = SubstanceSizeUtils
.getComponentFontSize(null);
int borderDelta = (int) Math.floor(SubstanceSizeUtils
.getBorderStrokeWidth(componentFontSize) / 2.0);
float borderThickness = SubstanceSizeUtils
.getBorderStrokeWidth(componentFontSize);
Graphics2D g2d = (Graphics2D) g.create();
SubstanceColorScheme scheme = SubstanceColorSchemeUtilities
.getColorScheme(applicationMenuPopupPanel,
ColorSchemeAssociationKind.BORDER,
ComponentState.ENABLED);
g2d.setColor(scheme.getMidColor());
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
RenderingHints.VALUE_STROKE_NORMALIZE);
int joinKind = BasicStroke.JOIN_ROUND;
int capKind = BasicStroke.CAP_BUTT;
g2d.setStroke(new BasicStroke(borderThickness, capKind,
joinKind));
boolean ltr = applicationMenuPopupPanel
.getComponentOrientation().isLeftToRight();
int lineX = ltr ? borderDelta : c.getWidth() - borderDelta - 1;
g2d.drawLine(lineX, borderDelta, lineX, height - 1 - 2
* borderDelta);
g2d.dispose();
}
});
this.mainPanel.setBorder(new SubstanceBorder());
}
}
@@ -0,0 +1,34 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import javax.swing.JTextField;
/**
*
* @author JPEXS
*/
public class MyTextField extends JTextField {
public MyTextField() {
this("");
}
public MyTextField(String text) {
super(text);
}
}
@@ -0,0 +1,63 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import java.awt.Color;
import javax.swing.JTree;
import javax.swing.tree.TreeModel;
/**
*
* @author JPEXS
*/
public class MyTree extends JTree {
public MyTree() {
setUI(new MyTreeUI());
setBackground(Color.white);
}
public MyTree(TreeModel newModel) {
super(newModel);
setUI(new MyTreeUI());
setBackground(Color.white);
}
private boolean overrideIsEnabled = false;
public void setOverrideIsEnable(boolean b) {
overrideIsEnabled = true;
}
public boolean isOverrideIsEnable(boolean b) {
return overrideIsEnabled;
}
@Override
public boolean isEnabled() {
if (overrideIsEnabled) {
return false;
}
return super.isEnabled();
}
/*
@Override
public void paint(Graphics g) {
g.setColor(Color.white);
g.fillRect(0, 0, getWidth(), getHeight());
super.paint(g);
}*/
}
@@ -0,0 +1,60 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
import java.lang.reflect.Field;
import javax.swing.tree.TreePath;
import org.pushingpixels.substance.internal.ui.SubstanceTreeUI;
/**
*
* @author JPEXS
*/
class MyTreeUI extends SubstanceTreeUI {
@Override
protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds,
Insets insets, Rectangle bounds, TreePath path, int row,
boolean isExpanded, boolean hasBeenExpanded, boolean isLeaf) {
System.out.println("");
if (this.tree instanceof MyTree) {
Field f = null;
Boolean v = false;
try {
f = SubstanceTreeUI.class.getDeclaredField("inside");
f.setAccessible(true);
v = (Boolean) f.get(this);
f.set(this, Boolean.TRUE);
((MyTree) this.tree).setOverrideIsEnable(true);
} catch (Throwable t) {
//want to default back to substanceUI if this fails.
}
super.paintHorizontalPartOfLeg(g, bounds, insets, bounds, path, row, isLeaf, isLeaf, isLeaf);
try {
f.set(this, v);
((MyTree) this.tree).setOverrideIsEnable(true);
} catch (Throwable t) {
//see above
}
}
}
//repeat for Vertical
}
@@ -0,0 +1,171 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.ApplicationInfo;
import com.jpexs.decompiler.flash.Version;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.URISyntaxException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
/**
*
* @author JPEXS
*/
public class NewVersionDialog extends AppDialog implements ActionListener {
static final String ACTION_OK = "OK";
static final String ACTION_CANCEL = "CANCEL";
Version latestVersion;
public NewVersionDialog(List<Version> versions) {
setSize(new Dimension(500, 300));
Container cnt = getContentPane();
cnt.setLayout(new BoxLayout(cnt, BoxLayout.PAGE_AXIS));
JEditorPane changesText = new JEditorPane();
changesText.setEditable(false);
changesText.setFont(UIManager.getFont("TextField.font"));
String changesStr = "";
SimpleDateFormat serverFormatter = new SimpleDateFormat("MM/dd/yyyy");
DateFormat formatter;
String customFormat = translate("customDateFormat");
if (customFormat.equals("default")) {
formatter = DateFormat.getDateInstance();
} else {
formatter = new SimpleDateFormat(customFormat);
}
boolean first = true;
for (Version v : versions) {
if (!first) {
changesStr += "<hr />";
}
first = false;
changesStr += "<b>" + translate("version") + " " + v.versionName + (v.nightly ? " nightly " + v.revision : "") + "</b><br />";
String releaseDate = v.releaseDate;
try {
Date date = serverFormatter.parse(releaseDate);
releaseDate = formatter.format(date);
} catch (ParseException ex) {
Logger.getLogger(NewVersionDialog.class.getName()).log(Level.SEVERE, null, ex);
}
changesStr += translate("releasedate") + " " + releaseDate;
if (!v.changes.isEmpty()) {
changesStr += "<br />";
changesStr += "<pre>";
for (String type : v.changes.keySet()) {
changesStr += type + ":" + "<br />";
for (String ch : v.changes.get(type)) {
changesStr += " - " + ch + "<br />";
}
}
changesStr += "</pre>";
}
}
latestVersion = null;
if (!versions.isEmpty()) {
latestVersion = versions.get(0);
}
changesText.setContentType("text/html");
changesText.setText("<html>" + changesStr + "</html>");
JLabel newAvailableLabel = new JLabel("<html><b><center>" + translate("newversionavailable") + " " + latestVersion.appName + " " + translate("version") + " " + latestVersion.versionName + (latestVersion.nightly ? " " + latestVersion.revision : "") + "</center></b></html>", SwingConstants.CENTER);
newAvailableLabel.setAlignmentX(JLabel.CENTER_ALIGNMENT);
cnt.add(newAvailableLabel);
JLabel changeslogLabel = new JLabel("<html>" + translate("changeslog") + "</html>");
changeslogLabel.setAlignmentX(JLabel.CENTER_ALIGNMENT);
cnt.add(changeslogLabel);
JScrollPane span = new JScrollPane(changesText);
span.setAlignmentX(JLabel.CENTER_ALIGNMENT);
cnt.add(span);
JPanel buttonsPanel = new JPanel(new FlowLayout());
JButton buttonOk = new JButton(translate("button.ok"));
buttonOk.setActionCommand(ACTION_OK);
buttonOk.addActionListener(this);
JButton buttonCancel = new JButton(translate("button.cancel"));
buttonCancel.setActionCommand(ACTION_CANCEL);
buttonCancel.addActionListener(this);
buttonsPanel.add(buttonOk);
buttonsPanel.add(buttonCancel);
buttonsPanel.setAlignmentX(JLabel.CENTER_ALIGNMENT);
JLabel downloadNowLabel = new JLabel("<html><b><center>" + translate("downloadnow") + "</center></b></html>", SwingConstants.CENTER);
downloadNowLabel.setAlignmentX(JLabel.CENTER_ALIGNMENT);
cnt.add(downloadNowLabel);
cnt.add(buttonsPanel);
setResizable(false);
setTitle(translate("dialog.title"));
this.getRootPane().setDefaultButton(buttonOk);
View.centerScreen(this);
setModalityType(ModalityType.APPLICATION_MODAL);
changesText.setCaretPosition(0);
View.setWindowIcon(this);
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand() == ACTION_OK) {
java.awt.Desktop desktop = null;
if (java.awt.Desktop.isDesktopSupported()) {
desktop = java.awt.Desktop.getDesktop();
if (desktop.isSupported(java.awt.Desktop.Action.BROWSE)) {
try {
if (latestVersion.updateLink != null) {
java.net.URI uri = new java.net.URI(latestVersion.updateLink);
desktop.browse(uri);
} else {
java.net.URI uri = new java.net.URI(ApplicationInfo.updatePage);
desktop.browse(uri);
}
Main.exit();
} catch (URISyntaxException | IOException ex) {
}
} else {
desktop = null;
}
}
if (desktop == null) {
View.showMessageDialog(null, translate("newvermessage").replace("%oldAppName%", ApplicationInfo.SHORT_APPLICATION_NAME).replace("%newAppName%", latestVersion.appName).replace("%projectPage%", ApplicationInfo.PROJECT_PAGE), translate("newversion"), JOptionPane.INFORMATION_MESSAGE);
}
}
setVisible(false);
}
}
@@ -0,0 +1,28 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
/**
*
* @author JPEXS
*/
public enum OpenFileResult {
OK,
NOT_FOUND,
ERROR
}
@@ -0,0 +1,26 @@
/*
* Copyright (C) 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
/**
*
* @author JPEXS
*/
public interface PlayerListener {
public void playingFinished();
}
@@ -0,0 +1,256 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.BoundedTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.tags.base.DrawableTag;
import com.jpexs.decompiler.flash.tags.base.ImageTag;
import com.jpexs.decompiler.flash.treeitems.FrameNodeItem;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
import com.jpexs.decompiler.flash.types.ColorTransform;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.helpers.SerializableImage;
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.AffineTransform;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
/**
*
* @author JPEXS
*/
public class PreviewImage extends JPanel {
private static final ExecutorService executor;
private static final int PREVIEW_SIZE = 150;
private static final int BORDER_SIZE = 5;
private Image image;
private boolean rendering;
private final MainPanel mainPanel;
private final TreeItem treeItem;
static {
executor = Executors.newFixedThreadPool(Configuration.parallelSpeedUp.get() ? Configuration.parallelThreadCount.get() : 1);
}
/**
*
* @param mainPanel
* @param treeItem
*/
public PreviewImage(final MainPanel mainPanel, final TreeItem treeItem) {
this.mainPanel = mainPanel;
this.treeItem = treeItem;
Dimension dim = new Dimension(PREVIEW_SIZE + 2 * BORDER_SIZE, PREVIEW_SIZE + 2 * BORDER_SIZE);
setMinimumSize(dim);
setMaximumSize(dim);
setPreferredSize(dim);
setSize(dim);
setLayout(null);
setBorder(BorderFactory.createLineBorder(Color.black));
if (treeItem instanceof Tag) {
JPopupMenu contextMenu = new JPopupMenu();
final JMenuItem removeMenuItem = new JMenuItem(mainPanel.translate("contextmenu.remove"));
removeMenuItem.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
mainPanel.removeTag((Tag) treeItem);
mainPanel.refreshTree();
}
});
contextMenu.add(removeMenuItem);
this.setComponentPopupMenu(contextMenu);
}
this.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() >= 2) {
mainPanel.setTreeItem(treeItem);
}
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
});
}
private synchronized void renderImageTask(final TreeItem treeItem) {
if (rendering) {
return;
}
rendering = true;
executor.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
image = renderImage(treeItem.getSwf(), treeItem);
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
revalidate();
repaint();
}
});
return null;
}
});
}
private Image renderImage(SWF swf, TreeItem treeItem) {
double scale = 1;
int width = 0;
int height = 0;
SerializableImage imgSrc = null;
Matrix m = new Matrix();
if (treeItem instanceof FrameNodeItem) {
FrameNodeItem fn = (FrameNodeItem) treeItem;
RECT rect = swf.displayRect;
imgSrc = SWF.frameToImageGet(swf.getTimeline(), fn.getFrame() - 1, 0, null, 0, rect, Matrix.getScaleInstance(1 / SWF.unitDivisor), new ColorTransform(), null);
width = (imgSrc.getWidth());
height = (imgSrc.getHeight());
} else if (treeItem instanceof ImageTag) {
imgSrc = ((ImageTag) treeItem).getImage();
width = (imgSrc.getWidth());
height = (imgSrc.getHeight());
} else if (treeItem instanceof BoundedTag) {
BoundedTag boundedTag = (BoundedTag) treeItem;
RECT rect = boundedTag.getRect();
width = (int) (rect.getWidth() / SWF.unitDivisor);
height = (int) (rect.getHeight() / SWF.unitDivisor);
m.translate(-rect.Xmin, -rect.Ymin);
}
int w1 = width;
int h1 = height;
int w2 = PREVIEW_SIZE;
int h2 = PREVIEW_SIZE;
int w;
int h = h1 * w2 / w1;
if (h > h2) {
w = w1 * h2 / h1;
h = h2;
} else {
w = w2;
}
scale = (double) w / (double) w1;
if (w1 <= w2 && h1 <= h2) {
scale = 1;
}
m = m.preConcatenate(Matrix.getScaleInstance(scale));
width = (int) (scale * width);
height = (int) (scale * height);
if (width == 0 || height == 0) {
return null;
}
SerializableImage image = new SerializableImage(width, height, SerializableImage.TYPE_INT_ARGB);
image.fillTransparent();
if (imgSrc == null) {
DrawableTag drawable = (DrawableTag) treeItem;
drawable.toImage(0, 0, 0, null, 0, image, m, new ColorTransform());
} else {
Graphics2D g = (Graphics2D) image.getGraphics();
g.setTransform(m.toTransform());
g.drawImage(imgSrc.getBufferedImage(), 0, 0, null);
}
return image.getBufferedImage();
}
public static Component createFolderPreviewImage(MainPanel mainPanel, TreeItem treeItem) {
JPanel pan = new JPanel(new BorderLayout());
PreviewImage imagePanel = new PreviewImage(mainPanel, treeItem);
pan.add(imagePanel, BorderLayout.CENTER);
String s;
if (treeItem instanceof Tag) {
s = ((Tag) treeItem).getTagName();
if (treeItem instanceof CharacterTag) {
s = s + " (" + ((CharacterTag) treeItem).getCharacterId() + ")";
}
} else {
s = treeItem.toString();
}
JLabel lab = new JLabel(s);
lab.setFont(lab.getFont().deriveFont(AffineTransform.getScaleInstance(0.8, 0.8)));
pan.add(lab, BorderLayout.SOUTH);
return pan;
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setPaint(View.transparentPaint);
g2d.fill(new Rectangle(0, 0, getWidth(), getHeight()));
g2d.setComposite(AlphaComposite.SrcOver);
g2d.setPaint(View.swfBackgroundColor);
g2d.fill(new Rectangle(0, 0, getWidth(), getHeight()));
if (image != null) {
int x = (getWidth() / 2) - (image.getWidth(this) / 2);
int y = (getHeight() / 2) - (image.getHeight(this) / 2);
g.drawImage(image, x, y, null);
} else {
renderImageTask(treeItem);
}
}
}
@@ -0,0 +1,920 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.AppStrings;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFOutputStream;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.parser.pcode.ASMParser;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.gui.player.FlashPlayerPanel;
import com.jpexs.decompiler.flash.gui.player.MediaDisplay;
import com.jpexs.decompiler.flash.gui.player.PlayerControls;
import com.jpexs.decompiler.flash.tags.DefineBitsTag;
import com.jpexs.decompiler.flash.tags.DefineMorphShape2Tag;
import com.jpexs.decompiler.flash.tags.DefineMorphShapeTag;
import com.jpexs.decompiler.flash.tags.DefineSoundTag;
import com.jpexs.decompiler.flash.tags.DefineTextTag;
import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag;
import com.jpexs.decompiler.flash.tags.DoActionTag;
import com.jpexs.decompiler.flash.tags.DoInitActionTag;
import com.jpexs.decompiler.flash.tags.EndTag;
import com.jpexs.decompiler.flash.tags.ExportAssetsTag;
import com.jpexs.decompiler.flash.tags.JPEGTablesTag;
import com.jpexs.decompiler.flash.tags.PlaceObject2Tag;
import com.jpexs.decompiler.flash.tags.SetBackgroundColorTag;
import com.jpexs.decompiler.flash.tags.ShowFrameTag;
import com.jpexs.decompiler.flash.tags.SoundStreamBlockTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.VideoFrameTag;
import com.jpexs.decompiler.flash.tags.base.AloneTag;
import com.jpexs.decompiler.flash.tags.base.BoundedTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.tags.base.Container;
import com.jpexs.decompiler.flash.tags.base.ContainerItem;
import com.jpexs.decompiler.flash.tags.base.FontTag;
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag;
import com.jpexs.decompiler.flash.tags.base.TextTag;
import com.jpexs.decompiler.flash.tags.gfx.DefineCompactedFont;
import com.jpexs.decompiler.flash.timeline.Timelined;
import com.jpexs.decompiler.flash.treeitems.FrameNodeItem;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
import com.jpexs.decompiler.flash.types.GLYPHENTRY;
import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.RGB;
import com.jpexs.decompiler.flash.types.TEXTRECORD;
import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD;
import com.jpexs.helpers.Helper;
import com.jpexs.helpers.SerializableImage;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.SwingConstants;
/**
*
* @author JPEXS
*/
public class PreviewPanel extends JSplitPane implements ActionListener {
private static final String FLASH_VIEWER_CARD = "FLASHVIEWER";
private static final String DRAW_PREVIEW_CARD = "DRAWPREVIEW";
private static final String GENERIC_TAG_CARD = "GENERICTAG";
private static final String BINARY_TAG_CARD = "BINARYTAG";
private static final String CARDTEXTPANEL = "Text card";
private static final String CARDFONTPANEL = "Font card";
private static final String ACTION_EDIT_GENERIC_TAG = "EDITGENERICTAG";
private static final String ACTION_SAVE_GENERIC_TAG = "SAVEGENERICTAG";
private static final String ACTION_CANCEL_GENERIC_TAG = "CANCELGENERICTAG";
private static final String ACTION_PREV_FONTS = "PREVFONTS";
private static final String ACTION_NEXT_FONTS = "NEXTFONTS";
private final MainPanel mainPanel;
private final JPanel viewerCards;
private PlayerControls flashControls;
private final FlashPlayerPanel flashPanel;
private File tempFile;
private ImagePanel imagePanel;
private PlayerControls imagePlayControls;
private BinaryPanel binaryPanel;
private GenericTagPanel genericTagPanel;
private JPanel displayWithPreview;
// Image tag buttons
private JButton replaceImageButton;
private JButton prevFontsButton;
private JButton nextFontsButton;
// Binary tag buttons
private JButton replaceBinaryButton;
// Generic tag buttons
private JButton editButton;
private JButton saveButton;
private JButton cancelButton;
private JPanel parametersPanel;
private FontPanel fontPanel;
private int fontPageNum;
private TextPanel textPanel;
private boolean splitsInited;
public PreviewPanel(MainPanel mainPanel, FlashPlayerPanel flashPanel) {
super(JSplitPane.HORIZONTAL_SPLIT);
this.mainPanel = mainPanel;
this.flashPanel = flashPanel;
addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent pce) {
if (splitsInited && getRightComponent().isVisible()) {
Configuration.guiPreviewSplitPaneDividerLocation.set((int) pce.getNewValue());
}
}
});
viewerCards = new JPanel();
viewerCards.setLayout(new CardLayout());
viewerCards.add(createFlashPlayerPanel(flashPanel), FLASH_VIEWER_CARD);
viewerCards.add(createImagesCard(), DRAW_PREVIEW_CARD);
viewerCards.add(createBinaryCard(), BINARY_TAG_CARD);
viewerCards.add(createGenericTagCard(), GENERIC_TAG_CARD);
setLeftComponent(viewerCards);
createParametersPanel();
showCardLeft(FLASH_VIEWER_CARD);
}
private void createParametersPanel() {
displayWithPreview = new JPanel(new CardLayout());
textPanel = new TextPanel(mainPanel);
displayWithPreview.add(textPanel, CARDTEXTPANEL);
fontPanel = new FontPanel(mainPanel);
displayWithPreview.add(fontPanel, CARDFONTPANEL);
JLabel paramsLabel = new HeaderLabel(mainPanel.translate("parameters"));
paramsLabel.setHorizontalAlignment(SwingConstants.CENTER);
//paramsLabel.setBorder(new BevelBorder(BevelBorder.RAISED));
parametersPanel = new JPanel(new BorderLayout());
parametersPanel.add(paramsLabel, BorderLayout.NORTH);
parametersPanel.add(displayWithPreview, BorderLayout.CENTER);
setRightComponent(parametersPanel);
}
private JPanel createImageButtonsPanel() {
replaceImageButton = new JButton(mainPanel.translate("button.replace"), View.getIcon("edit16"));
replaceImageButton.setMargin(new Insets(3, 3, 3, 10));
replaceImageButton.setActionCommand(MainPanel.ACTION_REPLACE);
replaceImageButton.addActionListener(mainPanel);
replaceImageButton.setVisible(false);
prevFontsButton = new JButton(mainPanel.translate("button.prev"), View.getIcon("prev16"));
prevFontsButton.setMargin(new Insets(3, 3, 3, 10));
prevFontsButton.setActionCommand(ACTION_PREV_FONTS);
prevFontsButton.addActionListener(this);
prevFontsButton.setVisible(false);
nextFontsButton = new JButton(mainPanel.translate("button.next"), View.getIcon("next16"));
nextFontsButton.setMargin(new Insets(3, 3, 3, 10));
nextFontsButton.setActionCommand(ACTION_NEXT_FONTS);
nextFontsButton.addActionListener(this);
nextFontsButton.setVisible(false);
ButtonsPanel imageButtonsPanel = new ButtonsPanel();
imageButtonsPanel.add(replaceImageButton);
imageButtonsPanel.add(prevFontsButton);
imageButtonsPanel.add(nextFontsButton);
return imageButtonsPanel;
}
private JPanel createBinaryButtonsPanel() {
replaceBinaryButton = new JButton(mainPanel.translate("button.replace"), View.getIcon("edit16"));
replaceBinaryButton.setMargin(new Insets(3, 3, 3, 10));
replaceBinaryButton.setActionCommand(MainPanel.ACTION_REPLACE);
replaceBinaryButton.addActionListener(mainPanel);
ButtonsPanel binaryButtonsPanel = new ButtonsPanel();
binaryButtonsPanel.add(replaceBinaryButton);
return binaryButtonsPanel;
}
private JPanel createGenericTagButtonsPanel() {
editButton = new JButton(mainPanel.translate("button.edit"), View.getIcon("edit16"));
editButton.setMargin(new Insets(3, 3, 3, 10));
editButton.setActionCommand(ACTION_EDIT_GENERIC_TAG);
editButton.addActionListener(this);
saveButton = new JButton(mainPanel.translate("button.save"), View.getIcon("save16"));
saveButton.setMargin(new Insets(3, 3, 3, 10));
saveButton.setActionCommand(ACTION_SAVE_GENERIC_TAG);
saveButton.addActionListener(this);
saveButton.setVisible(false);
cancelButton = new JButton(mainPanel.translate("button.cancel"), View.getIcon("cancel16"));
cancelButton.setMargin(new Insets(3, 3, 3, 10));
cancelButton.setActionCommand(ACTION_CANCEL_GENERIC_TAG);
cancelButton.addActionListener(this);
cancelButton.setVisible(false);
ButtonsPanel genericTagButtonsPanel = new ButtonsPanel();
genericTagButtonsPanel.add(editButton);
genericTagButtonsPanel.add(saveButton);
genericTagButtonsPanel.add(cancelButton);
return genericTagButtonsPanel;
}
private JPanel createFlashPlayerPanel(FlashPlayerPanel flashPanel) {
JPanel pan = new JPanel(new BorderLayout());
JLabel prevLabel = new HeaderLabel(mainPanel.translate("swfpreview"));
prevLabel.setHorizontalAlignment(SwingConstants.CENTER);
//prevLabel.setBorder(new BevelBorder(BevelBorder.RAISED));
pan.add(prevLabel, BorderLayout.NORTH);
Component leftComponent;
if (flashPanel != null) {
JPanel flashPlayPanel = new JPanel(new BorderLayout());
flashPlayPanel.add(flashPanel, BorderLayout.CENTER);
JPanel bottomPanel = new JPanel(new BorderLayout());
JPanel buttonsPanel = new JPanel(new FlowLayout());
JButton selectColorButton = new JButton(View.getIcon("color16"));
selectColorButton.addActionListener(mainPanel);
selectColorButton.setActionCommand(MainPanel.ACTION_SELECT_BKCOLOR);
selectColorButton.setToolTipText(AppStrings.translate("button.selectbkcolor.hint"));
buttonsPanel.add(selectColorButton);
bottomPanel.add(buttonsPanel, BorderLayout.EAST);
flashPlayPanel.add(bottomPanel, BorderLayout.SOUTH);
JPanel flashPlayPanel2 = new JPanel(new BorderLayout());
flashPlayPanel2.add(flashPlayPanel, BorderLayout.CENTER);
flashPlayPanel2.add(flashControls = new PlayerControls(flashPanel), BorderLayout.SOUTH);
leftComponent = flashPlayPanel2;
} else {
JPanel swtPanel = new JPanel(new BorderLayout());
swtPanel.add(new JLabel("<html><center>" + mainPanel.translate("notavailonthisplatform") + "</center></html>", JLabel.CENTER), BorderLayout.CENTER);
swtPanel.setBackground(View.DEFAULT_BACKGROUND_COLOR);
leftComponent = swtPanel;
}
pan.add(leftComponent, BorderLayout.CENTER);
return pan;
}
private JPanel createImagesCard() {
JPanel shapesCard = new JPanel(new BorderLayout());
JPanel previewPanel = new JPanel(new BorderLayout());
JPanel previewCnt = new JPanel(new BorderLayout());
imagePanel = new ImagePanel();
previewCnt.add(imagePanel, BorderLayout.CENTER);
previewCnt.add(imagePlayControls = new PlayerControls(imagePanel), BorderLayout.SOUTH);
imagePlayControls.setMedia(imagePanel);
previewPanel.add(previewCnt, BorderLayout.CENTER);
JLabel prevIntLabel = new HeaderLabel(mainPanel.translate("swfpreview.internal"));
prevIntLabel.setHorizontalAlignment(SwingConstants.CENTER);
//prevIntLabel.setBorder(new BevelBorder(BevelBorder.RAISED));
previewPanel.add(prevIntLabel, BorderLayout.NORTH);
shapesCard.add(previewPanel, BorderLayout.CENTER);
shapesCard.add(createImageButtonsPanel(), BorderLayout.SOUTH);
return shapesCard;
}
private JPanel createBinaryCard() {
JPanel binaryCard = new JPanel(new BorderLayout());
binaryPanel = new BinaryPanel();
binaryCard.add(binaryPanel, BorderLayout.CENTER);
binaryCard.add(createBinaryButtonsPanel(), BorderLayout.SOUTH);
return binaryCard;
}
private JPanel createGenericTagCard() {
JPanel genericTagCard = new JPanel(new BorderLayout());
genericTagPanel = new GenericTagTreePanel();
genericTagCard.add(genericTagPanel, BorderLayout.CENTER);
genericTagCard.add(createGenericTagButtonsPanel(), BorderLayout.SOUTH);
return genericTagCard;
}
private void showCardLeft(String card) {
CardLayout cl = (CardLayout) (viewerCards.getLayout());
cl.show(viewerCards, card);
}
private void showCardRight(String card) {
CardLayout cl = (CardLayout) (displayWithPreview.getLayout());
cl.show(displayWithPreview, card);
}
public void setSplitsInited() {
splitsInited = true;
}
public TextPanel getTextPanel() {
return textPanel;
}
public void setParametersPanelVisible(boolean show) {
parametersPanel.setVisible(show);
}
public void showFlashViewerPanel() {
parametersPanel.setVisible(false);
showCardLeft(FLASH_VIEWER_CARD);
}
public void showImagePanel(Timelined timelined, SWF swf, int frame) {
showCardLeft(DRAW_PREVIEW_CARD);
parametersPanel.setVisible(false);
imagePlayControls.setMedia(imagePanel);
imagePanel.setTimelined(timelined, swf, frame);
}
public void showImagePanel(SerializableImage image) {
showCardLeft(DRAW_PREVIEW_CARD);
parametersPanel.setVisible(false);
imagePlayControls.setMedia(imagePanel);
imagePanel.setImage(image);
}
public void setMedia(MediaDisplay media) {
imagePlayControls.setMedia(media);
}
public void showFontPanel(FontTag fontTag) {
fontPageNum = 0;
showFontPage(fontTag);
showCardRight(CARDFONTPANEL);
parametersPanel.setVisible(true);
setDividerLocation(Configuration.guiPreviewSplitPaneDividerLocation.get(getWidth() / 2));
fontPanel.showFontTag(fontTag);
int pageCount = getFontPageCount(fontTag);
if (pageCount > 1) {
prevFontsButton.setVisible(true);
nextFontsButton.setVisible(true);
}
}
private void showFontPage(FontTag fontTag) {
if (mainPanel.isInternalFlashViewerSelected() /*|| ft instanceof GFxDefineCompactedFont*/) {
showImagePanel(MainPanel.makeTimelined(fontTag), fontTag.getSwf(), fontPageNum);
}
}
public static int getFontPageCount(FontTag fontTag) {
int pageCount = (fontTag.getGlyphShapeTable().size() - 1) / SHAPERECORD.MAX_CHARACTERS_IN_FONT_PREVIEW + 1;
if (pageCount < 1) {
pageCount = 1;
}
return pageCount;
}
public void showTextPanel(TextTag textTag) {
if (mainPanel.isInternalFlashViewerSelected() /*|| ft instanceof GFxDefineCompactedFont*/) {
showImagePanel(MainPanel.makeTimelined(textTag), textTag.getSwf(), 0);
}
showCardRight(CARDTEXTPANEL);
parametersPanel.setVisible(true);
setDividerLocation(Configuration.guiPreviewSplitPaneDividerLocation.get(getWidth() / 2));
textPanel.setText(textTag.getFormattedText());
}
public void setEditText(boolean edit) {
textPanel.setEditText(edit);
}
public void clear() {
imagePanel.stop();
binaryPanel.setBinaryData(null);
genericTagPanel.clear();
fontPanel.clear();
}
public void showBinaryPanel(byte[] data) {
showCardLeft(BINARY_TAG_CARD);
binaryPanel.setBinaryData(data);
parametersPanel.setVisible(false);
}
public void showGenericTagPanel(Tag tag) {
showCardLeft(GENERIC_TAG_CARD);
editButton.setVisible(true);
saveButton.setVisible(false);
cancelButton.setVisible(false);
genericTagPanel.setEditMode(false, tag);
parametersPanel.setVisible(false);
}
public void setImageReplaceButtonVisible(boolean show) {
replaceImageButton.setVisible(show);
prevFontsButton.setVisible(false);
nextFontsButton.setVisible(false);
}
private static Tag classicTag(Tag t) {
if (t instanceof DefineCompactedFont) {
return ((DefineCompactedFont) t).toClassicFont();
}
return t;
}
public void createAndShowTempSwf(TreeItem tagObj) {
SWF swf;
try {
if (tempFile != null) {
tempFile.delete();
}
tempFile = File.createTempFile("temp", ".swf");
tempFile.deleteOnExit();
Color backgroundColor = View.swfBackgroundColor;
if (tagObj instanceof FontTag) { //Fonts are always black on white
backgroundColor = View.DEFAULT_BACKGROUND_COLOR;
}
if (tagObj instanceof FrameNodeItem) {
FrameNodeItem fn = (FrameNodeItem) tagObj;
swf = fn.getSwf();
if (fn.getParent() == null) {
for (Tag t : swf.tags) {
if (t instanceof SetBackgroundColorTag) {
backgroundColor = ((SetBackgroundColorTag) t).backgroundColor.toColor();
break;
}
}
}
} else {
Tag tag = (Tag) tagObj;
swf = tag.getSwf();
}
int frameCount = 1;
int frameRate = swf.frameRate;
HashMap<Integer, VideoFrameTag> videoFrames = new HashMap<>();
if (tagObj instanceof DefineVideoStreamTag) {
DefineVideoStreamTag vs = (DefineVideoStreamTag) tagObj;
SWF.populateVideoFrames(vs.getCharacterId(), swf.tags, videoFrames);
frameCount = videoFrames.size();
}
List<SoundStreamBlockTag> soundFrames = new ArrayList<>();
if (tagObj instanceof SoundStreamHeadTypeTag) {
soundFrames = ((SoundStreamHeadTypeTag) tagObj).getBlocks();
frameCount = soundFrames.size();
}
if ((tagObj instanceof DefineMorphShapeTag) || (tagObj instanceof DefineMorphShape2Tag)) {
frameRate = MainPanel.MORPH_SHAPE_ANIMATION_FRAME_RATE;
frameCount = MainPanel.MORPH_SHAPE_ANIMATION_LENGTH * frameRate;
}
if (tagObj instanceof DefineSoundTag) {
frameCount = 1;
}
byte[] data;
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
SWFOutputStream sos2 = new SWFOutputStream(baos, 10);
int width = swf.displayRect.Xmax - swf.displayRect.Xmin;
int height = swf.displayRect.Ymax - swf.displayRect.Ymin;
sos2.writeRECT(swf.displayRect);
sos2.writeUI8(0);
sos2.writeUI8(frameRate);
sos2.writeUI16(frameCount); //framecnt
/*FileAttributesTag fa = new FileAttributesTag();
sos2.writeTag(fa);
*/
new SetBackgroundColorTag(swf, new RGB(backgroundColor)).writeTag(sos2);
if (tagObj instanceof FrameNodeItem) {
FrameNodeItem fn = (FrameNodeItem) tagObj;
Tag parent = fn.getParent();
List<ContainerItem> subs = new ArrayList<>();
if (parent == null) {
subs.addAll(swf.tags);
} else {
if (parent instanceof Container) {
subs = ((Container) parent).getSubItems();
}
}
List<Integer> doneCharacters = new ArrayList<>();
int frameCnt = 1;
for (ContainerItem item : subs) {
if (item instanceof ShowFrameTag) {
frameCnt++;
continue;
}
if (frameCnt > fn.getFrame()) {
break;
}
if (item instanceof DoActionTag || item instanceof DoInitActionTag) {
// todo: Maybe DoABC tags should be removed, too
continue;
}
Tag t = (Tag) item;
Set<Integer> needed = t.getDeepNeededCharacters(swf.characters);
for (int n : needed) {
if (!doneCharacters.contains(n)) {
classicTag(swf.characters.get(n)).writeTag(sos2);
doneCharacters.add(n);
}
}
if (t instanceof CharacterTag) {
int characterId = ((CharacterTag) t).getCharacterId();
if (!doneCharacters.contains(characterId)) {
doneCharacters.add(((CharacterTag) t).getCharacterId());
}
}
classicTag(t).writeTag(sos2);
if (parent != null) {
if (t instanceof PlaceObjectTypeTag) {
PlaceObjectTypeTag pot = (PlaceObjectTypeTag) t;
int chid = pot.getCharacterId();
int depth = pot.getDepth();
MATRIX mat = pot.getMatrix();
if (mat == null) {
mat = new MATRIX();
}
mat = Helper.deepCopy(mat);
if (parent instanceof BoundedTag) {
RECT r = ((BoundedTag) parent).getRect();
mat.translateX = mat.translateX + width / 2 - r.getWidth() / 2;
mat.translateY = mat.translateY + height / 2 - r.getHeight() / 2;
} else {
mat.translateX += width / 2;
mat.translateY += height / 2;
}
new PlaceObject2Tag(swf, false, false, false, false, false, true, false, true, depth, chid, mat, null, 0, null, 0, null).writeTag(sos2);
}
}
}
new ShowFrameTag(swf).writeTag(sos2);
} else {
if (tagObj instanceof DefineBitsTag) {
JPEGTablesTag jtt = swf.jtt;
if (jtt != null) {
jtt.writeTag(sos2);
}
} else if (tagObj instanceof AloneTag) {
} else {
Set<Integer> needed = ((Tag) tagObj).getDeepNeededCharacters(swf.characters);
for (int n : needed) {
classicTag(swf.characters.get(n)).writeTag(sos2);
}
}
classicTag((Tag) tagObj).writeTag(sos2);
int chtId = 0;
if (tagObj instanceof CharacterTag) {
chtId = ((CharacterTag) tagObj).getCharacterId();
}
MATRIX mat = new MATRIX();
mat.hasRotate = false;
mat.hasScale = false;
mat.translateX = 0;
mat.translateY = 0;
if (tagObj instanceof BoundedTag) {
RECT r = ((BoundedTag) tagObj).getRect();
mat.translateX = -r.Xmin;
mat.translateY = -r.Ymin;
mat.translateX = mat.translateX + width / 2 - r.getWidth() / 2;
mat.translateY = mat.translateY + height / 2 - r.getHeight() / 2;
} else {
mat.translateX = width / 4;
mat.translateY = height / 4;
}
if (tagObj instanceof FontTag) {
int countGlyphsTotal = ((FontTag) tagObj).getGlyphShapeTable().size();
int countGlyphs = Math.min(SHAPERECORD.MAX_CHARACTERS_IN_FONT_PREVIEW, countGlyphsTotal);
int fontId = ((FontTag) tagObj).getFontId();
int cols = (int) Math.ceil(Math.sqrt(countGlyphs));
int rows = (int) Math.ceil(((float) countGlyphs) / ((float) cols));
int x = 0;
int y = 1;
int firstGlyphIndex = fontPageNum * SHAPERECORD.MAX_CHARACTERS_IN_FONT_PREVIEW;
countGlyphs = Math.min(SHAPERECORD.MAX_CHARACTERS_IN_FONT_PREVIEW, countGlyphsTotal - firstGlyphIndex);
for (int f = firstGlyphIndex; f < firstGlyphIndex + countGlyphs; f++) {
if (x >= cols) {
x = 0;
y++;
}
List<TEXTRECORD> rec = new ArrayList<>();
TEXTRECORD tr = new TEXTRECORD();
int textHeight = height / rows;
tr.fontId = fontId;
tr.styleFlagsHasFont = true;
tr.textHeight = textHeight;
tr.glyphEntries = new GLYPHENTRY[1];
tr.styleFlagsHasColor = true;
tr.textColor = new RGB(0, 0, 0);
tr.glyphEntries[0] = new GLYPHENTRY();
tr.glyphEntries[0].glyphAdvance = 0;
tr.glyphEntries[0].glyphIndex = f;
rec.add(tr);
mat.translateX = x * width / cols;
mat.translateY = y * height / rows;
new DefineTextTag(swf, 999 + f, new RECT(0, width, 0, height), new MATRIX(), rec).writeTag(sos2);
new PlaceObject2Tag(swf, false, false, false, true, false, true, true, false, 1 + f, 999 + f, mat, null, 0, null, 0, null).writeTag(sos2);
x++;
}
new ShowFrameTag(swf).writeTag(sos2);
} else if ((tagObj instanceof DefineMorphShapeTag) || (tagObj instanceof DefineMorphShape2Tag)) {
new PlaceObject2Tag(swf, false, false, false, true, false, true, true, false, 1, chtId, mat, null, 0, null, 0, null).writeTag(sos2);
new ShowFrameTag(swf).writeTag(sos2);
for (int ratio = 0; ratio < 65536; ratio += 65536 / frameCount) {
new PlaceObject2Tag(swf, false, false, false, true, false, true, false, true, 1, chtId, mat, null, ratio, null, 0, null).writeTag(sos2);
new ShowFrameTag(swf).writeTag(sos2);
}
} else if (tagObj instanceof SoundStreamHeadTypeTag) {
for (SoundStreamBlockTag blk : soundFrames) {
blk.writeTag(sos2);
new ShowFrameTag(swf).writeTag(sos2);
}
} else if (tagObj instanceof DefineSoundTag) {
ExportAssetsTag ea = new ExportAssetsTag(swf);
DefineSoundTag ds = (DefineSoundTag) tagObj;
ea.tags.add(ds.soundId);
ea.names.add("my_define_sound");
ea.writeTag(sos2);
List<Action> actions;
DoActionTag doa;
doa = new DoActionTag(swf, new byte[0], new byte[0], 0);
actions = ASMParser.parse(0, 0, false,
"ConstantPool \"_root\" \"my_sound\" \"Sound\" \"my_define_sound\" \"attachSound\"\n"
+ "Push \"_root\"\n"
+ "GetVariable\n"
+ "Push \"my_sound\" 0.0 \"Sound\"\n"
+ "NewObject\n"
+ "SetMember\n"
+ "Push \"my_define_sound\" 1 \"_root\"\n"
+ "GetVariable\n"
+ "Push \"my_sound\"\n"
+ "GetMember\n"
+ "Push \"attachSound\"\n"
+ "CallMethod\n"
+ "Pop\n"
+ "Stop", swf.version, false);
doa.setActions(actions);
doa.writeTag(sos2);
new ShowFrameTag(swf).writeTag(sos2);
actions = ASMParser.parse(0, 0, false,
"ConstantPool \"_root\" \"my_sound\" \"Sound\" \"my_define_sound\" \"attachSound\" \"start\"\n"
+ "StopSounds\n"
+ "Push \"_root\"\n"
+ "GetVariable\n"
+ "Push \"my_sound\" 0.0 \"Sound\"\n"
+ "NewObject\n"
+ "SetMember\n"
+ "Push \"my_define_sound\" 1 \"_root\"\n"
+ "GetVariable\n"
+ "Push \"my_sound\"\n"
+ "GetMember\n"
+ "Push \"attachSound\"\n"
+ "CallMethod\n"
+ "Pop\n"
+ "Push 9999 0.0 2 \"_root\"\n"
+ "GetVariable\n"
+ "Push \"my_sound\"\n"
+ "GetMember\n"
+ "Push \"start\"\n"
+ "CallMethod\n"
+ "Pop\n"
+ "Stop", swf.version, false);
doa.setActions(actions);
doa.writeTag(sos2);
new ShowFrameTag(swf).writeTag(sos2);
actions = ASMParser.parse(0, 0, false,
"ConstantPool \"_root\" \"my_sound\" \"Sound\" \"my_define_sound\" \"attachSound\" \"onSoundComplete\" \"start\" \"execParam\"\n"
+ "StopSounds\n"
+ "Push \"_root\"\n"
+ "GetVariable\n"
+ "Push \"my_sound\" 0.0 \"Sound\"\n"
+ "NewObject\n"
+ "SetMember\n"
+ "Push \"my_define_sound\" 1 \"_root\"\n"
+ "GetVariable\n"
+ "Push \"my_sound\"\n"
+ "GetMember\n"
+ "Push \"attachSound\"\n"
+ "CallMethod\n"
+ "Pop\n"
+ "Push \"_root\"\n"
+ "GetVariable\n"
+ "Push \"my_sound\"\n"
+ "GetMember\n"
+ "Push \"onSoundComplete\"\n"
+ "DefineFunction2 \"\" 0 2 false true true false true false true false false {\n"
+ "Push 0.0 register1 \"my_sound\"\n"
+ "GetMember\n"
+ "Push \"start\"\n"
+ "CallMethod\n"
+ "Pop\n"
+ "}\n"
+ "SetMember\n"
+ "Push \"_root\"\n"
+ "GetVariable\n"
+ "Push \"execParam\"\n"
+ "GetMember\n"
+ "Push 1 \"_root\"\n"
+ "GetVariable\n"
+ "Push \"my_sound\"\n"
+ "GetMember\n"
+ "Push \"start\"\n"
+ "CallMethod\n"
+ "Pop\n"
+ "Stop", swf.version, false);
doa.setActions(actions);
doa.writeTag(sos2);
new ShowFrameTag(swf).writeTag(sos2);
actions = ASMParser.parse(0, 0, false,
"StopSounds\n"
+ "Stop", swf.version, false);
doa.setActions(actions);
doa.writeTag(sos2);
new ShowFrameTag(swf).writeTag(sos2);
new ShowFrameTag(swf).writeTag(sos2);
if (flashPanel != null) {
flashPanel.specialPlayback = true;
}
} else if (tagObj instanceof DefineVideoStreamTag) {
new PlaceObject2Tag(swf, false, false, false, false, false, true, true, false, 1, chtId, mat, null, 0, null, 0, null).writeTag(sos2);
List<VideoFrameTag> frs = new ArrayList<>(videoFrames.values());
Collections.sort(frs, new Comparator<VideoFrameTag>() {
@Override
public int compare(VideoFrameTag o1, VideoFrameTag o2) {
return o1.frameNum - o2.frameNum;
}
});
boolean first = true;
int ratio = 0;
for (VideoFrameTag f : frs) {
if (!first) {
ratio++;
new PlaceObject2Tag(swf, false, false, false, true, false, false, false, true, 1, 0, null, null, ratio, null, 0, null).writeTag(sos2);
}
f.writeTag(sos2);
new ShowFrameTag(swf).writeTag(sos2);
first = false;
}
} else {
new PlaceObject2Tag(swf, false, false, false, true, false, true, true, false, 1, chtId, mat, null, 0, null, 0, null).writeTag(sos2);
new ShowFrameTag(swf).writeTag(sos2);
}
}//not showframe
new EndTag(swf).writeTag(sos2);
data = baos.toByteArray();
}
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(tempFile))) {
SWFOutputStream sos = new SWFOutputStream(fos, Math.max(10, swf.version));
sos.write("FWS".getBytes());
sos.write(swf.version);
sos.writeUI32(sos.getPos() + data.length + 4);
sos.write(data);
fos.flush();
}
if (flashPanel != null) {
flashPanel.displaySWF(tempFile.getAbsolutePath(), backgroundColor, frameRate);
}
showFlashViewerPanel();
} catch (IOException | com.jpexs.decompiler.flash.action.parser.ParseException ex) {
Logger.getLogger(MainPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void showSwf(SWF swf) {
Color backgroundColor = View.DEFAULT_BACKGROUND_COLOR;
for (Tag t : swf.tags) {
if (t instanceof SetBackgroundColorTag) {
backgroundColor = ((SetBackgroundColorTag) t).backgroundColor.toColor();
break;
}
}
if (tempFile != null) {
tempFile.delete();
}
try {
tempFile = File.createTempFile("temp", ".swf");
tempFile.deleteOnExit();
swf.saveTo(new BufferedOutputStream(new FileOutputStream(tempFile)));
flashPanel.displaySWF(tempFile.getAbsolutePath(), backgroundColor, swf.frameRate);
} catch (IOException iex) {
Logger.getLogger(PreviewPanel.class.getName()).log(Level.SEVERE, "Cannot create tempfile", iex);
}
}
@Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case ACTION_EDIT_GENERIC_TAG: {
TreeItem item = mainPanel.tagTree.getCurrentTreeItem();
if (item == null) {
return;
}
if (item instanceof Tag) {
editButton.setVisible(false);
saveButton.setVisible(true);
cancelButton.setVisible(true);
//genericTagPanel.generateEditControls((Tag) item, false);
genericTagPanel.setEditMode(true, (Tag) item);
}
}
break;
case ACTION_SAVE_GENERIC_TAG: {
genericTagPanel.save();
mainPanel.refreshTree();
mainPanel.setTreeItem(genericTagPanel.getTag());
editButton.setVisible(true);
saveButton.setVisible(false);
cancelButton.setVisible(false);
genericTagPanel.setEditMode(false, null);
}
break;
case ACTION_CANCEL_GENERIC_TAG: {
editButton.setVisible(true);
saveButton.setVisible(false);
cancelButton.setVisible(false);
genericTagPanel.setEditMode(false, null);
}
break;
case ACTION_PREV_FONTS: {
FontTag fontTag = fontPanel.getFontTag();
int pageCount = getFontPageCount(fontTag);
fontPageNum = (fontPageNum + pageCount - 1) % pageCount;
if (mainPanel.isInternalFlashViewerSelected() /*|| ft instanceof GFxDefineCompactedFont*/) {
imagePanel.setTimelined(MainPanel.makeTimelined(fontTag), fontTag.getSwf(), fontPageNum);
}
}
break;
case ACTION_NEXT_FONTS: {
FontTag fontTag = fontPanel.getFontTag();
int pageCount = getFontPageCount(fontTag);
fontPageNum = (fontPageNum + 1) % pageCount;
if (mainPanel.isInternalFlashViewerSelected() /*|| ft instanceof GFxDefineCompactedFont*/) {
imagePanel.setTimelined(MainPanel.makeTimelined(fontTag), fontTag.getSwf(), fontPageNum);
}
}
break;
}
}
}
@@ -0,0 +1,34 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import org.pushingpixels.flamingo.api.common.JCommandButton;
import org.pushingpixels.flamingo.api.common.icon.ResizableIcon;
/**
*
* @author JPEXS
*/
public class RecentFilesButton extends JCommandButton {
public String fileName;
public RecentFilesButton(String title, ResizableIcon icon) {
super(title, icon);
}
}
@@ -0,0 +1,121 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.abc.RenameType;
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;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
/**
*
* @author JPEXS
*/
public class RenameDialog extends AppDialog implements ActionListener {
static final String ACTION_OK = "OK";
static final String ACTION_CANCEL = "CANCEL";
private final JRadioButton typeNumberRadioButton = new JRadioButton(translate("rename.type.typenumber"));
private final JRadioButton randomWordRadioButton = new JRadioButton(translate("rename.type.randomword"));
private final JButton okButton = new JButton(translate("button.ok"));
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;
}
public RenameDialog() {
setSize(300, 150);
setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
int renameType = Configuration.lastRenameType.get();
ButtonGroup group = new ButtonGroup();
group.add(typeNumberRadioButton);
group.add(randomWordRadioButton);
JPanel pan = new JPanel();
pan.setLayout(new BoxLayout(pan, BoxLayout.Y_AXIS));
pan.add(typeNumberRadioButton);
pan.add(randomWordRadioButton);
typeNumberRadioButton.setSelected(renameType == 1);
randomWordRadioButton.setSelected(renameType == 2);
setLayout(new BorderLayout());
add(new JLabel(translate("rename.type")), BorderLayout.NORTH);
add(pan, BorderLayout.CENTER);
JPanel panButtons = new JPanel(new FlowLayout());
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"));
getRootPane().setDefaultButton(okButton);
pack();
View.centerScreen(this);
}
@Override
public void setVisible(boolean b) {
if (b) {
confirmed = false;
}
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;
}
}
public boolean isConfirmed() {
return confirmed;
}
public RenameType display() {
setVisible(true);
return getRenameType();
}
}
@@ -0,0 +1,26 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
/**
*
* @author JPEXS
*/
public enum SaveFileMode {
SAVE, SAVEAS, EXE
}
@@ -0,0 +1,131 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
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.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
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 SearchDialog extends AppDialog implements ActionListener {
static final String ACTION_OK = "OK";
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 JRadioButton searchInASRadioButton = new JRadioButton(translate("checkbox.searchAS"));
public JRadioButton searchInTextsRadioButton = new JRadioButton(translate("checkbox.searchText"));
public boolean result = false;
public SearchDialog() {
setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
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);
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);
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();
java.util.List<Image> 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() == 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);
}
}
@@ -0,0 +1,27 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
/**
*
* @author JPEXS
* @param <E>
*/
public interface SearchListener<E> {
public void updateSearchPos(E item);
}
@@ -0,0 +1,152 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.AppStrings;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.text.JTextComponent;
import jsyntaxpane.actions.DocumentSearchData;
/**
*
* @author JPEXS
* @param <E>
*/
public class SearchPanel<E> extends JPanel implements ActionListener {
static final String ACTION_SEARCH_PREV = "SEARCHPREV";
static final String ACTION_SEARCH_NEXT = "SEARCHNEXT";
static final String ACTION_SEARCH_CANCEL = "SEARCHCANCEL";
private final SearchListener<E> listener;
private final JLabel searchPos;
private int foundPos = 0;
private final JLabel searchForLabel;
private String searchFor;
private boolean searchIgnoreCase;
private boolean searchRegexp;
private List<E> found = new ArrayList<>();
public SearchPanel(LayoutManager lm, SearchListener<E> listener) {
super(lm);
this.listener = listener;
JButton prevSearchButton = new JButton(View.getIcon("prev16"));
prevSearchButton.setMargin(new Insets(3, 3, 3, 3));
prevSearchButton.addActionListener(this);
prevSearchButton.setActionCommand(ACTION_SEARCH_PREV);
JButton nextSearchButton = new JButton(View.getIcon("next16"));
nextSearchButton.setMargin(new Insets(3, 3, 3, 3));
nextSearchButton.addActionListener(this);
nextSearchButton.setActionCommand(ACTION_SEARCH_NEXT);
JButton cancelSearchButton = new JButton(View.getIcon("cancel16"));
cancelSearchButton.setMargin(new Insets(3, 3, 3, 3));
cancelSearchButton.addActionListener(this);
cancelSearchButton.setActionCommand(ACTION_SEARCH_CANCEL);
searchPos = new JLabel("0/0");
searchForLabel = new JLabel(AppStrings.translate("search.info").replace("%text%", ""));
add(searchForLabel);
add(prevSearchButton);
add(new JLabel(AppStrings.translate("search.script") + " "));
add(searchPos);
add(nextSearchButton);
add(cancelSearchButton);
setVisible(false);
}
public void showQuickFindDialog(JTextComponent editor) {
DocumentSearchData dsd = DocumentSearchData.getFromEditor(editor);
dsd.setPattern(searchFor, searchRegexp, searchIgnoreCase);
dsd.showQuickFindDialogEx(editor, searchIgnoreCase, searchRegexp);
}
public void setSearchText(String txt) {
searchFor = txt;
searchForLabel.setText(AppStrings.translate("search.info").replace("%text%", txt) + " ");
}
public boolean setResults(List<E> results) {
found = results;
if (found.isEmpty()) {
setVisible(false);
return false;
} else {
setPos(0);
setVisible(true);
return true;
}
}
public void setOptions(boolean ignoreCase, boolean regExp) {
searchIgnoreCase = ignoreCase;
searchRegexp = regExp;
}
public void setPos(int pos) {
foundPos = pos;
doUpdate();
}
public void clear() {
foundPos = 0;
found.clear();
}
private void doUpdate() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
searchPos.setText((foundPos + 1) + "/" + found.size());
listener.updateSearchPos(found.get(foundPos));
}
});
}
@Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case ACTION_SEARCH_CANCEL:
foundPos = 0;
setVisible(false);
found = new ArrayList<>();
searchFor = null;
break;
case ACTION_SEARCH_PREV:
foundPos--;
if (foundPos < 0) {
foundPos += found.size();
}
doUpdate();
break;
case ACTION_SEARCH_NEXT:
foundPos = (foundPos + 1) % found.size();
doUpdate();
break;
}
}
}
@@ -0,0 +1,149 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.AppStrings;
import com.jpexs.decompiler.flash.configuration.Configuration;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Locale;
import java.util.ResourceBundle;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import jsyntaxpane.DefaultSyntaxKit;
/**
*
* @author JPEXS
*/
public class SelectLanguageDialog extends AppDialog implements ActionListener {
static final String ACTION_OK = "OK";
static final String ACTION_CANCEL = "CANCEL";
JComboBox<Language> languageCombobox = new JComboBox<>();
public String languageCode = null;
private static final String[] languages = new String[]{"en", "cs", "zh", "de", "es", "fr", "hu", "nl", "pt", "pt-BR", "ru", "sv", "uk"};
public SelectLanguageDialog() {
setSize(350, 130);
Container cnt1 = getContentPane();
JPanel cnt = new JPanel();
cnt1.setLayout(new BorderLayout());
cnt1.add(cnt, BorderLayout.CENTER);
String currentLanguage = Configuration.locale.get(Locale.getDefault().getLanguage());
boolean found = false;
int enIndex = 0;
for (String code : languages) {
String name = ResourceBundle.getBundle(AppStrings.getResourcePath(getClass()), Locale.forLanguageTag(code.equals("en") ? "" : code)).getString("language");
if (name.length() > 1) {
name = name.substring(0, 1).toUpperCase() + name.substring(1);
}
if (code.equals("en")) {
enIndex = languageCombobox.getItemCount();
}
languageCombobox.addItem(new Language(code, name));
if (code.equals(currentLanguage)) {
languageCombobox.setSelectedIndex(languageCombobox.getItemCount() - 1);
found = true;
}
}
if (!found) {
languageCombobox.setSelectedIndex(enIndex);
}
cnt.setBorder(new EmptyBorder(10, 10, 10, 10));
cnt.setLayout(new BoxLayout(cnt, BoxLayout.Y_AXIS));
JLabel langLabel = new JLabel(translate("language.label"));
langLabel.setAlignmentX(0.5f);
cnt.add(langLabel);
languageCombobox.setAlignmentX(0.5f);
cnt.add(languageCombobox);
JPanel buttonsPanel = new JPanel(new FlowLayout());
buttonsPanel.setAlignmentX(0.5f);
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);
buttonsPanel.add(okButton);
buttonsPanel.add(cancelButton);
cnt.add(buttonsPanel);
getRootPane().setDefaultButton(okButton);
setModalityType(ModalityType.APPLICATION_MODAL);
View.setWindowIcon(this);
View.centerScreen(this);
setTitle(translate("dialog.title"));
pack();
if (getWidth() < 350) {
setSize(350, getHeight());
}
}
@Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case ACTION_OK:
if (languageCombobox.getSelectedIndex() == -1) {
} else {
languageCode = ((Language) languageCombobox.getSelectedItem()).code;
String newLanguage = languageCode;
if (newLanguage.equals("en")) {
newLanguage = "";
}
Configuration.locale.set(newLanguage);
setVisible(false);
reloadUi();
}
break;
case ACTION_CANCEL:
setVisible(false);
break;
}
}
public static void reloadUi() {
View.execInEventDispatchLater(new Runnable() {
@Override
public void run() {
Locale.setDefault(Locale.forLanguageTag(Configuration.locale.get()));
DefaultSyntaxKit.reloadConfigs();
Main.initLang();
Main.reloadApp();
}
});
}
public static String[] getAvailableLanguages() {
return languages;
}
public String display() {
setVisible(true);
return languageCode;
}
}
@@ -0,0 +1,211 @@
/*
* Copyright (C) 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.gui.player.MediaDisplay;
import com.jpexs.decompiler.flash.tags.base.SoundTag;
import com.jpexs.helpers.SoundPlayer;
import java.awt.Color;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
/**
*
* @author JPEXS
*/
public class SoundTagPlayer implements MediaDisplay {
private final SoundPlayer player;
private Thread thr;
private int actualPos = 0;
private final SoundTag tag;
private final List<PlayerListener> listeners = new ArrayList<>();
public void addListener(PlayerListener l) {
listeners.add(l);
}
public void removeListener(PlayerListener l) {
listeners.remove(l);
}
public void fireFinished() {
for (PlayerListener l : listeners) {
l.playingFinished();
}
}
private static final int FRAME_DIVISOR = 8000;
private int loops;
private boolean paused = true;
private final Object playLock = new Object();
public SoundTagPlayer(SoundTag tag, int loops) throws LineUnavailableException, IOException, UnsupportedAudioFileException {
this.tag = tag;
this.loops = loops;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ByteArrayInputStream bais = new ByteArrayInputStream(tag.getRawSoundData());
tag.getSoundFormat().createWav(bais, baos);
player = new SoundPlayer(new ByteArrayInputStream(baos.toByteArray()));
}
@Override
public synchronized int getCurrentFrame() {
synchronized (playLock) {
if (isPlaying()) {
actualPos = (int) (player.getSamplePosition() / FRAME_DIVISOR);
}
return actualPos;
}
}
@Override
public synchronized int getTotalFrames() {
int ret = (int) (player.samplesCount() / FRAME_DIVISOR);
return ret;
}
@Override
public synchronized void pause() {
if (!isPlaying()) {
paused = true;
return;
}
synchronized (playLock) {
actualPos = (int) (player.getSamplePosition() / FRAME_DIVISOR);
}
waitStop();
}
private void waitStop() {
synchronized (playLock) {
if (!paused) {
paused = true;
player.stop();
try {
playLock.wait();
} catch (InterruptedException ex) {
Logger.getLogger(SoundTagPlayer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public void play(boolean async) {
waitStop();
Runnable r = new Runnable() {
@Override
public void run() {
boolean playAgain = true;
while (playAgain) {
int startPos = 0;
synchronized (playLock) {
startPos = actualPos * FRAME_DIVISOR;
}
player.setPosition(startPos);
player.play();
synchronized (playLock) {
playAgain = !paused && loops > 0;
if (!paused) {
if (loops == 0) {
paused = true;
} else if (loops != Integer.MAX_VALUE) {
loops--;
}
}
if (playAgain) {
actualPos = 0;
}
}
}
fireFinished();
synchronized (playLock) {
playLock.notifyAll();
}
}
};
synchronized (playLock) {
paused = false;
}
if (async) {
thr = new Thread(r);
thr.start();
} else {
r.run();
}
}
@Override
public synchronized void play() {
play(true);
}
@Override
public void rewind() {
gotoFrame(0);
}
@Override
public boolean isPlaying() {
return player.isPlaying();
}
@Override
public synchronized void gotoFrame(int frame) {
pause();
synchronized (playLock) {
actualPos = frame;
}
}
@Override
public void setBackground(Color color) {
}
@Override
public int getFrameRate() {
if (player == null) {
return 1;
}
return (int) (player.getFrameRate() / FRAME_DIVISOR);
}
@Override
public boolean isLoaded() {
return true;
}
}
@@ -0,0 +1,52 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.AppStrings;
import com.jpexs.helpers.ReReadableInputStream;
import java.util.ResourceBundle;
/**
*
* @author JPEXS
*/
public class SwfInMemory {
public ReReadableInputStream is;
public int version;
public long fileSize;
public com.jpexs.process.Process process;
public SwfInMemory(ReReadableInputStream is, int version, long fileSize, com.jpexs.process.Process process) {
this.is = is;
this.version = version;
this.fileSize = fileSize;
this.process = process;
}
private static final ResourceBundle resourceBundle = ResourceBundle.getBundle(AppStrings.getResourcePath(LoadFromMemoryFrame.class));
public String translate(String key) {
return resourceBundle.getString(key);
}
@Override
public String toString() {
String p = translate("swfitem").replace("%version%", "" + version).replace("%size%", "" + fileSize);
return p;
}
}
@@ -0,0 +1,304 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.ScriptPack;
import com.jpexs.decompiler.flash.gui.treenodes.TagTreeRoot;
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG2Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG3Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG4Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsLossless2Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsLosslessTag;
import com.jpexs.decompiler.flash.tags.DefineBitsTag;
import com.jpexs.decompiler.flash.tags.DefineButton2Tag;
import com.jpexs.decompiler.flash.tags.DefineButtonTag;
import com.jpexs.decompiler.flash.tags.DefineEditTextTag;
import com.jpexs.decompiler.flash.tags.DefineFont2Tag;
import com.jpexs.decompiler.flash.tags.DefineFont3Tag;
import com.jpexs.decompiler.flash.tags.DefineFont4Tag;
import com.jpexs.decompiler.flash.tags.DefineFontTag;
import com.jpexs.decompiler.flash.tags.DefineMorphShape2Tag;
import com.jpexs.decompiler.flash.tags.DefineMorphShapeTag;
import com.jpexs.decompiler.flash.tags.DefineShape2Tag;
import com.jpexs.decompiler.flash.tags.DefineShape3Tag;
import com.jpexs.decompiler.flash.tags.DefineShape4Tag;
import com.jpexs.decompiler.flash.tags.DefineShapeTag;
import com.jpexs.decompiler.flash.tags.DefineSoundTag;
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
import com.jpexs.decompiler.flash.tags.DefineText2Tag;
import com.jpexs.decompiler.flash.tags.DefineTextTag;
import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag;
import com.jpexs.decompiler.flash.tags.ShowFrameTag;
import com.jpexs.decompiler.flash.tags.SoundStreamHead2Tag;
import com.jpexs.decompiler.flash.tags.SoundStreamHeadTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.tags.gfx.DefineCompactedFont;
import com.jpexs.decompiler.flash.treeitems.AS2PackageNodeItem;
import com.jpexs.decompiler.flash.treeitems.AS3PackageNodeItem;
import com.jpexs.decompiler.flash.treeitems.FrameNodeItem;
import com.jpexs.decompiler.flash.treeitems.SWFList;
import com.jpexs.decompiler.flash.treeitems.StringItem;
import com.jpexs.decompiler.flash.treeitems.TreeElementItem;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
import com.jpexs.decompiler.flash.treenodes.TreeNode;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JTree;
import javax.swing.plaf.basic.BasicLabelUI;
import javax.swing.plaf.basic.BasicTreeUI;
import javax.swing.tree.DefaultTreeCellRenderer;
/**
*
* @author JPEXS
*/
public class TagTree extends JTree {
public class TagTreeCellRenderer extends DefaultTreeCellRenderer {
@Override
public Component getTreeCellRendererComponent(
JTree tree,
Object value,
boolean sel,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus) {
super.getTreeCellRendererComponent(
tree, value, sel,
expanded, leaf, row,
hasFocus);
TreeNode treeNode = (TreeNode) value;
TreeItem val = treeNode.getItem();
TreeNodeType type = getTreeNodeType(val);
if (type != null) {
if (type == TreeNodeType.FOLDER && expanded) {
type = TreeNodeType.FOLDER_OPEN;
}
String itemName = type.toString();
if (type == TreeNodeType.FOLDER || type == TreeNodeType.FOLDER_OPEN) {
if (val instanceof StringItem) {
StringItem si = (StringItem) val;
if (!TagTreeRoot.FOLDER_ROOT.equals(si.getName())) {
itemName = "folder" + si.getName();
}
}
}
String tagTypeStr = itemName.toLowerCase().replace("_", "");
setIcon(View.getIcon(tagTypeStr + "16"));
}
Font font = getFont();
boolean isModified = false;
if (treeNode instanceof TreeNode) {
if (treeNode.getItem() instanceof Tag) {
Tag tag = (Tag) treeNode.getItem();
if (tag.isModified()) {
isModified = true;
}
}
}
if (isModified) {
font = font.deriveFont(Font.BOLD);
} else {
font = font.deriveFont(Font.PLAIN);
}
setFont(font);
setUI(new BasicLabelUI());
setOpaque(false);
//setBackground(Color.green);
setBackgroundNonSelectionColor(Color.white);
//setBackgroundSelectionColor(Color.ORANGE);
return this;
}
}
TagTree(TagTreeModel treeModel) {
super(treeModel);
setCellRenderer(new TagTreeCellRenderer());
setRootVisible(false);
setBackground(Color.white);
setUI(new BasicTreeUI() {
@Override
public void paint(Graphics g, JComponent c) {
setHashColor(Color.gray);
super.paint(g, c);
}
});
}
public static TreeNodeType getTreeNodeType(TreeItem t) {
if ((t instanceof DefineFontTag)
|| (t instanceof DefineFont2Tag)
|| (t instanceof DefineFont3Tag)
|| (t instanceof DefineFont4Tag)
|| (t instanceof DefineCompactedFont)) {
return TreeNodeType.FONT;
}
if ((t instanceof DefineTextTag)
|| (t instanceof DefineText2Tag)
|| (t instanceof DefineEditTextTag)) {
return TreeNodeType.TEXT;
}
if ((t instanceof DefineBitsTag)
|| (t instanceof DefineBitsJPEG2Tag)
|| (t instanceof DefineBitsJPEG3Tag)
|| (t instanceof DefineBitsJPEG4Tag)
|| (t instanceof DefineBitsLosslessTag)
|| (t instanceof DefineBitsLossless2Tag)) {
return TreeNodeType.IMAGE;
}
if ((t instanceof DefineShapeTag)
|| (t instanceof DefineShape2Tag)
|| (t instanceof DefineShape3Tag)
|| (t instanceof DefineShape4Tag)) {
return TreeNodeType.SHAPE;
}
if ((t instanceof DefineMorphShapeTag) || (t instanceof DefineMorphShape2Tag)) {
return TreeNodeType.MORPH_SHAPE;
}
if (t instanceof DefineSpriteTag) {
return TreeNodeType.SPRITE;
}
if ((t instanceof DefineButtonTag) || (t instanceof DefineButton2Tag)) {
return TreeNodeType.BUTTON;
}
if (t instanceof ASMSource) {
return TreeNodeType.AS;
}
if (t instanceof ScriptPack) {
return TreeNodeType.AS;
}
if (t instanceof AS2PackageNodeItem) {
return TreeNodeType.PACKAGE;
}
if (t instanceof AS3PackageNodeItem) {
return TreeNodeType.PACKAGE;
}
if (t instanceof FrameNodeItem) {
return TreeNodeType.FRAME;
}
if (t instanceof ShowFrameTag) {
return TreeNodeType.SHOW_FRAME;
}
if (t instanceof DefineVideoStreamTag) {
return TreeNodeType.MOVIE;
}
if ((t instanceof DefineSoundTag) || (t instanceof SoundStreamHeadTag) || (t instanceof SoundStreamHead2Tag)) {
return TreeNodeType.SOUND;
}
if (t instanceof DefineBinaryDataTag) {
return TreeNodeType.BINARY_DATA;
}
if (t instanceof SWF) {
return TreeNodeType.FLASH;
}
if (t instanceof SWFList) {
SWFList slist = (SWFList) t;
if (slist.name != null) {
if (slist.name.toLowerCase().endsWith(".zip")) {
return TreeNodeType.BUNDLE_ZIP;
}
if (slist.name.toLowerCase().endsWith(".swc")) {
return TreeNodeType.BUNDLE_SWC;
} else {
return TreeNodeType.BUNDLE_BINARY;
}
}
}
if (t instanceof Tag) {
return TreeNodeType.OTHER_TAG;
}
/*if(t instanceof StringNode){
StringNode sn=(StringNode)t;
String name = sn.getItem().getName();
if(name!=null){
switch(name){
case TagTreeModel.FOLDER_BINARY_DATA:
break;
case TagTreeModel.FOLDER_BUTTONS:
break;
case TagTreeModel.FOLDER_FONTS:
break;
case TagTreeModel.FOLDER_FRAMES:
break;
case TagTreeModel.FOLDER_IMAGES:
break;
case TagTreeModel.FOLDER_MORPHSHAPES:
break;
case TagTreeModel.FOLDER_MOVIES:
break;
case TagTreeModel.FOLDER_OTHERS:
break;
case TagTreeModel.FOLDER_SCRIPTS:
break;
case TagTreeModel.FOLDER_SHAPES:
break;
case TagTreeModel.FOLDER_SOUNDS:
break;
case TagTreeModel.FOLDER_SPRITES:
break;
case TagTreeModel.FOLDER_TEXTS:
break;
}
}
}*/
return TreeNodeType.FOLDER;
}
public List<TreeElementItem> getTagsWithType(List<TreeElementItem> list, TreeNodeType type) {
List<TreeElementItem> ret = new ArrayList<>();
for (TreeElementItem item : list) {
TreeNodeType ttype = getTreeNodeType(item);
if (type == ttype) {
ret.add(item);
}
}
return ret;
}
public TreeItem getCurrentTreeItem() {
TreeNode treeNode = (TreeNode) getLastSelectedPathComponent();
if (treeNode == null) {
return null;
}
return treeNode.getItem();
}
}
@@ -0,0 +1,460 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.gui.abc.ClassesListTreeModel;
import com.jpexs.decompiler.flash.gui.abc.treenodes.ClassesListNode;
import com.jpexs.decompiler.flash.gui.abc.treenodes.TreeElement;
import com.jpexs.decompiler.flash.gui.treenodes.SWFBundleNode;
import com.jpexs.decompiler.flash.gui.treenodes.SWFContainerNode;
import com.jpexs.decompiler.flash.gui.treenodes.SWFNode;
import com.jpexs.decompiler.flash.gui.treenodes.StringNode;
import com.jpexs.decompiler.flash.gui.treenodes.TagTreeRoot;
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
import com.jpexs.decompiler.flash.tags.ShowFrameTag;
import com.jpexs.decompiler.flash.tags.SoundStreamBlockTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag;
import com.jpexs.decompiler.flash.treeitems.FrameNodeItem;
import com.jpexs.decompiler.flash.treeitems.SWFList;
import com.jpexs.decompiler.flash.treeitems.StringItem;
import com.jpexs.decompiler.flash.treeitems.TreeElementItem;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
import com.jpexs.decompiler.flash.treenodes.FrameNode;
import com.jpexs.decompiler.flash.treenodes.TagNode;
import com.jpexs.decompiler.flash.treenodes.TreeNode;
import com.jpexs.helpers.Helper;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
public class TagTreeModel implements TreeModel {
public static final String FOLDER_TEXTS = "texts";
public static final String FOLDER_IMAGES = "images";
public static final String FOLDER_MOVIES = "movies";
public static final String FOLDER_SOUNDS = "sounds";
public static final String FOLDER_BINARY_DATA = "binaryData";
public static final String FOLDER_FONTS = "fonts";
public static final String FOLDER_SPRITES = "sprites";
public static final String FOLDER_SHAPES = "shapes";
public static final String FOLDER_MORPHSHAPES = "morphshapes";
public static final String FOLDER_BUTTONS = "buttons";
public static final String FOLDER_FRAMES = "frames";
public static final String FOLDER_OTHERS = "others";
public static final String FOLDER_SCRIPTS = "scripts";
private final TagTreeRoot root = new TagTreeRoot();
private final List<SWFContainerNode> swfs;
private final Map<SWF, SWFNode> swfToSwfNode;
private final MainFrame mainFrame;
public TagTreeModel(MainFrame mainFrame, List<SWFList> swfs) {
this.mainFrame = mainFrame;
this.swfs = new ArrayList<>();
swfToSwfNode = new HashMap<>();
for (SWFList swfList : swfs) {
if (swfList.isBundle) {
SWFBundleNode bundleNode = new SWFBundleNode(swfList, swfList.name);
for (SWF swf : swfList) {
bundleNode.swfs.add(createSwfNode(swf));
}
this.swfs.add(bundleNode);
} else {
SWF swf = swfList.get(0);
this.swfs.add(createSwfNode(swf));
}
}
}
private SWFNode createSwfNode(SWF swf) {
ClassesListTreeModel classTreeModel = new ClassesListTreeModel(swf);
SWFNode swfNode = new SWFNode(swf, swf.getShortFileName());
swfNode.list = createTagList(swf.tags, null, swf, swfNode, classTreeModel);
swfToSwfNode.put(swf, swfNode);
return swfNode;
}
private String translate(String key) {
return mainFrame.translate(key);
}
private List<TreeNode> createTagList(List<Tag> list, Tag parent, SWF swf, SWFNode swfNode, ClassesListTreeModel classTreeModel) {
boolean hasAbc = swf.abcList != null && !swf.abcList.isEmpty();
List<TreeNode> ret = new ArrayList<>();
List<TreeNode> frames = new ArrayList<>();
List<TreeNode> shapes = new ArrayList<>();
List<TreeNode> morphShapes = new ArrayList<>();
List<TreeNode> sprites = new ArrayList<>();
List<TreeNode> buttons = new ArrayList<>();
List<TreeNode> images = new ArrayList<>();
List<TreeNode> fonts = new ArrayList<>();
List<TreeNode> texts = new ArrayList<>();
List<TreeNode> movies = new ArrayList<>();
List<TreeNode> sounds = new ArrayList<>();
List<TreeNode> binaryData = new ArrayList<>();
List<TreeNode> others = new ArrayList<>();
List<TreeNode> actionScript = SWF.createASTagList(list, null);
List<Tag> actionScriptTags = new ArrayList<>();
SWF.getTagsFromTreeNodes(actionScript, actionScriptTags);
int frameCnt = 0;
for (Tag t : list) {
TreeNodeType ttype = TagTree.getTreeNodeType(t);
switch (ttype) {
case SHOW_FRAME:
ShowFrameTag showFrameTag = (ShowFrameTag) t;
frames.add(new FrameNode(new FrameNodeItem(t.getSwf(), ++frameCnt, parent, showFrameTag, true), showFrameTag.innerTags, false));
break;
case SHAPE:
shapes.add(new TagNode(t));
break;
case MORPH_SHAPE:
morphShapes.add(new TagNode(t));
break;
case SPRITE:
sprites.add(new TagNode(t));
break;
case BUTTON:
buttons.add(new TagNode(t));
break;
case IMAGE:
images.add(new TagNode(t));
break;
case FONT:
fonts.add(new TagNode(t));
break;
case TEXT:
texts.add(new TagNode(t));
break;
case MOVIE:
movies.add(new TagNode(t));
break;
case SOUND:
sounds.add(new TagNode(t));
break;
case BINARY_DATA:
TagNode bt;
binaryData.add(bt = new TagNode(t));
DefineBinaryDataTag b=(DefineBinaryDataTag)t;
try {
SWF bswf=new SWF(new ByteArrayInputStream(b.binaryData),Configuration.parallelSpeedUp.get());
bswf.fileTitle = "(SWF Data)";
SWFNode snode=createSwfNode(bswf);
snode.binaryData = b;
bt.subNodes.add(snode);
} catch (IOException | InterruptedException ex) {
//ignore
}
break;
default:
if (!actionScriptTags.contains(t) && !ShowFrameTag.isNestedTagType(t.getId())) {
others.add(new TagNode(t));
}
break;
}
}
for (int i = 0; i < sounds.size(); i++) {
if (sounds.get(i).getItem() instanceof SoundStreamHeadTypeTag) {
List<SoundStreamBlockTag> blocks = ((SoundStreamHeadTypeTag) sounds.get(i).getItem()).getBlocks();
if (blocks.isEmpty()) {
sounds.remove(i);
i--;
}
}
}
for (TreeNode n : sprites) {
Tag tag = n.getItem() instanceof Tag ? (Tag) n.getItem() : null;
n.subNodes = createSubTagList(((DefineSpriteTag) n.getItem()).subTags, tag, swf, actionScriptTags);
}
StringNode textsNode = new StringNode(new StringItem(translate("node.texts"), FOLDER_TEXTS, swf));
textsNode.subNodes.addAll(texts);
StringNode imagesNode = new StringNode(new StringItem(translate("node.images"), FOLDER_IMAGES, swf));
imagesNode.subNodes.addAll(images);
StringNode moviesNode = new StringNode(new StringItem(translate("node.movies"), FOLDER_MOVIES, swf));
moviesNode.subNodes.addAll(movies);
StringNode soundsNode = new StringNode(new StringItem(translate("node.sounds"), FOLDER_SOUNDS, swf));
soundsNode.subNodes.addAll(sounds);
StringNode binaryDataNode = new StringNode(new StringItem(translate("node.binaryData"), FOLDER_BINARY_DATA, swf));
binaryDataNode.subNodes.addAll(binaryData);
StringNode fontsNode = new StringNode(new StringItem(translate("node.fonts"), FOLDER_FONTS, swf));
fontsNode.subNodes.addAll(fonts);
StringNode spritesNode = new StringNode(new StringItem(translate("node.sprites"), FOLDER_SPRITES, swf));
spritesNode.subNodes.addAll(sprites);
StringNode shapesNode = new StringNode(new StringItem(translate("node.shapes"), FOLDER_SHAPES, swf));
shapesNode.subNodes.addAll(shapes);
StringNode morphShapesNode = new StringNode(new StringItem(translate("node.morphshapes"), FOLDER_MORPHSHAPES, swf));
morphShapesNode.subNodes.addAll(morphShapes);
StringNode buttonsNode = new StringNode(new StringItem(translate("node.buttons"), FOLDER_BUTTONS, swf));
buttonsNode.subNodes.addAll(buttons);
StringNode framesNode = new StringNode(new StringItem(translate("node.frames"), FOLDER_FRAMES, swf));
framesNode.subNodes.addAll(frames);
StringNode otherNode = new StringNode(new StringItem(translate("node.others"), FOLDER_OTHERS, swf));
otherNode.subNodes.addAll(others);
TreeNode actionScriptNode;
if (hasAbc) {
actionScriptNode = new ClassesListNode(classTreeModel);
} else {
actionScriptNode = new StringNode(new StringItem(translate("node.scripts"), FOLDER_SCRIPTS, swf));
actionScriptNode.subNodes.addAll(actionScript);
}
swfNode.scriptsNode = actionScriptNode;
if (!shapesNode.subNodes.isEmpty()) {
ret.add(shapesNode);
}
if (!morphShapesNode.subNodes.isEmpty()) {
ret.add(morphShapesNode);
}
if (!spritesNode.subNodes.isEmpty()) {
ret.add(spritesNode);
}
if (!textsNode.subNodes.isEmpty()) {
ret.add(textsNode);
}
if (!imagesNode.subNodes.isEmpty()) {
ret.add(imagesNode);
}
if (!moviesNode.subNodes.isEmpty()) {
ret.add(moviesNode);
}
if (!soundsNode.subNodes.isEmpty()) {
ret.add(soundsNode);
}
if (!buttonsNode.subNodes.isEmpty()) {
ret.add(buttonsNode);
}
if (!fontsNode.subNodes.isEmpty()) {
ret.add(fontsNode);
}
if (!binaryDataNode.subNodes.isEmpty()) {
ret.add(binaryDataNode);
}
if (!framesNode.subNodes.isEmpty()) {
ret.add(framesNode);
}
if (!otherNode.subNodes.isEmpty()) {
ret.add(otherNode);
}
if ((!actionScriptNode.subNodes.isEmpty()) || hasAbc) {
ret.add(actionScriptNode);
}
return ret;
}
private List<TreeNode> createSubTagList(List<Tag> list, Tag parent, SWF swf, List<Tag> actionScriptTags) {
List<TreeNode> ret = new ArrayList<>();
List<TreeNode> frames = new ArrayList<>();
List<TreeNode> others = new ArrayList<>();
int frameCnt = 0;
for (Tag t : list) {
TreeNodeType ttype = TagTree.getTreeNodeType(t);
switch (ttype) {
case SHOW_FRAME:
ShowFrameTag showFrameTag = (ShowFrameTag) t;
frames.add(new FrameNode(new FrameNodeItem(t.getSwf(), ++frameCnt, parent, showFrameTag, true), showFrameTag.innerTags, false));
break;
default:
if (!actionScriptTags.contains(t) && !ShowFrameTag.isNestedTagType(t.getId())) {
if (!(t instanceof SoundStreamHeadTypeTag)) {
others.add(new TagNode(t));
}
}
break;
}
}
ret.addAll(frames);
if (!others.isEmpty()) {
StringNode otherNode = new StringNode(new StringItem(translate("node.others"), FOLDER_OTHERS, swf));
otherNode.subNodes.addAll(others);
ret.add(otherNode);
}
return ret;
}
private List<TreeNode> searchTag(TreeItem obj, TreeNode parent, List<TreeNode> path) {
List<TreeNode> ret = null;
int cnt = getChildCount(parent);
for (int i = 0; i < cnt; i++) {
TreeNode n = getChild(parent, i);
List<TreeNode> newPath = new ArrayList<>();
newPath.addAll(path);
newPath.add(n);
if (n instanceof TreeElement) {
TreeElement te = (TreeElement) n;
TreeElementItem it = te.getItem();
if (obj == it) {
return newPath;
}
}
if (n instanceof TreeNode) {
TreeNode nd = (TreeNode) n;
if (obj instanceof StringItem && nd.getItem() instanceof StringItem) {
// StringItems are always recreated, so compare them by name
StringItem nds = (StringItem) nd.getItem();
StringItem objs = (StringItem) obj;
if (objs.getName().equals(nds.getName())) {
return newPath;
}
} else {
if (nd.getItem() == obj) {
return newPath;
}
}
}
ret = searchTag(obj, n, newPath);
if (ret != null) {
return ret;
}
}
return ret;
}
public SWFNode getSwfNode(SWF swf) {
return swfToSwfNode.get(swf);
}
public TreePath getTagPath(TreeItem obj) {
List<TreeNode> path = new ArrayList<>();
path.add(getRoot());
path = searchTag(obj, getRoot(), path);
if (path == null) {
return null;
}
TreePath tp = new TreePath(path.toArray(new Object[path.size()]));
return tp;
}
@Override
public TreeNode getRoot() {
return root;
}
@Override
public TreeNode getChild(Object parent, int index) {
TreeNode parentNode = (TreeNode) parent;
if (parent instanceof TreeElement) {
return ((TreeElement) parent).getChild(index);
} else {
if (parentNode.getItem() instanceof ClassesListTreeModel) {
ClassesListTreeModel clt = (ClassesListTreeModel) parentNode.getItem();
return clt.getChild(clt.getRoot(), index);
}
}
if (parent == root) {
return swfs.get(index);
} else if (parent instanceof SWFBundleNode) {
return ((SWFBundleNode) parent).swfs.get(index);
} else if (parent instanceof SWFNode) {
return ((SWFNode) parent).list.get(index);
}
return parentNode.subNodes.get(index);
}
@Override
public int getChildCount(Object parent) {
TreeNode parentNode = (TreeNode) parent;
if (parent == root) {
return swfs.size();
} else if (parent instanceof TreeElement) {
return ((TreeElement) parent).getChildCount();
} else if (parent instanceof SWFBundleNode) {
return ((SWFBundleNode) parent).swfs.size();
} else if (parent instanceof SWFNode) {
return ((SWFNode) parent).list.size();
} else {
if (parentNode.getItem() instanceof ClassesListTreeModel) {
ClassesListTreeModel clt = (ClassesListTreeModel) parentNode.getItem();
return clt.getChildCount(clt.getRoot());
}
return parentNode.subNodes.size();
}
}
@Override
public boolean isLeaf(Object node) {
return (getChildCount(node) == 0);
}
@Override
public void valueForPathChanged(TreePath path, Object newValue) {
}
@Override
public int getIndexOfChild(Object parent, Object child) {
TreeNode parentNode = (TreeNode) parent;
if (parent == root) {
return swfs.indexOf(child);
} else if (parent instanceof TreeElement) {
return ((TreeElement) parent).getIndexOfChild((TreeElement) child);
} else if (parent instanceof SWFBundleNode) {
return ((SWFBundleNode) parent).swfs.indexOf(child);
} else if (parent instanceof SWFNode) {
return ((SWFNode) parent).list.indexOf(child);
} else {
if (parentNode.getItem() instanceof ClassesListTreeModel) {
ClassesListTreeModel clt = (ClassesListTreeModel) parentNode.getItem();
return clt.getIndexOfChild(clt.getRoot(), child);
}
return parentNode.subNodes.indexOf(child);
}
}
@Override
public void addTreeModelListener(TreeModelListener l) {
}
@Override
public void removeTreeModelListener(TreeModelListener l) {
}
}
@@ -0,0 +1,133 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.gui.abc.LineMarkedEditorPane;
import com.jpexs.decompiler.flash.tags.base.TextTag;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
/**
*
* @author JPEXS
*/
public class TextPanel extends JPanel implements ActionListener {
private static final String ACTION_EDIT_TEXT = "EDITTEXT";
private static final String ACTION_CANCEL_TEXT = "CANCELTEXT";
private static final String ACTION_SAVE_TEXT = "SAVETEXT";
private final MainPanel mainPanel;
private final SearchPanel<TextTag> textSearchPanel;
private final LineMarkedEditorPane textValue;
private final JButton textSaveButton;
private final JButton textEditButton;
private final JButton textCancelButton;
public TextPanel(MainPanel mainPanel) {
super(new BorderLayout());
this.mainPanel = mainPanel;
textSearchPanel = new SearchPanel<>(new FlowLayout(), mainPanel);
add(textSearchPanel, BorderLayout.NORTH);
textValue = new LineMarkedEditorPane();
add(new JScrollPane(textValue), BorderLayout.CENTER);
textValue.setEditable(false);
JPanel textButtonsPanel = new JPanel();
textButtonsPanel.setLayout(new FlowLayout());
textSaveButton = new JButton(mainPanel.translate("button.save"), View.getIcon("save16"));
textSaveButton.setMargin(new Insets(3, 3, 3, 10));
textSaveButton.setActionCommand(ACTION_SAVE_TEXT);
textSaveButton.addActionListener(this);
textEditButton = new JButton(mainPanel.translate("button.edit"), View.getIcon("edit16"));
textEditButton.setMargin(new Insets(3, 3, 3, 10));
textEditButton.setActionCommand(ACTION_EDIT_TEXT);
textEditButton.addActionListener(this);
textCancelButton = new JButton(mainPanel.translate("button.cancel"), View.getIcon("cancel16"));
textCancelButton.setMargin(new Insets(3, 3, 3, 10));
textCancelButton.setActionCommand(ACTION_CANCEL_TEXT);
textCancelButton.addActionListener(this);
textButtonsPanel.add(textEditButton);
textButtonsPanel.add(textSaveButton);
textButtonsPanel.add(textCancelButton);
textSaveButton.setVisible(false);
textCancelButton.setVisible(false);
add(textButtonsPanel, BorderLayout.SOUTH);
}
public SearchPanel<TextTag> getSearchPanel() {
return textSearchPanel;
}
public void setText(String text) {
textValue.setContentType("text/swf_text");
// textValue.setFont(new Font("Monospaced", Font.PLAIN, 13));
textValue.setText(text);
textValue.setCaretPosition(0);
}
public void setEditText(boolean edit) {
textValue.setEditable(edit);
textSaveButton.setVisible(edit);
textEditButton.setVisible(!edit);
textCancelButton.setVisible(edit);
}
public void updateSearchPos() {
textValue.setCaretPosition(0);
textSearchPanel.showQuickFindDialog(textValue);
}
@Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case ACTION_EDIT_TEXT:
setEditText(true);
break;
case ACTION_CANCEL_TEXT:
setEditText(false);
mainPanel.reload(true);
break;
case ACTION_SAVE_TEXT:
TreeItem item = mainPanel.tagTree.getCurrentTreeItem();
if (item instanceof TextTag) {
TextTag textTag = (TextTag) item;
if (mainPanel.saveText(textTag, textValue.getText(), null)) {
setEditText(false);
mainPanel.reload(true);
}
SWF.clearImageCache();
}
break;
}
}
}
@@ -0,0 +1,46 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
/**
*
* @author JPEXS
*/
public enum TreeNodeType {
FLASH,
FONT,
TEXT,
IMAGE,
SHAPE,
MORPH_SHAPE,
SPRITE,
BUTTON,
AS,
PACKAGE,
FRAME,
SHOW_FRAME,
MOVIE,
SOUND,
BINARY_DATA,
OTHER_TAG,
FOLDER,
FOLDER_OPEN,
BUNDLE_ZIP,
BUNDLE_SWC,
BUNDLE_BINARY
}
@@ -0,0 +1,502 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.AppStrings;
import com.jpexs.decompiler.flash.configuration.ConfigurationItem;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.TexturePaint;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.plaf.FontUIResource;
import javax.swing.plaf.basic.BasicColorChooserUI;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import org.pushingpixels.flamingo.api.common.icon.ImageWrapperResizableIcon;
import org.pushingpixels.substance.api.ComponentState;
import org.pushingpixels.substance.api.SubstanceColorScheme;
import org.pushingpixels.substance.api.SubstanceConstants;
import org.pushingpixels.substance.api.SubstanceLookAndFeel;
import org.pushingpixels.substance.api.fonts.FontPolicy;
import org.pushingpixels.substance.api.fonts.FontSet;
import org.pushingpixels.substance.api.skin.SubstanceOfficeBlue2007LookAndFeel;
import org.pushingpixels.substance.internal.utils.SubstanceColorSchemeUtilities;
/**
* Contains methods for GUI
*
* @author JPEXS
*/
public class View {
public static final Color DEFAULT_BACKGROUND_COLOR = new Color(217, 231, 250);
public static Color swfBackgroundColor = DEFAULT_BACKGROUND_COLOR;
private static final BufferedImage transparentTexture;
public static final TexturePaint transparentPaint;
private static final Color transparentColor1 = new Color(0x99, 0x99, 0x99);
private static final Color transparentColor2 = new Color(0x66, 0x66, 0x66);
static {
transparentTexture = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
Graphics g = transparentTexture.getGraphics();
g.setColor(transparentColor1);
g.fillRect(0, 0, 16, 16);
g.setColor(transparentColor2);
g.fillRect(0, 0, 8, 8);
g.fillRect(8, 8, 8, 8);
transparentPaint = new TexturePaint(View.transparentTexture, new Rectangle(0, 0, transparentTexture.getWidth(), transparentTexture.getHeight()));
}
/**
* Sets windows Look and Feel
*/
public static void setLookAndFeel() {
//Save default font for Chinese characters
final Font defaultFont = (new JLabel()).getFont();
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException ignored) {
}
execInEventDispatch(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(new SubstanceOfficeBlue2007LookAndFeel());
UIManager.put(SubstanceLookAndFeel.COLORIZATION_FACTOR, 0.999);//This works for not changing labels color and not changing Dialogs title
UIManager.put("Tree.expandedIcon", getIcon("expand16"));
UIManager.put("Tree.collapsedIcon", getIcon("collapse16"));
UIManager.put("ColorChooserUI", BasicColorChooserUI.class.getName());
UIManager.put("ColorChooser.swatchesRecentSwatchSize", new Dimension(20, 20));
UIManager.put("ColorChooser.swatchesSwatchSize", new Dimension(20, 20));
UIManager.put("RibbonApplicationMenuPopupPanelUI", MyRibbonApplicationMenuPopupPanelUI.class.getName());
UIManager.put("RibbonApplicationMenuButtonUI", MyRibbonApplicationMenuButtonUI.class.getName());
UIManager.put("ProgressBarUI", MyProgressBarUI.class.getName());
UIManager.put("TextField.background", Color.WHITE);
UIManager.put("FormattedTextField.background", Color.WHITE);
UIManager.put("CommandButtonUI", MyCommandButtonUI.class.getName());
FontPolicy pol = SubstanceLookAndFeel.getFontPolicy();
final FontSet fs = pol.getFontSet("Substance", null);
//Restore default font for chinese characters
SubstanceLookAndFeel.setFontPolicy(new FontPolicy() {
private final FontSet fontSet = new FontSet() {
private FontUIResource controlFont;
private FontUIResource menuFont;
private FontUIResource titleFont;
private FontUIResource windowTitleFont;
private FontUIResource smallFont;
private FontUIResource messageFont;
@Override
public FontUIResource getControlFont() {
if (controlFont == null) {
FontUIResource f = fs.getControlFont();
controlFont = new FontUIResource(defaultFont.getName(), f.getStyle(), f.getSize());
}
return controlFont;
}
@Override
public FontUIResource getMenuFont() {
if (menuFont == null) {
FontUIResource f = fs.getMenuFont();
menuFont = new FontUIResource(defaultFont.getName(), f.getStyle(), f.getSize());
}
return menuFont;
}
@Override
public FontUIResource getTitleFont() {
if (titleFont == null) {
FontUIResource f = fs.getTitleFont();
titleFont = new FontUIResource(defaultFont.getName(), f.getStyle(), f.getSize());
}
return titleFont;
}
@Override
public FontUIResource getWindowTitleFont() {
if (windowTitleFont == null) {
FontUIResource f = fs.getWindowTitleFont();
windowTitleFont = new FontUIResource(defaultFont.getName(), f.getStyle(), f.getSize());
}
return windowTitleFont;
}
@Override
public FontUIResource getSmallFont() {
if (smallFont == null) {
FontUIResource f = fs.getSmallFont();
smallFont = new FontUIResource(defaultFont.getName(), f.getStyle(), f.getSize());
}
return smallFont;
}
@Override
public FontUIResource getMessageFont() {
if (messageFont == null) {
FontUIResource f = fs.getMessageFont();
messageFont = new FontUIResource(defaultFont.getName(), f.getStyle(), f.getSize());
}
return messageFont;
}
};
@Override
public FontSet getFontSet(String string, UIDefaults uid) {
return fontSet;
}
});
} catch (UnsupportedLookAndFeelException ex) {
Logger.getLogger(View.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
UIManager.put(SubstanceLookAndFeel.TABBED_PANE_CONTENT_BORDER_KIND, SubstanceConstants.TabContentPaneBorderKind.SINGLE_FULL);
JFrame.setDefaultLookAndFeelDecorated(true);
JDialog.setDefaultLookAndFeelDecorated(true);
}
/**
* Loads image from resources
*
* @param name Name of the image
* @return loaded Image
*/
public static BufferedImage loadImage(String name) {
java.net.URL imageURL = View.class.getResource("/com/jpexs/decompiler/flash/gui/graphics/" + name + ".png");
try {
return ImageIO.read(imageURL);
} catch (IOException ex) {
return null;
}
}
/**
* Sets icon of specified frame to ASDec icon
*
* @param f Frame to set icon in
*/
public static void setWindowIcon(Window f) {
java.util.List<Image> images = new ArrayList<>();
images.add(loadImage("icon16"));
images.add(loadImage("icon32"));
images.add(loadImage("icon48"));
images.add(loadImage("icon256"));
f.setIconImages(images);
}
/**
* Centers specified frame on the screen
*
* @param f Frame to center on the screen
*/
public static void centerScreen(Window f) {
centerScreen(f, 0); // todo, set screen to the currently active screen instead of the first screen in a multi screen setup, (maybe by using the screen where the main window is now classic or ribbon?)
}
public static void centerScreen(Window f, int screen) {
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] allDevices = env.getScreenDevices();
int topLeftX, topLeftY, screenX, screenY, windowPosX, windowPosY;
if (screen < allDevices.length && screen > -1) {
topLeftX = allDevices[screen].getDefaultConfiguration().getBounds().x;
topLeftY = allDevices[screen].getDefaultConfiguration().getBounds().y;
screenX = allDevices[screen].getDefaultConfiguration().getBounds().width;
screenY = allDevices[screen].getDefaultConfiguration().getBounds().height;
} else {
topLeftX = allDevices[0].getDefaultConfiguration().getBounds().x;
topLeftY = allDevices[0].getDefaultConfiguration().getBounds().y;
screenX = allDevices[0].getDefaultConfiguration().getBounds().width;
screenY = allDevices[0].getDefaultConfiguration().getBounds().height;
}
windowPosX = ((screenX - f.getWidth()) / 2) + topLeftX;
windowPosY = ((screenY - f.getHeight()) / 2) + topLeftY;
f.setLocation(windowPosX, windowPosY);
}
public static ImageIcon getIcon(String name) {
return new ImageIcon(View.class.getClassLoader().getResource("com/jpexs/decompiler/flash/gui/graphics/" + name + ".png"));
}
private static final KeyStroke escapeStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
private static final String dispatchWindowClosingActionMapKey = "com.jpexs.dispatch:WINDOW_CLOSING";
public static void installEscapeCloseOperation(final JDialog dialog) {
Action dispatchClosing = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent event) {
dialog.dispatchEvent(new WindowEvent(
dialog, WindowEvent.WINDOW_CLOSING));
}
};
JRootPane root = dialog.getRootPane();
root.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
escapeStroke, dispatchWindowClosingActionMapKey);
root.getActionMap().put(dispatchWindowClosingActionMapKey, dispatchClosing);
}
public static ImageWrapperResizableIcon getResizableIcon(String resource) {
return ImageWrapperResizableIcon.getIcon(View.class.getResource("/com/jpexs/decompiler/flash/gui/graphics/" + resource + ".png"), new Dimension(256, 256));
}
public static MyResizableIcon getMyResizableIcon(String resource) {
try {
return new MyResizableIcon(ImageIO.read(View.class.getResourceAsStream("/com/jpexs/decompiler/flash/gui/graphics/" + resource + ".png")));
} catch (IOException ex) {
Logger.getLogger(View.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
public static void execInEventDispatch(Runnable r) {
if (SwingUtilities.isEventDispatchThread()) {
r.run();
} else {
try {
SwingUtilities.invokeAndWait(r);
} catch (InterruptedException ex) {
} catch (InvocationTargetException ex) {
Logger.getLogger(View.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public static void execInEventDispatchLater(Runnable r) {
if (SwingUtilities.isEventDispatchThread()) {
r.run();
} else {
SwingUtilities.invokeLater(r);
}
}
public static int showOptionDialog(final Component parentComponent, final Object message, final String title, final int optionType, final int messageType, final Icon icon, final Object[] options, final Object initialValue) {
final int[] ret = new int[1];
execInEventDispatch(new Runnable() {
@Override
public void run() {
ret[0] = JOptionPane.showOptionDialog(parentComponent, message, title, optionType, messageType, icon, options, initialValue);
}
});
return ret[0];
}
public static int showConfirmDialog(final Component parentComponent, final Object message, final String title, final int optionType) {
return showConfirmDialog(parentComponent, message, title, optionType, JOptionPane.PLAIN_MESSAGE);
}
public static int showConfirmDialog(final Component parentComponent, final Object message, final String title, final int optionType, final int messageTyp) {
final int ret[] = new int[1];
execInEventDispatch(new Runnable() {
@Override
public void run() {
ret[0] = JOptionPane.showConfirmDialog(parentComponent, message, title, optionType, messageTyp);
}
});
return ret[0];
}
public static int showConfirmDialog(final Component parentComponent, String message, final String title, final int optionType, final int messageTyp, ConfigurationItem<Boolean> showAgainConfig, int defaultOption) {
JLabel warLabel = new JLabel(message);
final JPanel warPanel = new JPanel(new BorderLayout());
warPanel.add(warLabel, BorderLayout.CENTER);
JCheckBox donotShowAgainCheckBox = new JCheckBox(AppStrings.translate("message.confirm.donotshowagain"));
donotShowAgainCheckBox.setSelected(!showAgainConfig.get());
warPanel.add(donotShowAgainCheckBox, BorderLayout.SOUTH);
if (donotShowAgainCheckBox.isSelected()) {
return defaultOption;
}
final int ret[] = new int[1];
execInEventDispatch(new Runnable() {
@Override
public void run() {
ret[0] = JOptionPane.showConfirmDialog(parentComponent, warPanel, title, optionType, messageTyp);
}
});
showAgainConfig.set(!donotShowAgainCheckBox.isSelected());
return ret[0];
}
public static void showMessageDialog(final Component parentComponent, final Object message, final String title, final int messageType) {
execInEventDispatch(new Runnable() {
@Override
public void run() {
JOptionPane.showMessageDialog(parentComponent, message, title, messageType);
}
});
}
public static void showMessageDialog(final Component parentComponent, final Object message) {
execInEventDispatch(new Runnable() {
@Override
public void run() {
JOptionPane.showMessageDialog(parentComponent, message);
}
});
}
public static String showInputDialog(final Object message, final Object initialSelection) {
final String[] ret = new String[1];
execInEventDispatch(new Runnable() {
@Override
public void run() {
ret[0] = JOptionPane.showInputDialog(message, initialSelection);
}
});
return ret[0];
}
public static SubstanceColorScheme getColorScheme() {
return SubstanceColorSchemeUtilities.getActiveColorScheme(new JButton(), ComponentState.ENABLED);
}
public static void refreshTree(JTree tree, TreeModel model) {
List<List<String>> expandedNodes = getExpandedNodes(tree);
tree.setModel(model);
expandTreeNodes(tree, expandedNodes);
}
private static List<List<String>> getExpandedNodes(JTree tree) {
List<List<String>> expandedNodes = new ArrayList<>();
int rowCount = tree.getRowCount();
for (int i = 0; i < rowCount; i++) {
TreePath path = tree.getPathForRow(i);
if (tree.isExpanded(path)) {
List<String> pathAsStringList = new ArrayList<>();
for (Object pathCompnent : path.getPath()) {
pathAsStringList.add(pathCompnent.toString());
}
expandedNodes.add(pathAsStringList);
}
}
return expandedNodes;
}
private static void expandTreeNodes(JTree tree, List<List<String>> pathsToExpand) {
for (List<String> pathAsStringList : pathsToExpand) {
expandTreeNode(tree, pathAsStringList);
}
}
private static void expandTreeNode(JTree tree, List<String> pathAsStringList) {
TreeModel model = tree.getModel();
Object node = model.getRoot();
if (pathAsStringList.isEmpty()) {
return;
}
if (!pathAsStringList.get(0).equals(node.toString())) {
return;
}
List<Object> path = new ArrayList<>();
path.add(node);
for (int i = 1; i < pathAsStringList.size(); i++) {
String name = pathAsStringList.get(i);
int childCount = model.getChildCount(node);
for (int j = 0; j < childCount; j++) {
Object child = model.getChild(node, j);
if (child.toString().equals(name)) {
node = child;
path.add(node);
break;
}
}
}
TreePath tp = new TreePath(path.toArray(new Object[path.size()]));
tree.expandPath(tp);
}
public static void expandTreeNodesRecursive(JTree tree, TreePath parent, boolean expand) {
TreeModel model = tree.getModel();
Object node = parent.getLastPathComponent();
int childCount = model.getChildCount(node);
for (int j = 0; j < childCount; j++) {
Object child = model.getChild(node, j);
TreePath path = parent.pathByAddingChild(child);
expandTreeNodesRecursive(tree, path, expand);
}
if (expand) {
tree.expandPath(parent);
} else {
tree.collapsePath(parent);
}
}
}
@@ -0,0 +1,196 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui;
/**
*
* @author JPEXS
*/
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Insets;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
/**
* FlowLayout subclass that fully supports wrapping of components.
*
* Taken from: http://tips4java.wordpress.com/2008/11/06/wrap-layout/
*/
public class WrapLayout extends FlowLayout {
private Dimension preferredLayoutSize;
/**
* Constructs a new <code>WrapLayout</code> with a left alignment and a
* default 5-unit horizontal and vertical gap.
*/
public WrapLayout() {
super();
}
/**
* Constructs a new <code>FlowLayout</code> with the specified alignment and
* a default 5-unit horizontal and vertical gap. The value of the alignment
* argument must be one of <code>WrapLayout</code>, <code>WrapLayout</code>,
* or <code>WrapLayout</code>.
*
* @param align the alignment value
*/
public WrapLayout(int align) {
super(align);
}
/**
* Creates a new flow layout manager with the indicated alignment and the
* indicated horizontal and vertical gaps.
* <p>
* The value of the alignment argument must be one of
* <code>WrapLayout</code>, <code>WrapLayout</code>, or
* <code>WrapLayout</code>.
*
* @param align the alignment value
* @param hgap the horizontal gap between components
* @param vgap the vertical gap between components
*/
public WrapLayout(int align, int hgap, int vgap) {
super(align, hgap, vgap);
}
/**
* Returns the preferred dimensions for this layout given the
* <i>visible</i> components in the specified target container.
*
* @param target the component which needs to be laid out
* @return the preferred dimensions to lay out the subcomponents of the
* specified container
*/
@Override
public Dimension preferredLayoutSize(Container target) {
return layoutSize(target, true);
}
/**
* Returns the minimum dimensions needed to layout the <i>visible</i>
* components contained in the specified target container.
*
* @param target the component which needs to be laid out
* @return the minimum dimensions to lay out the subcomponents of the
* specified container
*/
@Override
public Dimension minimumLayoutSize(Container target) {
Dimension minimum = layoutSize(target, false);
minimum.width -= (getHgap() + 1);
return minimum;
}
/**
* Returns the minimum or preferred dimension needed to layout the target
* container.
*
* @param target target to get layout size for
* @param preferred should preferred size be calculated
* @return the dimension to layout the target container
*/
private Dimension layoutSize(Container target, boolean preferred) {
synchronized (target.getTreeLock()) {
// Each row must fit with the width allocated to the containter.
// When the container width = 0, the preferred width of the container
// has not yet been calculated so lets ask for the maximum.
int targetWidth = target.getSize().width;
if (targetWidth == 0) {
targetWidth = Integer.MAX_VALUE;
}
int hgap = getHgap();
int vgap = getVgap();
Insets insets = target.getInsets();
int horizontalInsetsAndGap = insets.left + insets.right + (hgap * 2);
int maxWidth = targetWidth - horizontalInsetsAndGap;
// Fit components into the allowed width
Dimension dim = new Dimension(0, 0);
int rowWidth = 0;
int rowHeight = 0;
int nmembers = target.getComponentCount();
for (int i = 0; i < nmembers; i++) {
Component m = target.getComponent(i);
if (m.isVisible()) {
Dimension d = preferred ? m.getPreferredSize() : m.getMinimumSize();
// Can't add the component to current row. Start a new row.
if (rowWidth + d.width > maxWidth) {
addRow(dim, rowWidth, rowHeight);
rowWidth = 0;
rowHeight = 0;
}
// Add a horizontal gap for all components after the first
if (rowWidth != 0) {
rowWidth += hgap;
}
rowWidth += d.width;
rowHeight = Math.max(rowHeight, d.height);
}
}
addRow(dim, rowWidth, rowHeight);
dim.width += horizontalInsetsAndGap;
dim.height += insets.top + insets.bottom + vgap * 2;
// When using a scroll pane or the DecoratedLookAndFeel we need to
// make sure the preferred size is less than the size of the
// target containter so shrinking the container size works
// correctly. Removing the horizontal gap is an easy way to do this.
Container scrollPane = SwingUtilities.getAncestorOfClass(JScrollPane.class, target);
if (scrollPane != null && target.isValid()) {
dim.width -= (hgap + 1);
}
return dim;
}
}
/*
* A new row has been completed. Use the dimensions of this row
* to update the preferred size for the container.
*
* @param dim update the width and height when appropriate
* @param rowWidth the width of the row to add
* @param rowHeight the height of the row to add
*/
private void addRow(Dimension dim, int rowWidth, int rowHeight) {
dim.width = Math.max(dim.width, rowWidth);
if (dim.height > 0) {
dim.height += getVgap();
}
dim.height += rowHeight;
}
}
@@ -0,0 +1,70 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import java.util.Collections;
import java.util.List;
import javax.swing.ComboBoxModel;
import javax.swing.event.ListDataListener;
public class ABCComboBoxModel implements ComboBoxModel<ABCContainerTag> {
public List<ABCContainerTag> list;
public int itemIndex = 0;
public static final ABCContainerTag ROOT = new RootABCContainerTag();
public ABCComboBoxModel(List<ABCContainerTag> list) {
this.list = list;
Collections.sort(this.list);
}
@Override
public int getSize() {
return 1 + list.size();
}
@Override
public ABCContainerTag getElementAt(int index) {
if (index == 0) {
return ROOT;
}
return list.get(index - 1);
}
@Override
public void addListDataListener(ListDataListener l) {
}
@Override
public void removeListDataListener(ListDataListener l) {
}
@Override
public void setSelectedItem(Object anItem) {
if (anItem == ROOT) {
itemIndex = 0;
} else {
itemIndex = 1 + list.indexOf(anItem);
}
}
@Override
public ABCContainerTag getSelectedItem() {
return getElementAt(itemIndex);
}
}
@@ -0,0 +1,818 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.AppStrings;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.ClassPath;
import com.jpexs.decompiler.flash.abc.ScriptPack;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocal0Ins;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnVoidIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushScopeIns;
import com.jpexs.decompiler.flash.abc.avm2.parser.ParseException;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.ActionScriptParser;
import com.jpexs.decompiler.flash.abc.types.ABCException;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.flash.abc.types.Multiname;
import com.jpexs.decompiler.flash.abc.types.Namespace;
import com.jpexs.decompiler.flash.abc.types.ValueKind;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter;
import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst;
import com.jpexs.decompiler.flash.abc.types.traits.Traits;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.gui.HeaderLabel;
import com.jpexs.decompiler.flash.gui.Main;
import com.jpexs.decompiler.flash.gui.MainPanel;
import com.jpexs.decompiler.flash.gui.SearchListener;
import com.jpexs.decompiler.flash.gui.SearchPanel;
import com.jpexs.decompiler.flash.gui.TagTreeModel;
import com.jpexs.decompiler.flash.gui.View;
import com.jpexs.decompiler.flash.gui.abc.tablemodels.DecimalTableModel;
import com.jpexs.decompiler.flash.gui.abc.tablemodels.DoubleTableModel;
import com.jpexs.decompiler.flash.gui.abc.tablemodels.IntTableModel;
import com.jpexs.decompiler.flash.gui.abc.tablemodels.MultinameTableModel;
import com.jpexs.decompiler.flash.gui.abc.tablemodels.NamespaceSetTableModel;
import com.jpexs.decompiler.flash.gui.abc.tablemodels.NamespaceTableModel;
import com.jpexs.decompiler.flash.gui.abc.tablemodels.StringTableModel;
import com.jpexs.decompiler.flash.gui.abc.tablemodels.UIntTableModel;
import com.jpexs.decompiler.flash.helpers.Freed;
import com.jpexs.decompiler.flash.helpers.collections.MyEntry;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.decompiler.flash.tags.SymbolClassTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.treenodes.TreeNode;
import com.jpexs.decompiler.graph.CompilationException;
import com.jpexs.helpers.CancellableWorker;
import com.jpexs.helpers.Helper;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JToggleButton;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.BevelBorder;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableColumnModel;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import javax.swing.tree.TreePath;
import jsyntaxpane.DefaultSyntaxKit;
public class ABCPanel extends JPanel implements ItemListener, ActionListener, SearchListener<ABCPanelSearchResult>, Freed {
private MainPanel mainPanel;
public TraitsList navigator;
public ABC abc;
public SWF swf;
public JComboBox<ABCContainerTag> abcComboBox;
public int listIndex = -1;
public DecompiledEditorPane decompiledTextArea;
public JScrollPane decompiledScrollPane;
public JSplitPane splitPane;
//public JSplitPane splitPaneTreeVSNavigator;
//public JSplitPane splitPaneTreeNavVSDecompiledDetail;
private JTable constantTable;
public JComboBox<String> constantTypeList;
public JLabel asmLabel = new HeaderLabel(AppStrings.translate("panel.disassembled"));
public JLabel decLabel = new HeaderLabel(AppStrings.translate("panel.decompiled"));
public DetailPanel detailPanel;
public JPanel navPanel;
public JTabbedPane tabbedPane;
public SearchPanel<ABCPanelSearchResult> searchPanel;
private NewTraitDialog newTraitDialog;
public JLabel scriptNameLabel;
static final String ACTION_SAVE_DECOMPILED = "SAVEDECOMPILED";
static final String ACTION_EDIT_DECOMPILED = "EDITDECOMPILED";
static final String ACTION_CANCEL_DECOMPILED = "CANCELDECOMPILED";
public JLabel experimentalLabel = new JLabel(AppStrings.translate("action.edit.experimental"));
public JButton editDecompiledButton = new JButton(AppStrings.translate("button.edit"), View.getIcon("edit16"));
public JButton saveDecompiledButton = new JButton(AppStrings.translate("button.save"), View.getIcon("save16"));
public JButton cancelDecompiledButton = new JButton(AppStrings.translate("button.cancel"), View.getIcon("cancel16"));
static final String ACTION_ADD_TRAIT = "ADDTRAIT";
public boolean search(String txt, boolean ignoreCase, boolean regexp) {
if ((txt != null) && (!txt.isEmpty())) {
searchPanel.setOptions(ignoreCase, regexp);
TagTreeModel ttm = (TagTreeModel) mainPanel.tagTree.getModel();
TreeNode scriptsNode = ttm.getSwfNode(mainPanel.getCurrentSwf()).scriptsNode;
final List<ABCPanelSearchResult> found = new ArrayList<>();
if (scriptsNode.getItem() instanceof ClassesListTreeModel) {
ClassesListTreeModel clModel = (ClassesListTreeModel) scriptsNode.getItem();
List<MyEntry<ClassPath, ScriptPack>> allpacks = clModel.getList();
final Pattern pat = regexp
? Pattern.compile(txt, ignoreCase ? Pattern.CASE_INSENSITIVE : 0)
: Pattern.compile(Pattern.quote(txt), ignoreCase ? Pattern.CASE_INSENSITIVE : 0);
int pos = 0;
for (final MyEntry<ClassPath, ScriptPack> item : allpacks) {
pos++;
String workText = AppStrings.translate("work.searching");
String decAdd = "";
if (!decompiledTextArea.isCached(item.value)) {
decAdd = ", " + AppStrings.translate("work.decompiling");
}
try {
CancellableWorker worker = new CancellableWorker() {
@Override
public Void doInBackground() throws Exception {
decompiledTextArea.cacheScriptPack(item.value, swf.abcList);
if (pat.matcher(decompiledTextArea.getCachedText(item.value)).find()) {
ABCPanelSearchResult searchResult = new ABCPanelSearchResult();
searchResult.scriptPack = item.value;
searchResult.classPath = item.key;
found.add(searchResult);
}
return null;
}
};
worker.execute();
Main.startWork(workText + " \"" + txt + "\"" + decAdd + " - (" + pos + "/" + allpacks.size() + ") " + item.key.toString() + "... ", worker);
worker.get();
} catch (InterruptedException ex) {
break;
} catch (ExecutionException ex) {
Logger.getLogger(ABCPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
System.gc();
Main.stopWork();
searchPanel.setSearchText(txt);
return searchPanel.setResults(found);
}
return false;
}
private JTable autoResizeColWidth(final JTable table, final TableModel model) {
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setModel(model);
int margin = 5;
for (int i = 0; i < table.getColumnCount(); i++) {
int vColIndex = i;
DefaultTableColumnModel colModel = (DefaultTableColumnModel) table.getColumnModel();
TableColumn col = colModel.getColumn(vColIndex);
int width;
// Get width of column header
TableCellRenderer renderer = col.getHeaderRenderer();
if (renderer == null) {
renderer = table.getTableHeader().getDefaultRenderer();
}
Component comp = renderer.getTableCellRendererComponent(table, col.getHeaderValue(), false, false, 0, 0);
width = comp.getPreferredSize().width;
// Get maximum width of column data
for (int r = 0; r < table.getRowCount(); r++) {
renderer = table.getCellRenderer(r, vColIndex);
comp = renderer.getTableCellRendererComponent(table, table.getValueAt(r, vColIndex), false, false,
r, vColIndex);
width = Math.max(width, comp.getPreferredSize().width);
}
// Add margin
width += 2 * margin;
// Set the width
col.setPreferredWidth(width);
}
((DefaultTableCellRenderer) table.getTableHeader().getDefaultRenderer()).setHorizontalAlignment(
SwingConstants.LEFT);
// table.setAutoCreateRowSorter(true);
table.getTableHeader().setReorderingAllowed(false);
}
});
return table;
}
public void setAbc(ABC abc) {
this.abc = abc;
updateConstList();
}
public void updateConstList() {
switch (constantTypeList.getSelectedIndex()) {
case 0:
autoResizeColWidth(constantTable, new UIntTableModel(abc));
break;
case 1:
autoResizeColWidth(constantTable, new IntTableModel(abc));
break;
case 2:
autoResizeColWidth(constantTable, new DoubleTableModel(abc));
break;
case 3:
autoResizeColWidth(constantTable, new DecimalTableModel(abc));
break;
case 4:
autoResizeColWidth(constantTable, new StringTableModel(abc));
break;
case 5:
autoResizeColWidth(constantTable, new NamespaceTableModel(abc));
break;
case 6:
autoResizeColWidth(constantTable, new NamespaceSetTableModel(abc));
break;
case 7:
autoResizeColWidth(constantTable, new MultinameTableModel(abc));
break;
}
//DefaultTableColumnModel colModel = (DefaultTableColumnModel) constantTable.getColumnModel();
//colModel.getColumn(0).setMaxWidth(50);
}
public void clearSwf() {
this.swf = null;
this.abc = null;
constantTable.setModel(new DefaultTableModel());
abcComboBox.setModel(new ABCComboBoxModel(new ArrayList<ABCContainerTag>()));
navigator.clearABC();
}
public void setSwf(SWF swf) {
if (this.swf != swf) {
this.swf = swf;
listIndex = -1;
switchAbc(0); // todo honika: do we need this?
abcComboBox.setModel(new ABCComboBoxModel(swf.abcList));
if (swf.abcList.size() > 0) {
this.abc = swf.abcList.get(0).getABC();
}
navigator.setABC(swf.abcList, abc);
}
}
public void switchAbc(int index) {
listIndex = index;
if (index != -1) {
this.abc = swf.abcList.get(index).getABC();
}
updateConstList();
}
public void initSplits() {
//splitPaneTreeVSNavigator.setDividerLocation(splitPaneTreeVSNavigator.getHeight() / 2);
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(ABCPanel.class.getName()).log(Level.SEVERE, null, ex);
}
//splitPaneTreeNavVSDecompiledDetail.setDividerLocation(splitPaneTreeNavVSDecompiledDetail.getWidth() * 1 / 3);
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(ABCPanel.class.getName()).log(Level.SEVERE, null, ex);
}
splitPane.setDividerLocation(Configuration.guiAvm2SplitPaneDividerLocation.get(splitPane.getWidth() * 1 / 2));
}
private boolean isFreeing;
@Override
public boolean isFreeing() {
return isFreeing;
}
@Override
public void free() {
isFreeing = true;
Helper.emptyObject(this);
}
public ABCPanel(MainPanel mainPanel) {
DefaultSyntaxKit.initKit();
this.mainPanel = mainPanel;
setLayout(new BorderLayout());
decompiledTextArea = new DecompiledEditorPane(this);
searchPanel = new SearchPanel<>(new FlowLayout(), this);
decompiledScrollPane = new JScrollPane(decompiledTextArea);
JPanel iconDecPanel = new JPanel();
iconDecPanel.setLayout(new BoxLayout(iconDecPanel, BoxLayout.Y_AXIS));
JPanel iconsPanel = new JPanel();
iconsPanel.setLayout(new BoxLayout(iconsPanel, BoxLayout.X_AXIS));
JButton newTraitButton = new JButton(View.getIcon("traitadd16"));
newTraitButton.setMargin(new Insets(5, 5, 5, 5));
newTraitButton.addActionListener(this);
newTraitButton.setActionCommand(ACTION_ADD_TRAIT);
newTraitButton.setToolTipText(AppStrings.translate("button.addtrait"));
iconsPanel.add(newTraitButton);
scriptNameLabel = new JLabel("-");
scriptNameLabel.setAlignmentX(0);
iconsPanel.setAlignmentX(0);
decompiledScrollPane.setAlignmentX(0);
iconDecPanel.add(scriptNameLabel);
iconDecPanel.add(iconsPanel);
iconDecPanel.add(decompiledScrollPane);
JPanel decButtonsPan = new JPanel(new FlowLayout());
decButtonsPan.setBorder(new BevelBorder(BevelBorder.RAISED));
decButtonsPan.add(editDecompiledButton);
decButtonsPan.add(experimentalLabel);
decButtonsPan.add(saveDecompiledButton);
decButtonsPan.add(cancelDecompiledButton);
editDecompiledButton.setMargin(new Insets(3, 3, 3, 10));
saveDecompiledButton.setMargin(new Insets(3, 3, 3, 10));
cancelDecompiledButton.setMargin(new Insets(3, 3, 3, 10));
saveDecompiledButton.addActionListener(this);
saveDecompiledButton.setActionCommand(ACTION_SAVE_DECOMPILED);
editDecompiledButton.addActionListener(this);
editDecompiledButton.setActionCommand(ACTION_EDIT_DECOMPILED);
cancelDecompiledButton.addActionListener(this);
cancelDecompiledButton.setActionCommand(ACTION_CANCEL_DECOMPILED);
saveDecompiledButton.setVisible(false);
cancelDecompiledButton.setVisible(false);
decButtonsPan.setAlignmentX(0);
JPanel decPanel = new JPanel(new BorderLayout());
decPanel.add(searchPanel, BorderLayout.NORTH);
decPanel.add(iconDecPanel, BorderLayout.CENTER);
decPanel.add(decButtonsPan, BorderLayout.SOUTH);
detailPanel = new DetailPanel(this);
JPanel panB = new JPanel();
panB.setLayout(new BorderLayout());
panB.add(decPanel, BorderLayout.CENTER);
panB.add(decLabel, BorderLayout.NORTH);
decLabel.setHorizontalAlignment(SwingConstants.CENTER);
//decLabel.setBorder(new BevelBorder(BevelBorder.RAISED));
splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
panB, detailPanel);
splitPane.setResizeWeight(0.5);
splitPane.setContinuousLayout(true);
splitPane.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent pce) {
if (!directEditing) {
Configuration.guiAvm2SplitPaneDividerLocation.set((int) pce.getNewValue());
}
}
});
decompiledTextArea.setContentType("text/actionscript");
decompiledTextArea.setFont(new Font("Monospaced", Font.PLAIN, decompiledTextArea.getFont().getSize()));
JPanel pan2 = new JPanel();
pan2.setLayout(new BorderLayout());
pan2.add((abcComboBox = new JComboBox<>(new ABCComboBoxModel(new ArrayList<ABCContainerTag>()))), BorderLayout.NORTH);
navigator = new TraitsList(this);
navPanel = new JPanel(new BorderLayout());
JPanel navIconsPanel = new JPanel();
navIconsPanel.setLayout(new BoxLayout(navIconsPanel, BoxLayout.X_AXIS));
final JToggleButton sortButton = new JToggleButton(View.getIcon("sort16"));
sortButton.setMargin(new Insets(3, 3, 3, 3));
navIconsPanel.add(sortButton);
navPanel.add(navIconsPanel, BorderLayout.SOUTH);
navPanel.add(new JScrollPane(navigator), BorderLayout.CENTER);
sortButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
navigator.setSorted(sortButton.isSelected());
navigator.updateUI();
}
});
Main.startWork(AppStrings.translate("work.buildingscripttree") + "...");
/* splitPaneTreeVSNavigator = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
treePanel,
navPanel);
splitPaneTreeVSNavigator.setResizeWeight(0.5);
splitPaneTreeVSNavigator.setContinuousLayout(true);*/
tabbedPane = new JTabbedPane();
tabbedPane.addTab(AppStrings.translate("traits"), navPanel);
//tabbedPane.setTabPlacement(JTabbedPane.BOTTOM);
//pan2.add(tabbedPane, BorderLayout.CENTER);
abcComboBox.addItemListener(this);
/*
splitPaneTreeNavVSDecompiledDetail = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
pan2,
splitPaneDecompiledVSDetail);
splitPaneTreeNavVSDecompiledDetail.setResizeWeight(0);
splitPaneTreeNavVSDecompiledDetail.setContinuousLayout(true);
//pan2.setPreferredSize(new Dimension(300, 200));
add(splitPaneTreeNavVSDecompiledDetail, BorderLayout.CENTER);*/
add(splitPane, BorderLayout.CENTER);
JPanel panConstants = new JPanel();
panConstants.setLayout(new BorderLayout());
constantTypeList = new JComboBox<>(new String[]{"UINT", "INT", "DOUBLE", "DECIMAL", "STRING", "NAMESPACE", "NAMESPACESET", "MULTINAME"});
constantTable = new JTable();
if (abc != null) {
autoResizeColWidth(constantTable, new UIntTableModel(abc));
}
constantTable.setAutoCreateRowSorter(true);
final ABCPanel t = this;
constantTable.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
if (constantTypeList.getSelectedIndex() == 7) { //MULTINAME
int rowIndex = constantTable.getSelectedRow();
if (rowIndex == -1) {
return;
}
int multinameIndex = constantTable.convertRowIndexToModel(rowIndex);
if (multinameIndex > 0) {
UsageFrame usageFrame = new UsageFrame(t.swf.abcList, abc, multinameIndex, t);
usageFrame.setVisible(true);
}
}
}
}
});
constantTypeList.addItemListener(this);
panConstants.add(constantTypeList, BorderLayout.NORTH);
panConstants.add(new JScrollPane(constantTable), BorderLayout.CENTER);
tabbedPane.addTab(AppStrings.translate("constants"), panConstants);
}
public void reload() {
switchAbc(listIndex);
decompiledTextArea.clearScriptCache();
decompiledTextArea.reloadClass();
detailPanel.methodTraitPanel.methodCodePanel.clear();
}
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getSource() == abcComboBox) {
int index = ((JComboBox) e.getSource()).getSelectedIndex();
if (index == -1) {
return;
}
switchAbc(index - 1);
}
if (e.getSource() == constantTypeList) {
int index = ((JComboBox) e.getSource()).getSelectedIndex();
if (index == -1) {
return;
}
updateConstList();
}
}
public void display() {
setVisible(true);
}
public void hilightScript(SWF swf, String name) {
TagTreeModel ttm = (TagTreeModel) mainPanel.tagTree.getModel();
TreeNode scriptsNode = ttm.getSwfNode(swf).scriptsNode;
if (scriptsNode.getItem() instanceof ClassesListTreeModel) {
ClassesListTreeModel clModel = (ClassesListTreeModel) scriptsNode.getItem();
ScriptPack pack = null;
for (MyEntry<ClassPath, ScriptPack> item : clModel.getList()) {
if (item.key.toString().equals(name)) {
pack = item.value;
break;
}
}
if (pack != null) {
hilightScript(pack);
}
}
}
public void hilightScript(ScriptPack pack) {
TagTreeModel ttm = (TagTreeModel) mainPanel.tagTree.getModel();
final TreePath tp = ttm.getTagPath(pack);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
mainPanel.tagTree.setSelectionPath(tp);
mainPanel.tagTree.scrollPathToVisible(tp);
}
});
}
@Override
public void updateSearchPos(ABCPanelSearchResult item) {
ScriptPack pack = item.scriptPack;
setAbc(pack.abc);
decompiledTextArea.setScript(pack, swf.abcList);
hilightScript(pack);
decompiledTextArea.setCaretPosition(0);
searchPanel.showQuickFindDialog(decompiledTextArea);
}
public String lastDecompiled = null;
public boolean directEditing = false;
private int detWidth = 0;
private int detsp = 0;
public void setDecompiledEditMode(boolean val) {
if (val) {
lastDecompiled = decompiledTextArea.getText();
decompiledTextArea.setEditable(true);
saveDecompiledButton.setVisible(true);
editDecompiledButton.setVisible(false);
experimentalLabel.setVisible(false);
cancelDecompiledButton.setVisible(true);
decompiledTextArea.getCaret().setVisible(true);
decLabel.setIcon(View.getIcon("editing16"));
directEditing = true;
detWidth = detailPanel.getWidth();
detsp = splitPane.getDividerLocation();
detailPanel.setVisible(false);
} else {
decompiledTextArea.setText(lastDecompiled);
decompiledTextArea.setEditable(false);
saveDecompiledButton.setVisible(false);
editDecompiledButton.setVisible(true);
experimentalLabel.setVisible(true);
cancelDecompiledButton.setVisible(false);
decompiledTextArea.getCaret().setVisible(true);
decLabel.setIcon(null);
directEditing = false;
detailPanel.setVisible(true);
detailPanel.setSize(detailPanel.getHeight(), detWidth);
splitPane.setDividerLocation(detsp);
}
decompiledTextArea.ignoreCarret = directEditing;
decompiledTextArea.requestFocusInWindow();
}
@Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case ACTION_EDIT_DECOMPILED:
File swc = Configuration.getPlayerSWC();
final String adobePage = "http://www.adobe.com/support/flashplayer/downloads.html";
if (swc == null) {
if (View.showConfirmDialog(this, AppStrings.translate("message.action.playerglobal.needed").replace("%adobehomepage%", adobePage), AppStrings.translate("message.action.playerglobal.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE) == JOptionPane.OK_OPTION) {
java.awt.Desktop desktop = null;
if (java.awt.Desktop.isDesktopSupported()) {
desktop = java.awt.Desktop.getDesktop();
if (desktop.isSupported(java.awt.Desktop.Action.BROWSE)) {
try {
java.net.URI uri = new java.net.URI(adobePage);
desktop.browse(uri);
} catch (URISyntaxException | IOException ex) {
}
} else {
desktop = null;
}
}
int ret = 0;
do {
ret = View.showConfirmDialog(this, AppStrings.translate("message.action.playerglobal.place").replace("%libpath%", Configuration.getFlashLibPath().getAbsolutePath()), AppStrings.translate("message.action.playerglobal.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE);
swc = Configuration.getPlayerSWC();
} while (ret == JOptionPane.OK_OPTION && swc == null);
}
}
if (swc != null) {
if (View.showConfirmDialog(null, AppStrings.translate("message.confirm.experimental.function"), AppStrings.translate("message.warning"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, Configuration.warningExperimentalAS3Edit, JOptionPane.OK_OPTION) == JOptionPane.OK_OPTION) {
setDecompiledEditMode(true);
}
}
break;
case ACTION_CANCEL_DECOMPILED:
setDecompiledEditMode(false);
break;
case ACTION_SAVE_DECOMPILED:
ScriptPack pack = decompiledTextArea.getScriptLeaf();
String scriptName = pack.getPathScriptName() + ".as";
int oldIndex = pack.scriptIndex;
int newIndex = abc.script_info.size();
String documentClass = "";
loopt:
for (Tag t : swf.tags) {
if (t instanceof SymbolClassTag) {
SymbolClassTag sc = (SymbolClassTag) t;
for (int i = 0; i < sc.tags.length; i++) {
if (sc.tags[i] == 0) {
documentClass = sc.names[i];
break loopt;
}
}
}
}
boolean isDocumentClass = documentClass.equals(pack.getPath().toString());
try {
ActionScriptParser.compile(decompiledTextArea.getText(), abc,new ArrayList<ABC>(), isDocumentClass, scriptName);
//Move newly added script to its position
abc.script_info.set(oldIndex, abc.script_info.get(newIndex));
abc.script_info.remove(newIndex);
((Tag) abc.parentTag).setModified(true);
lastDecompiled = decompiledTextArea.getText();
mainPanel.updateClassesList();
List<MyEntry<ClassPath,ScriptPack>> packs = abc.script_info.get(oldIndex).getPacks(abc, oldIndex);
if(!packs.isEmpty()){
hilightScript(swf,packs.get(0).key.toString());
}
//decompiledTextArea.setClassIndex(-1);
//navigator.setClassIndex(-1, oldIndex);
setDecompiledEditMode(false);
View.showMessageDialog(this, AppStrings.translate("message.action.saved"));
//reload();
} catch (ParseException ex) {
ex.printStackTrace();
View.showMessageDialog(this, AppStrings.translate("error.action.save").replace("%error%", ex.text).replace("%line%", "" + ex.line), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
decompiledTextArea.gotoLine((int) ex.line);
} catch (CompilationException ex) {
ex.printStackTrace();
View.showMessageDialog(this, AppStrings.translate("error.action.save").replace("%error%", ex.text).replace("%line%", "" + ex.line), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
decompiledTextArea.gotoLine((int) ex.line);
} catch (IOException | InterruptedException ex) {
//ignore
}
break;
case ACTION_ADD_TRAIT:
int class_index = decompiledTextArea.getClassIndex();
if (class_index < 0) {
return;
}
if (newTraitDialog == null) {
newTraitDialog = new NewTraitDialog();
}
int void_type = abc.constants.getPublicQnameId("void", true);//abc.constants.forceGetMultinameId(new Multiname(Multiname.QNAME, abc.constants.forceGetStringId("void"), abc.constants.forceGetNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abc.constants.forceGetStringId("")), 0), -1, -1, new ArrayList<Integer>()));
int int_type = abc.constants.getPublicQnameId("int", true); //abc.constants.forceGetMultinameId(new Multiname(Multiname.QNAME, abc.constants.forceGetStringId("int"), abc.constants.forceGetNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abc.constants.forceGetStringId("")), 0), -1, -1, new ArrayList<Integer>()));
Trait t = null;
int kind;
int nskind;
String name = null;
boolean isStatic;
Multiname m;
boolean again = false;
loopm:
do {
if (again) {
View.showMessageDialog(null, AppStrings.translate("error.trait.exists").replace("%name%", name), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
}
again = false;
if (!newTraitDialog.display()) {
return;
}
kind = newTraitDialog.getTraitType();
nskind = newTraitDialog.getNamespaceKind();
name = newTraitDialog.getTraitName();
isStatic = newTraitDialog.getStatic();
m = new Multiname(Multiname.QNAME, abc.constants.getStringId(name, true), abc.constants.getNamespaceId(new Namespace(nskind, abc.constants.getStringId("", true)), 0, true), -1, -1, new ArrayList<Integer>());
int mid = abc.constants.getMultinameId(m);
if (mid == 0) {
break;
}
for (Trait tr : abc.class_info.get(class_index).static_traits.traits) {
if (tr.name_index == mid) {
again = true;
break;
}
}
for (Trait tr : abc.instance_info.get(class_index).instance_traits.traits) {
if (tr.name_index == mid) {
again = true;
break;
}
}
} while (again);
switch (kind) {
case Trait.TRAIT_GETTER:
case Trait.TRAIT_SETTER:
case Trait.TRAIT_METHOD:
TraitMethodGetterSetter tm = new TraitMethodGetterSetter();
MethodInfo mi = new MethodInfo(new int[0], void_type, abc.constants.getStringId(name, true), 0, new ValueKind[0], new int[0]);
int method_info = abc.addMethodInfo(mi);
tm.method_info = method_info;
MethodBody body = new MethodBody();
body.method_info = method_info;
body.init_scope_depth = 1;
body.max_regs = 1;
body.max_scope_depth = 1;
body.max_stack = 1;
body.exceptions = new ABCException[0];
AVM2Code code = new AVM2Code();
code.code.add(new AVM2Instruction(0, new GetLocal0Ins(), new int[0], new byte[0]));
code.code.add(new AVM2Instruction(0, new PushScopeIns(), new int[0], new byte[0]));
code.code.add(new AVM2Instruction(0, new ReturnVoidIns(), new int[0], new byte[0]));
body.code = code;
Traits traits = new Traits();
traits.traits = new ArrayList<>();
body.traits = traits;
abc.addMethodBody(body);
mi.setBody(body);
t = tm;
break;
case Trait.TRAIT_SLOT:
case Trait.TRAIT_CONST:
TraitSlotConst ts = new TraitSlotConst();
ts.type_index = int_type;
ts.value_kind = ValueKind.CONSTANT_Int;
ts.value_index = abc.constants.getIntId(0, true);
t = ts;
break;
}
if (t != null) {
t.kindType = kind;
t.name_index = abc.constants.getMultinameId(m, true);
int traitId;
if (isStatic) {
traitId = abc.class_info.get(class_index).static_traits.addTrait(t);
} else {
traitId = abc.class_info.get(class_index).static_traits.traits.size() + abc.instance_info.get(class_index).instance_traits.addTrait(t);
}
reload();
decompiledTextArea.gotoTrait(traitId);
}
break;
}
}
}
@@ -0,0 +1,30 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.abc.ClassPath;
import com.jpexs.decompiler.flash.abc.ScriptPack;
/**
*
* @author JPEXS
*/
public class ABCPanelSearchResult {
public ScriptPack scriptPack;
public ClassPath classPath;
}
@@ -0,0 +1,344 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.UnknownInstructionCode;
import com.jpexs.decompiler.flash.abc.avm2.graph.AVM2Graph;
import com.jpexs.decompiler.flash.abc.avm2.parser.ParseException;
import com.jpexs.decompiler.flash.abc.avm2.parser.pcode.ASM3Parser;
import com.jpexs.decompiler.flash.abc.avm2.parser.pcode.MissingSymbolHandler;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.gui.GraphFrame;
import com.jpexs.decompiler.flash.gui.View;
import com.jpexs.decompiler.flash.helpers.HilightedText;
import com.jpexs.decompiler.flash.helpers.HilightedTextWriter;
import com.jpexs.decompiler.flash.helpers.hilight.Highlighting;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.helpers.Helper;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
public class ASMSourceEditorPane extends LineMarkedEditorPane implements CaretListener {
public ABC abc;
public int bodyIndex = -1;
private List<Highlighting> disassembledHilights = new ArrayList<>();
private List<Highlighting> specialHilights = new ArrayList<>();
private final DecompiledEditorPane decompiledEditor;
private boolean ignoreCarret = false;
private String name;
private HilightedText textWithHex;
private HilightedText textNoHex;
private HilightedText textHexOnly;
private ScriptExportMode exportMode = ScriptExportMode.PCODE;
private Trait trait;
public ScriptExportMode getExportMode() {
return exportMode;
}
private HilightedText getHilightedText(ScriptExportMode exportMode) {
HilightedTextWriter writer = new HilightedTextWriter(Configuration.getCodeFormatting(), true);
abc.bodies.get(bodyIndex).code.toASMSource(abc.constants, trait, abc.method_info.get(abc.bodies.get(bodyIndex).method_info), abc.bodies.get(bodyIndex), exportMode, writer);
return new HilightedText(writer);
}
public void setHex(ScriptExportMode exportMode, boolean force) {
if (this.exportMode == exportMode & !force) {
return;
}
this.exportMode = exportMode;
long oldOffset = getSelectedOffset();
if (exportMode == ScriptExportMode.PCODE) {
setContentType("text/flasm");
if (textNoHex == null) {
textNoHex = getHilightedText(exportMode);
}
setText(textNoHex);
} else if (exportMode == ScriptExportMode.PCODE_HEX) {
setContentType("text/flasm");
if (textWithHex == null) {
textWithHex = getHilightedText(exportMode);
}
setText(textWithHex);
} else {
setContentType("text/plain");
if (textHexOnly == null) {
HilightedTextWriter writer = new HilightedTextWriter(Configuration.getCodeFormatting(), true);
Helper.byteArrayToHexWithHeader(writer, abc.bodies.get(bodyIndex).code.getBytes());
textHexOnly = new HilightedText(writer);
}
setText(textHexOnly);
}
hilighOffset(oldOffset);
}
public void setIgnoreCarret(boolean ignoreCarret) {
this.ignoreCarret = ignoreCarret;
}
public ASMSourceEditorPane(DecompiledEditorPane decompiledEditor) {
this.decompiledEditor = decompiledEditor;
addCaretListener(this);
}
public void hilighSpecial(String type, int index) {
Highlighting h2 = null;
for (Highlighting sh : specialHilights) {
if (type.equals(sh.getPropertyString("subtype"))) {
if (sh.getPropertyString("index").equals("" + index)) {
h2 = sh;
break;
}
}
}
if (h2 != null) {
ignoreCarret = true;
if (h2.startPos <= getDocument().getLength()) {
setCaretPosition(h2.startPos);
}
getCaret().setVisible(true);
ignoreCarret = false;
}
}
public void hilighOffset(long offset) {
if (isEditable()) {
return;
}
Highlighting h2 = Highlighting.search(disassembledHilights, "offset", "" + offset);
if (h2 != null) {
ignoreCarret = true;
if (h2.startPos <= getDocument().getLength()) {
setCaretPosition(h2.startPos);
}
getCaret().setVisible(true);
ignoreCarret = false;
}
}
@Override
public String getName() {
return super.getName();
}
public void setBodyIndex(int bodyIndex, ABC abc, String name, Trait trait) {
this.bodyIndex = bodyIndex;
this.abc = abc;
this.name = name;
this.trait = trait;
if (bodyIndex == -1) {
return;
}
textWithHex = null;
textNoHex = null;
setHex(exportMode, true);
}
public void graph() {
try {
AVM2Graph gr = new AVM2Graph(abc.bodies.get(bodyIndex).code, abc, abc.bodies.get(bodyIndex), false, -1, -1, new HashMap<Integer, GraphTargetItem>(), new Stack<GraphTargetItem>(), new HashMap<Integer, String>(), new ArrayList<String>(), new HashMap<Integer, Integer>(), abc.bodies.get(bodyIndex).code.visitCode(abc.bodies.get(bodyIndex)));
(new GraphFrame(gr, name)).setVisible(true);
} catch (InterruptedException ex) {
Logger.getLogger(ASMSourceEditorPane.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void exec() {
HashMap<Integer, Object> args = new HashMap<>();
args.put(0, new Object()); //object "this"
args.put(1, new Long(466561)); //param1
Object o = abc.bodies.get(bodyIndex).code.execute(args, abc.constants);
View.showMessageDialog(this, "Returned object:" + o.toString());
}
public boolean save(ConstantPool constants) {
try {
String text = getText();
if (text.trim().startsWith("#hexdata")) {
byte[] data = Helper.getBytesFromHexaText(text);
MethodBody mb = abc.bodies.get(bodyIndex);
mb.codeBytes = data;
try {
mb.code = new AVM2Code(new ByteArrayInputStream(mb.codeBytes));
} catch (UnknownInstructionCode re) {
mb.code = new AVM2Code();
Logger.getLogger(ABC.class.getName()).log(Level.SEVERE, null, re);
}
mb.code.compact();
} else {
AVM2Code acode = ASM3Parser.parse(new StringReader(text), constants, trait, new MissingSymbolHandler() {
//no longer ask for adding new constants
@Override
public boolean missingString(String value) {
return true;
}
@Override
public boolean missingInt(long value) {
return true;
}
@Override
public boolean missingUInt(long value) {
return true;
}
@Override
public boolean missingDouble(double value) {
return true;
}
}, abc.bodies.get(bodyIndex), abc.method_info.get(abc.bodies.get(bodyIndex).method_info));
acode.getBytes(abc.bodies.get(bodyIndex).codeBytes);
abc.bodies.get(bodyIndex).code = acode;
}
((Tag) abc.parentTag).setModified(true);
} catch (IOException ex) {
} catch (InterruptedException ex) {
} catch (ParseException ex) {
View.showMessageDialog(this, (ex.text + " on line " + ex.line));
selectLine((int) ex.line);
return false;
}
return true;
}
@Override
public void setText(String t) {
disassembledHilights = new ArrayList<>();
specialHilights = new ArrayList<>();
super.setText(t);
setCaretPosition(0);
}
public void setText(HilightedText hilightedText) {
disassembledHilights = hilightedText.instructionHilights;
specialHilights = hilightedText.specialHilights;
super.setText(hilightedText.text);
setCaretPosition(0);
}
public void clear() {
setText("");
bodyIndex = -1;
setCaretPosition(0);
}
public void selectInstruction(int pos) {
String text = getText();
int lineCnt = 1;
int lineStart = 0;
int lineEnd;
int instrCount = 0;
int dot = -2;
for (int i = 0; i < text.length(); i++) {
if (text.charAt(i) == '\n') {
lineCnt++;
lineEnd = i;
String ins = text.substring(lineStart, lineEnd).trim();
if (!((i > 0) && (text.charAt(i - 1) == ':'))) {
if (!ins.startsWith("exception ")) {
instrCount++;
}
}
if (instrCount == pos + 1) {
break;
}
lineStart = i + 1;
}
}
if (lineCnt == -1) {
//lineEnd = text.length() - 1;
}
//select(lineStart, lineEnd);
setCaretPosition(lineStart);
//requestFocus();
}
public void selectLine(int line) {
String text = getText();
int lineCnt = 1;
int lineStart = 0;
int lineEnd = -1;
for (int i = 0; i < text.length(); i++) {
if (text.charAt(i) == '\n') {
lineCnt++;
if (lineCnt == line) {
lineStart = i;
}
if (lineCnt == line + 1) {
lineEnd = i;
}
}
}
if (lineCnt == -1) {
lineEnd = text.length() - 1;
}
select(lineStart, lineEnd);
requestFocus();
}
public Highlighting getSelectedSpecial() {
return Highlighting.search(specialHilights, getCaretPosition());
}
public long getSelectedOffset() {
int pos = getCaretPosition();
Highlighting lastH = null;
for (Highlighting h : disassembledHilights) {
if (pos < h.startPos) {
break;
}
lastH = h;
}
return lastH == null ? 0 : lastH.getPropertyLong("offset");
}
@Override
public void caretUpdate(CaretEvent e) {
if (isEditable()) {
return;
}
if (ignoreCarret) {
return;
}
getCaret().setVisible(true);
decompiledEditor.hilightOffset(getSelectedOffset());
Highlighting spec = getSelectedSpecial();
if (spec != null) {
decompiledEditor.hilightSpecial(spec.getPropertyString("subtype"), (int) (long) spec.getPropertyLong("index"));
}
}
}
@@ -0,0 +1,65 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.helpers.HilightedText;
import com.jpexs.decompiler.flash.helpers.hilight.Highlighting;
import java.io.Serializable;
import java.util.List;
/**
*
* @author JPEXS
*/
public class CachedDecompilation implements Serializable {
public String text;
public List<Highlighting> traitHilights;
public List<Highlighting> classHilights;
public List<Highlighting> methodHilights;
public List<Highlighting> instructionHilights;
public List<Highlighting> specialHilights;
public List<Highlighting> getInstructionHighlights() {
return instructionHilights;
}
public List<Highlighting> getTraitHighlights() {
return traitHilights;
}
public List<Highlighting> getMethodHighlights() {
return methodHilights;
}
public List<Highlighting> getClassHighlights() {
return classHilights;
}
public List<Highlighting> getSpecialHighligths() {
return specialHilights;
}
public CachedDecompilation(HilightedText hilightedText) {
this.text = hilightedText.text;
this.traitHilights = hilightedText.traitHilights;
this.classHilights = hilightedText.classHilights;
this.methodHilights = hilightedText.methodHilights;
this.instructionHilights = hilightedText.instructionHilights;
this.specialHilights = hilightedText.specialHilights;
}
}
@@ -0,0 +1,188 @@
/*
* Copyright (C) 2010-2014 JPEXS, Paolo Cancedda
*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.AppStrings;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.ClassPath;
import com.jpexs.decompiler.flash.abc.ScriptPack;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.abc.types.traits.TraitClass;
import com.jpexs.decompiler.flash.gui.abc.treenodes.TreeElement;
import com.jpexs.decompiler.flash.helpers.collections.MyEntry;
import com.jpexs.decompiler.flash.treeitems.TreeElementItem;
import com.jpexs.decompiler.flash.treenodes.TreeNode;
import java.util.ArrayList;
import java.util.List;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
class ClassIndexVisitor implements TreeVisitor {
private TreeElement found = null;
private int classIndex = 0;
public ClassIndexVisitor(int classIndex) {
this.classIndex = classIndex;
}
@Override
public void onBranch(TreeElement branch) {
Object o = branch.getItem();
if (o == null) {
return;
}
ScriptPack sc = (ScriptPack) o;
for (Trait t : sc.abc.script_info.get(sc.scriptIndex).traits.traits) {
if (t instanceof TraitClass) {
if (((TraitClass) t).class_info == classIndex) {
found = branch;
return;
}
}
}
}
@Override
public void onLeaf(TreeElement leaf) {
Object o = leaf.getItem();
if (o == null) {
return;
}
ScriptPack sc = (ScriptPack) o;
for (Trait t : sc.abc.script_info.get(sc.scriptIndex).traits.traits) {
if (t instanceof TraitClass) {
if (((TraitClass) t).class_info == classIndex) {
found = leaf;
return;
}
}
}
}
public TreeElement getFound() {
return found;
}
}
public class ClassesListTreeModel implements TreeModel, TreeElementItem {
private SWF swf;
private Tree classTree;
private List<MyEntry<ClassPath, ScriptPack>> list;
private final List<TreeModelListener> listeners = new ArrayList<>();
public List<MyEntry<ClassPath, ScriptPack>> getList() {
return list;
}
public ClassesListTreeModel(SWF swf) {
this(swf, null);
}
public ClassesListTreeModel(SWF swf, String filter) {
this.swf = swf;
this.list = swf.getAS3Packs();
setFilter(filter);
}
@Override
public SWF getSwf() {
return swf;
}
public final void update() {
this.list = swf.getAS3Packs();
TreeModelEvent event = new TreeModelEvent(this, new TreePath(classTree.getRoot()));
for (TreeModelListener listener : listeners) {
listener.treeStructureChanged(event);
}
}
public final void setFilter(String filter) {
classTree = new Tree();
filter = (filter == null || filter.isEmpty()) ? null : filter.toLowerCase();
for (MyEntry<ClassPath, ScriptPack> item : list) {
if (filter != null) {
if (!item.key.toString().toLowerCase().contains(filter)) {
continue;
}
}
//String nsName = path.contains(".") ? path.substring(path.lastIndexOf(".") + 1) : path;
//String packageName = path.contains(".") ? path.substring(0, path.lastIndexOf(".")) : "";
classTree.add(item.key.className, item.key.packageStr, item.value);
}
}
public TreeElement getElementByClassIndex(int classIndex) {
ClassIndexVisitor civ = new ClassIndexVisitor(classIndex);
classTree.visit(civ);
return civ.getFound();
}
@Override
public TreeElement getRoot() {
return classTree.getRoot();
}
@Override
public TreeNode getChild(Object parent, int index) {
TreeElement pte = (TreeElement) parent;
TreeElement te = pte.getChild(index);
return te;
}
@Override
public int getChildCount(Object parent) {
TreeElement te = (TreeElement) parent;
return te.getChildCount();
}
@Override
public boolean isLeaf(Object node) {
TreeElement te = (TreeElement) node;
return te.isLeaf();
}
@Override
public void valueForPathChanged(TreePath path, Object newValue) {
}
@Override
public int getIndexOfChild(Object parent, Object child) {
TreeElement te1 = (TreeElement) parent;
TreeElement te2 = (TreeElement) child;
return te1.getIndexOfChild(te2);
}
@Override
public void addTreeModelListener(TreeModelListener l) {
listeners.add(l);
}
@Override
public void removeTreeModelListener(TreeModelListener l) {
listeners.remove(l);
}
@Override
public String toString() {
return AppStrings.translate("node.scripts");
}
}
@@ -0,0 +1,103 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.helpers.Helper;
import java.util.ArrayList;
import javax.swing.ListModel;
import javax.swing.event.ListDataListener;
public class ConstantsListModel implements ListModel {
private final ConstantPool constants;
public static final int TYPE_UINT = 0;
public static final int TYPE_INT = 1;
public static final int TYPE_DOUBLE = 2;
public static final int TYPE_DECIMAL = 3;
public static final int TYPE_STRING = 4;
public static final int TYPE_NAMESPACE = 5;
public static final int TYPE_NAMESPACESET = 6;
public static final int TYPE_MULTINAME = 7;
private int type = TYPE_INT;
public ConstantsListModel(ConstantPool constants, int type) {
this.type = type;
this.constants = constants;
}
private int makeUp(int i) {
if (i < 0) {
return 0;
}
return i;
}
@Override
public int getSize() {
switch (type) {
case TYPE_UINT:
return makeUp(constants.getUIntCount() - 1);
case TYPE_INT:
return makeUp(constants.getIntCount() - 1);
case TYPE_DOUBLE:
return makeUp(constants.getDoubleCount() - 1);
case TYPE_DECIMAL:
return makeUp(constants.getDecimalCount() - 1);
case TYPE_STRING:
return makeUp(constants.getStringCount() - 1);
case TYPE_NAMESPACE:
return makeUp(constants.getNamespaceCount() - 1);
case TYPE_NAMESPACESET:
return makeUp(constants.getNamespaceSetCount() - 1);
case TYPE_MULTINAME:
return makeUp(constants.getMultinameCount() - 1);
}
return 0;
}
@Override
public Object getElementAt(int index) {
switch (type) {
case TYPE_UINT:
return "" + (index + 1) + ":" + constants.getUInt(index + 1);
case TYPE_INT:
return "" + (index + 1) + ":" + constants.getInt(index + 1);
case TYPE_DOUBLE:
return "" + (index + 1) + ":" + constants.getDouble(index + 1);
case TYPE_DECIMAL:
return "" + (index + 1) + ":" + constants.getDecimal(index + 1);
case TYPE_STRING:
return "" + (index + 1) + ":" + Helper.escapeString(constants.getString(index + 1));
case TYPE_NAMESPACE:
return "" + (index + 1) + ":" + constants.getNamespace(index + 1).getNameWithKind(constants);
case TYPE_NAMESPACESET:
return "" + (index + 1) + ":" + constants.getNamespaceSet(index + 1).toString(constants);
case TYPE_MULTINAME:
return "" + (index + 1) + ":" + constants.getMultiname(index + 1).toString(constants, new ArrayList<String>());
}
return null;
}
@Override
public void addListDataListener(ListDataListener l) {
}
@Override
public void removeListDataListener(ListDataListener l) {
}
}
@@ -0,0 +1,520 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.AppStrings;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.ScriptPack;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.types.ScriptInfo;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction;
import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter;
import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.gui.View;
import com.jpexs.decompiler.flash.helpers.HilightedText;
import com.jpexs.decompiler.flash.helpers.HilightedTextWriter;
import com.jpexs.decompiler.flash.helpers.hilight.Highlighting;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.helpers.Cache;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.SwingUtilities;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretListener {
private List<Highlighting> highlights = new ArrayList<>();
private List<Highlighting> specialHighlights = new ArrayList<>();
private List<Highlighting> traitHighlights = new ArrayList<>();
private List<Highlighting> methodHighlights = new ArrayList<>();
private List<Highlighting> classHighlights = new ArrayList<>();
private Highlighting currentMethodHighlight;
private Highlighting currentTraitHighlight;
private ABC abc;
private ScriptPack script;
public int lastTraitIndex = 0;
public boolean ignoreCarret = false;
private boolean reset = false;
private final ABCPanel abcPanel;
private int classIndex = -1;
private boolean isStatic = false;
private final Cache<CachedDecompilation> cache = Cache.getInstance(true);
private Trait currentTrait = null;
public Trait getCurrentTrait() {
return currentTrait;
}
public ScriptPack getScriptLeaf() {
return script;
}
public boolean getIsStatic() {
return isStatic;
}
public void setNoTrait() {
abcPanel.detailPanel.showCard(DetailPanel.UNSUPPORTED_TRAIT_CARD, null);
}
public void hilightSpecial(String type, int index) {
int startPos;
int endPos;
if (currentMethodHighlight == null) {
if (currentTraitHighlight == null) {
return;
}
startPos = currentTraitHighlight.startPos;
endPos = currentTraitHighlight.startPos + currentTraitHighlight.len;
} else {
startPos = currentMethodHighlight.startPos;
endPos = currentMethodHighlight.startPos + currentMethodHighlight.len;
}
List<Highlighting> allh = new ArrayList<>();
for (Highlighting h : traitHighlights) {
if (h.getPropertyString("index").equals("" + lastTraitIndex)) {
for (Highlighting sh : specialHighlights) {
if (sh.startPos >= h.startPos && (sh.startPos + sh.len < h.startPos + h.len)) {
allh.add(sh);
}
}
}
}
if (currentMethodHighlight != null) {
for (Highlighting h : specialHighlights) {
if (h.startPos >= startPos && (h.startPos + h.len < endPos)) {
allh.add(h);
}
}
}
for (Highlighting h : allh) {
if (h.getPropertyString("subtype").equals(type) && ((long) h.getPropertyLong("index") == index)) {
ignoreCarret = true;
if (h.startPos <= getDocument().getLength()) {
setCaretPosition(h.startPos);
}
getCaret().setVisible(true);
ignoreCarret = false;
break;
}
}
}
public void hilightOffset(long offset) {
if (currentMethodHighlight == null) {
return;
}
List<Highlighting> allh = new ArrayList<>();
for (Highlighting h : traitHighlights) {
if (h.getPropertyString("index").equals("" + lastTraitIndex)) {
Highlighting h2 = Highlighting.search(highlights, "offset", "" + offset, h.startPos, h.startPos + h.len);
if (h2 != null) {
ignoreCarret = true;
if (h2.startPos <= getDocument().getLength()) {
setCaretPosition(h2.startPos);
}
getCaret().setVisible(true);
ignoreCarret = false;
}
}
}
}
public void setClassIndex(int classIndex) {
this.classIndex = classIndex;
}
private boolean displayMethod(int pos, int methodIndex, String name, Trait trait, boolean isStatic) {
if (abc == null) {
return false;
}
int bi = abc.findBodyIndex(methodIndex);
if (bi == -1) {
return false;
}
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
}
});
//fix for inner functions:
if (trait instanceof TraitMethodGetterSetter) {
TraitMethodGetterSetter tm = (TraitMethodGetterSetter) trait;
if (tm.method_info != methodIndex) {
trait = null;
}
}
if (trait instanceof TraitFunction) {
TraitFunction tf = (TraitFunction) trait;
if (tf.method_info != methodIndex) {
trait = null;
}
}
abcPanel.detailPanel.showCard(DetailPanel.METHOD_TRAIT_CARD, trait);
if (reset || (abcPanel.detailPanel.methodTraitPanel.methodCodePanel.getBodyIndex() != bi)) {
abcPanel.detailPanel.methodTraitPanel.methodCodePanel.setBodyIndex(bi, abc, name, trait);
abcPanel.detailPanel.setEditMode(false);
this.isStatic = isStatic;
}
boolean success = false;
Highlighting h = Highlighting.search(highlights, pos);
if (h != null) {
abcPanel.detailPanel.methodTraitPanel.methodCodePanel.hilighOffset(h.getPropertyLong("offset"));
success = true;
}
Highlighting sh = Highlighting.search(specialHighlights, pos);
if (sh != null) {
abcPanel.detailPanel.methodTraitPanel.methodCodePanel.hilighSpecial(sh.getPropertyString("subtype"), (int) (long) sh.getPropertyLong("index"));
success = true;
}
return success;
}
public void displayClass(int classIndex, int scriptIndex) {
if (abcPanel.navigator.getClassIndex() != classIndex) {
abcPanel.navigator.setClassIndex(classIndex, scriptIndex);
}
}
public void resetEditing() {
reset = true;
caretUpdate(null);
reset = false;
}
public int getMultinameUnderCursor() {
int pos = getCaretPosition();
Highlighting h = Highlighting.search(highlights, pos);
if (h != null) {
List<AVM2Instruction> list = abc.bodies.get(abcPanel.detailPanel.methodTraitPanel.methodCodePanel.getBodyIndex()).code.code;
AVM2Instruction lastIns = null;
long inspos = 0;
AVM2Instruction selIns = null;
for (AVM2Instruction ins : list) {
if (h.getPropertyLong("offset") == ins.getOffset()) {
selIns = ins;
break;
}
if (ins.getOffset() > h.getPropertyLong("offset")) {
inspos = h.getPropertyLong("offset") - lastIns.offset;
selIns = lastIns;
break;
}
lastIns = ins;
}
if (selIns != null) {
for (int i = 0; i < selIns.definition.operands.length; i++) {
if (selIns.definition.operands[i] == AVM2Code.DAT_MULTINAME_INDEX) {
return selIns.operands[i];
}
}
}
}
int currentMethod = -1;
if (currentTrait instanceof TraitMethodGetterSetter) {
currentMethod = ((TraitMethodGetterSetter) currentTrait).method_info;
}
if (currentMethodHighlight != null) {
currentMethod = (int) (long) currentMethodHighlight.getPropertyLong("index");
}
Highlighting sh = Highlighting.search(specialHighlights, pos);
if (sh != null) {
switch (sh.getPropertyString("subtype")) {
case "traittypename":
if (currentTrait instanceof TraitSlotConst) {
TraitSlotConst ts = (TraitSlotConst) currentTrait;
return ts.type_index;
}
break;
case "traitname":
if (currentTrait != null) {
return currentTrait.name_index;
}
break;
case "returns":
if (currentMethod > -1) {
return abc.method_info.get(currentMethod).ret_type;
}
break;
case "param":
if (currentMethod > -1) {
return abc.method_info.get(currentMethod).param_types[(int) (long) sh.getPropertyLong("index")];
}
break;
}
}
return -1;
}
@Override
public void caretUpdate(final CaretEvent e) {
if (!SwingUtilities.isEventDispatchThread()) {
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
caretUpdate(e);
}
});
return;
}
if (abc == null) {
return;
}
if (ignoreCarret) {
return;
}
getCaret().setVisible(true);
int pos = getCaretPosition();
abcPanel.detailPanel.methodTraitPanel.methodCodePanel.setIgnoreCarret(true);
try {
classIndex = -1;
Highlighting cm = Highlighting.search(classHighlights, pos);
if (cm != null) {
classIndex = (int) (long) cm.getPropertyLong("index");
displayClass(classIndex, script.scriptIndex);
}
Highlighting tm = Highlighting.search(methodHighlights, pos);
if (tm != null) {
String name = "";
if (abc != null) {
if (classIndex > -1) {
name = abc.instance_info.get(classIndex).getName(abc.constants).getNameWithNamespace(abc.constants);
}
}
currentTrait = null;
currentTraitHighlight = Highlighting.search(traitHighlights, pos);
if (currentTraitHighlight != null) {
lastTraitIndex = (int) (long) currentTraitHighlight.getPropertyLong("index");
if ((abc != null) && (classIndex != -1)) {
currentTrait = abc.findTraitByTraitId(classIndex, lastTraitIndex);
isStatic = abc.isStaticTraitId(classIndex, lastTraitIndex);
if (currentTrait != null) {
name += ":" + currentTrait.getName(abc).getName(abc.constants, new ArrayList<String>());
}
}
}
displayMethod(pos, (int) (long) tm.getPropertyLong("index"), name, currentTrait, isStatic);
currentMethodHighlight = tm;
return;
}
if (classIndex == -1) {
setNoTrait();
return;
}
currentTrait = null;
currentTraitHighlight = Highlighting.search(traitHighlights, pos);
if (currentTraitHighlight != null) {
lastTraitIndex = (int) (long) currentTraitHighlight.getPropertyLong("index");
currentTrait = abc.findTraitByTraitId(classIndex, (int) (long) currentTraitHighlight.getPropertyLong("index"));
if (currentTrait != null) {
if (currentTrait instanceof TraitSlotConst) {
abcPanel.detailPanel.slotConstTraitPanel.load((TraitSlotConst) currentTrait, abc,
abc.isStaticTraitId(classIndex, lastTraitIndex));
abcPanel.detailPanel.showCard(DetailPanel.SLOT_CONST_TRAIT_CARD, currentTrait);
abcPanel.detailPanel.setEditMode(false);
currentMethodHighlight = null;
Highlighting spec = Highlighting.search(specialHighlights, pos, null, null, currentTraitHighlight.startPos, currentTraitHighlight.startPos + currentTraitHighlight.len);
if (spec != null) {
abcPanel.detailPanel.slotConstTraitPanel.hilightSpecial(spec);
}
return;
}
}
currentMethodHighlight = null;
String name = "";
currentTrait = null;
if (abc != null) {
name = abc.instance_info.get(classIndex).getName(abc.constants).getNameWithNamespace(abc.constants);
currentTrait = abc.findTraitByTraitId(classIndex, lastTraitIndex);
isStatic = abc.isStaticTraitId(classIndex, lastTraitIndex);
if (currentTrait != null) {
name += ":" + currentTrait.getName(abc).getName(abc.constants, new ArrayList<String>());
}
}
displayMethod(pos, abc.findMethodIdByTraitId(classIndex, (int) (long) currentTraitHighlight.getPropertyLong("index")), name, currentTrait, isStatic);
return;
}
setNoTrait();
} finally {
abcPanel.detailPanel.methodTraitPanel.methodCodePanel.setIgnoreCarret(false);
}
}
private void uncache(ScriptPack pack) {
cache.remove(pack);
}
public boolean isCached(ScriptPack pack) {
return cache.contains(pack);
}
private CachedDecompilation getCached(ScriptPack pack) throws InterruptedException {
if (!cache.contains(pack)) {
cacheScriptPack(pack, abcList);
}
return (CachedDecompilation) cache.get(pack);
}
public String getCachedText(ScriptPack pack) throws InterruptedException {
return getCached(pack).text;
}
public void gotoLastTrait() {
gotoTrait(lastTraitIndex);
}
public void gotoTrait(int traitId) {
if (traitId == -1) {
setCaretPosition(0);
return;
}
Highlighting tc = Highlighting.search(classHighlights, "index", "" + classIndex);
if (tc != null) {
Highlighting th = Highlighting.search(traitHighlights, "index", "" + traitId, tc.startPos, tc.startPos + tc.len);
if (th != null) {
ignoreCarret = true;
int startPos = th.startPos + th.len - 1;
if (startPos <= getDocument().getLength()) {
setCaretPosition(startPos);
}
ignoreCarret = false;
final int pos = th.startPos;
new Timer().schedule(new TimerTask() {
@Override
public void run() {
if (pos <= getDocument().getLength()) {
setCaretPosition(pos);
}
}
}, 100);
return;
}
}
setCaretPosition(0);
}
public DecompiledEditorPane(ABCPanel abcPanel) {
setEditable(false);
getCaret().setVisible(true);
addCaretListener(this);
this.abcPanel = abcPanel;
}
private List<ABCContainerTag> abcList;
public void clearScriptCache() {
cache.clear();
}
public void cacheScriptPack(ScriptPack scriptLeaf, List<ABCContainerTag> abcList) throws InterruptedException {
int maxCacheSize = 50;
int scriptIndex = scriptLeaf.scriptIndex;
HilightedText hilightedCode = null;
ScriptInfo script = null;
ABC abc = scriptLeaf.abc;
if (scriptIndex > -1) {
script = abc.script_info.get(scriptIndex);
}
if (!cache.contains(scriptLeaf)) {
boolean parallel = Configuration.parallelSpeedUp.get();
HilightedTextWriter writer = new HilightedTextWriter(Configuration.getCodeFormatting(), true);
scriptLeaf.toSource(writer, abcList, script.traits.traits, ScriptExportMode.AS, parallel);
hilightedCode = new HilightedText(writer);
cache.put(scriptLeaf, new CachedDecompilation(hilightedCode));
}
}
public void setScript(ScriptPack scriptLeaf, List<ABCContainerTag> abcList) {
abcPanel.scriptNameLabel.setText(scriptLeaf.getPath().toString());
int scriptIndex = scriptLeaf.scriptIndex;
ScriptInfo script = null;
ABC abc = scriptLeaf.abc;
if (scriptIndex > -1) {
script = abc.script_info.get(scriptIndex);
}
if (script == null) {
highlights = new ArrayList<>();
specialHighlights = new ArrayList<>();
traitHighlights = new ArrayList<>();
methodHighlights = new ArrayList<>();
this.script = scriptLeaf;
return;
}
setText("//" + AppStrings.translate("pleasewait") + "...");
this.abc = abc;
this.abcList = abcList;
this.script = scriptLeaf;
CachedDecompilation cd = null;
try {
cacheScriptPack(scriptLeaf, abcList);
cd = getCached(scriptLeaf);
} catch (InterruptedException ex) {
}
if (cd != null) {
final String hilightedCode = cd.text;
highlights = cd.getInstructionHighlights();
specialHighlights = cd.getSpecialHighligths();
traitHighlights = cd.getTraitHighlights();
methodHighlights = cd.getMethodHighlights();
classHighlights = cd.getClassHighlights();
setContentType("text/actionscript");
setText(hilightedCode);
}
}
public void reloadClass() {
int ci = classIndex;
uncache(script);
if ((script != null) && (abc != null)) {
setScript(script, abcList);
}
setNoTrait();
setClassIndex(ci);
}
public int getClassIndex() {
return classIndex;
}
public void setABC(ABC abc) {
this.abc = abc;
cache.clear();
setText("");
}
@Override
public void setText(String t) {
super.setText(t);
setCaretPosition(0);
}
}
@@ -0,0 +1,128 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.gui.AppDialog;
import com.jpexs.decompiler.flash.gui.View;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Hashtable;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
/**
*
* @author JPEXS
*/
public class DeobfuscationDialog extends AppDialog implements ActionListener {
static final String ACTION_OK = "OK";
static final String ACTION_CANCEL = "CANCEL";
public JCheckBox processAllCheckbox = new JCheckBox(translate("processallclasses"));
public JSlider codeProcessingLevel;
public boolean ok = false;
public static final int LEVEL_REMOVE_DEAD_CODE = 1;
public static final int LEVEL_REMOVE_TRAPS = 2;
public static final int LEVEL_RESTORE_CONTROL_FLOW = 3;
@SuppressWarnings("unchecked")
public DeobfuscationDialog() {
setDefaultCloseOperation(HIDE_ON_CLOSE);
setSize(new Dimension(330, 270));
setTitle(translate("dialog.title"));
Container cp = getContentPane();
cp.setLayout(new BoxLayout(cp, BoxLayout.Y_AXIS));
codeProcessingLevel = new JSlider(JSlider.VERTICAL, 1, 3, 3);
codeProcessingLevel.setMajorTickSpacing(1);
codeProcessingLevel.setPaintTicks(true);
codeProcessingLevel.setMinorTickSpacing(1);
codeProcessingLevel.setSnapToTicks(true);
JLabel lab1 = new JLabel(translate("deobfuscation.level"));
//lab1.setBounds(30, 0, getWidth() - 60, 25);
lab1.setAlignmentX(0.5f);
cp.add(lab1);
Hashtable labelTable = new Hashtable();
//labelTable.put(new Integer(LEVEL_NONE), new JLabel("None"));
labelTable.put(new Integer(LEVEL_REMOVE_DEAD_CODE), new JLabel(translate("deobfuscation.removedeadcode")));
labelTable.put(new Integer(LEVEL_REMOVE_TRAPS), new JLabel(translate("deobfuscation.removetraps")));
labelTable.put(new Integer(LEVEL_RESTORE_CONTROL_FLOW), new JLabel(translate("deobfuscation.restorecontrolflow")));
codeProcessingLevel.setLabelTable(labelTable);
codeProcessingLevel.setPaintLabels(true);
codeProcessingLevel.setAlignmentX(Component.CENTER_ALIGNMENT);
//codeProcessingLevel.setSize(300, 200);
//codeProcessingLevel.setBounds(30, 25, getWidth() - 60, 125);
codeProcessingLevel.setAlignmentX(0.5f);
add(codeProcessingLevel);
//processAllCheckbox.setBounds(50, 150, getWidth() - 100, 25);
processAllCheckbox.setAlignmentX(0.5f);
add(processAllCheckbox);
processAllCheckbox.setSelected(true);
JButton cancelButton = new JButton(translate("button.cancel"));
cancelButton.addActionListener(this);
cancelButton.setActionCommand(ACTION_CANCEL);
JButton okButton = new JButton(translate("button.ok"));
okButton.addActionListener(this);
okButton.setActionCommand(ACTION_OK);
JPanel buttonsPanel = new JPanel(new FlowLayout());
buttonsPanel.add(okButton);
buttonsPanel.add(cancelButton);
buttonsPanel.setAlignmentX(0.5f);
cp.add(buttonsPanel);
setModal(true);
View.centerScreen(this);
//View.setWindowIcon(this);
setIconImage(View.loadImage("deobfuscate16"));
}
@Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case ACTION_OK:
ok = true;
setVisible(false);
break;
case ACTION_CANCEL:
ok = false;
setVisible(false);
break;
}
}
@Override
public void setVisible(boolean b) {
if (b) {
ok = false;
}
super.setVisible(b);
}
}
@@ -0,0 +1,208 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.AppStrings;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.gui.HeaderLabel;
import com.jpexs.decompiler.flash.gui.View;
import com.jpexs.helpers.CancellableWorker;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.FlowLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashMap;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.border.BevelBorder;
/**
*
* @author JPEXS
*/
public class DetailPanel extends JPanel implements ActionListener {
static final String ACTION_SAVE_DETAIL = "SAVEDETAIL";
static final String ACTION_EDIT_DETAIL = "EDITDETAIL";
static final String ACTION_CANCEL_DETAIL = "CANCELDETAIL";
public MethodTraitDetailPanel methodTraitPanel;
public JPanel unsupportedTraitPanel;
public SlotConstTraitDetailPanel slotConstTraitPanel;
public static final String METHOD_TRAIT_CARD = AppStrings.translate("abc.detail.methodtrait");
public static final String UNSUPPORTED_TRAIT_CARD = AppStrings.translate("abc.detail.unsupported");
public static final String SLOT_CONST_TRAIT_CARD = AppStrings.translate("abc.detail.slotconsttrait");
private final JPanel innerPanel;
public JButton saveButton = new JButton(AppStrings.translate("button.save"), View.getIcon("save16"));
public JButton editButton = new JButton(AppStrings.translate("button.edit"), View.getIcon("edit16"));
public JButton cancelButton = new JButton(AppStrings.translate("button.cancel"), View.getIcon("cancel16"));
private final HashMap<String, JComponent> cardMap = new HashMap<>();
private String selectedCard;
private final JLabel selectedLabel;
private boolean editMode = false;
private final JPanel buttonsPanel;
private final ABCPanel abcPanel;
private final JLabel traitNameLabel;
public DetailPanel(ABCPanel abcPanel) {
this.abcPanel = abcPanel;
innerPanel = new JPanel();
CardLayout layout = new CardLayout();
innerPanel.setLayout(layout);
methodTraitPanel = new MethodTraitDetailPanel(abcPanel);
cardMap.put(METHOD_TRAIT_CARD, methodTraitPanel);
unsupportedTraitPanel = new JPanel(new BorderLayout());
JLabel unsup = new JLabel(AppStrings.translate("info.selecttrait"), SwingConstants.CENTER);
unsupportedTraitPanel.add(unsup, BorderLayout.CENTER);
cardMap.put(UNSUPPORTED_TRAIT_CARD, unsupportedTraitPanel);
slotConstTraitPanel = new SlotConstTraitDetailPanel(abcPanel.decompiledTextArea);
cardMap.put(SLOT_CONST_TRAIT_CARD, slotConstTraitPanel);
for (String key : cardMap.keySet()) {
innerPanel.add(cardMap.get(key), key);
}
setLayout(new BorderLayout());
add(innerPanel, BorderLayout.CENTER);
editButton.setMargin(new Insets(3, 3, 3, 10));
saveButton.setMargin(new Insets(3, 3, 3, 10));
cancelButton.setMargin(new Insets(3, 3, 3, 10));
buttonsPanel = new JPanel();
buttonsPanel.setLayout(new FlowLayout());
saveButton.setActionCommand(ACTION_SAVE_DETAIL);
saveButton.addActionListener(this);
editButton.setActionCommand(ACTION_EDIT_DETAIL);
editButton.addActionListener(this);
cancelButton.setActionCommand(ACTION_CANCEL_DETAIL);
cancelButton.addActionListener(this);
buttonsPanel.setBorder(new BevelBorder(BevelBorder.RAISED));
buttonsPanel.add(editButton);
buttonsPanel.add(saveButton);
buttonsPanel.add(cancelButton);
add(buttonsPanel, BorderLayout.SOUTH);
selectedCard = UNSUPPORTED_TRAIT_CARD;
layout.show(innerPanel, UNSUPPORTED_TRAIT_CARD);
buttonsPanel.setVisible(false);
selectedLabel = new HeaderLabel("");
selectedLabel.setText(selectedCard);
//selectedLabel.setBorder(new BevelBorder(BevelBorder.RAISED));
selectedLabel.setHorizontalAlignment(SwingConstants.CENTER);
JPanel topPanel = new JPanel(new BorderLayout());
topPanel.add(selectedLabel, BorderLayout.NORTH);
traitNameLabel = new JLabel("");
JPanel traitInfoPanel = new JPanel();
traitInfoPanel.setLayout(new BoxLayout(traitInfoPanel, BoxLayout.LINE_AXIS));
//traitInfoPanel.add(new JLabel(" " + translate("abc.detail.traitname")));
traitInfoPanel.add(traitNameLabel);
topPanel.add(traitInfoPanel, BorderLayout.CENTER);
add(topPanel, BorderLayout.NORTH);
}
public void setEditMode(boolean val) {
slotConstTraitPanel.setEditMode(val);
methodTraitPanel.setEditMode(val);
saveButton.setVisible(val);
editButton.setVisible(!val);
cancelButton.setVisible(val);
editMode = val;
if (val) {
selectedLabel.setIcon(View.getIcon("editing16"));
} else {
selectedLabel.setIcon(null);
}
}
public void showCard(String name, Trait trait) {
CardLayout layout = (CardLayout) innerPanel.getLayout();
layout.show(innerPanel, name);
boolean b = cardMap.get(name) instanceof TraitDetail;
buttonsPanel.setVisible(b);
TraitDetail newDetail = null;
if (b) {
newDetail = (TraitDetail) cardMap.get(name);
}
for (JComponent v : cardMap.values()) {
if (v instanceof TraitDetail) {
if (v != newDetail) {
TraitDetail oldDetail = (TraitDetail) v;
oldDetail.setActive(false);
}
}
}
if (newDetail != null) {
newDetail.setActive(true);
}
selectedCard = name;
selectedLabel.setText(selectedCard);
if (trait == null) {
traitNameLabel.setText("-");
} else {
traitNameLabel.setText(trait.getName(abcPanel.abc).getName(abcPanel.abc.constants, new ArrayList<String>()));
}
}
@Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case ACTION_EDIT_DETAIL:
setEditMode(true);
methodTraitPanel.methodCodePanel.focusEditor();
break;
case ACTION_CANCEL_DETAIL:
setEditMode(false);
abcPanel.decompiledTextArea.resetEditing();
break;
case ACTION_SAVE_DETAIL:
if (cardMap.get(selectedCard) instanceof TraitDetail) {
if (((TraitDetail) cardMap.get(selectedCard)).save()) {
CancellableWorker worker = new CancellableWorker() {
@Override
public Void doInBackground() throws Exception {
int lasttrait = abcPanel.decompiledTextArea.lastTraitIndex;
abcPanel.decompiledTextArea.reloadClass();
abcPanel.decompiledTextArea.gotoTrait(lasttrait);
return null;
}
@Override
protected void done() {
setEditMode(false);
View.showMessageDialog(null, AppStrings.translate("message.trait.saved"));
}
};
worker.execute();
}
}
break;
}
}
}
@@ -0,0 +1,45 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.AppStrings;
import com.jpexs.decompiler.flash.abc.avm2.parser.pcode.MissingSymbolHandler;
import com.jpexs.decompiler.flash.gui.View;
import javax.swing.JOptionPane;
public class DialogMissingSymbolHandler implements MissingSymbolHandler {
@Override
public boolean missingString(String value) {
return View.showConfirmDialog(null, AppStrings.translate("message.constant.new.string").replace("%value%", value), AppStrings.translate("message.constant.new.string.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.OK_OPTION;
}
@Override
public boolean missingInt(long value) {
return View.showConfirmDialog(null, AppStrings.translate("message.constant.new.integer").replace("%value%", "" + value), AppStrings.translate("message.constant.new.integer.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.OK_OPTION;
}
@Override
public boolean missingUInt(long value) {
return View.showConfirmDialog(null, AppStrings.translate("message.constant.new.unsignedinteger").replace("%value%", "" + value), AppStrings.translate("message.constant.new.unsignedinteger.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.OK_OPTION;
}
@Override
public boolean missingDouble(double value) {
return View.showConfirmDialog(null, AppStrings.translate("message.constant.new.double").replace("%value%", "" + value), AppStrings.translate("message.constant.new.double.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.OK_OPTION;
}
}
@@ -0,0 +1,72 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.gui.View;
import java.awt.Component;
import javax.swing.DefaultListCellRenderer;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JList;
public class IconListRenderer extends DefaultListCellRenderer {
private final Icon constIcon;
private final Icon functionIcon;
private final Icon variableIcon;
private Icon loadIcon(String path) {
ClassLoader cldr = this.getClass().getClassLoader();
java.net.URL imageURL = cldr.getResource(path);
return new ImageIcon(imageURL);
}
public IconListRenderer() {
constIcon = View.getIcon("constant");
functionIcon = View.getIcon("function");
variableIcon = View.getIcon("variable");
}
@Override
public Component getListCellRendererComponent(
JList list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
// Get the renderer component from parent class
JLabel label
= (JLabel) super.getListCellRendererComponent(list,
value, index, isSelected, cellHasFocus);
// Get icon to use for the list item value
TraitsListItem tli = (TraitsListItem) value;
if (tli.getType() == TraitsListItem.Type.CONST) {
label.setIcon(constIcon);
}
if (tli.getType() == TraitsListItem.Type.VAR) {
label.setIcon(variableIcon);
}
if (tli.getType() == TraitsListItem.Type.METHOD) {
label.setIcon(functionIcon);
}
if (tli.getType() == TraitsListItem.Type.INITIALIZER) {
label.setIcon(functionIcon);
}
return label;
}
}
@@ -0,0 +1,91 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.configuration.Configuration;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.Element;
import jsyntaxpane.actions.ActionUtils;
/**
*
* @author JPEXS
*/
public class LineMarkedEditorPane extends UndoFixedEditorPane {
int lastLine = -1;
public int getLine() {
return lastLine;
}
public void gotoLine(int line) {
setCaretPosition(ActionUtils.getDocumentPosition(this, line, 0));
}
public LineMarkedEditorPane() {
setOpaque(false);
addCaretListener(new CaretListener() {
@Override
public void caretUpdate(CaretEvent e) {
int caretPosition = getCaretPosition();
Element root = getDocument().getDefaultRootElement();
int currentLine = root.getElementIndex(caretPosition);
if (currentLine != lastLine) {
lastLine = currentLine;
repaint();
}
}
});
}
@Override
public void setText(String t) {
lastLine = -1;
if (Configuration.debugMode.get() && t.length() > 4192) {
t = t.substring(0, 4192);
}
super.setText(t);
setCaretPosition(0); //scroll to top
}
@Override
public void setText(String t, String contentType) {
lastLine = -1;
super.setText(t, contentType);
setCaretPosition(0); //scroll to top
}
@Override
public void paint(Graphics g) {
g.setColor(Color.white);
g.fillRect(0, 0, getWidth(), getHeight());
FontMetrics fontMetrics = g.getFontMetrics();
int lh = fontMetrics.getHeight();
int a = fontMetrics.getAscent();
int d = fontMetrics.getDescent();
int h = a + d;
int rH = h;
g.setColor(new Color(0xee, 0xee, 0xee));
g.fillRect(0, d + lh * lastLine - 1, getWidth(), lh);
super.paint(g);
}
}
@@ -0,0 +1,173 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.AppStrings;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.gui.Main;
import com.jpexs.decompiler.flash.gui.View;
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToggleButton;
/**
*
* @author JPEXS
*/
public class MethodCodePanel extends JPanel implements ActionListener {
static final String ACTION_GRAPH = "GRAPH";
static final String ACTION_HEX = "HEX";
static final String ACTION_HEX_ONLY = "HEXONLY";
private final ASMSourceEditorPane sourceTextArea;
public JPanel buttonsPanel;
private final JToggleButton hexButton;
private final JToggleButton hexOnlyButton;
public void focusEditor() {
sourceTextArea.requestFocusInWindow();
}
public String getTraitName() {
return sourceTextArea.getName();
}
public void setIgnoreCarret(boolean ignoreCarret) {
sourceTextArea.setIgnoreCarret(ignoreCarret);
}
public void hilighOffset(long offset) {
sourceTextArea.hilighOffset(offset);
}
public void hilighSpecial(String type, int index) {
sourceTextArea.hilighSpecial(type, index);
}
public void setBodyIndex(int bodyIndex, ABC abc, Trait trait) {
sourceTextArea.setBodyIndex(bodyIndex, abc, sourceTextArea.getName(), trait);
}
public void setBodyIndex(int bodyIndex, ABC abc, String name, Trait trait) {
sourceTextArea.setBodyIndex(bodyIndex, abc, name, trait);
}
public int getBodyIndex() {
return sourceTextArea.bodyIndex;
}
public void clear() {
sourceTextArea.clear();
}
public boolean save(ConstantPool constants) {
return sourceTextArea.save(constants);
}
public MethodCodePanel(DecompiledEditorPane decompiledEditor) {
sourceTextArea = new ASMSourceEditorPane(decompiledEditor);
setLayout(new BorderLayout());
add(new JScrollPane(sourceTextArea), BorderLayout.CENTER);
sourceTextArea.setContentType("text/flasm3");
sourceTextArea.setFont(new Font("Monospaced", Font.PLAIN, sourceTextArea.getFont().getSize()));
buttonsPanel = new JPanel();
buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.X_AXIS));
JButton graphButton = new JButton(View.getIcon("graph16"));
graphButton.setActionCommand(ACTION_GRAPH);
graphButton.addActionListener(this);
graphButton.setToolTipText(AppStrings.translate("button.viewgraph"));
graphButton.setMargin(new Insets(3, 3, 3, 3));
hexButton = new JToggleButton(View.getIcon("hexas16"));
hexButton.setActionCommand(ACTION_HEX);
hexButton.addActionListener(this);
hexButton.setToolTipText(AppStrings.translate("button.viewhex"));
hexButton.setMargin(new Insets(3, 3, 3, 3));
hexOnlyButton = new JToggleButton(View.getIcon("hex16"));
hexOnlyButton.setActionCommand(ACTION_HEX_ONLY);
hexOnlyButton.addActionListener(this);
hexOnlyButton.setToolTipText(AppStrings.translate("button.viewhex"));
hexOnlyButton.setMargin(new Insets(3, 3, 3, 3));
buttonsPanel.add(graphButton);
buttonsPanel.add(hexButton);
buttonsPanel.add(hexOnlyButton);
buttonsPanel.add(new JPanel());
// buttonsPanel.add(saveButton);
// buttonsPan.add(execButton);
add(buttonsPanel, BorderLayout.NORTH);
}
@Override
public void actionPerformed(ActionEvent e) {
if (Main.isWorking()) {
return;
}
switch (e.getActionCommand()) {
case ACTION_GRAPH:
sourceTextArea.graph();
break;
case ACTION_HEX:
case ACTION_HEX_ONLY:
if (e.getActionCommand() == ACTION_HEX) {
hexOnlyButton.setSelected(false);
} else {
hexButton.setSelected(false);
}
sourceTextArea.setHex(getExportMode(), false);
break;
}
}
private ScriptExportMode getExportMode() {
ScriptExportMode exportMode = hexOnlyButton.isSelected() ? ScriptExportMode.HEX
: (hexButton.isSelected() ? ScriptExportMode.PCODE_HEX : ScriptExportMode.PCODE);
return exportMode;
}
public void setEditMode(boolean val) {
ScriptExportMode exportMode = getExportMode();
if (val) {
sourceTextArea.setHex(exportMode == ScriptExportMode.HEX ? ScriptExportMode.HEX : ScriptExportMode.PCODE, false);
} else {
if (exportMode != ScriptExportMode.PCODE) {
sourceTextArea.setHex(exportMode, false);
}
}
sourceTextArea.setEditable(val);
sourceTextArea.getCaret().setVisible(true);
buttonsPanel.setVisible(!val);
}
}
@@ -0,0 +1,57 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import java.awt.BorderLayout;
import javax.swing.JPanel;
/**
*
* @author JPEXS
*/
public class MethodTraitDetailPanel extends JPanel implements TraitDetail {
public MethodCodePanel methodCodePanel;
public ABCPanel abcPanel;
public MethodTraitDetailPanel(ABCPanel abcPanel) {
this.abcPanel = abcPanel;
methodCodePanel = new MethodCodePanel(abcPanel.decompiledTextArea);
setLayout(new BorderLayout());
add(methodCodePanel, BorderLayout.CENTER);
}
@Override
public boolean save() {
if (!methodCodePanel.save(abcPanel.abc.constants)) {
return false;
}
return true;
}
@Override
public void setEditMode(boolean val) {
methodCodePanel.setEditMode(val);
}
private boolean active = false;
@Override
public void setActive(boolean val) {
this.active = val;
}
}
@@ -0,0 +1,179 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.AppStrings;
import com.jpexs.decompiler.flash.abc.types.Namespace;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.gui.AppDialog;
import com.jpexs.decompiler.flash.gui.View;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
/**
*
* @author JPEXS
*/
public class NewTraitDialog extends AppDialog implements ActionListener {
static final String ACTION_OK = "OK";
static final String ACTION_CANCEL = "CANCEL";
private static final int modifiers[] = new int[]{
Namespace.KIND_PACKAGE,
Namespace.KIND_PRIVATE,
Namespace.KIND_PROTECTED,
Namespace.KIND_NAMESPACE,
Namespace.KIND_PACKAGE_INTERNAL,
Namespace.KIND_EXPLICIT,
Namespace.KIND_STATIC_PROTECTED
};
private static final int types[] = new int[]{
Trait.TRAIT_METHOD,
Trait.TRAIT_GETTER,
Trait.TRAIT_SETTER,
Trait.TRAIT_CONST,
Trait.TRAIT_SLOT
};
private final JComboBox<String> accessComboBox;
private final JComboBox<String> typeComboBox;
private final JCheckBox staticCheckbox;
private final JTextField nameField;
public boolean getStatic() {
return staticCheckbox.isSelected();
}
public int getNamespaceKind() {
return modifiers[accessComboBox.getSelectedIndex()];
}
public int getTraitType() {
return types[typeComboBox.getSelectedIndex()];
}
public String getTraitName() {
return nameField.getText();
}
public NewTraitDialog() {
setSize(500, 300);
setTitle(translate("dialog.title"));
View.centerScreen(this);
View.setWindowIcon(this);
Container cnt = getContentPane();
cnt.setLayout(new BorderLayout());
JPanel optionsPanel = new JPanel(new FlowLayout());
//optionsPanel.add(new JLabel(translate("label.type")));
typeComboBox = new JComboBox<>(new String[]{
translate("type.method"),
translate("type.getter"),
translate("type.setter"),
translate("type.const"),
translate("type.slot"),});
staticCheckbox = new JCheckBox(translate("checkbox.static"));
optionsPanel.add(staticCheckbox);
String accessStrings[] = new String[modifiers.length];
for (int i = 0; i < accessStrings.length; i++) {
String pref = Namespace.kindToPrefix(modifiers[i]);
String name = Namespace.kindToStr(modifiers[i]);
accessStrings[i] = (pref.isEmpty() ? "" : pref + " ") + "(" + name + ")";
}
//optionsPanel.add(new JLabel(translate("label.access")));
accessComboBox = new JComboBox<>(accessStrings);
optionsPanel.add(accessComboBox);
optionsPanel.add(typeComboBox);
//optionsPanel.add(new JLabel(translate("label.name")));
nameField = new JTextField();
nameField.setPreferredSize(new Dimension(300, nameField.getPreferredSize().height));
optionsPanel.add(nameField);
cnt.add(optionsPanel, BorderLayout.CENTER);
JPanel buttonsPanel = new JPanel(new FlowLayout());
JButton buttonOk = new JButton(AppStrings.translate("button.ok"));
buttonOk.setActionCommand(ACTION_OK);
buttonOk.addActionListener(this);
JButton buttonCancel = new JButton(AppStrings.translate("button.cancel"));
buttonCancel.setActionCommand(ACTION_CANCEL);
buttonCancel.addActionListener(this);
buttonsPanel.add(buttonOk);
buttonsPanel.add(buttonCancel);
cnt.add(buttonsPanel, BorderLayout.SOUTH);
pack();
setDefaultCloseOperation(HIDE_ON_CLOSE);
setModalityType(ModalityType.APPLICATION_MODAL);
nameField.addAncestorListener(new AncestorListener() {
@Override
public void ancestorAdded(AncestorEvent event) {
JComponent component = event.getComponent();
component.requestFocusInWindow();
}
@Override
public void ancestorRemoved(AncestorEvent event) {
}
@Override
public void ancestorMoved(AncestorEvent event) {
}
});
getRootPane().setDefaultButton(buttonOk);
}
public boolean display() {
nameField.setText("");
setVisible(true);
return result;
}
private boolean result = false;
@Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case ACTION_OK:
if (nameField.getText().trim().isEmpty()) {
View.showMessageDialog(null, translate("error.name"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
return;
}
result = true;
setVisible(false);
break;
case ACTION_CANCEL:
result = false;
setVisible(false);
break;
}
}
}
@@ -0,0 +1,46 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
/**
*
* @author JPEXS
*/
public class RootABCContainerTag implements ABCContainerTag {
@Override
public ABC getABC() {
return null;
}
@Override
public int compareTo(ABCContainerTag t) {
if (t instanceof RootABCContainerTag) {
return 0;
}
return -1;
}
@Override
public String toString() {
return " - all - ";
}
}
@@ -0,0 +1,142 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.AppStrings;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.parser.ParseException;
import com.jpexs.decompiler.flash.abc.avm2.parser.pcode.ASM3Parser;
import com.jpexs.decompiler.flash.abc.types.ValueKind;
import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.gui.View;
import com.jpexs.decompiler.flash.helpers.HilightedTextWriter;
import com.jpexs.decompiler.flash.helpers.hilight.Highlighting;
import java.awt.BorderLayout;
import java.io.IOException;
import java.io.StringReader;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JEditorPane;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
/**
*
* @author JPEXS
*/
public class SlotConstTraitDetailPanel extends JPanel implements TraitDetail {
public JEditorPane slotConstEditor;
private ABC abc;
private TraitSlotConst trait;
private boolean showWarning = false;
private List<Highlighting> specialHilights;
private boolean ignoreCaret = false;
public SlotConstTraitDetailPanel(final DecompiledEditorPane editor) {
slotConstEditor = new LineMarkedEditorPane();
setLayout(new BorderLayout());
add(new JScrollPane(slotConstEditor), BorderLayout.CENTER);
slotConstEditor.setContentType("text/flasm3");
slotConstEditor.addCaretListener(new CaretListener() {
@Override
public void caretUpdate(CaretEvent e) {
if (ignoreCaret) {
return;
}
Highlighting spec = Highlighting.search(specialHilights, slotConstEditor.getCaretPosition());
if (spec != null) {
editor.hilightSpecial(spec.getPropertyString("subtype"), (int) (long) spec.getPropertyLong("index"));
slotConstEditor.getCaret().setVisible(true);
}
}
});
}
public void hilightSpecial(Highlighting special) {
Highlighting sel = null;
for (Highlighting h : specialHilights) {
if (h.getPropertyString("subtype").equals(special.getPropertyString("subtype"))) {
if (h.getPropertyString("index").equals(special.getPropertyString("index"))) {
sel = h;
break;
}
}
}
if (sel != null) {
ignoreCaret = true;
slotConstEditor.setCaretPosition(sel.startPos);
slotConstEditor.getCaret().setVisible(true);
ignoreCaret = false;
}
}
public void load(TraitSlotConst trait, ABC abc, boolean isStatic) {
this.abc = abc;
this.trait = trait;
HilightedTextWriter writer = new HilightedTextWriter(Configuration.getCodeFormatting(), true);
writer.appendNoHilight("trait ");
writer.hilightSpecial(abc.constants.multinameToString(trait.name_index), "traitname");
writer.appendNoHilight(" ");
writer.hilightSpecial(trait.isConst() ? "const" : "slot", "traittype");
writer.appendNoHilight(" slotid ");
writer.hilightSpecial("" + trait.slot_id, "slotid");
writer.appendNoHilight(" type ");
writer.hilightSpecial(abc.constants.multinameToString(trait.type_index), "traittypename");
writer.appendNoHilight(" value ");
writer.hilightSpecial((new ValueKind(trait.value_index, trait.value_kind).toASMString(abc.constants)), "traitvalue");
String s = writer.toString();
specialHilights = writer.specialHilights;
showWarning = trait.isConst() || isStatic;
slotConstEditor.setText(s);
}
@Override
public boolean save() {
try {//(slotConstEditor.getText(), trait, abc)
if (!ASM3Parser.parseSlotConst(new StringReader(slotConstEditor.getText()), abc.constants, trait)) {
return false;
}
} catch (ParseException ex) {
View.showMessageDialog(slotConstEditor, ex.text, AppStrings.translate("error.slotconst.typevalue"), JOptionPane.ERROR_MESSAGE);
return false;
} catch (IOException ex) {
Logger.getLogger(SlotConstTraitDetailPanel.class.getName()).log(Level.SEVERE, null, ex);
return false;
}
return true;
}
@Override
public void setEditMode(boolean val) {
if (val && active) {
JOptionPane.showMessageDialog(null, AppStrings.translate("warning.initializers"), AppStrings.translate("message.warning"), JOptionPane.WARNING_MESSAGE);
}
slotConstEditor.setEditable(val);
}
private boolean active = false;
@Override
public void setActive(boolean val) {
this.active = val;
}
}
@@ -0,0 +1,30 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
/**
*
* @author JPEXS
*/
public interface TraitDetail {
public void setEditMode(boolean val);
public boolean save();
public void setActive(boolean val);
}
@@ -0,0 +1,103 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.List;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class TraitsList extends JList<Object> implements ListSelectionListener {
ABC abc;
List<ABCContainerTag> abcTags;
int classIndex = -1;
private final ABCPanel abcPanel;
private boolean sorted = false;
public void setSorted(boolean sorted) {
if (getModel() instanceof TraitsListModel) {
((TraitsListModel) getModel()).setSorted(sorted);
}
this.sorted = sorted;
}
public int getClassIndex() {
return classIndex;
}
public TraitsList(ABCPanel abcPanel) {
addListSelectionListener(this);
this.abcPanel = abcPanel;
setCellRenderer(new IconListRenderer());
//setUI(new BasicListUI());
setBackground(Color.white);
}
public void clearABC() {
this.abc = null;
this.abcTags = null;
setModel(new DefaultListModel<>());
}
public void setABC(List<ABCContainerTag> abcTags, ABC abc) {
this.abc = abc;
this.abcTags = abcTags;
setModel(new DefaultListModel<>());
setClassIndex(-1, -1);
}
public void setClassIndex(int classIndex, int scriptIndex) {
if (classIndex >= abc.instance_info.size()) {
return;
}
this.classIndex = classIndex;
if (classIndex == -1) {
setModel(new DefaultListModel<>());
} else {
if (abc != null) {
setModel(new TraitsListModel(abcTags, abc, classIndex, scriptIndex, sorted));
}
}
}
private int lastSelected = -1;
@Override
public void valueChanged(ListSelectionEvent e) {
if (getSelectedIndex() == lastSelected) {
return;
}
lastSelected = getSelectedIndex();
TraitsListItem sel = (TraitsListItem) getSelectedValue();
abcPanel.decompiledTextArea.gotoTrait(sel == null ? -1 : sel.getGlobalTraitId());
}
@Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setComposite(AlphaComposite.SrcOver);
super.paint(g);
}
}
@@ -0,0 +1,142 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.AppStrings;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter;
import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.helpers.HilightedTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class TraitsListItem {
private final Type type;
private final boolean isStatic;
private final List<ABCContainerTag> abcTags;
private final ABC abc;
private final int classIndex;
private final int index;
private final int scriptIndex;
public String STR_INSTANCE_INITIALIZER = AppStrings.translate("abc.traitslist.instanceinitializer");
public String STR_CLASS_INITIALIZER = AppStrings.translate("abc.traitslist.classinitializer");
public TraitsListItem(Type type, int index, boolean isStatic, List<ABCContainerTag> abcTags, ABC abc, int classIndex, int scriptIndex) {
this.type = type;
this.index = index;
this.isStatic = isStatic;
this.abcTags = abcTags;
this.abc = abc;
this.classIndex = classIndex;
this.scriptIndex = scriptIndex;
}
public int getGlobalTraitId() {
if (type == Type.INITIALIZER) {
if (!isStatic) {
return abc.class_info.get(classIndex).static_traits.traits.size() + abc.instance_info.get(classIndex).instance_traits.traits.size();
} else {
return abc.class_info.get(classIndex).static_traits.traits.size() + abc.instance_info.get(classIndex).instance_traits.traits.size() + 1;
}
}
if (isStatic) {
return index;
} else {
return abc.class_info.get(classIndex).static_traits.traits.size() + index;
}
}
public String toStringName() {
if ((type != Type.INITIALIZER) && isStatic) {
return abc.class_info.get(classIndex).static_traits.traits.get(index).getName(abc).getName(abc.constants, new ArrayList<String>());
} else if ((type != Type.INITIALIZER) && (!isStatic)) {
return abc.instance_info.get(classIndex).instance_traits.traits.get(index).getName(abc).getName(abc.constants, new ArrayList<String>());
} else if (!isStatic) {
return "__" + STR_INSTANCE_INITIALIZER;
} else {
return "__" + STR_CLASS_INITIALIZER;
}
}
@Override
public String toString() {
String s = "";
try {
if ((type != Type.INITIALIZER) && isStatic) {
abc.class_info.get(classIndex).static_traits.traits.get(index).convertHeader(null, "", abcTags, abc, true, ScriptExportMode.AS, scriptIndex, classIndex, new NulWriter(), new ArrayList<String>(), false);
HilightedTextWriter writer = new HilightedTextWriter(Configuration.getCodeFormatting(), false);
abc.class_info.get(classIndex).static_traits.traits.get(index).toStringHeader(null, "", abcTags, abc, true, ScriptExportMode.AS, scriptIndex, classIndex, writer, new ArrayList<String>(), false);
s = writer.toString();
} else if ((type != Type.INITIALIZER) && (!isStatic)) {
abc.instance_info.get(classIndex).instance_traits.traits.get(index).convertHeader(null, "", abcTags, abc, false, ScriptExportMode.AS, scriptIndex, classIndex, new NulWriter(), new ArrayList<String>(), false);
HilightedTextWriter writer = new HilightedTextWriter(Configuration.getCodeFormatting(), false);
abc.instance_info.get(classIndex).instance_traits.traits.get(index).toStringHeader(null, "", abcTags, abc, false, ScriptExportMode.AS, scriptIndex, classIndex, writer, new ArrayList<String>(), false);
s = writer.toString();
} else if (!isStatic) {
s = STR_INSTANCE_INITIALIZER;
} else {
s = STR_CLASS_INITIALIZER;
}
} catch (InterruptedException ex) {
Logger.getLogger(TraitsListItem.class.getName()).log(Level.SEVERE, null, ex);
}
s = s.replaceAll("[ \r\n]+", " ");
return s;
}
public Type getType() {
return type;
}
public boolean isStatic() {
return isStatic;
}
public enum Type {
METHOD,
VAR,
CONST,
INITIALIZER;
public static Type getTypeForTrait(Trait t) {
if (t instanceof TraitMethodGetterSetter) {
return METHOD;
}
if (t instanceof TraitSlotConst) {
if (((TraitSlotConst) t).isConst()) {
return CONST;
} else {
return VAR;
}
}
return null;
}
}
}
@@ -0,0 +1,89 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.swing.ListModel;
import javax.swing.event.ListDataListener;
public final class TraitsListModel implements ListModel<Object> {
private List<TraitsListItem> items;
private final List<ABCContainerTag> abcTags;
private final ABC abc;
private final int classIndex;
private final int scriptIndex;
public void setSorted(boolean sorted) {
if (sorted) {
Collections.sort(items, new Comparator<TraitsListItem>() {
@Override
public int compare(TraitsListItem o1, TraitsListItem o2) {
return o1.toStringName().compareTo(o2.toStringName());
}
});
} else {
reset();
}
}
private void reset() {
items = new ArrayList<>();
for (int t = 0; t < abc.class_info.get(classIndex).static_traits.traits.size(); t++) {
items.add(new TraitsListItem(TraitsListItem.Type.getTypeForTrait(abc.class_info.get(classIndex).static_traits.traits.get(t)), t, true, abcTags, abc, classIndex, scriptIndex));
}
for (int t = 0; t < abc.instance_info.get(classIndex).instance_traits.traits.size(); t++) {
items.add(new TraitsListItem(TraitsListItem.Type.getTypeForTrait(abc.instance_info.get(classIndex).instance_traits.traits.get(t)), t, false, abcTags, abc, classIndex, scriptIndex));
}
items.add(new TraitsListItem(TraitsListItem.Type.INITIALIZER, 0, false, abcTags, abc, classIndex, scriptIndex));
items.add(new TraitsListItem(TraitsListItem.Type.INITIALIZER, 0, true, abcTags, abc, classIndex, scriptIndex));
}
public TraitsListModel(List<ABCContainerTag> abcTags, ABC abc, int classIndex, int scriptIndex, boolean sorted) {
this.abcTags = abcTags;
this.abc = abc;
this.classIndex = classIndex;
this.scriptIndex = scriptIndex;
reset();
if (sorted) {
setSorted(true);
}
}
@Override
public int getSize() {
return items.size();
}
@Override
public Object getElementAt(int index) {
return items.get(index);
}
@Override
public void addListDataListener(ListDataListener l) {
}
@Override
public void removeListDataListener(ListDataListener l) {
}
}
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2010-2014 Paolo Cancedda
*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.abc.ScriptPack;
import com.jpexs.decompiler.flash.gui.abc.treenodes.AS3PackageNode;
import com.jpexs.decompiler.flash.gui.abc.treenodes.TreeElement;
import com.jpexs.decompiler.flash.treeitems.AS3PackageNodeItem;
import java.util.StringTokenizer;
public class Tree {
private final TreeElement ROOT = new AS3PackageNode("", "", new AS3PackageNodeItem(null, null), null);
public void add(String name, String path, ScriptPack item) {
StringTokenizer st = new StringTokenizer(path, ".");
TreeElement parent = ROOT;
while (st.hasMoreTokens()) {
String pathElement = st.nextToken();
parent = parent.getBranch(pathElement, item.getSwf());
}
parent.addLeaf(name, item);
}
public TreeElement getRoot() {
return ROOT;
}
public void visit(TreeVisitor visitor) {
ROOT.visitLeafs(visitor);
ROOT.visitBranches(visitor);
}
}
@@ -0,0 +1,26 @@
/*
* Copyright (C) 2010-2014 Paolo Cancedda
*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.gui.abc.treenodes.TreeElement;
public interface TreeVisitor {
public void onBranch(TreeElement branch);
public void onLeaf(TreeElement leaf);
}
@@ -0,0 +1,76 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.configuration.Configuration;
import java.awt.event.KeyEvent;
import javax.swing.JEditorPane;
import javax.swing.text.Document;
import jsyntaxpane.SyntaxDocument;
/**
*
* @author JPEXS
*/
public class UndoFixedEditorPane extends JEditorPane {
@Override
public void setText(String t) {
if (getText() != t) {
super.setText(t);
clearUndos();
}
}
public void setText(String t, String contentType) {
if (getText() != t) {
// OK to check reference equals, because the string object should be the same
super.setText(null);
if (t.length() > Configuration.syntaxHighlightLimit.get()) {
setContentType("text/plain");
} else {
if (!getContentType().equals(contentType)) {
setContentType(contentType);
}
}
super.setText(t);
clearUndos();
}
}
@Override
protected void processKeyEvent(KeyEvent ke) {
if (!isEditable()) {
// disable Ctrl-E: delete line
// and Ctrl-H: Search and replace
if ((ke.getKeyCode() == KeyEvent.VK_E && ke.isControlDown())
|| (ke.getKeyCode() == KeyEvent.VK_H && ke.isControlDown())) {
return;
}
}
super.processKeyEvent(ke);
}
public void clearUndos() {
Document doc = getDocument();
if (doc instanceof SyntaxDocument) {
SyntaxDocument sdoc = (SyntaxDocument) doc;
sdoc.clearUndos();
}
}
}
@@ -0,0 +1,154 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.usages.InsideClassMultinameUsage;
import com.jpexs.decompiler.flash.abc.usages.MethodMultinameUsage;
import com.jpexs.decompiler.flash.abc.usages.MultinameUsage;
import com.jpexs.decompiler.flash.abc.usages.TraitMultinameUsage;
import com.jpexs.decompiler.flash.gui.AppFrame;
import com.jpexs.decompiler.flash.gui.View;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
/**
*
* @author JPEXS
*/
public class UsageFrame extends AppFrame implements ActionListener, MouseListener {
static final String ACTION_GOTO = "GOTO";
static final String ACTION_CANCEL = "CANCEL";
private final JButton gotoButton = new JButton(translate("button.goto"));
private final JButton cancelButton = new JButton(translate("button.cancel"));
private final JList usageList;
private final UsageListModel usageListModel;
private final ABC abc;
private final ABCPanel abcPanel;
public UsageFrame(List<ABCContainerTag> abcTags, ABC abc, int multinameIndex, ABCPanel abcPanel) {
this.abcPanel = abcPanel;
List<MultinameUsage> usages = abc.findMultinameUsage(multinameIndex);
this.abc = abc;
usageListModel = new UsageListModel(abcTags, abc);
for (MultinameUsage u : usages) {
usageListModel.addElement(u);
}
usageList = new JList<>(usageListModel);
usageList.setBackground(Color.white);
gotoButton.setActionCommand(ACTION_GOTO);
gotoButton.addActionListener(this);
cancelButton.setActionCommand(ACTION_CANCEL);
cancelButton.addActionListener(this);
JPanel buttonsPanel = new JPanel();
buttonsPanel.setLayout(new FlowLayout());
buttonsPanel.add(gotoButton);
buttonsPanel.add(cancelButton);
usageList.addMouseListener(this);
Container cont = getContentPane();
cont.setLayout(new BorderLayout());
cont.add(new JScrollPane(usageList), BorderLayout.CENTER);
cont.add(buttonsPanel, BorderLayout.SOUTH);
setSize(400, 300);
setTitle(translate("dialog.title") + abc.constants.getMultiname(multinameIndex).getNameWithNamespace(abc.constants));
View.centerScreen(this);
View.setWindowIcon(this);
}
private void gotoUsage() {
if (usageList.getSelectedIndex() != -1) {
MultinameUsage usage = usageListModel.getUsage(usageList.getSelectedIndex());
if (usage instanceof InsideClassMultinameUsage) {
InsideClassMultinameUsage icu = (InsideClassMultinameUsage) usage;
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
}
if (usage instanceof TraitMultinameUsage) {
TraitMultinameUsage tmu = (TraitMultinameUsage) usage;
int traitIndex;
if (tmu.parentTraitIndex > -1) {
traitIndex = tmu.parentTraitIndex;
} else {
traitIndex = tmu.traitIndex;
}
if (!tmu.isStatic) {
traitIndex += abc.class_info.get(tmu.classIndex).static_traits.traits.size();
}
if (tmu instanceof MethodMultinameUsage) {
MethodMultinameUsage mmu = (MethodMultinameUsage) usage;
if (mmu.isInitializer == true) {
traitIndex = abc.class_info.get(mmu.classIndex).static_traits.traits.size() + abc.instance_info.get(mmu.classIndex).instance_traits.traits.size() + (mmu.isStatic ? 1 : 0);
}
}
abcPanel.decompiledTextArea.gotoTrait(traitIndex);
}
}
}
}
@Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case ACTION_GOTO:
gotoUsage();
setVisible(false);
break;
case ACTION_CANCEL:
setVisible(false);
break;
}
}
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
gotoUsage();
}
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}
@@ -0,0 +1,64 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.usages.MultinameUsage;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultListModel;
/**
*
* @author JPEXS
*/
public class UsageListModel extends DefaultListModel<Object> {
private final ABC abc;
private final List<ABCContainerTag> abcTags;
public UsageListModel(List<ABCContainerTag> abcTags, ABC abc) {
this.abc = abc;
this.abcTags = abcTags;
}
@Override
public Object get(int index) {
try {
return ((MultinameUsage) super.get(index)).toString(abcTags, abc);
} catch (InterruptedException ex) {
Logger.getLogger(UsageListModel.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
@Override
public Object getElementAt(int index) {
try {
return ((MultinameUsage) super.getElementAt(index)).toString(abcTags, abc);
} catch (InterruptedException ex) {
Logger.getLogger(UsageListModel.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
public MultinameUsage getUsage(int index) {
return ((MultinameUsage) super.getElementAt(index));
}
}

Some files were not shown because too many files have changed in this diff Show More