From bd04ffba495cc2615bdece9427a267bccb23c17f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Tue, 2 Sep 2014 20:25:56 +0200 Subject: [PATCH] Timeline view with preview and object hilighting. Embedded timeline view instead of new window. code formatting --- libsrc/jpproxy/nbbuild.xml | 147 +- libsrc/jpproxy/nbproject/build-impl.xml | 2790 +++++++++-------- libsrc/jpproxy/nbproject/genfiles.properties | 16 +- .../decompiler/flash/gui/ImagePanel.java | 63 +- .../flash/gui/MainFrameRibbonMenu.java | 59 +- .../jpexs/decompiler/flash/gui/MainPanel.java | 82 +- .../flash/gui/NewVersionDialog.java | 2 +- src/com/jpexs/decompiler/flash/gui/View.java | 3 +- .../flash/gui/dumpview/DumpViewPanel.java | 24 +- .../decompiler/flash/gui/hexview/HexView.java | 36 +- .../flash/gui/hexview/HexViewTableModel.java | 8 +- .../flash/gui/proxy/ProxyFrame.java | 10 +- .../flash/gui/timeline/TimelineBodyPanel.java | 584 ++-- .../flash/gui/timeline/TimelineFrame.java | 50 - .../flash/gui/timeline/TimelinePanel.java | 230 +- .../flash/gui/timeline/TimelineViewPanel.java | 71 + .../process/win32/Win32ProcessTools.java | 8 +- 17 files changed, 2181 insertions(+), 2002 deletions(-) delete mode 100644 src/com/jpexs/decompiler/flash/gui/timeline/TimelineFrame.java create mode 100644 src/com/jpexs/decompiler/flash/gui/timeline/TimelineViewPanel.java diff --git a/libsrc/jpproxy/nbbuild.xml b/libsrc/jpproxy/nbbuild.xml index 6579262e5..7369c29a9 100644 --- a/libsrc/jpproxy/nbbuild.xml +++ b/libsrc/jpproxy/nbbuild.xml @@ -1,74 +1,73 @@ - - - - - - - - - - - Builds, tests, and runs the project JPProxy. - - - + + + + + + + + + + + Builds, tests, and runs the project JPProxy. + + + diff --git a/libsrc/jpproxy/nbproject/build-impl.xml b/libsrc/jpproxy/nbproject/build-impl.xml index 4277fdc2e..fa9ad0fbe 100644 --- a/libsrc/jpproxy/nbproject/build-impl.xml +++ b/libsrc/jpproxy/nbproject/build-impl.xml @@ -1,1394 +1,1396 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must set src.dir - Must set build.dir - Must set dist.dir - Must set build.classes.dir - Must set dist.javadoc.dir - Must set build.test.classes.dir - Must set build.test.results.dir - Must set build.classes.excludes - Must set dist.jar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must set javac.includes - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - No tests executed. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must set JVM to use for profiling in profiler.info.jvm - Must set profiler agent JVM arguments in profiler.info.jvmargs.agent - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must select some files in the IDE or set javac.includes - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - To run this application from the command line without Ant, try: - - - - - - - java -cp "${run.classpath.with.dist.jar}" ${main.class} - - - - - - - - - - - - - - - - - - - - - - - - - To run this application from the command line without Ant, try: - - java -jar "${dist.jar.resolved}" - - - - - - - - - - - - - - - - - - - - - - - - - Must select one file in the IDE or set run.class - - - - Must select one file in the IDE or set run.class - - - - - - - - - - - - - - - - - - - - - - - Must select one file in the IDE or set debug.class - - - - - Must select one file in the IDE or set debug.class - - - - - Must set fix.includes - - - - - - - - - - This target only works when run from inside the NetBeans IDE. - - - - - - - - - Must select one file in the IDE or set profile.class - This target only works when run from inside the NetBeans IDE. - - - - - - - - - This target only works when run from inside the NetBeans IDE. - - - - - - - - - - - - - This target only works when run from inside the NetBeans IDE. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must select one file in the IDE or set run.class - - - - - - Must select some files in the IDE or set test.includes - - - - - Must select one file in the IDE or set run.class - - - - - Must select one file in the IDE or set applet.url - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must select some files in the IDE or set javac.includes - - - - - - - - - - - - - - - - - - Some tests failed; see details above. - - - - - - - - - Must select some files in the IDE or set test.includes - - - - Some tests failed; see details above. - - - - Must select some files in the IDE or set test.class - Must select some method in the IDE or set test.method - - - - Some tests failed; see details above. - - - - - Must select one file in the IDE or set test.class - - - - Must select one file in the IDE or set test.class - Must select some method in the IDE or set test.method - - - - - - - - - - - - - - Must select one file in the IDE or set applet.url - - - - - - - - - Must select one file in the IDE or set applet.url - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set build.dir + Must set dist.dir + Must set build.classes.dir + Must set dist.javadoc.dir + Must set build.test.classes.dir + Must set build.test.results.dir + Must set build.classes.excludes + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + No tests executed. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set JVM to use for profiling in profiler.info.jvm + Must set profiler agent JVM arguments in profiler.info.jvmargs.agent + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + java -jar "${dist.jar.resolved}" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + Must select one file in the IDE or set run.class + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set debug.class + + + + + Must select one file in the IDE or set debug.class + + + + + Must set fix.includes + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + Must select one file in the IDE or set profile.class + This target only works when run from inside the NetBeans IDE. + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + + + Must select some files in the IDE or set test.includes + + + + + Must select one file in the IDE or set run.class + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + Must select some files in the IDE or set test.includes + + + + Some tests failed; see details above. + + + + Must select some files in the IDE or set test.class + Must select some method in the IDE or set test.method + + + + Some tests failed; see details above. + + + + + Must select one file in the IDE or set test.class + + + + Must select one file in the IDE or set test.class + Must select some method in the IDE or set test.method + + + + + + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libsrc/jpproxy/nbproject/genfiles.properties b/libsrc/jpproxy/nbproject/genfiles.properties index dba5b2a05..9e4b5fd3d 100644 --- a/libsrc/jpproxy/nbproject/genfiles.properties +++ b/libsrc/jpproxy/nbproject/genfiles.properties @@ -1,8 +1,8 @@ -nbbuild.xml.data.CRC32=0a5363c8 -nbbuild.xml.script.CRC32=e4148738 -nbbuild.xml.stylesheet.CRC32=28e38971@1.38.2.45 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=0a5363c8 -nbproject/build-impl.xml.script.CRC32=949d71fd -nbproject/build-impl.xml.stylesheet.CRC32=c6d2a60f@1.56.1.46 +nbbuild.xml.data.CRC32=0a5363c8 +nbbuild.xml.script.CRC32=2eebe506 +nbbuild.xml.stylesheet.CRC32=8064a381@1.74.2.48 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=0a5363c8 +nbproject/build-impl.xml.script.CRC32=13f57099 +nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.74.2.48 diff --git a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java index ad7891373..a701988d7 100644 --- a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java +++ b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java @@ -17,12 +17,14 @@ package com.jpexs.decompiler.flash.gui; import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.exporters.ShapeExporter; 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.DrawableTag; import com.jpexs.decompiler.flash.tags.base.SoundTag; import com.jpexs.decompiler.flash.timeline.DepthState; import com.jpexs.decompiler.flash.timeline.Timeline; @@ -85,6 +87,14 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis private final List soundPlayers = new ArrayList<>(); private final IconPanel iconPanel; private int time = 0; + private int selectedDepth = -1; + + public void selectDepth(int depth) { + if (depth != selectedDepth) { + this.selectedDepth = depth; + } + hideMouseSelection(); + } private class IconPanel extends JPanel { @@ -271,6 +281,26 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis } } + private void showSelectedName() { + if (selectedDepth > -1 && frame > -1) { + DepthState ds = timelined.getTimeline().frames.get(frame).layers.get(selectedDepth); + if (ds != null) { + CharacterTag cht = timelined.getTimeline().swf.characters.get(ds.characterId); + if (cht != null) { + debugLabel.setText(cht.getName()); + } + } + } + } + + public void hideMouseSelection() { + if (selectedDepth > -1) { + showSelectedName(); + } else { + debugLabel.setText(" - "); + } + } + public ImagePanel() { super(new BorderLayout()); //iconPanel.setHorizontalAlignment(JLabel.CENTER); @@ -301,8 +331,9 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis @Override public void mouseExited(MouseEvent e) { stateUnderCursor = null; + lastMouseEvent = null; drawFrame(); - debugLabel.setText(" - "); + hideMouseSelection(); } @Override @@ -489,8 +520,8 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis } } - 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()); + private static SerializableImage getFrame(SWF swf, int frame, int time, Timelined drawable, DepthState stateUnderCursor, int mouseButton, int selectedDepth) { + String key = "drawable_" + frame + "_" + drawable.hashCode() + "_" + mouseButton + "_depth" + selectedDepth + "_" + (stateUnderCursor == null ? "out" : stateUnderCursor.hashCode()); SerializableImage img = SWF.getFromCache(key); if (img == null) { if (drawable instanceof BoundedTag) { @@ -514,6 +545,30 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis gg.setTransform(AffineTransform.getTranslateInstance(0, 0)); List dss = new ArrayList<>(); List os = new ArrayList<>(); + DepthState ds = drawable.getTimeline().frames.get(frame).layers.get(selectedDepth); + if (ds != null) { + CharacterTag cht = swf.characters.get(ds.characterId); + if (cht != null) { + if (cht instanceof DrawableTag) { + DrawableTag dt = (DrawableTag) cht; + Shape outline = dt.getOutline(0, ds.time, ds.ratio, stateUnderCursor, mouseButton, new Matrix(ds.matrix)); + Rectangle bounds = outline.getBounds(); + bounds.x /= 20; + bounds.y /= 20; + bounds.width /= 20; + bounds.height /= 20; + bounds.x -= rect.Xmin / 20; + bounds.y -= rect.Ymin / 20; + //SHAPERECORD.resizeSHAPE(outline, 1/20) + gg.setStroke(new BasicStroke(2.0f, + BasicStroke.CAP_BUTT, + BasicStroke.JOIN_MITER, + 10.0f, new float[]{10.0f}, 0.0f)); + gg.setPaint(Color.red); + gg.draw(bounds); + } + } + } /*drawable.getTimeline().getObjectsOutlines(frame, frame, stateUnderCursor, mouseButton, m, dss, os); //gg.setTransform(AffineTransform.getTranslateInstance(0, 0)); @@ -544,7 +599,7 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis mat.translateX = swf.displayRect.Xmin; mat.translateY = swf.displayRect.Ymin; updatePos(lastMouseEvent, false); - SerializableImage img = getFrame(swf, frame, time, timelined, stateUnderCursor, mouseButton); + SerializableImage img = getFrame(swf, frame, time, timelined, stateUnderCursor, mouseButton, selectedDepth); List sounds = new ArrayList<>(); List soundClasses = new ArrayList<>(); timeline.getSounds(frame, time, stateUnderCursor, mouseButton, sounds, soundClasses); diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java index b65e2223f..3ab485b69 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java @@ -48,6 +48,7 @@ import javax.swing.JDialog; import javax.swing.JEditorPane; import javax.swing.JOptionPane; import javax.swing.JPanel; +import javax.swing.JToggleButton; import javax.swing.SwingUtilities; import org.pushingpixels.flamingo.api.common.AbstractCommandButton; import org.pushingpixels.flamingo.api.common.CommandButtonDisplayState; @@ -122,6 +123,7 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener { static final String ACTION_CHECK_RESOURCES = "CHECKRESOURCES"; static final String ACTION_VIEWMODE_RESOURCES = "VIEWMODERESOURCES"; static final String ACTION_VIEWMODE_HEX = "VIEWMODEHEX"; + static final String ACTION_VIEWMODE_TIMELINE = "VIEWMODETIMELINE"; static final String ACTION_DEOBFUSCATION_MODE_OLD = "DEOBFUSCATIONMODEOLD"; static final String ACTION_DEOBFUSCATION_MODE_NEW = "DEOBFUSCATIONMODENEW"; @@ -153,10 +155,13 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener { private JCommandButton globalrenameCommandButton; private JCommandButton deobfuscationCommandButton; private JCommandButton searchCommandButton; - private JCommandButton timeLineCommandButton; + private JCommandToggleButton timeLineToggleButton; + private CommandToggleButtonGroup timeLineToggleGroup; private JCommandButton gotoDocumentClassCommandButton; private JCommandButton clearRecentFilesCommandButton; + private CommandToggleButtonGroup viewModeToggleGroup; + RibbonApplicationMenuEntryPrimary exportFlaMenu; RibbonApplicationMenuEntryPrimary exportAllMenu; RibbonApplicationMenuEntryPrimary exportSelMenu; @@ -280,7 +285,7 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener { resizePolicies.add(new BaseRibbonBandResizePolicy(ribbonBand.getControlPanel()) { @Override public int getPreferredWidth(int i, int i1) { - return ribbonBand.getGraphics().getFontMetrics(ribbonBand.getFont()).stringWidth(ribbonBand.getTitle())+20; + return ribbonBand.getGraphics().getFontMetrics(ribbonBand.getFont()).stringWidth(ribbonBand.getTitle()) + 20; } @Override @@ -357,7 +362,7 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener { JRibbonBand viewBand = new JRibbonBand(translate("menu.view"), null); viewBand.setResizePolicies(getResizePolicies(viewBand)); - CommandToggleButtonGroup grpViewMode = new CommandToggleButtonGroup(); + viewModeToggleGroup = new CommandToggleButtonGroup(); viewModeResourcesToggleButton = new JCommandToggleButton(fixCommandTitle(translate("menu.file.view.resources")), View.getResizableIcon("viewresources16")); assignListener(viewModeResourcesToggleButton, ACTION_VIEWMODE_RESOURCES); @@ -365,13 +370,13 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener { viewModeHexToggleButton = new JCommandToggleButton(fixCommandTitle(translate("menu.file.view.hex")), View.getResizableIcon("viewhex16")); assignListener(viewModeHexToggleButton, ACTION_VIEWMODE_HEX); - grpViewMode.add(viewModeResourcesToggleButton); - grpViewMode.add(viewModeHexToggleButton); + viewModeToggleGroup.add(viewModeResourcesToggleButton); + viewModeToggleGroup.add(viewModeHexToggleButton); if (Configuration.dumpView.get()) { - grpViewMode.setSelected(viewModeHexToggleButton, true); + viewModeToggleGroup.setSelected(viewModeHexToggleButton, true); } else { - grpViewMode.setSelected(viewModeResourcesToggleButton, true); + viewModeToggleGroup.setSelected(viewModeResourcesToggleButton, true); } viewBand.addCommandButton(viewModeResourcesToggleButton, RibbonElementPriority.MEDIUM); @@ -389,8 +394,11 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener { 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); + timeLineToggleButton = new JCommandToggleButton(fixCommandTitle(translate("menu.tools.timeline")), View.getResizableIcon("timeline32")); + assignListener(timeLineToggleButton, ACTION_TIMELINE); + + timeLineToggleGroup = new CommandToggleButtonGroup(); + timeLineToggleGroup.add(timeLineToggleButton); gotoDocumentClassCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.gotodocumentclass")), View.getResizableIcon("gotomainclass32")); assignListener(gotoDocumentClassCommandButton, ACTION_GOTO_DOCUMENT_CLASS); @@ -405,7 +413,7 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener { assignListener(loadCacheCommandButton, ACTION_LOAD_CACHE); toolsBand.addCommandButton(searchCommandButton, RibbonElementPriority.TOP); - toolsBand.addCommandButton(timeLineCommandButton, RibbonElementPriority.TOP); + toolsBand.addCommandButton(timeLineToggleButton, RibbonElementPriority.TOP); toolsBand.addCommandButton(gotoDocumentClassCommandButton, RibbonElementPriority.TOP); toolsBand.addCommandButton(proxyCommandButton, RibbonElementPriority.MEDIUM); toolsBand.addCommandButton(loadMemoryCommandButton, RibbonElementPriority.MEDIUM); @@ -614,7 +622,7 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener { globalrenameCommandButton.setEnabled(swfLoaded); deobfuscationCommandButton.setEnabled(swfLoaded); searchCommandButton.setEnabled(swfLoaded); - timeLineCommandButton.setEnabled(swfLoaded); + timeLineToggleButton.setEnabled(swfLoaded); gotoDocumentClassCommandButton.setEnabled(hasAbc); deobfuscationCommandButton.setEnabled(hasAbc); @@ -705,11 +713,13 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener { case ACTION_VIEWMODE_RESOURCES: Configuration.dumpView.set(false); - mainFrame.panel.showDumpView(false); + mainFrame.panel.showView(MainPanel.VIEW_RESOURCES); + timeLineToggleGroup.setSelected(timeLineToggleButton, false); break; case ACTION_VIEWMODE_HEX: Configuration.dumpView.set(true); - mainFrame.panel.showDumpView(true); + mainFrame.panel.showView(MainPanel.VIEW_DUMP); + timeLineToggleGroup.setSelected(timeLineToggleButton, false); break; case ACTION_DEOBFUSCATION_MODE_OLD: Configuration.deobfuscationMode.set(0); @@ -719,15 +729,28 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener { Configuration.deobfuscationMode.set(1); mainFrame.panel.autoDeobfuscateChanged(); break; - case ACTION_DUMP_VIEW_SWITCH: - Configuration.dumpView.set(miDumpView.isSelected()); - mainFrame.panel.showDumpView(miDumpView.isSelected()); - break; case ACTION_SEARCH: mainFrame.panel.searchAs(); break; case ACTION_TIMELINE: - mainFrame.panel.timeline(); + timeLineToggleGroup.setSelected(timeLineToggleButton, timeLineToggleGroup.getSelected() == timeLineToggleButton); + if (timeLineToggleGroup.getSelected() == timeLineToggleButton) { + if (!mainFrame.panel.showView(MainPanel.VIEW_TIMELINE)) { + timeLineToggleGroup.setSelected(timeLineToggleButton, false); + } else { + viewModeToggleGroup.setSelected(viewModeHexToggleButton, false); + viewModeToggleGroup.setSelected(viewModeResourcesToggleButton, false); + } + } else { + if (Configuration.dumpView.get()) { + viewModeToggleGroup.setSelected(viewModeHexToggleButton, true); + mainFrame.panel.showView(MainPanel.VIEW_DUMP); + } else { + viewModeToggleGroup.setSelected(viewModeResourcesToggleButton, true); + mainFrame.panel.showView(MainPanel.VIEW_RESOURCES); + } + + } 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) { diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index c04f03b27..c9d54b1a2 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -63,7 +63,8 @@ import com.jpexs.decompiler.flash.gui.dumpview.DumpTree; import com.jpexs.decompiler.flash.gui.dumpview.DumpTreeModel; import com.jpexs.decompiler.flash.gui.dumpview.DumpViewPanel; import com.jpexs.decompiler.flash.gui.player.FlashPlayerPanel; -import com.jpexs.decompiler.flash.gui.timeline.TimelineFrame; +import com.jpexs.decompiler.flash.gui.timeline.TimelineViewPanel; +import com.jpexs.decompiler.flash.gui.timeline.TimelinePanel; import com.jpexs.decompiler.flash.gui.treenodes.SWFBundleNode; import com.jpexs.decompiler.flash.gui.treenodes.SWFNode; import com.jpexs.decompiler.flash.gui.treenodes.StringNode; @@ -219,6 +220,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec private ABCPanel abcPanel; private ActionPanel actionPanel; private final JPanel welcomePanel; + private final TimelineViewPanel timelineViewPanel; private final MainFrameStatusPanel statusPanel; private final MainFrameMenu mainMenu; private final JProgressBar progressBar = new JProgressBar(0, 100); @@ -241,6 +243,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec private static final String DETAILCARDEMPTYPANEL = "Empty card"; private static final String SPLIT_PANE1 = "SPLITPANE1"; private static final String WELCOME_PANEL = "WELCOMEPANEL"; + private static final String TIMELINE_PANEL = "TIMELINEPANEL"; private final JSplitPane splitPane1; private final JSplitPane splitPane2; private boolean splitsInited = false; @@ -560,10 +563,13 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec } }); + timelineViewPanel = new TimelineViewPanel(); + CardLayout cl3 = new CardLayout(); contentPanel = new JPanel(cl3); contentPanel.add(welcomePanel, WELCOME_PANEL); contentPanel.add(splitPane1, SPLIT_PANE1); + contentPanel.add(timelineViewPanel, TIMELINE_PANEL); add(contentPanel); cl3.show(contentPanel, WELCOME_PANEL); @@ -578,7 +584,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec }); detailPanel.setVisible(false); - showDumpView(Configuration.dumpView.get()); + showView(Configuration.dumpView.get() ? VIEW_DUMP : VIEW_RESOURCES); updateUi(); //Opening files with drag&drop to main window @@ -2143,19 +2149,52 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec return mainMenu.isInternalFlashViewerSelected(); } - public void showDumpView(boolean show) { - treePanel.removeAll(); - if (show) { - treePanel.add(new JScrollPane(dumpTree), BorderLayout.CENTER); - treePanelMode = TreePanelMode.DUMP_TREE; - showDetail(DETAILCARDEMPTYPANEL); - } else { - treePanel.add(new JScrollPane(tagTree), BorderLayout.CENTER); - treePanel.add(searchPanel, BorderLayout.SOUTH); - treePanelMode = TreePanelMode.TAG_TREE; + public static final int VIEW_RESOURCES = 0; + public static final int VIEW_DUMP = 1; + public static final int VIEW_TIMELINE = 2; + + public boolean showView(int view) { + + CardLayout cl = (CardLayout) (contentPanel.getLayout()); + switch (view) { + case VIEW_DUMP: + if (!isWelcomeScreen) { + cl.show(contentPanel, SPLIT_PANE1); + } + treePanel.removeAll(); + treePanel.add(new JScrollPane(dumpTree), BorderLayout.CENTER); + treePanelMode = TreePanelMode.DUMP_TREE; + showDetail(DETAILCARDEMPTYPANEL); + reload(true); + treePanel.revalidate(); + return true; + case VIEW_RESOURCES: + if (!isWelcomeScreen) { + cl.show(contentPanel, SPLIT_PANE1); + } + treePanel.removeAll(); + treePanel.add(new JScrollPane(tagTree), BorderLayout.CENTER); + treePanel.add(searchPanel, BorderLayout.SOUTH); + treePanelMode = TreePanelMode.TAG_TREE; + reload(true); + treePanel.revalidate(); + return true; + case VIEW_TIMELINE: + final SWF swf = getCurrentSwf(); + if (swf != null) { + TreeItem item = tagTree.getCurrentTreeItem(); + if (item instanceof DefineSpriteTag) { + timelineViewPanel.setTimelined((DefineSpriteTag) item); + } else { + timelineViewPanel.setTimelined(swf); + } + cl.show(contentPanel, TIMELINE_PANEL); + return true; + } + return false; } - reload(true); - treePanel.revalidate(); + return false; + } private void dumpViewReload(boolean forceReload) { @@ -2499,21 +2538,6 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec statusPanel.setErrorState(errorState); } - public void timeline() { - final SWF swf = getCurrentSwf(); - if (swf != null) { - TreeItem item = tagTree.getCurrentTreeItem(); - if (item instanceof DefineSpriteTag) { - TimelineFrame tf = new TimelineFrame((DefineSpriteTag) item); - tf.setVisible(true); - return; - } - - TimelineFrame tf = new TimelineFrame(swf); - tf.setVisible(true); - } - } - public static Timelined makeTimelined(final Tag tag) { return new Timelined() { diff --git a/src/com/jpexs/decompiler/flash/gui/NewVersionDialog.java b/src/com/jpexs/decompiler/flash/gui/NewVersionDialog.java index 36b4e8b5c..2a39af5f7 100644 --- a/src/com/jpexs/decompiler/flash/gui/NewVersionDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/NewVersionDialog.java @@ -141,7 +141,7 @@ public class NewVersionDialog extends AppDialog implements ActionListener { @Override public void actionPerformed(ActionEvent e) { if (e.getActionCommand() == ACTION_OK) { - String url; + String url; if (latestVersion.updateLink != null) { url = latestVersion.updateLink; } else { diff --git a/src/com/jpexs/decompiler/flash/gui/View.java b/src/com/jpexs/decompiler/flash/gui/View.java index 04ea9cc20..1b921ac91 100644 --- a/src/com/jpexs/decompiler/flash/gui/View.java +++ b/src/com/jpexs/decompiler/flash/gui/View.java @@ -537,8 +537,7 @@ public class View { } } } - + return false; } } - diff --git a/src/com/jpexs/decompiler/flash/gui/dumpview/DumpViewPanel.java b/src/com/jpexs/decompiler/flash/gui/dumpview/DumpViewPanel.java index 81c8ee31c..11914de31 100644 --- a/src/com/jpexs/decompiler/flash/gui/dumpview/DumpViewPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/dumpview/DumpViewPanel.java @@ -49,7 +49,7 @@ public class DumpViewPanel extends JPanel { super(new BorderLayout()); this.dumpTree = dumpTree; - + selectedByteInfo = new JLabel(); selectedByteInfo.setMinimumSize(new Dimension(100, 20)); selectedByteInfo.setText("-"); @@ -64,13 +64,13 @@ public class DumpViewPanel extends JPanel { dumpViewHexTable.addListener(new HexViewListener() { private int lastAddressUnderCursor = -1; - + @Override public void byteValueChanged(int address, byte b) { if (skipValueChange) { return; } - + if (address != -1) { TreeModel model = dumpTree.getModel(); DumpInfo di = DumpInfoSwfNode.getSwfNode(selectedDumpInfo); @@ -100,7 +100,7 @@ public class DumpViewPanel extends JPanel { dumpTree.setSelectionPath(tp); dumpTree.scrollPathToVisible(tp); } - + byte[] data = dumpViewHexTable.getData(); byteMouseMoved(lastAddressUnderCursor, lastAddressUnderCursor == -1 ? 0 : data[lastAddressUnderCursor]); } @@ -115,20 +115,20 @@ public class DumpViewPanel extends JPanel { b = data[address]; } } - + if (address != -1) { int b2 = b & 0xff; - selectedByteInfo.setText("Addr: " + Helper.padZeros(address, 8) + - " Hex: " + Helper.padZeros(Integer.toHexString(b2), 2) + - " Dec: " + b2 + - " Bin: " + Helper.padZeros(Integer.toBinaryString(b2), 8) + - " Ascii: " + (char) b2); + selectedByteInfo.setText("Addr: " + Helper.padZeros(address, 8) + + " Hex: " + Helper.padZeros(Integer.toHexString(b2), 2) + + " Dec: " + b2 + + " Bin: " + Helper.padZeros(Integer.toBinaryString(b2), 8) + + " Ascii: " + (char) b2); } else { selectedByteInfo.setText("-"); } } }); - + add(new JScrollPane(dumpViewHexTable), BorderLayout.CENTER); } @@ -137,7 +137,7 @@ public class DumpViewPanel extends JPanel { skipNextScroll = false; return; } - + this.selectedDumpInfo = dumpInfo; byte[] data = DumpInfoSwfNode.getSwfNode(dumpInfo).getSwf().originalUncompressedData; List dumpInfos = new ArrayList<>(); diff --git a/src/com/jpexs/decompiler/flash/gui/hexview/HexView.java b/src/com/jpexs/decompiler/flash/gui/hexview/HexView.java index a981ed27d..b07599270 100644 --- a/src/com/jpexs/decompiler/flash/gui/hexview/HexView.java +++ b/src/com/jpexs/decompiler/flash/gui/hexview/HexView.java @@ -50,11 +50,11 @@ public class HexView extends JTable { private final Color bgColorAlternate = Color.decode("#EDEDED"); private int mouseOverIdx = -1; private HexViewListener listener; - + private class HighlightCellRenderer extends DefaultTableCellRenderer { public int byteIndex; - + @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) { @@ -81,7 +81,7 @@ public class HexView extends JTable { foreground = Color.black; background = row % 2 == 0 ? bgColor : bgColorAlternate; } - + if (idx != -1 && idx == mouseOverIdx) { foreground = new Color(255 - foreground.getRed(), 255 - foreground.getGreen(), 255 - foreground.getBlue()); background = new Color(255 - background.getRed(), 255 - background.getGreen(), 255 - background.getBlue()); @@ -92,18 +92,18 @@ public class HexView extends JTable { return l; } } - + private class HexViewSelectionListener implements ListSelectionListener { private final HexView table; - + public HexViewSelectionListener(HexView table) { this.table = table; } - + @Override public void valueChanged(ListSelectionEvent e) { - + int col = table.getSelectedColumn(); int row = table.getSelectedRow(); @@ -118,7 +118,7 @@ public class HexView extends JTable { @Override public void mouseExited(MouseEvent e) { - HexView table = (HexView) e.getSource(); + HexView table = (HexView) e.getSource(); Point point = e.getPoint(); int col = table.columnAtPoint(point); int row = table.rowAtPoint(point); @@ -131,17 +131,17 @@ public class HexView extends JTable { } private class HexViewMouseMotionAdapter extends MouseMotionAdapter { - + @Override public void mouseMoved(MouseEvent e) { - HexView table = (HexView) e.getSource(); + HexView table = (HexView) e.getSource(); Point point = e.getPoint(); int col = table.columnAtPoint(point); int row = table.rowAtPoint(point); int idx = getIdxByColAndRow(row, col); mouseOverIdx = idx; getModel().fireTableCellUpdated(row, col); - + if (listener != null) { listener.byteMouseMoved(idx, idx == -1 ? 0 : getModel().getData()[idx]); } @@ -182,7 +182,7 @@ public class HexView extends JTable { column.setMaxWidth(10); column.setCellRenderer(cellRenderer); } - + addMouseListener(new HexViewMouseAdapter()); addMouseMotionListener(new HexViewMouseMotionAdapter()); ListSelectionModel rowSelModel = getSelectionModel(); @@ -195,9 +195,9 @@ public class HexView extends JTable { @Override public HexViewTableModel getModel() { TableModel model = super.getModel(); - return (HexViewTableModel) model; + return (HexViewTableModel) model; } - + public void setData(byte[] data, long[] highlightStarts, long[] highlightEnds) { if ((highlightStarts == null) ^ (highlightEnds == null)) { @@ -216,7 +216,7 @@ public class HexView extends JTable { public byte[] getData() { return getModel().getData(); } - + public void scrollToByte(long byteNum) { int row = (int) (byteNum / bytesInRow); @@ -237,7 +237,7 @@ public class HexView extends JTable { } return idx; } - + public int getFocusedByteIdx() { int col = getSelectedColumn(); int row = getSelectedRow(); @@ -245,7 +245,7 @@ public class HexView extends JTable { int idx = getIdxByColAndRow(row, col); return idx; } - + public void scrollToByte(long[] byteNumStarts, long[] byteNumEnds) { for (int i = 0; i < byteNumStarts.length; i++) { scrollToByte(byteNumStarts[i]); @@ -253,7 +253,7 @@ public class HexView extends JTable { scrollToByte(byteNumStarts[i]); } } - + public void addListener(HexViewListener listener) { this.listener = listener; } diff --git a/src/com/jpexs/decompiler/flash/gui/hexview/HexViewTableModel.java b/src/com/jpexs/decompiler/flash/gui/hexview/HexViewTableModel.java index d5588b777..b35a9d442 100644 --- a/src/com/jpexs/decompiler/flash/gui/hexview/HexViewTableModel.java +++ b/src/com/jpexs/decompiler/flash/gui/hexview/HexViewTableModel.java @@ -23,7 +23,7 @@ import javax.swing.table.AbstractTableModel; * @author JPEXS */ public class HexViewTableModel extends AbstractTableModel { - + private byte[] data; private final int bytesInRow; @@ -79,15 +79,15 @@ public class HexViewTableModel extends AbstractTableModel { return null; } } - + public byte[] getData() { return data; } - + public void setData(byte[] data) { this.data = data; } - + @Override public void fireTableCellUpdated(int row, int columnd) { super.fireTableCellUpdated(bytesInRow, bytesInRow); diff --git a/src/com/jpexs/decompiler/flash/gui/proxy/ProxyFrame.java b/src/com/jpexs/decompiler/flash/gui/proxy/ProxyFrame.java index d11184d41..6510f226e 100644 --- a/src/com/jpexs/decompiler/flash/gui/proxy/ProxyFrame.java +++ b/src/com/jpexs/decompiler/flash/gui/proxy/ProxyFrame.java @@ -369,9 +369,9 @@ public class ProxyFrame extends AppFrame implements ActionListener, CatchedListe if ((!sniffOSCheckBox.isSelected()) && (contentType.equals("application/octet-stream"))) { return null; } - + byte[] result = null; - + if (!listModel.contains(url)) { try { byte[] hdr = new byte[3]; @@ -387,16 +387,16 @@ public class ProxyFrame extends AppFrame implements ActionListener, CatchedListe try (FileOutputStream fos = new FileOutputStream(new File(tempFilePath))) { fos.write(dataArray); } - + result = SWFDecompilerPlugin.fireProxyFileCatched(dataArray); - + Replacement r = new Replacement(url, tempFilePath); r.lastAccess = Calendar.getInstance(); listModel.addURL(r); } catch (IOException e) { } } - + return result; } diff --git a/src/com/jpexs/decompiler/flash/gui/timeline/TimelineBodyPanel.java b/src/com/jpexs/decompiler/flash/gui/timeline/TimelineBodyPanel.java index 1aeb0f642..6ebc516c0 100644 --- a/src/com/jpexs/decompiler/flash/gui/timeline/TimelineBodyPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/timeline/TimelineBodyPanel.java @@ -1,273 +1,311 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.gui.timeline; - -import com.jpexs.decompiler.flash.timeline.DepthState; -import com.jpexs.decompiler.flash.timeline.Timeline; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.util.ArrayList; -import java.util.List; -import javax.swing.JPanel; - -/** - * - * @author JPEXS - */ -public class TimelineBodyPanel extends JPanel implements MouseListener { - - private final Timeline timeLine; - - public static Color frameColor = Color.lightGray; - public static Color emptyFrameColor = Color.white; - public static Color emptyFrameSecondColor = new Color(0xed, 0xed, 0xed); - public static Color borderColor = Color.black; - public static Color emptyBorderColor = Color.lightGray; - public static Color keyColor = Color.black; - public static Color aColor = Color.black; - public static Color stopColor = Color.white; - public static Color stopBorderColor = Color.black; - public static Color borderLinesColor = new Color(0xde, 0xde, 0xde); - - public static Color selectedColor = new Color(113, 174, 235); - public static final int borderLinesLength = 2; - public static final float fontSize = 10.0f; - - private final List listeners = new ArrayList<>(); - - public Point cursor = null; - - public void addFrameSelectionListener(FrameSelectionListener l) { - listeners.add(l); - } - - public void removeFrameSelectionListener(FrameSelectionListener l) { - listeners.remove(l); - } - - public TimelineBodyPanel(Timeline timeLine) { - - this.timeLine = timeLine; - Dimension dim = new Dimension(TimelinePanel.FRAME_WIDTH * timeLine.getFrameCount() + 1, TimelinePanel.FRAME_HEIGHT * timeLine.getMaxDepth()); - setSize(dim); - setPreferredSize(dim); - addMouseListener(this); - } - - @Override - protected void paintComponent(Graphics g1) { - Graphics2D g = (Graphics2D) g1; - g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); - g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - - g.setColor(TimelinePanel.backgroundColor); - g.fillRect(0, 0, getWidth(), getHeight()); - Rectangle clip = g.getClipBounds(); - int start_f = clip.x / TimelinePanel.FRAME_WIDTH; - int start_d = clip.y / TimelinePanel.FRAME_HEIGHT; - int end_f = (clip.x + clip.width) / TimelinePanel.FRAME_WIDTH; - int end_d = (clip.y + clip.height) / TimelinePanel.FRAME_HEIGHT; - - int max_d = timeLine.getMaxDepth(); - if (max_d < end_d) { - end_d = max_d; - } - int max_f = timeLine.getFrameCount() - 1; - if (max_f < end_f) { - end_f = max_f; - } - - if (end_d - start_d + 1 < 0) { - return; - } - - boolean keyfound[] = new boolean[end_d - start_d + 1]; - - for (int f = start_f; f <= end_f; f++) { - for (int d = start_d; d <= end_d; d++) { - DepthState fl = timeLine.frames.get(f).layers.get(d); - if (fl == null) { - if ((f + 1) % 5 == 0) { - g.setColor(emptyFrameSecondColor); - } else { - g.setColor(emptyFrameColor); - } - g.fillRect(f * TimelinePanel.FRAME_WIDTH, d * TimelinePanel.FRAME_HEIGHT, TimelinePanel.FRAME_WIDTH, TimelinePanel.FRAME_HEIGHT); - g.setColor(emptyBorderColor); - g.drawRect(f * TimelinePanel.FRAME_WIDTH, d * TimelinePanel.FRAME_HEIGHT, TimelinePanel.FRAME_WIDTH, TimelinePanel.FRAME_HEIGHT); - } - } - } - for (int f = start_f; f <= end_f; f++) { - for (int d = start_d; d <= end_d; d++) { - DepthState fl = timeLine.frames.get(f).layers.get(d); - DepthState flNext = null; - if (f < max_f) { - flNext = timeLine.frames.get(f + 1).layers.get(d); - } - boolean selected = false; - if (cursor != null) { - if (f == cursor.x && d == cursor.y) { - selected = true; - } - } - if (selected) { - if (!(fl != null && (flNext == null || flNext.key))) { - g.setColor(selectedColor); - g.fillRect(f * TimelinePanel.FRAME_WIDTH + 1, d * TimelinePanel.FRAME_HEIGHT + 1, TimelinePanel.FRAME_WIDTH - 1, TimelinePanel.FRAME_HEIGHT - 1); - } - } - - if (fl == null) { - - if (d == 0) { - if (timeLine.frames.get(f).action != null) { - g.setColor(aColor); - g.setFont(getFont().deriveFont(fontSize)); - int awidth = g.getFontMetrics().stringWidth("a"); - g.drawString("a", f * TimelinePanel.FRAME_WIDTH + TimelinePanel.FRAME_WIDTH / 2 - awidth / 2, d * TimelinePanel.FRAME_HEIGHT + TimelinePanel.FRAME_HEIGHT / 2 + fontSize / 2); - } - } - continue; - } else { - - int draw_f = 0; - if (fl.key) { - draw_f = f; - keyfound[d - start_d] = true; - } else if (!keyfound[d - start_d]) { - for (int k = f - 1; k >= 0; k--) { - fl = timeLine.frames.get(k).layers.get(d); - if (fl == null) { - break; - } - if (fl.key) { - keyfound[d - start_d] = true; - draw_f = k; - break; - } - } - } else { - continue; - } - int num_frames = 1; - for (int n = draw_f + 1; n < timeLine.getFrameCount(); n++) { - fl = timeLine.frames.get(n).layers.get(d); - if (fl == null) { - break; - } - if (fl.key) { - break; - } - num_frames++; - } - g.setColor(frameColor); - g.fillRect(draw_f * TimelinePanel.FRAME_WIDTH, d * TimelinePanel.FRAME_HEIGHT, num_frames * TimelinePanel.FRAME_WIDTH, TimelinePanel.FRAME_HEIGHT); - - if (selected) { - g.setColor(selectedColor); - g.fillRect(draw_f * TimelinePanel.FRAME_WIDTH, d * TimelinePanel.FRAME_HEIGHT, TimelinePanel.FRAME_WIDTH, TimelinePanel.FRAME_HEIGHT); - } - - g.setColor(borderColor); - g.drawRect(draw_f * TimelinePanel.FRAME_WIDTH, d * TimelinePanel.FRAME_HEIGHT, num_frames * TimelinePanel.FRAME_WIDTH, TimelinePanel.FRAME_HEIGHT); - g.setColor(keyColor); - g.fillOval(draw_f * TimelinePanel.FRAME_WIDTH + TimelinePanel.FRAME_WIDTH / 4, d * TimelinePanel.FRAME_HEIGHT + TimelinePanel.FRAME_HEIGHT * 3 / 4 - TimelinePanel.FRAME_WIDTH / 2 / 2, TimelinePanel.FRAME_WIDTH / 2, TimelinePanel.FRAME_WIDTH / 2); - if (num_frames > 1) { - if (cursor != null && cursor.y == d && cursor.x == f + num_frames - 1) { - g.setColor(selectedColor); - g.fillRect((f + num_frames - 1) * TimelinePanel.FRAME_WIDTH + 1, d * TimelinePanel.FRAME_HEIGHT + 1, TimelinePanel.FRAME_WIDTH - 1, TimelinePanel.FRAME_HEIGHT - 1); - } - g.setColor(stopColor); - g.fillRect((draw_f + num_frames - 1) * TimelinePanel.FRAME_WIDTH + TimelinePanel.FRAME_WIDTH / 4, d * TimelinePanel.FRAME_HEIGHT + TimelinePanel.FRAME_HEIGHT / 2 - 2, TimelinePanel.FRAME_WIDTH / 2, TimelinePanel.FRAME_HEIGHT / 2); - g.setColor(stopBorderColor); - g.drawRect((draw_f + num_frames - 1) * TimelinePanel.FRAME_WIDTH + TimelinePanel.FRAME_WIDTH / 4, d * TimelinePanel.FRAME_HEIGHT + TimelinePanel.FRAME_HEIGHT / 2 - 2, TimelinePanel.FRAME_WIDTH / 2, TimelinePanel.FRAME_HEIGHT / 2); - - g.setColor(borderLinesColor); - for (int n = draw_f + 1; n < draw_f + num_frames; n++) { - g.drawLine(n * TimelinePanel.FRAME_WIDTH, d * TimelinePanel.FRAME_HEIGHT + 1, n * TimelinePanel.FRAME_WIDTH, d * TimelinePanel.FRAME_HEIGHT + borderLinesLength); - g.drawLine(n * TimelinePanel.FRAME_WIDTH, d * TimelinePanel.FRAME_HEIGHT + TimelinePanel.FRAME_HEIGHT - 1, n * TimelinePanel.FRAME_WIDTH, d * TimelinePanel.FRAME_HEIGHT + TimelinePanel.FRAME_HEIGHT - borderLinesLength); - } - } - } - } - } - - if (cursor != null && cursor.x >= start_f && cursor.x <= end_f) { - g.setColor(TimelinePanel.selectedBorderColor); - g.drawLine(cursor.x * TimelinePanel.FRAME_WIDTH + TimelinePanel.FRAME_WIDTH / 2, 0, cursor.x * TimelinePanel.FRAME_WIDTH + TimelinePanel.FRAME_WIDTH / 2, getHeight()); - } - } - - @Override - public void mouseClicked(MouseEvent e) { - - } - - public void frameSelect(int frame, int depth) { - if (cursor != null && cursor.x == frame && (cursor.y == depth || depth == -1)) { - return; - } - if (depth == -1 && cursor != null) { - depth = cursor.y; - } - cursor = new Point(frame, depth); - for (FrameSelectionListener l : listeners) { - l.frameSelected(frame, -1); - } - repaint(); - } - - @Override - public void mousePressed(MouseEvent e) { - Point p = e.getPoint(); - p.x = p.x / TimelinePanel.FRAME_WIDTH; - p.y = p.y / TimelinePanel.FRAME_HEIGHT; - if (p.x >= timeLine.getFrameCount()) { - p.x = timeLine.getFrameCount() - 1; - } - int maxDepth = timeLine.getMaxDepth(); - if (p.y > maxDepth) { - p.y = maxDepth; - } - frameSelect(p.x, p.y); - } - - @Override - public void mouseReleased(MouseEvent e) { - - } - - @Override - public void mouseEntered(MouseEvent e) { - - } - - @Override - public void mouseExited(MouseEvent e) { - - } - -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.gui.timeline; + +import com.jpexs.decompiler.flash.timeline.DepthState; +import com.jpexs.decompiler.flash.timeline.Timeline; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.ArrayList; +import java.util.List; +import javax.swing.JPanel; + +/** + * + * @author JPEXS + */ +public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListener { + + private final Timeline timeLine; + + public static Color frameColor = new Color(0xbd, 0xd8, 0xfc); + public static Color emptyFrameColor = Color.white; + public static Color emptyFrameSecondColor = new Color(0xea, 0xf2, 0xfc); + public static Color borderColor = Color.black; + public static Color emptyBorderColor = new Color(0xbd, 0xd8, 0xfc); + public static Color keyColor = Color.black; + public static Color aColor = Color.black; + public static Color stopColor = Color.white; + public static Color stopBorderColor = Color.black; + public static Color borderLinesColor = new Color(0xde, 0xde, 0xde); + + public static Color selectedColor = new Color(113, 174, 235); + public static final int borderLinesLength = 2; + public static final float fontSize = 10.0f; + + private final List listeners = new ArrayList<>(); + + public Point cursor = null; + + public void addFrameSelectionListener(FrameSelectionListener l) { + listeners.add(l); + } + + public void removeFrameSelectionListener(FrameSelectionListener l) { + listeners.remove(l); + } + + public TimelineBodyPanel(Timeline timeLine) { + + this.timeLine = timeLine; + Dimension dim = new Dimension(TimelinePanel.FRAME_WIDTH * timeLine.getFrameCount() + 1, TimelinePanel.FRAME_HEIGHT * timeLine.getMaxDepth()); + setSize(dim); + setPreferredSize(dim); + addMouseListener(this); + addKeyListener(this); + setFocusable(true); + } + + @Override + protected void paintComponent(Graphics g1) { + Graphics2D g = (Graphics2D) g1; + g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + g.setColor(TimelinePanel.backgroundColor); + g.fillRect(0, 0, getWidth(), getHeight()); + Rectangle clip = g.getClipBounds(); + int start_f = clip.x / TimelinePanel.FRAME_WIDTH; + int start_d = clip.y / TimelinePanel.FRAME_HEIGHT; + int end_f = (clip.x + clip.width) / TimelinePanel.FRAME_WIDTH; + int end_d = (clip.y + clip.height) / TimelinePanel.FRAME_HEIGHT; + + int max_d = timeLine.getMaxDepth(); + if (max_d < end_d) { + end_d = max_d; + } + int max_f = timeLine.getFrameCount() - 1; + if (max_f < end_f) { + end_f = max_f; + } + + if (end_d - start_d + 1 < 0) { + return; + } + + boolean keyfound[] = new boolean[end_d - start_d + 1]; + + for (int f = start_f; f <= end_f; f++) { + for (int d = start_d; d <= end_d; d++) { + DepthState fl = timeLine.frames.get(f).layers.get(d); + if (fl == null) { + if ((f + 1) % 5 == 0) { + g.setColor(emptyFrameSecondColor); + } else { + g.setColor(emptyFrameColor); + } + g.fillRect(f * TimelinePanel.FRAME_WIDTH, d * TimelinePanel.FRAME_HEIGHT, TimelinePanel.FRAME_WIDTH, TimelinePanel.FRAME_HEIGHT); + g.setColor(emptyBorderColor); + g.drawRect(f * TimelinePanel.FRAME_WIDTH, d * TimelinePanel.FRAME_HEIGHT, TimelinePanel.FRAME_WIDTH, TimelinePanel.FRAME_HEIGHT); + } + } + } + for (int f = start_f; f <= end_f; f++) { + for (int d = start_d; d <= end_d; d++) { + DepthState fl = timeLine.frames.get(f).layers.get(d); + DepthState flNext = null; + if (f < max_f) { + flNext = timeLine.frames.get(f + 1).layers.get(d); + } + boolean selected = false; + if (cursor != null) { + if (f == cursor.x && d == cursor.y) { + selected = true; + } + } + if (selected) { + if (!(fl != null && (flNext == null || flNext.key))) { + g.setColor(selectedColor); + g.fillRect(f * TimelinePanel.FRAME_WIDTH + 1, d * TimelinePanel.FRAME_HEIGHT + 1, TimelinePanel.FRAME_WIDTH - 1, TimelinePanel.FRAME_HEIGHT - 1); + } + } + + if (fl == null) { + + if (d == 0) { + if (timeLine.frames.get(f).action != null) { + g.setColor(aColor); + g.setFont(getFont().deriveFont(fontSize)); + int awidth = g.getFontMetrics().stringWidth("a"); + g.drawString("a", f * TimelinePanel.FRAME_WIDTH + TimelinePanel.FRAME_WIDTH / 2 - awidth / 2, d * TimelinePanel.FRAME_HEIGHT + TimelinePanel.FRAME_HEIGHT / 2 + fontSize / 2); + } + } + continue; + } else { + + int draw_f = 0; + if (fl.key) { + draw_f = f; + keyfound[d - start_d] = true; + } else if (!keyfound[d - start_d]) { + for (int k = f - 1; k >= 0; k--) { + fl = timeLine.frames.get(k).layers.get(d); + if (fl == null) { + break; + } + if (fl.key) { + keyfound[d - start_d] = true; + draw_f = k; + break; + } + } + } else { + continue; + } + int num_frames = 1; + for (int n = draw_f + 1; n < timeLine.getFrameCount(); n++) { + fl = timeLine.frames.get(n).layers.get(d); + if (fl == null) { + break; + } + if (fl.key) { + break; + } + num_frames++; + } + g.setColor(frameColor); + g.fillRect(draw_f * TimelinePanel.FRAME_WIDTH, d * TimelinePanel.FRAME_HEIGHT, num_frames * TimelinePanel.FRAME_WIDTH, TimelinePanel.FRAME_HEIGHT); + + if (selected) { + g.setColor(selectedColor); + g.fillRect(draw_f * TimelinePanel.FRAME_WIDTH, d * TimelinePanel.FRAME_HEIGHT, TimelinePanel.FRAME_WIDTH, TimelinePanel.FRAME_HEIGHT); + } + + g.setColor(borderColor); + g.drawRect(draw_f * TimelinePanel.FRAME_WIDTH, d * TimelinePanel.FRAME_HEIGHT, num_frames * TimelinePanel.FRAME_WIDTH, TimelinePanel.FRAME_HEIGHT); + g.setColor(keyColor); + g.fillOval(draw_f * TimelinePanel.FRAME_WIDTH + TimelinePanel.FRAME_WIDTH / 4, d * TimelinePanel.FRAME_HEIGHT + TimelinePanel.FRAME_HEIGHT * 3 / 4 - TimelinePanel.FRAME_WIDTH / 2 / 2, TimelinePanel.FRAME_WIDTH / 2, TimelinePanel.FRAME_WIDTH / 2); + if (num_frames > 1) { + if (cursor != null && cursor.y == d && cursor.x == f + num_frames - 1) { + g.setColor(selectedColor); + g.fillRect((f + num_frames - 1) * TimelinePanel.FRAME_WIDTH + 1, d * TimelinePanel.FRAME_HEIGHT + 1, TimelinePanel.FRAME_WIDTH - 1, TimelinePanel.FRAME_HEIGHT - 1); + } + g.setColor(stopColor); + g.fillRect((draw_f + num_frames - 1) * TimelinePanel.FRAME_WIDTH + TimelinePanel.FRAME_WIDTH / 4, d * TimelinePanel.FRAME_HEIGHT + TimelinePanel.FRAME_HEIGHT / 2 - 2, TimelinePanel.FRAME_WIDTH / 2, TimelinePanel.FRAME_HEIGHT / 2); + g.setColor(stopBorderColor); + g.drawRect((draw_f + num_frames - 1) * TimelinePanel.FRAME_WIDTH + TimelinePanel.FRAME_WIDTH / 4, d * TimelinePanel.FRAME_HEIGHT + TimelinePanel.FRAME_HEIGHT / 2 - 2, TimelinePanel.FRAME_WIDTH / 2, TimelinePanel.FRAME_HEIGHT / 2); + + g.setColor(borderLinesColor); + for (int n = draw_f + 1; n < draw_f + num_frames; n++) { + g.drawLine(n * TimelinePanel.FRAME_WIDTH, d * TimelinePanel.FRAME_HEIGHT + 1, n * TimelinePanel.FRAME_WIDTH, d * TimelinePanel.FRAME_HEIGHT + borderLinesLength); + g.drawLine(n * TimelinePanel.FRAME_WIDTH, d * TimelinePanel.FRAME_HEIGHT + TimelinePanel.FRAME_HEIGHT - 1, n * TimelinePanel.FRAME_WIDTH, d * TimelinePanel.FRAME_HEIGHT + TimelinePanel.FRAME_HEIGHT - borderLinesLength); + } + } + } + } + } + + if (cursor != null && cursor.x >= start_f && cursor.x <= end_f) { + g.setColor(TimelinePanel.selectedBorderColor); + g.drawLine(cursor.x * TimelinePanel.FRAME_WIDTH + TimelinePanel.FRAME_WIDTH / 2, 0, cursor.x * TimelinePanel.FRAME_WIDTH + TimelinePanel.FRAME_WIDTH / 2, getHeight()); + } + } + + @Override + public void mouseClicked(MouseEvent e) { + + } + + public void frameSelect(int frame, int depth) { + if (cursor != null && cursor.x == frame && (cursor.y == depth || depth == -1)) { + return; + } + if (depth == -1 && cursor != null) { + depth = cursor.y; + } + cursor = new Point(frame, depth); + for (FrameSelectionListener l : listeners) { + l.frameSelected(frame, depth); + } + repaint(); + } + + @Override + public void mousePressed(MouseEvent e) { + Point p = e.getPoint(); + p.x = p.x / TimelinePanel.FRAME_WIDTH; + p.y = p.y / TimelinePanel.FRAME_HEIGHT; + if (p.x >= timeLine.getFrameCount()) { + p.x = timeLine.getFrameCount() - 1; + } + int maxDepth = timeLine.getMaxDepth(); + if (p.y > maxDepth) { + p.y = maxDepth; + } + frameSelect(p.x, p.y); + } + + @Override + public void mouseReleased(MouseEvent e) { + + } + + @Override + public void mouseEntered(MouseEvent e) { + + } + + @Override + public void mouseExited(MouseEvent e) { + + } + + @Override + public void keyTyped(KeyEvent e) { + } + + @Override + public void keyPressed(KeyEvent e) { + switch (e.getKeyCode()) { + case 37: //left + if (cursor.x > 0) { + frameSelect(cursor.x - 1, cursor.y); + } + break; + case 39: //right + if (cursor.x < timeLine.frames.size() - 1) { + frameSelect(cursor.x + 1, cursor.y); + } + break; + case 38: //up + if (cursor.y > 0) { + frameSelect(cursor.x, cursor.y - 1); + } + break; + case 40: //down + if (cursor.y < timeLine.getMaxDepth()) { + frameSelect(cursor.x, cursor.y + 1); + } + break; + } + } + + @Override + public void keyReleased(KeyEvent e) { + } + +} diff --git a/src/com/jpexs/decompiler/flash/gui/timeline/TimelineFrame.java b/src/com/jpexs/decompiler/flash/gui/timeline/TimelineFrame.java deleted file mode 100644 index 538b93b79..000000000 --- a/src/com/jpexs/decompiler/flash/gui/timeline/TimelineFrame.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.gui.timeline; - -import com.jpexs.decompiler.flash.gui.AppFrame; -import com.jpexs.decompiler.flash.gui.View; -import com.jpexs.decompiler.flash.timeline.Timelined; -import java.awt.BorderLayout; -import java.awt.Container; -import java.awt.Image; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class TimelineFrame extends AppFrame { - - public TimelinePanel timeline; - - public TimelineFrame(Timelined timelined) { - setSize(800, 600); - View.setWindowIcon(this); - View.centerScreen(this); - setTitle(translate("dialog.title")); - Container cnt = getContentPane(); - cnt.setLayout(new BorderLayout()); - cnt.add(timeline = new TimelinePanel(timelined), BorderLayout.CENTER); - - List images = new ArrayList<>(); - images.add(View.loadImage("timeline16")); - images.add(View.loadImage("timeline32")); - setIconImages(images); - } -} diff --git a/src/com/jpexs/decompiler/flash/gui/timeline/TimelinePanel.java b/src/com/jpexs/decompiler/flash/gui/timeline/TimelinePanel.java index ae35bddfa..16814a317 100644 --- a/src/com/jpexs/decompiler/flash/gui/timeline/TimelinePanel.java +++ b/src/com/jpexs/decompiler/flash/gui/timeline/TimelinePanel.java @@ -1,106 +1,124 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.gui.timeline; - -import com.jpexs.decompiler.flash.timeline.Timeline; -import com.jpexs.decompiler.flash.timeline.Timelined; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.event.AdjustmentEvent; -import java.awt.event.AdjustmentListener; -import javax.swing.JPanel; -import javax.swing.JScrollPane; - -/** - * - * @author JPEXS - */ -public class TimelinePanel extends JPanel { - - public TimelineBodyPanel timelineBodyPanel; - public TimelineTimePanel timePanel; - public TimelineDepthPanel depthPanel; - public Timeline timeline; - - public static final int FRAME_WIDTH = 8; - public static final int FRAME_HEIGHT = 18; - - public static Color selectedColor = new Color(0xff, 0x99, 0x99); - public static Color selectedBorderColor = new Color(0xcc, 0, 0); - public static Color backgroundColor = new Color(0xee, 0xee, 0xee); - - public TimelinePanel(Timelined timelined) { - timeline = timelined.getTimeline(); - timelineBodyPanel = new TimelineBodyPanel(timeline); - setLayout(new BorderLayout()); - - JScrollPane sp = new JScrollPane(timelineBodyPanel); - - depthPanel = new TimelineDepthPanel(timeline); - - timePanel = new TimelineTimePanel(); - - JPanel row1Panel = new JPanel(); - row1Panel.setLayout(new BorderLayout()); - JPanel sepPanel = new JPanel(); - sepPanel.setBackground(TimelinePanel.backgroundColor); - sepPanel.setPreferredSize(new Dimension(depthPanel.getWidth(), timePanel.getHeight())); - row1Panel.add(sepPanel, BorderLayout.WEST); - row1Panel.add(timePanel, BorderLayout.CENTER); - - JPanel row2Panel = new JPanel(); - row2Panel.setLayout(new BorderLayout()); - row2Panel.add(depthPanel, BorderLayout.WEST); - row2Panel.add(sp, BorderLayout.CENTER); - - add(row1Panel, BorderLayout.NORTH); - add(row2Panel, BorderLayout.CENTER); - - sp.getHorizontalScrollBar().addAdjustmentListener(new AdjustmentListener() { - @Override - public void adjustmentValueChanged(AdjustmentEvent e) { - timePanel.scroll(e.getValue()); - } - }); - sp.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() { - - @Override - public void adjustmentValueChanged(AdjustmentEvent e) { - depthPanel.scroll(e.getValue()); - } - }); - - final TimelineTimePanel ftime = timePanel; - timelineBodyPanel.addFrameSelectionListener(new FrameSelectionListener() { - - @Override - public void frameSelected(int frame, int depth) { - ftime.frameSelect(frame); - } - }); - final TimelineBodyPanel ftimeline = timelineBodyPanel; - timePanel.addFrameSelectionListener(new FrameSelectionListener() { - - @Override - public void frameSelected(int frame, int depth) { - ftimeline.frameSelect(frame, depth); - } - }); - - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.gui.timeline; + +import com.jpexs.decompiler.flash.timeline.Timeline; +import com.jpexs.decompiler.flash.timeline.Timelined; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; +import javax.swing.JPanel; +import javax.swing.JScrollPane; + +/** + * + * @author JPEXS + */ +public class TimelinePanel extends JPanel { + + private TimelineBodyPanel timelineBodyPanel; + private TimelineTimePanel timePanel; + private TimelineDepthPanel depthPanel; + private Timeline timeline; + + public static final int FRAME_WIDTH = 8; + public static final int FRAME_HEIGHT = 18; + + public static Color selectedColor = new Color(0xff, 0x99, 0x99); + public static Color selectedBorderColor = new Color(0xcc, 0, 0); + public static Color backgroundColor = new Color(0xd9, 0xe7, 0xfa); + + public Timeline getTimeline() { + return timeline; + } + + public void addFrameSelectionListener(FrameSelectionListener l) { + timelineBodyPanel.addFrameSelectionListener(l); + } + + public void removeFrameSelectionListener(FrameSelectionListener l) { + timelineBodyPanel.removeFrameSelectionListener(l); + } + + public void setTimelined(Timelined timelined) { + this.removeAll(); + if (timelined == null) { + this.revalidate(); + return; + } + timeline = timelined.getTimeline(); + timelineBodyPanel = new TimelineBodyPanel(timeline); + setLayout(new BorderLayout()); + + JScrollPane sp = new JScrollPane(timelineBodyPanel); + + depthPanel = new TimelineDepthPanel(timeline); + + timePanel = new TimelineTimePanel(); + + JPanel row1Panel = new JPanel(); + row1Panel.setLayout(new BorderLayout()); + JPanel sepPanel = new JPanel(); + sepPanel.setBackground(TimelinePanel.backgroundColor); + sepPanel.setPreferredSize(new Dimension(depthPanel.getWidth(), timePanel.getHeight())); + row1Panel.add(sepPanel, BorderLayout.WEST); + row1Panel.add(timePanel, BorderLayout.CENTER); + + JPanel row2Panel = new JPanel(); + row2Panel.setLayout(new BorderLayout()); + row2Panel.add(depthPanel, BorderLayout.WEST); + row2Panel.add(sp, BorderLayout.CENTER); + + add(row1Panel, BorderLayout.NORTH); + add(row2Panel, BorderLayout.CENTER); + + sp.getHorizontalScrollBar().addAdjustmentListener(new AdjustmentListener() { + @Override + public void adjustmentValueChanged(AdjustmentEvent e) { + timePanel.scroll(e.getValue()); + } + }); + sp.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() { + + @Override + public void adjustmentValueChanged(AdjustmentEvent e) { + depthPanel.scroll(e.getValue()); + } + }); + + final TimelineTimePanel ftime = timePanel; + timelineBodyPanel.addFrameSelectionListener(new FrameSelectionListener() { + + @Override + public void frameSelected(int frame, int depth) { + ftime.frameSelect(frame); + } + }); + final TimelineBodyPanel ftimeline = timelineBodyPanel; + timePanel.addFrameSelectionListener(new FrameSelectionListener() { + + @Override + public void frameSelected(int frame, int depth) { + ftimeline.frameSelect(frame, depth); + } + }); + this.revalidate(); + } + +} diff --git a/src/com/jpexs/decompiler/flash/gui/timeline/TimelineViewPanel.java b/src/com/jpexs/decompiler/flash/gui/timeline/TimelineViewPanel.java new file mode 100644 index 000000000..b88ebdbdf --- /dev/null +++ b/src/com/jpexs/decompiler/flash/gui/timeline/TimelineViewPanel.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.gui.timeline; + +import com.jpexs.decompiler.flash.gui.AppFrame; +import com.jpexs.decompiler.flash.gui.ImagePanel; +import com.jpexs.decompiler.flash.gui.View; +import com.jpexs.decompiler.flash.timeline.Timelined; +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Image; +import java.util.ArrayList; +import java.util.List; +import javax.swing.JPanel; +import javax.swing.JSplitPane; + +/** + * + * @author JPEXS + */ +public class TimelineViewPanel extends JPanel { + + public TimelinePanel timeline; + public ImagePanel previewPanel; + + public TimelineViewPanel() { + + } + + public void setTimelined(Timelined timelined) { + removeAll(); + if (timelined == null) { + revalidate(); + return; + } + setLayout(new BorderLayout()); + timeline = new TimelinePanel(); + timeline.setTimelined(timelined); + add(new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, timeline, previewPanel = new ImagePanel())); + + previewPanel.setTimelined(timelined, timelined.getTimeline().swf, 0); + //previewPanel.setPreferredSize(new Dimension(400,300)); + previewPanel.pause(); + previewPanel.gotoFrame(0); + timeline.addFrameSelectionListener(new FrameSelectionListener() { + + @Override + public void frameSelected(int frame, int depth) { + previewPanel.selectDepth(depth); + previewPanel.pause(); + previewPanel.gotoFrame(frame); + } + }); + revalidate(); + } +} diff --git a/src/com/jpexs/process/win32/Win32ProcessTools.java b/src/com/jpexs/process/win32/Win32ProcessTools.java index 4248e2339..8dab1da15 100644 --- a/src/com/jpexs/process/win32/Win32ProcessTools.java +++ b/src/com/jpexs/process/win32/Win32ProcessTools.java @@ -390,11 +390,11 @@ public class Win32ProcessTools extends ProcessTools { for (int pg = 0; pg < pages.size(); pg++) { MEMORY_BASIC_INFORMATION mbi = pages.get(pg); if (pageReadable(mbi)) { - long addr = pointerToAddress(mbi.baseAddress); + long addr = pointerToAddress(mbi.baseAddress); int maxsize = mbi.regionSize.intValue(); long pos = 0; - long bufSize = 1024*512; - do { + long bufSize = 1024 * 512; + do { NativeLongByReference bytesReadRef = new NativeLongByReference(); Memory buf = new Memory(bufSize); boolean ok = Kernel32.INSTANCE.ReadProcessMemory(hOtherProcess, new Pointer(addr + pos), buf, new NativeLong(bufSize), bytesReadRef); @@ -530,7 +530,7 @@ public class Win32ProcessTools extends ProcessTools { private final List pages; private int currentPage = 0; private long pagePos = 0; - private static final int BUFFER_SIZE = 1024*512; + private static final int BUFFER_SIZE = 1024 * 512; private byte[] buf; private int bufPos; private final HANDLE hOtherProcess;