From 4c78517715674377a3327b43faec7610d61013d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 23 Nov 2014 11:36:07 +0100 Subject: [PATCH] Issue #722 Go to next/previous frame Fixed printing some debug info --- .../decompiler/flash/gui/ImagePanel.java | 10 ++ .../flash/gui/graphics/gotoframe16.png | Bin 0 -> 898 bytes .../flash/gui/graphics/nextframe16.png | Bin 0 -> 891 bytes .../flash/gui/graphics/prevframe16.png | Bin 0 -> 883 bytes .../flash/gui/locales/MainFrame.properties | 8 ++ .../flash/gui/locales/MainFrame_cs.properties | 10 ++ .../flash/gui/player/FlashPlayerPanel.java | 20 ++- .../flash/gui/player/PlayerControls.java | 124 ++++++++++++++++-- 8 files changed, 151 insertions(+), 21 deletions(-) create mode 100644 src/com/jpexs/decompiler/flash/gui/graphics/gotoframe16.png create mode 100644 src/com/jpexs/decompiler/flash/gui/graphics/nextframe16.png create mode 100644 src/com/jpexs/decompiler/flash/gui/graphics/prevframe16.png diff --git a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java index a64464a45..ec7112d9f 100644 --- a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java +++ b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java @@ -729,6 +729,16 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis @Override public void gotoFrame(int frame) { + if (timelined == null) { + return; + } + Timeline timeline = timelined.getTimeline(); + if (frame >= timeline.getFrameCount()) { + return; + } + if(frame<0){ + return; + } this.frame = frame; drawFrame(); } diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/gotoframe16.png b/src/com/jpexs/decompiler/flash/gui/graphics/gotoframe16.png new file mode 100644 index 0000000000000000000000000000000000000000..b989df9138deedff0399a773f47c1cff48217fd8 GIT binary patch literal 898 zcmV-|1AY97P)D+r9>D>_X;f1H000McNliru-U}BA3_DDb6mI|k0}n|= zK~y-)Wm8RW6K4>9_T6{w-SxNEYdcPiAx<1OA61%CQQ!h4Q3>UWMAcR~Y-AlN=S7J5;UzsarkU-5>X(jV?qf2SZDpQ`@Y))4ocFw%xE;vGoyKC z1njd9E^T)M=m8wvVJyg*MOe!)EVKN|+*m3-`0nEp00#gEz=R#(#AU||Ap35#{Qj6; z8H~$~QI%Q)j4@%$u$EWLc$hDWOAG(h@*DXdmj1o@jRC+GcY)uT9xhFuNLHq^2g0Wl zF)bO@H6;`ZDgmFjCl;V%ap`5RrZ9U|9BC3!su*hvZQ2wduZt$*xZ?&O!D1 z@YR(&_~=+K7M?ayssU>i;Keq@aLVs$l-FZb?k(A|<3$Rf`*5^67}X;g*-i2Fg`@cV z(w~@`90KPKuH=^AEcmmD47{ovsY3_T{VyM93h``$0MNVC=BP(iV756J->Zt_>`iPp zIl`eJf?|C{@@QcKAfQq!E4wM0Z4Nj8&@frJNsg+lkcp!p>jhKae~Z!E9i?Vqa%-y*pgVf}tNGQYSb z&;D`icAYT`>9`6#;DX{3vE5<_c_~s+8HBfR^_N_I!_sG0oxb^N7d*wCODz0U8c{wB z{)NhK*U$H7-pX{vbcFmWZ06wkmVw)AMLfKhU*6==*#+s$uLO7m0RMZYwCmZCZeAGl z*e^z1j+wP>hNj~#R1v;gqJxV?GB6LIked;2-&;bNG=_-It0L9#lu)e$g YKSAX|g^@WP@Bjb+07*qoM6N<$f?O_`u>b%7 literal 0 HcmV?d00001 diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/nextframe16.png b/src/com/jpexs/decompiler/flash/gui/graphics/nextframe16.png new file mode 100644 index 0000000000000000000000000000000000000000..532b101a297dd72c58c4764c26c1b47c6f8c2411 GIT binary patch literal 891 zcmV->1BCpEP)D+r9>D>_X;f1H000McNliru-U}BA0z1+YIpF{R0|-e( zK~y-)Ws}QKTy+%3KlgX<+_`gShIug$pmf>}Oh<$St5qXi_$aBmZ=x}-*vQJ%|HQax zY;@BVabe=h1gc#ajZ_BPia1PT(^7^JD4i$sx{sd=h6eO(PR_~se!nN@q3|Dj`}2bl z;1tNXbeyp3Si~1jg|&Q1-B^8C&+p{F+1UE&%LZVp$G|VmO_tw#bF?~_I~{#@I2jvF#ACil zB4I>o<^_n=D^`aj^Z_xpX?9dj!pPk6N>b zZQH0qkcGh7&(ik<#VnVu4?aRRE-PPi*O+;}VU8 z39HR1k3SX_K*-droZ;2z^xXc2Bn!76^&t`fp?Uyl*$^2p@u}9hY6OGgP(^awtE!IO zZJkg)iiN6Sy9%!BA~eGlK&{>tg=VXV*CS9>4|cD^jcYS~vO{H|9s01}OQq4JWordR zh^hwcl^XipbiMh;=uoT=zC^8M6EZbEdS~oJC*h#M`h!P2v%~ikMcvVW(#mdVJ?VK^ z3UsZ`fWH9#_e>f6@oOV)VZv|kPV2Ij zvu%ft^cHGF@0PWR^^!Qh3>22;mF5Y8V?@Ki2oMKC{d5i314>Kt%J%X4e*tqyQ!D+r9>D>_X;f1H000McNliru-U}BA1upQ8OU(cP0{}@x zK~y-)Ws}KoTU8jvfA7BM>DloR$79kO;>I;5kwO`zvS6rHV2=bsS!F|3sB94%{sY9K zqJkwN0ttx~5@A>%7J)h)2*GjHNKN9nPU?Do9^S;liIu=z-Sg@D&N({Yy%PU9uYKB` z24=vH*rpk@OkJ3Rc3ao#kG1M{<*zT_tpGM)0j6{^n7?lOfb6r;`b(E0ja=N_TT~VO zqG_5^t*w`K>ueUv^7h6~t57X`v%UY@=WW1{PYpk_JYRY9m2-{d?D@$zlCki)Xe8_j zg@T^Igl{GmP%gzCk7mOj)7X_4`a*Uz+It&A<=8-WdA@Sx>8aj_v#FHN=@4{!Lz-zHVb7Sij#T zmGIMQcWG)vwreitQ+{W!eh_O~zKRjMTvmYT=c3JAG%}R|c>l9M#(^&7GuSprlEf$9 zK42-I!Kb=NJ^4g>?$P~BF`i8dAd*n~i(b`pW*fF`0nl!>_~@(B7g@rVp%f({8Ui>fx1G0J ztUcUf9Q!~aS0Ko}2mFgjnjo=+glB)_(zIhnfiaB;l$=O^cH{(N+Am~-7 zb#yEX8eM}M*Ivfw7VJK3vU&GbXSJ+?`_@c_&ql1xQZeR zJWd&>Ln7o;@T&@Yhb?~iajjF;Bdfdih4o)P@Rm>yvOq++bHaGXmY~Cr9j;!eFhU2ZD1pEW=zt5C*K6r83D(1Y#;iA*lvW8*Ow_U|1 zlea5MZmTRVt^>uj6{&NE;1p33mg(} literal 0 HcmV?d00001 diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index 98abf35e2..23aaddfda 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -528,3 +528,11 @@ contextmenu.addTag = Add tag deobfuscation.comment.tryenable = Tip: You can try enabling "Automatic deobfucation" in Settings deobfuscation.comment.failed = Deobfuscation is activated but decompilation still failed. If the file is NOT obfuscated, disable "Automatic deobfucation" for better results. +#after version 4.0.2 +preview.nextframe = Next frame +preview.prevframe = Previous frame +preview.gotoframe = Goto frame... + +preview.gotoframe.dialog.title = Goto frame +preview.gotoframe.dialog.message = Enter frame number (%min% - %max%) +preview.gotoframe.dialog.frame.error = Invalid frame number. It must be number between %min% and %max%. \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties index 952284df9..90b69128c 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties @@ -520,3 +520,13 @@ menu.debugger.replacetrace = Nahradit vol\u00e1n\u00ed trace menu.debugger.showlog = Zobrazit Log message.debugger = Tento SWF Debugger slou\u017e\u00ed jen k pos\u00edl\u00e1n\u00ed zpr\u00e1v do okna logu, konzole prohl\u00ed\u017ee\u010de nebo alert oken.\r\nNEN\u00cd ur\u010den pro krokov\u00e1n\u00ed k\u00f3du, breakpointy atd. + + +#after version 4.0.2 +preview.nextframe = Dal\u0161\u00ed sn\u00edmek +preview.prevframe = P\u0159ede\u0161l\u00fd sn\u00edmek +preview.gotoframe = P\u0159ej\u00edt na sn\u00edmek... + +preview.gotoframe.dialog.title = P\u0159ej\u00edt na sn\u00edmek +preview.gotoframe.dialog.message = Zadejte \u010d\u00edslo sn\u00edmku (%min% - %max%) +preview.gotoframe.dialog.frame.error = Neplatn\u00e9 \u010d\u00edslo sn\u00edmku. Mus\u00ed to b\u00fdt \u010d\u00edslo v rozmez\u00ed %min% a %max%. \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/player/FlashPlayerPanel.java b/src/com/jpexs/decompiler/flash/gui/player/FlashPlayerPanel.java index 1f577a540..4664cd752 100644 --- a/src/com/jpexs/decompiler/flash/gui/player/FlashPlayerPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/player/FlashPlayerPanel.java @@ -137,17 +137,7 @@ public class FlashPlayerPanel extends Panel implements Closeable, MediaDisplay { } } } - }); - flash.addFSCommandListener(new ActiveXEventListener() { - - @Override - public void onEvent(ActiveXEvent axe) { - System.out.println("Event:" + axe.name); - for (String k : axe.args.keySet()) { - System.out.println(k + "=" + axe.args.get(k)); - } - } - }); + }); } public synchronized void stopSWF() { @@ -203,12 +193,18 @@ public class FlashPlayerPanel extends Panel implements Closeable, MediaDisplay { } @Override - public boolean isPlaying() { + public boolean isPlaying() { return flash.IsPlaying(); } @Override public void gotoFrame(int frame) { + if(frame<0){ + return; + } + if(frame>=getTotalFrames()){ + return; + } flash.GotoFrame(frame); } diff --git a/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java b/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java index db2cd8d67..043a9416c 100644 --- a/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java +++ b/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java @@ -35,6 +35,8 @@ import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; @@ -46,14 +48,20 @@ import java.util.HashMap; import java.util.Map; import java.util.Timer; import java.util.TimerTask; +import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JColorChooser; import javax.swing.JLabel; +import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JProgressBar; +import javax.swing.JTextField; import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.event.AncestorEvent; +import javax.swing.event.AncestorListener; /** * @@ -69,6 +77,9 @@ public class PlayerControls extends JPanel implements ActionListener { static final String ACTION_ZOOMFIT = "ZOOMFIT"; static final String ACTION_ZOOMNONE = "ZOOMNONE"; static final String ACTION_SNAPSHOT = "SNAPSHOT"; + static final String ACTION_NEXTFRAME = "NEXTFRAME"; + static final String ACTION_PREVFRAME = "PREVFRAME"; + static final String ACTION_GOTOFRAME = "SELECTFRAME"; private final JButton pauseButton; private boolean paused = false; @@ -86,6 +97,7 @@ public class PlayerControls extends JPanel implements ActionListener { private final JPanel zoomPanel; private final JPanel graphicControls; private final JPanel playbackControls; + private final JPanel frameControls; private double realZoom = 1.0; private final JButton zoomFitButton; @@ -157,11 +169,12 @@ public class PlayerControls extends JPanel implements ActionListener { add(graphicControls); graphicControls.setVisible(display.screenAvailable()); + playbackControls = new JPanel(); this.display = display; JPanel controlPanel = new JPanel(new BorderLayout()); - frameLabel = new JLabel("0", SwingConstants.RIGHT); + frameLabel = new JLabel("0", SwingConstants.CENTER); frameLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); frameLabel.addMouseMotionListener(new MouseMotionAdapter() { @@ -172,6 +185,8 @@ public class PlayerControls extends JPanel implements ActionListener { }); + frameLabel.setVisible(display.screenAvailable()); + Dimension min = new Dimension(frameLabel.getFontMetrics(notUnderlinedFont).stringWidth("000"), frameLabel.getPreferredSize().height); frameLabel.setMinimumSize(min); frameLabel.setPreferredSize(min); @@ -200,9 +215,40 @@ public class PlayerControls extends JPanel implements ActionListener { timeLabel = new JLabel("(00:00.00)"); totalTimeLabel = new JLabel("(00:00.00)"); totalFrameLabel = new JLabel("0"); + + totalFrameLabel.setVisible(display.screenAvailable()); + + frameControls = new JPanel(new FlowLayout()); + + JButton prevFrameButton = new JButton(View.getIcon("prevframe16")); + prevFrameButton.setToolTipText(AppStrings.translate("preview.prevframe")); + prevFrameButton.setMargin(new Insets(4, 2, 2, 2)); + prevFrameButton.setActionCommand(ACTION_PREVFRAME); + prevFrameButton.addActionListener(this); + frameControls.add(prevFrameButton); + frameControls.setVisible(display.screenAvailable()); + + + frameControls.add(frameLabel); + + JButton nextFrameButton = new JButton(View.getIcon("nextframe16")); + nextFrameButton.setToolTipText(AppStrings.translate("preview.nextframe")); + nextFrameButton.setMargin(new Insets(4, 2, 2, 2)); + nextFrameButton.setActionCommand(ACTION_NEXTFRAME); + nextFrameButton.addActionListener(this); + frameControls.add(nextFrameButton); + + JButton gotoFrameButton = new JButton(View.getIcon("gotoframe16")); + gotoFrameButton.setToolTipText(AppStrings.translate("preview.gotoframe")); + gotoFrameButton.setMargin(new Insets(4, 2, 2, 2)); + gotoFrameButton.setActionCommand(ACTION_GOTOFRAME); + gotoFrameButton.addActionListener(this); + frameControls.add(gotoFrameButton); + + JPanel currentPanel = new JPanel(new FlowLayout()); - currentPanel.add(frameLabel); + currentPanel.add(frameControls); currentPanel.add(timeLabel); JPanel totalPanel = new JPanel(new FlowLayout()); totalPanel.add(totalFrameLabel); @@ -213,16 +259,19 @@ public class PlayerControls extends JPanel implements ActionListener { playbackControls.setLayout(new BoxLayout(playbackControls, BoxLayout.Y_AXIS)); JPanel buttonsPanel = new JPanel(new FlowLayout()); - pauseButton = new JButton(AppStrings.translate("preview.pause"), pauseIcon); - pauseButton.setMargin(new Insets(0, 0, 0, 0)); + + pauseButton = new JButton(pauseIcon); + pauseButton.setToolTipText(AppStrings.translate("preview.pause")); + pauseButton.setMargin(new Insets(4, 2, 2, 2)); pauseButton.setActionCommand(ACTION_PAUSE); pauseButton.addActionListener(this); - JButton stopButton = new JButton(AppStrings.translate("preview.stop"), View.getIcon("stop16")); - stopButton.setMargin(new Insets(0, 0, 0, 0)); + JButton stopButton = new JButton(View.getIcon("stop16")); + stopButton.setToolTipText(AppStrings.translate("preview.stop")); + stopButton.setMargin(new Insets(4, 2, 2, 2)); stopButton.setActionCommand(ACTION_STOP); stopButton.addActionListener(this); buttonsPanel.add(pauseButton); - buttonsPanel.add(stopButton); + buttonsPanel.add(stopButton); controlPanel.add(buttonsPanel, BorderLayout.CENTER); progress = new JProgressBar(); @@ -288,6 +337,9 @@ public class PlayerControls extends JPanel implements ActionListener { percentLabel.setVisible(zoom != 0.0); zoomPanel.setVisible(display.zoomAvailable()); graphicControls.setVisible(display.screenAvailable()); + totalFrameLabel.setVisible(display.screenAvailable()); + frameLabel.setVisible(display.screenAvailable()); + frameControls.setVisible(display.screenAvailable()); int totalFrames = display.getTotalFrames(); int currentFrame = display.getCurrentFrame(); int frameRate = display.getFrameRate(); @@ -315,10 +367,10 @@ public class PlayerControls extends JPanel implements ActionListener { paused = !paused; if (paused) { - pauseButton.setText(AppStrings.translate("preview.play")); + pauseButton.setToolTipText(AppStrings.translate("preview.play")); pauseButton.setIcon(playIcon); } else { - pauseButton.setText(AppStrings.translate("preview.pause")); + pauseButton.setToolTipText(AppStrings.translate("preview.pause")); pauseButton.setIcon(pauseIcon); } } @@ -358,6 +410,60 @@ public class PlayerControls extends JPanel implements ActionListener { display.pause(); } break; + + case ACTION_GOTOFRAME: + final JPanel gotoPanel = new JPanel(new BorderLayout()); + final JTextField frameField = new JTextField("" + display.getCurrentFrame()); + gotoPanel.add(new JLabel(AppStrings.translate("preview.gotoframe.dialog.message").replace("%min%", "1").replace("%max%", "" + display.getTotalFrames())), BorderLayout.NORTH); + gotoPanel.add(frameField, BorderLayout.CENTER); + gotoPanel.addAncestorListener(new AncestorListener() { + + @Override + public void ancestorAdded(AncestorEvent event) { + final AncestorListener al = this; + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + frameField.selectAll(); + frameField.requestFocusInWindow(); + gotoPanel.removeAncestorListener(al); + + } + }); + + } + + @Override + public void ancestorRemoved(AncestorEvent event) { + + } + + @Override + public void ancestorMoved(AncestorEvent event) { + + } + }); + if (View.showConfirmDialog(this, gotoPanel, AppStrings.translate("preview.gotoframe.dialog.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE) == JOptionPane.OK_OPTION) { + int frame = -1; + try { + frame = Integer.parseInt(frameField.getText()); + } catch (NumberFormatException nfe) { + //handled as -1 + } + if (frame <= 0 || frame > display.getTotalFrames()) { + View.showMessageDialog(this, AppStrings.translate("preview.gotoframe.dialog.frame.error").replace("%min%", "1").replace("%max%", "" + display.getTotalFrames()), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); + return; + } + display.gotoFrame(frame - 1); + } + break; + case ACTION_NEXTFRAME: + display.gotoFrame(display.getCurrentFrame() + 1); + break; + case ACTION_PREVFRAME: + display.gotoFrame(display.getCurrentFrame() - 1); + break; case ACTION_STOP: display.pause(); display.rewind();