mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-05-25 21:07:08 +00:00
428 lines
16 KiB
Java
428 lines
16 KiB
Java
/*
|
|
* Copyright (C) 2010-2021 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.SWFSourceInfo;
|
|
import com.jpexs.decompiler.flash.configuration.Configuration;
|
|
import com.jpexs.helpers.Helper;
|
|
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.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.io.File;
|
|
import java.io.IOException;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
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 JPEXS
|
|
*/
|
|
public class LoadFromMemoryFrame extends AppFrame {
|
|
|
|
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 {
|
|
return new SearchInMemory(new SearchInMemoryListener() {
|
|
@Override
|
|
public void publish(Object... chunks) {
|
|
SelectProcessWorker.this.publish(chunks);
|
|
}
|
|
|
|
@Override
|
|
public void setProgress(int progress) {
|
|
SelectProcessWorker.this.setProgress(progress);
|
|
}
|
|
}).search(procs);
|
|
}
|
|
}
|
|
|
|
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(), swf.address});
|
|
} else {
|
|
String notFound = translate("notfound");
|
|
resTableModel.addRow(new Object[]{notFound, 0, "", "", 0});
|
|
}
|
|
}
|
|
|
|
private void refreshList() {
|
|
model.clear();
|
|
processList = ProcessTools.listProcesses();
|
|
if (processList != null) {
|
|
Collections.sort(processList);
|
|
for (com.jpexs.process.Process p : processList) {
|
|
model.addElement(p);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void openSwf() {
|
|
View.checkAccess();
|
|
|
|
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((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;
|
|
case 4:
|
|
return Long.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"));
|
|
resTableModel.addColumn(translate("column.address"));
|
|
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() == KeyEvent.VK_ENTER) { //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() == KeyEvent.VK_ENTER) { //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.addActionListener(this::selectProcessButtonActionPerformed);
|
|
JButton refreshButton = new JButton(translate("button.refresh"));
|
|
refreshButton.addActionListener(this::refreshProcessListButtonActionPerformed);
|
|
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.addActionListener(this::openSwfButtonActionPerformed);
|
|
|
|
JButton saveButton = new JButton(translate("button.save"));
|
|
saveButton.addActionListener(this::saveButtonActionPerformed);
|
|
|
|
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);
|
|
List<Image> images = new ArrayList<>();
|
|
images.add(View.loadImage("loadmemory16"));
|
|
images.add(View.loadImage("loadmemory32"));
|
|
setIconImages(images);
|
|
}
|
|
|
|
private void selectProcessButtonActionPerformed(ActionEvent evt) {
|
|
selectProcess();
|
|
}
|
|
|
|
private void openSwfButtonActionPerformed(ActionEvent evt) {
|
|
openSwf();
|
|
}
|
|
|
|
private void refreshProcessListButtonActionPerformed(ActionEvent evt) {
|
|
refreshList();
|
|
}
|
|
|
|
private void saveButtonActionPerformed(ActionEvent evt) {
|
|
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);
|
|
if (fc.showSaveDialog(f) == 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"));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|