mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-09-25 00:00:47 +00:00
Tabbed interface.
This commit is contained in:
@@ -16,451 +16,44 @@
|
|||||||
*/
|
*/
|
||||||
package com.jpexs.decompiler.flash.easygui;
|
package com.jpexs.decompiler.flash.easygui;
|
||||||
|
|
||||||
import com.jpexs.decompiler.flash.DefineBeforeUsageFixer;
|
|
||||||
import com.jpexs.decompiler.flash.ReadOnlyTagList;
|
|
||||||
import com.jpexs.decompiler.flash.SWF;
|
import com.jpexs.decompiler.flash.SWF;
|
||||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
|
||||||
import com.jpexs.decompiler.flash.gui.FasterScrollPane;
|
|
||||||
import com.jpexs.decompiler.flash.gui.ImagePanel;
|
|
||||||
import com.jpexs.decompiler.flash.gui.RegistrationPointPosition;
|
|
||||||
import com.jpexs.decompiler.flash.gui.TimelinedMaker;
|
|
||||||
import com.jpexs.decompiler.flash.gui.TransformPanel;
|
|
||||||
import com.jpexs.decompiler.flash.gui.View;
|
import com.jpexs.decompiler.flash.gui.View;
|
||||||
import com.jpexs.decompiler.flash.gui.controls.JPersistentSplitPane;
|
|
||||||
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
|
|
||||||
import com.jpexs.decompiler.flash.tags.PlaceObject2Tag;
|
|
||||||
import com.jpexs.decompiler.flash.tags.RemoveObject2Tag;
|
|
||||||
import com.jpexs.decompiler.flash.tags.ShowFrameTag;
|
|
||||||
import com.jpexs.decompiler.flash.tags.Tag;
|
|
||||||
import com.jpexs.decompiler.flash.tags.base.ButtonTag;
|
|
||||||
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
|
|
||||||
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
|
|
||||||
import com.jpexs.decompiler.flash.tags.base.ShapeTag;
|
|
||||||
import com.jpexs.decompiler.flash.tags.base.TextTag;
|
|
||||||
import com.jpexs.decompiler.flash.timeline.DepthState;
|
|
||||||
import com.jpexs.decompiler.flash.timeline.Frame;
|
|
||||||
import com.jpexs.decompiler.flash.timeline.Timelined;
|
|
||||||
import com.jpexs.decompiler.flash.types.MATRIX;
|
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.Container;
|
|
||||||
import java.awt.Dimension;
|
|
||||||
import java.awt.FlowLayout;
|
|
||||||
import java.awt.Insets;
|
|
||||||
import java.awt.datatransfer.Transferable;
|
|
||||||
import java.awt.datatransfer.UnsupportedFlavorException;
|
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
import java.awt.geom.Point2D;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.swing.JButton;
|
|
||||||
import javax.swing.JFrame;
|
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JScrollPane;
|
|
||||||
import javax.swing.JSplitPane;
|
|
||||||
import javax.swing.JTabbedPane;
|
|
||||||
import javax.swing.TransferHandler;
|
|
||||||
import javax.swing.UIManager;
|
|
||||||
import javax.swing.event.ChangeEvent;
|
|
||||||
import javax.swing.event.ChangeListener;
|
|
||||||
import javax.swing.event.ListSelectionEvent;
|
|
||||||
import javax.swing.event.ListSelectionListener;
|
|
||||||
import javax.swing.tree.DefaultMutableTreeNode;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author JPEXS
|
* @author JPEXS
|
||||||
*/
|
*/
|
||||||
public class EasyPanel extends JPanel {
|
public class EasyPanel extends JPanel {
|
||||||
|
private TabSwitcher<SWF> tabSwitcher;
|
||||||
private LibraryTreeTable libraryTreeTable;
|
private EasySwfPanel easySwfPanel;
|
||||||
private JSplitPane verticalSplitPane;
|
|
||||||
private JSplitPane horizontalSplitPane;
|
|
||||||
private ImagePanel libraryPreviewPanel;
|
|
||||||
private ImagePanel stagePanel;
|
|
||||||
private TimelinePanel timelinePanel;
|
|
||||||
private JButton undoButton;
|
|
||||||
private JButton redoButton;
|
|
||||||
private UndoManager undoManager;
|
|
||||||
private JTabbedPane rightTabbedPane;
|
|
||||||
private TransformPanel transformPanel;
|
|
||||||
|
|
||||||
public EasyPanel() {
|
public EasyPanel() {
|
||||||
setSize(1024, 768);
|
easySwfPanel = new EasySwfPanel();
|
||||||
|
tabSwitcher = new TabSwitcher<>(easySwfPanel);
|
||||||
setLayout(new BorderLayout());
|
setLayout(new BorderLayout());
|
||||||
|
add(tabSwitcher, BorderLayout.CENTER);
|
||||||
stagePanel = new ImagePanel();
|
tabSwitcher.addTabSwitchedListener(new TabSwitchedListener<SWF>() {
|
||||||
stagePanel.setTagNameResolver(new EasyTagNameResolver());
|
|
||||||
stagePanel.setShowAllDepthLevelsInfo(false);
|
|
||||||
stagePanel.setSelectionMode(true);
|
|
||||||
stagePanel.addPlaceObjectSelectedListener(new ActionListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void tabSwitched(SWF value) {
|
||||||
PlaceObjectTypeTag pl = stagePanel.getPlaceTagUnderCursor();
|
easySwfPanel.setTimelined(value);
|
||||||
if (pl != null) {
|
|
||||||
timelinePanel.setDepth(pl.getDepth());
|
|
||||||
}
|
|
||||||
transformPanel.setVisible(pl != null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
stagePanel.addTransformChangeListener(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
final int depth = stagePanel.getSelectedDepth();
|
|
||||||
final int frame = stagePanel.getFrame();
|
|
||||||
final MATRIX newMatrix = stagePanel.getNewMatrix().toMATRIX();
|
|
||||||
MATRIX previousMatrix = null;
|
|
||||||
synchronized (stagePanel) {
|
|
||||||
DepthState ds = stagePanel.getTimelined().getTimeline().getFrame(frame).layers.get(depth);
|
|
||||||
previousMatrix = ds.placeObjectTag.getMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
final Point2D regPoint = stagePanel.getRegistrationPoint();
|
|
||||||
final RegistrationPointPosition regPointPos = stagePanel.getRegistrationPointPosition();
|
|
||||||
|
|
||||||
final MATRIX fpreviousMatrix = previousMatrix;
|
|
||||||
|
|
||||||
final boolean transformEnabled = transformEnabled();
|
|
||||||
undoManager.doOperation(new DoableOperation() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void doOperation() {
|
|
||||||
timelinePanel.setFrame(frame, depth);
|
|
||||||
DepthState ds = stagePanel.getTimelined().getTimeline().getFrame(frame).layers.get(depth);
|
|
||||||
ds.placeObjectTag.setMatrix(newMatrix);
|
|
||||||
ds.placeObjectTag.setPlaceFlagHasMatrix(newMatrix != null);
|
|
||||||
stagePanel.getTimelined().resetTimeline();
|
|
||||||
stagePanel.repaint();
|
|
||||||
if (transformEnabled()) {
|
|
||||||
stagePanel.freeTransformDepth(depth);
|
|
||||||
stagePanel.setRegistrationPoint(regPoint);
|
|
||||||
if (regPointPos != null) {
|
|
||||||
stagePanel.setRegistrationPointPosition(regPointPos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void undoOperation() {
|
|
||||||
timelinePanel.setFrame(frame, depth);
|
|
||||||
DepthState ds = stagePanel.getTimelined().getTimeline().getFrame(frame).layers.get(depth);
|
|
||||||
ds.placeObjectTag.setMatrix(fpreviousMatrix);
|
|
||||||
ds.placeObjectTag.setPlaceFlagHasMatrix(fpreviousMatrix != null);
|
|
||||||
stagePanel.getTimelined().resetTimeline();
|
|
||||||
stagePanel.repaint();
|
|
||||||
if (transformEnabled()) {
|
|
||||||
stagePanel.freeTransformDepth(depth);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
|
||||||
return EasyStrings.translate(transformEnabled ? "action.transform" : "action.move");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
stagePanel.setTransferHandler(new TransferHandler() {
|
|
||||||
@Override
|
|
||||||
public boolean canImport(TransferHandler.TransferSupport support) {
|
|
||||||
return support.isDataFlavorSupported(CharacterTagTransferable.CHARACTERTAG_FLAVOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean importData(TransferHandler.TransferSupport support) {
|
|
||||||
if (!canImport(support)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Transferable transferable = support.getTransferable();
|
|
||||||
Integer characterId = (Integer) transferable.getTransferData(CharacterTagTransferable.CHARACTERTAG_FLAVOR);
|
|
||||||
CharacterTag tag = stagePanel.getTimelined().getSwf().getCharacter(characterId);
|
|
||||||
if ((tag instanceof DefineSpriteTag)
|
|
||||||
|| (tag instanceof ShapeTag)
|
|
||||||
|| (tag instanceof TextTag)
|
|
||||||
|| (tag instanceof ButtonTag)
|
|
||||||
) {
|
|
||||||
|
|
||||||
undoManager.doOperation(new DoableOperation() {
|
|
||||||
|
|
||||||
private PlaceObject2Tag place;
|
|
||||||
private RemoveObject2Tag remove;
|
|
||||||
private List<Tag> tags;
|
|
||||||
private int frame = stagePanel.getFrame();
|
|
||||||
private int depth = stagePanel.getSelectedDepth();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void doOperation() {
|
|
||||||
timelinePanel.setFrame(frame, depth);
|
|
||||||
CharacterTag ch = (CharacterTag) tag;
|
|
||||||
int maxDepth = stagePanel.getTimelined().getTimeline().getMaxDepth();
|
|
||||||
int newDepth = maxDepth + 1;
|
|
||||||
Timelined timelined = stagePanel.getTimelined();
|
|
||||||
|
|
||||||
tags = timelined.getSwf().getTags().toArrayList();
|
|
||||||
|
|
||||||
ShowFrameTag showFrameTag = timelined.getTimeline().getFrame(frame).showFrameTag;
|
|
||||||
place = new PlaceObject2Tag(timelined.getSwf());
|
|
||||||
place.depth = newDepth;
|
|
||||||
place.placeFlagHasCharacter = true;
|
|
||||||
place.characterId = ch.getCharacterId();
|
|
||||||
place.matrix = new MATRIX();
|
|
||||||
place.placeFlagHasMatrix = true;
|
|
||||||
place.setTimelined(timelined);
|
|
||||||
if (showFrameTag == null) {
|
|
||||||
timelined.addTag(place);
|
|
||||||
} else {
|
|
||||||
timelined.addTag(timelined.indexOfTag(showFrameTag), place);
|
|
||||||
|
|
||||||
remove = new RemoveObject2Tag(timelined.getSwf());
|
|
||||||
remove.depth = newDepth;
|
|
||||||
timelined.addTag(timelined.indexOfTag(showFrameTag) + 1, remove);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DefineBeforeUsageFixer fixer = new DefineBeforeUsageFixer();
|
|
||||||
boolean tagOrderChanged = fixer.fixDefineBeforeUsage(timelined.getSwf());
|
|
||||||
if (!tagOrderChanged) {
|
|
||||||
tags = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
timelined.resetTimeline();
|
|
||||||
stagePanel.repaint();
|
|
||||||
timelinePanel.refresh();
|
|
||||||
timelinePanel.setDepth(newDepth);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void undoOperation() {
|
|
||||||
Timelined timelined = place.getTimelined();
|
|
||||||
timelined.removeTag(place);
|
|
||||||
if (remove != null) {
|
|
||||||
timelined.removeTag(remove);
|
|
||||||
}
|
|
||||||
timelined.resetTimeline();
|
|
||||||
|
|
||||||
//Tag order changed, put the original tags back
|
|
||||||
if (tags != null) {
|
|
||||||
SWF swf = timelined.getSwf();
|
|
||||||
ReadOnlyTagList newTags = swf.getTags();
|
|
||||||
int size = newTags.size();
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
swf.removeTag(0);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < tags.size(); i++) {
|
|
||||||
if (tags.get(i) == place) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
swf.addTag(tags.get(i));
|
|
||||||
}
|
|
||||||
swf.resetTimeline();
|
|
||||||
}
|
|
||||||
|
|
||||||
stagePanel.repaint();
|
|
||||||
timelinePanel.refresh();
|
|
||||||
timelinePanel.setFrame(frame, depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
|
||||||
return EasyStrings.translate("action.addToStage");
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} catch (UnsupportedFlavorException | IOException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
//ignored
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
undoManager = new UndoManager();
|
|
||||||
|
|
||||||
JPanel topPanel = new JPanel(new BorderLayout());
|
|
||||||
|
|
||||||
JPanel toolbarPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
|
|
||||||
|
|
||||||
undoButton = new JButton(View.getIcon("rotateanticlockwise16"));
|
|
||||||
//undoButton.setToolTipText("Undo");
|
|
||||||
undoButton.setMargin(new Insets(5, 5, 5, 5));
|
|
||||||
undoButton.addActionListener(new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
undoManager.undo();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
redoButton = new JButton(View.getIcon("rotateclockwise16"));
|
|
||||||
//redoButton.setToolTipText("Redo");
|
|
||||||
redoButton.setMargin(new Insets(5, 5, 5, 5));
|
|
||||||
redoButton.addActionListener(new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
undoManager.redo();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Runnable undoChangeListener = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
undoButton.setEnabled(undoManager.canUndo());
|
|
||||||
redoButton.setEnabled(undoManager.canRedo());
|
|
||||||
if (undoManager.canUndo()) {
|
|
||||||
undoButton.setToolTipText(EasyStrings.translate("undo").replace("%action%",undoManager.getUndoName()));
|
|
||||||
} else {
|
|
||||||
undoButton.setToolTipText(EasyStrings.translate("undo.cannot"));
|
|
||||||
}
|
|
||||||
if (undoManager.canRedo()) {
|
|
||||||
redoButton.setToolTipText(EasyStrings.translate("redo").replace("%action%", undoManager.getRedoName()));
|
|
||||||
} else {
|
|
||||||
redoButton.setToolTipText(EasyStrings.translate("redo.cannot"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
undoManager.addChangeListener(undoChangeListener);
|
|
||||||
undoChangeListener.run();
|
|
||||||
|
|
||||||
toolbarPanel.add(undoButton);
|
|
||||||
toolbarPanel.add(redoButton);
|
|
||||||
|
|
||||||
topPanel.add(toolbarPanel, BorderLayout.NORTH);
|
|
||||||
topPanel.add(stagePanel, BorderLayout.CENTER);
|
|
||||||
|
|
||||||
timelinePanel = new TimelinePanel(undoManager);
|
|
||||||
|
|
||||||
timelinePanel.addChangeListener(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
stagePanel.repaint();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
timelinePanel.addFrameSelectionListener(new FrameSelectionListener() {
|
|
||||||
@Override
|
|
||||||
public void frameSelected(int frame, int depth) {
|
|
||||||
stagePanel.pause();
|
|
||||||
stagePanel.gotoFrame(frame + 1);
|
|
||||||
stagePanel.selectDepth(depth);
|
|
||||||
if (transformEnabled()) {
|
|
||||||
stagePanel.freeTransformDepth(depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (depth != -1) {
|
|
||||||
DepthState ds = stagePanel.getTimelined().getTimeline().getFrame(stagePanel.getFrame()).layers.get(depth);
|
|
||||||
if (ds == null) {
|
|
||||||
depth = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
transformPanel.setVisible(depth != -1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
verticalSplitPane = new JPersistentSplitPane(JSplitPane.VERTICAL_SPLIT, topPanel, timelinePanel, Configuration.guiSplitPaneEasyVerticaldividerLocationPercent);
|
|
||||||
|
|
||||||
libraryTreeTable = new LibraryTreeTable();
|
|
||||||
JScrollPane libraryScrollPane = new FasterScrollPane(libraryTreeTable);
|
|
||||||
|
|
||||||
JPanel libraryPanel = new JPanel(new BorderLayout());
|
|
||||||
libraryPanel.add(libraryScrollPane, BorderLayout.CENTER);
|
|
||||||
|
|
||||||
libraryPreviewPanel = new ImagePanel();
|
|
||||||
libraryPreviewPanel.setTopPanelVisible(false);
|
|
||||||
|
|
||||||
libraryPanel.add(libraryPreviewPanel, BorderLayout.NORTH);
|
|
||||||
|
|
||||||
libraryPreviewPanel.setPreferredSize(new Dimension(200, 200));
|
|
||||||
|
|
||||||
rightTabbedPane = new JTabbedPane();
|
|
||||||
rightTabbedPane.addTab(EasyStrings.translate("library"), libraryPanel);
|
|
||||||
|
|
||||||
JPanel transformTab = new JPanel(new BorderLayout());
|
|
||||||
transformPanel = new TransformPanel(stagePanel, false);
|
|
||||||
transformTab.add(new FasterScrollPane(transformPanel), BorderLayout.CENTER);
|
|
||||||
|
|
||||||
rightTabbedPane.addTab(EasyStrings.translate("transform"), transformTab);
|
|
||||||
rightTabbedPane.addChangeListener(new ChangeListener() {
|
|
||||||
@Override
|
|
||||||
public void stateChanged(ChangeEvent e) {
|
|
||||||
int depth = stagePanel.getSelectedDepth();
|
|
||||||
if (stagePanel.getFrame() >= stagePanel.getTimelined().getFrameCount()) {
|
|
||||||
depth = -1;
|
|
||||||
}
|
|
||||||
if (depth != -1) {
|
|
||||||
Frame frame = stagePanel.getTimelined().getTimeline().getFrame(stagePanel.getFrame());
|
|
||||||
if (frame == null) {
|
|
||||||
depth = -1;
|
|
||||||
} else {
|
|
||||||
DepthState ds = frame.layers.get(depth);
|
|
||||||
if (ds == null) {
|
|
||||||
depth = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
transformPanel.setVisible(depth != -1);
|
|
||||||
if (transformEnabled()) {
|
|
||||||
stagePanel.freeTransformDepth(depth);
|
|
||||||
stagePanel.setTransformSelectionMode(true);
|
|
||||||
} else {
|
|
||||||
stagePanel.freeTransformDepth(-1);
|
|
||||||
stagePanel.selectDepth(depth);
|
|
||||||
stagePanel.setTransformSelectionMode(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
horizontalSplitPane = new JPersistentSplitPane(JSplitPane.HORIZONTAL_SPLIT, verticalSplitPane, rightTabbedPane, Configuration.guiSplitPaneEasyHorizontaldividerLocationPercent);
|
|
||||||
|
|
||||||
if (View.isOceanic()) {
|
|
||||||
libraryScrollPane.getViewport().setBackground(Color.white);
|
|
||||||
} else {
|
|
||||||
libraryScrollPane.getViewport().setBackground(UIManager.getColor("Tree.background"));
|
|
||||||
}
|
|
||||||
add(horizontalSplitPane, BorderLayout.CENTER);
|
|
||||||
|
|
||||||
libraryTreeTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
|
||||||
@Override
|
|
||||||
public void valueChanged(ListSelectionEvent e) {
|
|
||||||
int row = libraryTreeTable.getSelectedRow();
|
|
||||||
if (row == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
DefaultMutableTreeNode n = (DefaultMutableTreeNode) libraryTreeTable.getModel().getValueAt(row, 0);
|
|
||||||
Object obj = n.getUserObject();
|
|
||||||
if (obj instanceof Tag) {
|
|
||||||
Tag t = (Tag) obj;
|
|
||||||
libraryPreviewPanel.setTimelined(TimelinedMaker.makeTimelined(t), t.getSwf(),
|
|
||||||
-1, false, true, true, true, true, false, true);
|
|
||||||
libraryPreviewPanel.zoomFit();
|
|
||||||
} else {
|
|
||||||
libraryPreviewPanel.clearAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean transformEnabled() {
|
|
||||||
return rightTabbedPane.getSelectedIndex() == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTimelined(Timelined timelined) {
|
public void setSwfs(List<SWF> swfs) {
|
||||||
SWF swf = timelined.getSwf();
|
tabSwitcher.clear();
|
||||||
libraryTreeTable.setSwf(swf);
|
for (SWF swf : swfs) {
|
||||||
stagePanel.setTimelined(swf, swf, 0, true, true, true, true, true, false, true);
|
tabSwitcher.addTab(swf, swf.getShortPathTitle(), View.getIcon("flash16"));
|
||||||
stagePanel.pause();
|
}
|
||||||
stagePanel.gotoFrame(0);
|
}
|
||||||
timelinePanel.setTimelined(swf);
|
|
||||||
|
public void setSwf(SWF swf) {
|
||||||
|
tabSwitcher.setValue(swf);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SWF getSwf() {
|
||||||
|
return tabSwitcher.getSelectedValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,488 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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.easygui;
|
||||||
|
|
||||||
|
import com.jpexs.decompiler.flash.DefineBeforeUsageFixer;
|
||||||
|
import com.jpexs.decompiler.flash.ReadOnlyTagList;
|
||||||
|
import com.jpexs.decompiler.flash.SWF;
|
||||||
|
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||||
|
import com.jpexs.decompiler.flash.gui.FasterScrollPane;
|
||||||
|
import com.jpexs.decompiler.flash.gui.ImagePanel;
|
||||||
|
import com.jpexs.decompiler.flash.gui.Main;
|
||||||
|
import com.jpexs.decompiler.flash.gui.RegistrationPointPosition;
|
||||||
|
import com.jpexs.decompiler.flash.gui.TimelinedMaker;
|
||||||
|
import com.jpexs.decompiler.flash.gui.TransformPanel;
|
||||||
|
import com.jpexs.decompiler.flash.gui.View;
|
||||||
|
import com.jpexs.decompiler.flash.gui.controls.JPersistentSplitPane;
|
||||||
|
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
|
||||||
|
import com.jpexs.decompiler.flash.tags.PlaceObject2Tag;
|
||||||
|
import com.jpexs.decompiler.flash.tags.RemoveObject2Tag;
|
||||||
|
import com.jpexs.decompiler.flash.tags.ShowFrameTag;
|
||||||
|
import com.jpexs.decompiler.flash.tags.Tag;
|
||||||
|
import com.jpexs.decompiler.flash.tags.base.ButtonTag;
|
||||||
|
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
|
||||||
|
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
|
||||||
|
import com.jpexs.decompiler.flash.tags.base.ShapeTag;
|
||||||
|
import com.jpexs.decompiler.flash.tags.base.TextTag;
|
||||||
|
import com.jpexs.decompiler.flash.timeline.DepthState;
|
||||||
|
import com.jpexs.decompiler.flash.timeline.Frame;
|
||||||
|
import com.jpexs.decompiler.flash.timeline.Timelined;
|
||||||
|
import com.jpexs.decompiler.flash.treeitems.Openable;
|
||||||
|
import com.jpexs.decompiler.flash.types.MATRIX;
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.FlowLayout;
|
||||||
|
import java.awt.Insets;
|
||||||
|
import java.awt.datatransfer.Transferable;
|
||||||
|
import java.awt.datatransfer.UnsupportedFlavorException;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.geom.Point2D;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JScrollPane;
|
||||||
|
import javax.swing.JSplitPane;
|
||||||
|
import javax.swing.JTabbedPane;
|
||||||
|
import javax.swing.TransferHandler;
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
|
import javax.swing.event.ListSelectionEvent;
|
||||||
|
import javax.swing.event.ListSelectionListener;
|
||||||
|
import javax.swing.tree.DefaultMutableTreeNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author JPEXS
|
||||||
|
*/
|
||||||
|
public class EasySwfPanel extends JPanel {
|
||||||
|
|
||||||
|
private LibraryTreeTable libraryTreeTable;
|
||||||
|
private JSplitPane verticalSplitPane;
|
||||||
|
private JSplitPane horizontalSplitPane;
|
||||||
|
private ImagePanel libraryPreviewPanel;
|
||||||
|
private ImagePanel stagePanel;
|
||||||
|
private TimelinePanel timelinePanel;
|
||||||
|
private JButton undoButton;
|
||||||
|
private JButton redoButton;
|
||||||
|
private UndoManager undoManager;
|
||||||
|
private JTabbedPane rightTabbedPane;
|
||||||
|
private TransformPanel transformPanel;
|
||||||
|
private Timelined timelined;
|
||||||
|
|
||||||
|
public EasySwfPanel() {
|
||||||
|
setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
stagePanel = new ImagePanel();
|
||||||
|
stagePanel.setTagNameResolver(new EasyTagNameResolver());
|
||||||
|
stagePanel.setShowAllDepthLevelsInfo(false);
|
||||||
|
stagePanel.setSelectionMode(true);
|
||||||
|
stagePanel.addPlaceObjectSelectedListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
PlaceObjectTypeTag pl = stagePanel.getPlaceTagUnderCursor();
|
||||||
|
if (pl != null) {
|
||||||
|
timelinePanel.setDepth(pl.getDepth());
|
||||||
|
}
|
||||||
|
transformPanel.setVisible(pl != null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
stagePanel.addTransformChangeListener(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
final int depth = stagePanel.getSelectedDepth();
|
||||||
|
final int frame = stagePanel.getFrame();
|
||||||
|
final MATRIX newMatrix = stagePanel.getNewMatrix().toMATRIX();
|
||||||
|
MATRIX previousMatrix = null;
|
||||||
|
synchronized (stagePanel) {
|
||||||
|
DepthState ds = stagePanel.getTimelined().getTimeline().getFrame(frame).layers.get(depth);
|
||||||
|
previousMatrix = ds.placeObjectTag.getMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
final Point2D regPoint = stagePanel.getRegistrationPoint();
|
||||||
|
final RegistrationPointPosition regPointPos = stagePanel.getRegistrationPointPosition();
|
||||||
|
|
||||||
|
final MATRIX fpreviousMatrix = previousMatrix;
|
||||||
|
|
||||||
|
final boolean transformEnabled = transformEnabled();
|
||||||
|
undoManager.doOperation(new DoableOperation() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doOperation() {
|
||||||
|
timelinePanel.setFrame(frame, depth);
|
||||||
|
DepthState ds = stagePanel.getTimelined().getTimeline().getFrame(frame).layers.get(depth);
|
||||||
|
ds.placeObjectTag.setMatrix(newMatrix);
|
||||||
|
ds.placeObjectTag.setPlaceFlagHasMatrix(newMatrix != null);
|
||||||
|
ds.placeObjectTag.setModified(true);
|
||||||
|
stagePanel.getTimelined().resetTimeline();
|
||||||
|
stagePanel.repaint();
|
||||||
|
if (transformEnabled()) {
|
||||||
|
stagePanel.freeTransformDepth(depth);
|
||||||
|
stagePanel.setRegistrationPoint(regPoint);
|
||||||
|
if (regPointPos != null) {
|
||||||
|
stagePanel.setRegistrationPointPosition(regPointPos);
|
||||||
|
}
|
||||||
|
transformPanel.setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void undoOperation() {
|
||||||
|
timelinePanel.setFrame(frame, depth);
|
||||||
|
DepthState ds = stagePanel.getTimelined().getTimeline().getFrame(frame).layers.get(depth);
|
||||||
|
ds.placeObjectTag.setMatrix(fpreviousMatrix);
|
||||||
|
ds.placeObjectTag.setPlaceFlagHasMatrix(fpreviousMatrix != null);
|
||||||
|
stagePanel.getTimelined().resetTimeline();
|
||||||
|
stagePanel.repaint();
|
||||||
|
if (transformEnabled()) {
|
||||||
|
stagePanel.freeTransformDepth(depth);
|
||||||
|
transformPanel.setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return EasyStrings.translate(transformEnabled ? "action.transform" : "action.move");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
stagePanel.setTransferHandler(new TransferHandler() {
|
||||||
|
@Override
|
||||||
|
public boolean canImport(TransferHandler.TransferSupport support) {
|
||||||
|
return support.isDataFlavorSupported(CharacterTagTransferable.CHARACTERTAG_FLAVOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean importData(TransferHandler.TransferSupport support) {
|
||||||
|
if (!canImport(support)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Transferable transferable = support.getTransferable();
|
||||||
|
Integer characterId = (Integer) transferable.getTransferData(CharacterTagTransferable.CHARACTERTAG_FLAVOR);
|
||||||
|
CharacterTag tag = stagePanel.getTimelined().getSwf().getCharacter(characterId);
|
||||||
|
if ((tag instanceof DefineSpriteTag)
|
||||||
|
|| (tag instanceof ShapeTag)
|
||||||
|
|| (tag instanceof TextTag)
|
||||||
|
|| (tag instanceof ButtonTag)
|
||||||
|
) {
|
||||||
|
|
||||||
|
undoManager.doOperation(new DoableOperation() {
|
||||||
|
|
||||||
|
private PlaceObject2Tag place;
|
||||||
|
private RemoveObject2Tag remove;
|
||||||
|
private List<Tag> tags;
|
||||||
|
private int frame = stagePanel.getFrame();
|
||||||
|
private int depth = stagePanel.getSelectedDepth();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doOperation() {
|
||||||
|
timelinePanel.setFrame(frame, depth);
|
||||||
|
CharacterTag ch = (CharacterTag) tag;
|
||||||
|
int maxDepth = stagePanel.getTimelined().getTimeline().getMaxDepth();
|
||||||
|
int newDepth = maxDepth + 1;
|
||||||
|
Timelined timelined = stagePanel.getTimelined();
|
||||||
|
|
||||||
|
tags = timelined.getSwf().getTags().toArrayList();
|
||||||
|
|
||||||
|
ShowFrameTag showFrameTag = timelined.getTimeline().getFrame(frame).showFrameTag;
|
||||||
|
place = new PlaceObject2Tag(timelined.getSwf());
|
||||||
|
place.depth = newDepth;
|
||||||
|
place.placeFlagHasCharacter = true;
|
||||||
|
place.characterId = ch.getCharacterId();
|
||||||
|
place.matrix = new MATRIX();
|
||||||
|
place.placeFlagHasMatrix = true;
|
||||||
|
place.setTimelined(timelined);
|
||||||
|
if (showFrameTag == null) {
|
||||||
|
timelined.addTag(place);
|
||||||
|
} else {
|
||||||
|
timelined.addTag(timelined.indexOfTag(showFrameTag), place);
|
||||||
|
|
||||||
|
remove = new RemoveObject2Tag(timelined.getSwf());
|
||||||
|
remove.depth = newDepth;
|
||||||
|
timelined.addTag(timelined.indexOfTag(showFrameTag) + 1, remove);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DefineBeforeUsageFixer fixer = new DefineBeforeUsageFixer();
|
||||||
|
boolean tagOrderChanged = fixer.fixDefineBeforeUsage(timelined.getSwf());
|
||||||
|
if (!tagOrderChanged) {
|
||||||
|
tags = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
timelined.resetTimeline();
|
||||||
|
stagePanel.repaint();
|
||||||
|
timelinePanel.refresh();
|
||||||
|
timelinePanel.setDepth(newDepth);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void undoOperation() {
|
||||||
|
Timelined timelined = place.getTimelined();
|
||||||
|
timelined.removeTag(place);
|
||||||
|
if (remove != null) {
|
||||||
|
timelined.removeTag(remove);
|
||||||
|
}
|
||||||
|
timelined.resetTimeline();
|
||||||
|
|
||||||
|
//Tag order changed, put the original tags back
|
||||||
|
if (tags != null) {
|
||||||
|
SWF swf = timelined.getSwf();
|
||||||
|
ReadOnlyTagList newTags = swf.getTags();
|
||||||
|
int size = newTags.size();
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
swf.removeTag(0);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < tags.size(); i++) {
|
||||||
|
if (tags.get(i) == place) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
swf.addTag(tags.get(i));
|
||||||
|
}
|
||||||
|
swf.resetTimeline();
|
||||||
|
}
|
||||||
|
|
||||||
|
stagePanel.repaint();
|
||||||
|
timelinePanel.refresh();
|
||||||
|
timelinePanel.setFrame(frame, depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return EasyStrings.translate("action.addToStage");
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (UnsupportedFlavorException | IOException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
//ignored
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
undoManager = new UndoManager();
|
||||||
|
|
||||||
|
JPanel topPanel = new JPanel(new BorderLayout());
|
||||||
|
|
||||||
|
JPanel toolbarPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
|
||||||
|
|
||||||
|
undoButton = new JButton(View.getIcon("rotateanticlockwise16"));
|
||||||
|
//undoButton.setToolTipText("Undo");
|
||||||
|
undoButton.setMargin(new Insets(5, 5, 5, 5));
|
||||||
|
undoButton.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
undoManager.undo();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
redoButton = new JButton(View.getIcon("rotateclockwise16"));
|
||||||
|
//redoButton.setToolTipText("Redo");
|
||||||
|
redoButton.setMargin(new Insets(5, 5, 5, 5));
|
||||||
|
redoButton.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
undoManager.redo();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
undoButton.setEnabled(false);
|
||||||
|
redoButton.setEnabled(false);
|
||||||
|
undoButton.setToolTipText(EasyStrings.translate("undo.cannot"));
|
||||||
|
redoButton.setToolTipText(EasyStrings.translate("redo.cannot"));
|
||||||
|
|
||||||
|
Runnable undoChangeListener = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
undoButton.setEnabled(undoManager.canUndo());
|
||||||
|
redoButton.setEnabled(undoManager.canRedo());
|
||||||
|
if (undoManager.canUndo()) {
|
||||||
|
undoButton.setToolTipText(EasyStrings.translate("undo").replace("%action%",undoManager.getUndoName()));
|
||||||
|
} else {
|
||||||
|
undoButton.setToolTipText(EasyStrings.translate("undo.cannot"));
|
||||||
|
}
|
||||||
|
if (undoManager.canRedo()) {
|
||||||
|
redoButton.setToolTipText(EasyStrings.translate("redo").replace("%action%", undoManager.getRedoName()));
|
||||||
|
} else {
|
||||||
|
redoButton.setToolTipText(EasyStrings.translate("redo.cannot"));
|
||||||
|
}
|
||||||
|
if (stagePanel.getTimelined() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Main.getMainFrame().getPanel().updateUiWithCurrentOpenable();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
undoManager.addChangeListener(undoChangeListener);
|
||||||
|
|
||||||
|
toolbarPanel.add(undoButton);
|
||||||
|
toolbarPanel.add(redoButton);
|
||||||
|
|
||||||
|
topPanel.add(toolbarPanel, BorderLayout.NORTH);
|
||||||
|
topPanel.add(stagePanel, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
timelinePanel = new TimelinePanel(undoManager);
|
||||||
|
|
||||||
|
timelinePanel.addChangeListener(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
stagePanel.repaint();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
timelinePanel.addFrameSelectionListener(new FrameSelectionListener() {
|
||||||
|
@Override
|
||||||
|
public void frameSelected(int frame, int depth) {
|
||||||
|
stagePanel.pause();
|
||||||
|
stagePanel.gotoFrame(frame + 1);
|
||||||
|
stagePanel.selectDepth(depth);
|
||||||
|
if (transformEnabled()) {
|
||||||
|
stagePanel.freeTransformDepth(depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depth != -1) {
|
||||||
|
DepthState ds = stagePanel.getTimelined().getTimeline().getFrame(stagePanel.getFrame()).layers.get(depth);
|
||||||
|
if (ds == null) {
|
||||||
|
depth = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
transformPanel.setVisible(depth != -1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
verticalSplitPane = new JPersistentSplitPane(JSplitPane.VERTICAL_SPLIT, topPanel, timelinePanel, Configuration.guiSplitPaneEasyVerticaldividerLocationPercent);
|
||||||
|
|
||||||
|
libraryTreeTable = new LibraryTreeTable();
|
||||||
|
JScrollPane libraryScrollPane = new FasterScrollPane(libraryTreeTable);
|
||||||
|
|
||||||
|
JPanel libraryPanel = new JPanel(new BorderLayout());
|
||||||
|
libraryPanel.add(libraryScrollPane, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
libraryPreviewPanel = new ImagePanel();
|
||||||
|
libraryPreviewPanel.setTopPanelVisible(false);
|
||||||
|
|
||||||
|
libraryPanel.add(libraryPreviewPanel, BorderLayout.NORTH);
|
||||||
|
|
||||||
|
libraryPreviewPanel.setPreferredSize(new Dimension(200, 200));
|
||||||
|
|
||||||
|
rightTabbedPane = new JTabbedPane();
|
||||||
|
rightTabbedPane.addTab(EasyStrings.translate("library"), libraryPanel);
|
||||||
|
|
||||||
|
JPanel transformTab = new JPanel(new BorderLayout());
|
||||||
|
transformPanel = new TransformPanel(stagePanel, false);
|
||||||
|
transformTab.add(new FasterScrollPane(transformPanel), BorderLayout.CENTER);
|
||||||
|
|
||||||
|
rightTabbedPane.addTab(EasyStrings.translate("transform"), transformTab);
|
||||||
|
rightTabbedPane.addChangeListener(new ChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void stateChanged(ChangeEvent e) {
|
||||||
|
if (stagePanel.getTimelined() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int depth = stagePanel.getSelectedDepth();
|
||||||
|
if (stagePanel.getFrame() >= stagePanel.getTimelined().getFrameCount()) {
|
||||||
|
depth = -1;
|
||||||
|
}
|
||||||
|
if (depth != -1) {
|
||||||
|
Frame frame = stagePanel.getTimelined().getTimeline().getFrame(stagePanel.getFrame());
|
||||||
|
if (frame == null) {
|
||||||
|
depth = -1;
|
||||||
|
} else {
|
||||||
|
DepthState ds = frame.layers.get(depth);
|
||||||
|
if (ds == null) {
|
||||||
|
depth = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
transformPanel.setVisible(depth != -1);
|
||||||
|
if (transformEnabled()) {
|
||||||
|
stagePanel.freeTransformDepth(depth);
|
||||||
|
stagePanel.setTransformSelectionMode(true);
|
||||||
|
} else {
|
||||||
|
stagePanel.freeTransformDepth(-1);
|
||||||
|
stagePanel.selectDepth(depth);
|
||||||
|
stagePanel.setTransformSelectionMode(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
horizontalSplitPane = new JPersistentSplitPane(JSplitPane.HORIZONTAL_SPLIT, verticalSplitPane, rightTabbedPane, Configuration.guiSplitPaneEasyHorizontaldividerLocationPercent);
|
||||||
|
|
||||||
|
if (View.isOceanic()) {
|
||||||
|
libraryScrollPane.getViewport().setBackground(Color.white);
|
||||||
|
} else {
|
||||||
|
libraryScrollPane.getViewport().setBackground(UIManager.getColor("Tree.background"));
|
||||||
|
}
|
||||||
|
add(horizontalSplitPane, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
libraryTreeTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||||
|
@Override
|
||||||
|
public void valueChanged(ListSelectionEvent e) {
|
||||||
|
int row = libraryTreeTable.getSelectedRow();
|
||||||
|
if (row == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DefaultMutableTreeNode n = (DefaultMutableTreeNode) libraryTreeTable.getModel().getValueAt(row, 0);
|
||||||
|
Object obj = n.getUserObject();
|
||||||
|
if (obj instanceof Tag) {
|
||||||
|
Tag t = (Tag) obj;
|
||||||
|
libraryPreviewPanel.setTimelined(TimelinedMaker.makeTimelined(t), t.getSwf(),
|
||||||
|
-1, false, true, true, true, true, false, true);
|
||||||
|
libraryPreviewPanel.zoomFit();
|
||||||
|
} else {
|
||||||
|
libraryPreviewPanel.clearAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean transformEnabled() {
|
||||||
|
return rightTabbedPane.getSelectedIndex() == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimelined(Timelined timelined) {
|
||||||
|
this.timelined = timelined;
|
||||||
|
if (timelined == null) {
|
||||||
|
stagePanel.clearAll();
|
||||||
|
timelinePanel.setTimelined(null);
|
||||||
|
} else {
|
||||||
|
SWF swf = timelined.getSwf();
|
||||||
|
libraryTreeTable.setSwf(swf);
|
||||||
|
stagePanel.setTimelined(swf, swf, 0, true, true, true, true, true, false, true);
|
||||||
|
stagePanel.pause();
|
||||||
|
stagePanel.gotoFrame(0);
|
||||||
|
timelinePanel.setTimelined(swf);
|
||||||
|
}
|
||||||
|
undoManager.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Openable getOpenable() {
|
||||||
|
return timelined.getSwf();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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.easygui;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tab switching listener.
|
||||||
|
* @author JPEXS
|
||||||
|
*/
|
||||||
|
public interface TabSwitchedListener<E> {
|
||||||
|
public void tabSwitched(E value);
|
||||||
|
}
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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.easygui;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.event.ComponentAdapter;
|
||||||
|
import java.awt.event.ComponentEvent;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.swing.Icon;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JTabbedPane;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component for switching tabs which has only single tab component.
|
||||||
|
* @author JPEXS
|
||||||
|
* @param <E> Element
|
||||||
|
*/
|
||||||
|
public class TabSwitcher<E> extends JPanel {
|
||||||
|
private final JTabbedPane tabbedPane;
|
||||||
|
private final List<E> values;
|
||||||
|
private final List<String> titles;
|
||||||
|
private Component tabComponent;
|
||||||
|
private final JPanel centralPanel;
|
||||||
|
private final List<TabSwitchedListener<E>> listeners = new ArrayList<>();
|
||||||
|
|
||||||
|
public TabSwitcher(Component tabComponent) {
|
||||||
|
titles = new ArrayList<>();
|
||||||
|
values = new ArrayList<>();
|
||||||
|
tabbedPane = new JTabbedPane();
|
||||||
|
tabbedPane.addChangeListener(new ChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void stateChanged(ChangeEvent e) {
|
||||||
|
int index = tabbedPane.getSelectedIndex();
|
||||||
|
if (index == -1) {
|
||||||
|
fireTabSwitched(null);
|
||||||
|
} else {
|
||||||
|
fireTabSwitched(values.get(index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.tabComponent = tabComponent;
|
||||||
|
centralPanel = new JPanel();
|
||||||
|
centralPanel.setLayout(null);
|
||||||
|
centralPanel.add(tabbedPane);
|
||||||
|
centralPanel.add(tabComponent);
|
||||||
|
setLayout(new BorderLayout());
|
||||||
|
add(centralPanel, BorderLayout.CENTER);
|
||||||
|
addComponentListener(new ComponentAdapter() {
|
||||||
|
@Override
|
||||||
|
public void componentResized(ComponentEvent e) {
|
||||||
|
updateSizes();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTabSwitchedListener(TabSwitchedListener<E> listener) {
|
||||||
|
listeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeTabSwitchedListener(TabSwitchedListener<E> listener) {
|
||||||
|
listeners.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fireTabSwitched(E value) {
|
||||||
|
for (TabSwitchedListener<E> listener : listeners) {
|
||||||
|
listener.tabSwitched(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateSizes() {
|
||||||
|
tabbedPane.setBounds(0, 0, centralPanel.getWidth(), centralPanel.getHeight());
|
||||||
|
int maxH = 0;
|
||||||
|
for (int i = 0; i < tabbedPane.getTabCount(); i++) {
|
||||||
|
Rectangle r = tabbedPane.getUI().getTabBounds(tabbedPane, i);
|
||||||
|
int h = r.y + r.height;
|
||||||
|
if (h > maxH) {
|
||||||
|
maxH = h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tabbedPane.setBounds(0, 0, centralPanel.getWidth(), maxH);
|
||||||
|
tabComponent.setBounds(0, maxH, centralPanel.getWidth(), centralPanel.getHeight() - maxH);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component getTabComponent() {
|
||||||
|
return tabComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTabComponent(Component component) {
|
||||||
|
if (this.tabComponent != null) {
|
||||||
|
centralPanel.remove(this.tabComponent);
|
||||||
|
}
|
||||||
|
this.tabComponent = component;
|
||||||
|
|
||||||
|
centralPanel.add(component);
|
||||||
|
revalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTab(E value, String title, Icon icon) {
|
||||||
|
titles.add(title);
|
||||||
|
values.add(value);
|
||||||
|
tabbedPane.insertTab(title, icon, new JPanel(), null, values.size() - 1);
|
||||||
|
updateSizes();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTabTitleAtIndex(int index) {
|
||||||
|
return titles.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public E getValueAtIndex(int index) {
|
||||||
|
return values.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValueCount() {
|
||||||
|
return values.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
values.clear();
|
||||||
|
titles.clear();
|
||||||
|
tabbedPane.removeAll();
|
||||||
|
fireTabSwitched(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectedIndex(int index) {
|
||||||
|
tabbedPane.setSelectedIndex(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(E value) {
|
||||||
|
int index = values.indexOf(value);
|
||||||
|
setSelectedIndex(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public E getSelectedValue() {
|
||||||
|
int index = tabbedPane.getSelectedIndex();
|
||||||
|
if (index == -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return values.get(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1082,7 +1082,7 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setTimeline(Timeline timeline) {
|
public void setTimeline(Timeline timeline) {
|
||||||
this.timeline = timeline;
|
this.timeline = timeline;
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,8 +158,15 @@ public class TimelinePanel extends JPanel {
|
|||||||
|
|
||||||
public void setTimelined(Timelined timelined) {
|
public void setTimelined(Timelined timelined) {
|
||||||
this.timelined = timelined;
|
this.timelined = timelined;
|
||||||
timelineBodyPanel.setTimeline(timelined.getTimeline());
|
if (timelined == null) {
|
||||||
depthPanel.setTimeline(timelined.getTimeline());
|
timelineBodyPanel.setTimeline(null);
|
||||||
timePanel.setTimeline(timelined.getTimeline());
|
depthPanel.setTimeline(null);
|
||||||
|
timePanel.setTimeline(null);
|
||||||
|
} else {
|
||||||
|
timelineBodyPanel.setTimeline(timelined.getTimeline());
|
||||||
|
depthPanel.setTimeline(timelined.getTimeline());
|
||||||
|
timePanel.setTimeline(timelined.getTimeline());
|
||||||
|
timelineBodyPanel.frameSelect(0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ public abstract class TimelinedTagListDoableOperation implements DoableOperation
|
|||||||
@Override
|
@Override
|
||||||
public void doOperation() {
|
public void doOperation() {
|
||||||
saveTagList();
|
saveTagList();
|
||||||
|
timelined.setModified(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void saveTagList() {
|
protected void saveTagList() {
|
||||||
|
|||||||
@@ -94,4 +94,10 @@ public class UndoManager {
|
|||||||
public boolean canRedo() {
|
public boolean canRedo() {
|
||||||
return history.size() > historyPos;
|
return history.size() > historyPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
history.clear();
|
||||||
|
historyPos = 0;
|
||||||
|
fireChange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1125,7 +1125,7 @@ public abstract class MainFrameMenu implements MenuBuilder {
|
|||||||
|
|
||||||
setMenuEnabled("/tools/search", openableSelected);
|
setMenuEnabled("/tools/search", openableSelected);
|
||||||
setMenuEnabled("/tools/replace", swfSelected);
|
setMenuEnabled("/tools/replace", swfSelected);
|
||||||
setMenuEnabled("/file/view/timeline", swfSelected);
|
//setMenuEnabled("/file/view/timeline", swfSelected);
|
||||||
setMenuEnabled("/tools/abcExplorer", isAs3);
|
setMenuEnabled("/tools/abcExplorer", isAs3);
|
||||||
|
|
||||||
setMenuEnabled("/tools/gotoDocumentClass", hasAbc);
|
setMenuEnabled("/tools/gotoDocumentClass", hasAbc);
|
||||||
@@ -1178,6 +1178,9 @@ public abstract class MainFrameMenu implements MenuBuilder {
|
|||||||
case MainPanel.VIEW_DUMP:
|
case MainPanel.VIEW_DUMP:
|
||||||
setGroupSelection("view", "/file/view/viewHex");
|
setGroupSelection("view", "/file/view/viewHex");
|
||||||
break;
|
break;
|
||||||
|
case MainPanel.VIEW_TIMELINE:
|
||||||
|
setMenuChecked("/file/view/timeline", true);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1522,6 +1525,9 @@ public abstract class MainFrameMenu implements MenuBuilder {
|
|||||||
case MainPanel.VIEW_DUMP:
|
case MainPanel.VIEW_DUMP:
|
||||||
setMenuChecked("/file/view/viewHex", true);
|
setMenuChecked("/file/view/viewHex", true);
|
||||||
break;
|
break;
|
||||||
|
case MainPanel.VIEW_TIMELINE:
|
||||||
|
setMenuChecked("/file/view/timeline", true);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1468,7 +1468,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<List<String>> expandedNodes = View.getExpandedNodes(tagTree);
|
List<List<String>> expandedNodes = View.getExpandedNodes(tagTree);
|
||||||
previewPanel.clear();
|
previewPanel.clear();
|
||||||
openables.set(index, newSwfs);
|
openables.set(index, newSwfs);
|
||||||
|
|
||||||
@@ -1477,6 +1477,11 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
Main.searchResultsStorage.destroySwf(s);
|
Main.searchResultsStorage.destroySwf(s);
|
||||||
}
|
}
|
||||||
Openable openable = newSwfs.size() > 0 ? newSwfs.get(0) : null;
|
Openable openable = newSwfs.size() > 0 ? newSwfs.get(0) : null;
|
||||||
|
|
||||||
|
easyPanel.setSwfs(new ArrayList<>(getAllSwfs()));
|
||||||
|
if (openable instanceof SWF) {
|
||||||
|
easyPanel.setSwf((SWF) openable);
|
||||||
|
}
|
||||||
if (openable != null) {
|
if (openable != null) {
|
||||||
updateUi(openable);
|
updateUi(openable);
|
||||||
}
|
}
|
||||||
@@ -1495,6 +1500,9 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
previewPanel.clear();
|
previewPanel.clear();
|
||||||
|
|
||||||
openables.add(newOpenables);
|
openables.add(newOpenables);
|
||||||
|
|
||||||
|
easyPanel.setSwfs(new ArrayList<>(getAllSwfs()));
|
||||||
|
|
||||||
Openable openable = newOpenables.size() > 0 ? newOpenables.get(0) : null;
|
Openable openable = newOpenables.size() > 0 ? newOpenables.get(0) : null;
|
||||||
if (openable != null) {
|
if (openable != null) {
|
||||||
updateUi(openable);
|
updateUi(openable);
|
||||||
@@ -1556,6 +1564,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case VIEW_TIMELINE:
|
case VIEW_TIMELINE:
|
||||||
|
updateUi(easyPanel.getSwf());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1564,7 +1573,11 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
View.checkAccess();
|
View.checkAccess();
|
||||||
|
|
||||||
if (isWelcomeScreen) {
|
if (isWelcomeScreen) {
|
||||||
showContentPanelCard(SPLIT_PANE1);
|
if (currentView == VIEW_TIMELINE) {
|
||||||
|
showContentPanelCard(TIMELINE_PANEL);
|
||||||
|
} else {
|
||||||
|
showContentPanelCard(SPLIT_PANE1);
|
||||||
|
}
|
||||||
isWelcomeScreen = false;
|
isWelcomeScreen = false;
|
||||||
}
|
}
|
||||||
SWF swf = null;
|
SWF swf = null;
|
||||||
@@ -5695,7 +5708,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
pinsPanel.setVisible(false);
|
pinsPanel.setVisible(false);
|
||||||
currentView = view;
|
currentView = view;
|
||||||
Configuration.lastView.set(currentView);
|
Configuration.lastView.set(currentView);
|
||||||
final SWF swf = getCurrentSwf();
|
/*final SWF swf = getCurrentSwf();
|
||||||
if (swf != null) {
|
if (swf != null) {
|
||||||
TreeItem item = tagTree.getCurrentTreeItem();
|
TreeItem item = tagTree.getCurrentTreeItem();
|
||||||
if (item instanceof TagScript) {
|
if (item instanceof TagScript) {
|
||||||
@@ -5712,8 +5725,13 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
showView(VIEW_RESOURCES);
|
showView(VIEW_RESOURCES);
|
||||||
}
|
}*/
|
||||||
return false;
|
Set<SWF> swfs = getAllSwfs();
|
||||||
|
easyPanel.setSwfs(new ArrayList<>(swfs));
|
||||||
|
if (!isWelcomeScreen) {
|
||||||
|
showContentPanelCard(TIMELINE_PANEL);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
case VIEW_TAGLIST:
|
case VIEW_TAGLIST:
|
||||||
pinsPanel.setVisible(true);
|
pinsPanel.setVisible(true);
|
||||||
currentView = view;
|
currentView = view;
|
||||||
@@ -6061,7 +6079,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
if (currentView == VIEW_DUMP) {
|
if (currentView == VIEW_DUMP) {
|
||||||
dumpViewReload(forceReload);
|
dumpViewReload(forceReload);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/*else if (currentView == VIEW_TAGLIST) {
|
/*else if (currentView == VIEW_TAGLIST) {
|
||||||
tagListViewReload(forceReload);
|
tagListViewReload(forceReload);
|
||||||
return;
|
return;
|
||||||
@@ -6073,6 +6091,16 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
if (treePath != null && tree.getFullModel().treePathExists(treePath)) {
|
if (treePath != null && tree.getFullModel().treePathExists(treePath)) {
|
||||||
treeItem = (TreeItem) treePath.getLastPathComponent();
|
treeItem = (TreeItem) treePath.getLastPathComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentView == VIEW_TIMELINE) {
|
||||||
|
if (treeItem != null) {
|
||||||
|
Openable op = treeItem.getOpenable();
|
||||||
|
if (op instanceof SWF) {
|
||||||
|
easyPanel.setSwf((SWF) op);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// save last selected node to config
|
// save last selected node to config
|
||||||
if (treeItem != null && !(treeItem instanceof OpenableList)) {
|
if (treeItem != null && !(treeItem instanceof OpenableList)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user