From 3cdf3f7ba81256831c1359e21cb28820f08f1370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=F8=EDk?= Date: Sun, 2 Feb 2014 23:01:50 +0100 Subject: [PATCH] Timeline view (still not very useful) Dialog icons Search icon --- .../flash/gui/LoadFromCacheFrame.java | 6 + .../flash/gui/LoadFromMemoryFrame.java | 5 + .../com/jpexs/decompiler/flash/gui/Main.java | 2 +- .../flash/gui/MainFrameRibbonMenu.java | 17 +- .../jpexs/decompiler/flash/gui/MainPanel.java | 9 + .../decompiler/flash/gui/SearchDialog.java | 6 + .../decompiler/flash/gui/TimeLinePanel.java | 197 ------------- .../com/jpexs/decompiler/flash/gui/View.java | 10 +- .../flash/gui/graphics/loadcache32.png | Bin 0 -> 1714 bytes .../flash/gui/graphics/loadmemory32.png | Bin 1673 -> 920 bytes .../flash/gui/graphics/search16.png | Bin 615 -> 720 bytes .../flash/gui/graphics/search32.png | Bin 1336 -> 1390 bytes .../flash/gui/graphics/timeline16.png | Bin 0 -> 962 bytes .../flash/gui/graphics/timeline32.png | Bin 0 -> 2686 bytes .../flash/gui/locales/MainFrame.properties | 3 + .../flash/gui/locales/MainFrame_cs.properties | 5 +- .../TimelineFrame.properties} | 0 .../gui/timeline/FrameSelectionListener.java | 26 ++ .../flash/gui/timeline/TimelineBodyPanel.java | 270 ++++++++++++++++++ .../gui/timeline/TimelineDepthPanel.java | 72 +++++ .../flash/gui/timeline/TimelineFrame.java | 49 ++++ .../flash/gui/timeline/TimelinePanel.java | 113 ++++++++ .../flash/gui/timeline/TimelineTimePanel.java | 126 ++++++++ .../decompiler/flash/timeline/DepthState.java | 2 +- .../decompiler/flash/timeline/Frame.java | 4 +- .../decompiler/flash/timeline/TimeLine.java | 12 +- 26 files changed, 725 insertions(+), 209 deletions(-) delete mode 100644 trunk/src/com/jpexs/decompiler/flash/gui/TimeLinePanel.java create mode 100644 trunk/src/com/jpexs/decompiler/flash/gui/graphics/loadcache32.png create mode 100644 trunk/src/com/jpexs/decompiler/flash/gui/graphics/timeline16.png create mode 100644 trunk/src/com/jpexs/decompiler/flash/gui/graphics/timeline32.png rename trunk/src/com/jpexs/decompiler/flash/gui/locales/{TimeLineFrame.properties => timeline/TimelineFrame.properties} (100%) create mode 100644 trunk/src/com/jpexs/decompiler/flash/gui/timeline/FrameSelectionListener.java create mode 100644 trunk/src/com/jpexs/decompiler/flash/gui/timeline/TimelineBodyPanel.java create mode 100644 trunk/src/com/jpexs/decompiler/flash/gui/timeline/TimelineDepthPanel.java create mode 100644 trunk/src/com/jpexs/decompiler/flash/gui/timeline/TimelineFrame.java create mode 100644 trunk/src/com/jpexs/decompiler/flash/gui/timeline/TimelinePanel.java create mode 100644 trunk/src/com/jpexs/decompiler/flash/gui/timeline/TimelineTimePanel.java diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/LoadFromCacheFrame.java b/trunk/src/com/jpexs/decompiler/flash/gui/LoadFromCacheFrame.java index 4d0a8f1cf..c2424f13e 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/LoadFromCacheFrame.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/LoadFromCacheFrame.java @@ -27,6 +27,7 @@ import com.jpexs.helpers.ReReadableInputStream; import java.awt.BorderLayout; import java.awt.Container; import java.awt.FlowLayout; +import java.awt.Image; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; @@ -147,6 +148,11 @@ public class LoadFromCacheFrame extends AppFrame implements ActionListener { progressBar.setVisible(false); openButton.setEnabled(false); saveButton.setEnabled(false); + + java.util.List images = new ArrayList<>(); + images.add(View.loadImage("loadcache16")); + images.add(View.loadImage("loadcache32")); + setIconImages(images); refresh(); } diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/LoadFromMemoryFrame.java b/trunk/src/com/jpexs/decompiler/flash/gui/LoadFromMemoryFrame.java index c35b141bc..1db9cc0b5 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/LoadFromMemoryFrame.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/LoadFromMemoryFrame.java @@ -31,6 +31,7 @@ import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.FlowLayout; +import java.awt.Image; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; @@ -388,6 +389,10 @@ public class LoadFromMemoryFrame extends AppFrame implements ActionListener { cnt.add(new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, rightPanel), BorderLayout.CENTER); View.setWindowIcon(this); View.centerScreen(this); + java.util.List images = new ArrayList<>(); + images.add(View.loadImage("loadmemory16")); + images.add(View.loadImage("loadmemory32")); + setIconImages(images); } @Override diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/Main.java b/trunk/src/com/jpexs/decompiler/flash/gui/Main.java index 1a0d6e216..e4b1eb046 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/Main.java @@ -720,7 +720,7 @@ public class Main { autoCheckForUpdates(); offerAssociation(); } - + public static void showModeFrame() { View.execInEventDispatch(new Runnable() { @Override diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java b/trunk/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java index 0977d6151..809ac993c 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java @@ -86,7 +86,8 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener { static final String ACTION_GOTO_DOCUMENT_CLASS = "GOTODOCUMENTCLASS"; static final String ACTION_PARALLEL_SPEED_UP = "PARALLELSPEEDUP"; static final String ACTION_INTERNAL_VIEWER_SWITCH = "INTERNALVIEWERSWITCH"; - static final String ACTION_SEARCH_AS = "SEARCHAS"; + static final String ACTION_SEARCH = "SEARCH"; + static final String ACTION_TIMELINE = "TIMELINE"; static final String ACTION_AUTO_DEOBFUSCATE = "AUTODEOBFUSCATE"; static final String ACTION_EXIT = "EXIT"; @@ -138,6 +139,7 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener { private JCommandButton globalrenameCommandButton; private JCommandButton deobfuscationCommandButton; private JCommandButton searchCommandButton; + private JCommandButton timeLineCommandButton; private JCommandButton gotoDocumentClassCommandButton; private JCommandButton clearRecentFilesCommandButton; @@ -320,7 +322,11 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener { toolsBand.setResizePolicies(getResizePolicies(toolsBand)); searchCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.search")), View.getResizableIcon("search32")); - assignListener(searchCommandButton, ACTION_SEARCH_AS); + assignListener(searchCommandButton, ACTION_SEARCH); + + timeLineCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.timeline")), View.getResizableIcon("timeline32")); + assignListener(timeLineCommandButton, ACTION_TIMELINE); + gotoDocumentClassCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.gotodocumentclass")), View.getResizableIcon("gotomainclass32")); assignListener(gotoDocumentClassCommandButton, ACTION_GOTO_DOCUMENT_CLASS); @@ -334,6 +340,7 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener { assignListener(loadCacheCommandButton, ACTION_LOAD_CACHE); toolsBand.addCommandButton(searchCommandButton, RibbonElementPriority.TOP); + toolsBand.addCommandButton(timeLineCommandButton, RibbonElementPriority.TOP); toolsBand.addCommandButton(gotoDocumentClassCommandButton, RibbonElementPriority.TOP); toolsBand.addCommandButton(proxyCommandButton, RibbonElementPriority.MEDIUM); toolsBand.addCommandButton(loadMemoryCommandButton, RibbonElementPriority.MEDIUM); @@ -507,6 +514,7 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener { globalrenameCommandButton.setEnabled(swfLoaded); deobfuscationCommandButton.setEnabled(swfLoaded); searchCommandButton.setEnabled(swfLoaded); + timeLineCommandButton.setEnabled(swfLoaded); gotoDocumentClassCommandButton.setEnabled(hasAbc); deobfuscationCommandButton.setEnabled(hasAbc); @@ -598,9 +606,12 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener { Configuration.internalFlashViewer.set(miInternalViewer.isSelected()); mainFrame.panel.reload(true); break; - case ACTION_SEARCH_AS: + case ACTION_SEARCH: mainFrame.panel.searchAs(); break; + case ACTION_TIMELINE: + mainFrame.panel.timeline(); + break; case ACTION_AUTO_DEOBFUSCATE: if (View.showConfirmDialog(mainFrame.panel, translate("message.confirm.autodeobfuscate") + "\r\n" + (miAutoDeobfuscation.isSelected() ? translate("message.confirm.on") : translate("message.confirm.off")), translate("message.confirm"), JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) { Configuration.autoDeobfuscate.set(miAutoDeobfuscation.isSelected()); diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/MainPanel.java index 08ed3e697..ae24faff3 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -16,6 +16,7 @@ */ package com.jpexs.decompiler.flash.gui; +import com.jpexs.decompiler.flash.gui.timeline.TimelineFrame; import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler; import com.jpexs.decompiler.flash.AppStrings; import com.jpexs.decompiler.flash.ApplicationInfo; @@ -2956,4 +2957,12 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec public void setErrorState(ErrorState errorState) { statusPanel.setErrorState(errorState); } + + public void timeline() { + final SWF swf = getCurrentSwf(); + if (swf != null) { + TimelineFrame tf = new TimelineFrame(swf); + tf.setVisible(true); + } + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/SearchDialog.java b/trunk/src/com/jpexs/decompiler/flash/gui/SearchDialog.java index 653044274..1b407f16d 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/SearchDialog.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/SearchDialog.java @@ -19,8 +19,10 @@ package com.jpexs.decompiler.flash.gui; import java.awt.Container; import java.awt.Dimension; import java.awt.FlowLayout; +import java.awt.Image; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.ArrayList; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import javax.swing.BoxLayout; @@ -94,6 +96,10 @@ public class SearchDialog extends AppDialog implements ActionListener { setTitle(translate("dialog.title")); setModalityType(ModalityType.APPLICATION_MODAL); pack(); + java.util.List images = new ArrayList<>(); + images.add(View.loadImage("search16")); + images.add(View.loadImage("search32")); + setIconImages(images); } @Override diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/TimeLinePanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/TimeLinePanel.java deleted file mode 100644 index b4a54f96a..000000000 --- a/trunk/src/com/jpexs/decompiler/flash/gui/TimeLinePanel.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.gui; - -import com.jpexs.decompiler.flash.SWF; -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.Point; -import java.awt.Rectangle; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import javax.swing.JPanel; - -/** - * - * @author JPEXS - */ -public class TimeLinePanel extends JPanel implements MouseListener { - - private final SWF swf; - private final TimeLine timeLine; - public static final int FRAME_WIDTH = 10; - public static final int FRAME_HEIGHT = 20; - public static final Color frameColor = Color.lightGray; - public static final Color emptyFrameColor = Color.white; - public static final Color borderColor = Color.black; - public static final Color emptyBorderColor = Color.lightGray; - public static final Color keyColor = Color.black; - public static final Color selectedColor = new Color(113, 174, 235); - public static final Color timeColor = Color.red; - - public Point cursor = null; - - public TimeLinePanel(SWF swf) { - this.swf = swf; - this.timeLine = new TimeLine(swf); - Dimension dim = new Dimension(FRAME_WIDTH * timeLine.getFrameCount() + 1, FRAME_HEIGHT * timeLine.getMaxDepth()); - setSize(dim); - setPreferredSize(dim); - addMouseListener(this); - } - - @Override - protected void paintComponent(Graphics g) { - //super.paintComponent(g); - Rectangle clip = g.getClipBounds(); - int start_f = clip.x / FRAME_WIDTH; - int start_d = clip.y / FRAME_HEIGHT; - int end_f = (clip.x + clip.width) / FRAME_WIDTH; - int end_d = (clip.y + clip.height) / 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; - } - - 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) { - g.setColor(emptyFrameColor); - g.fillRect(f * FRAME_WIDTH, d * FRAME_HEIGHT, FRAME_WIDTH, FRAME_HEIGHT); - g.setColor(emptyBorderColor); - g.drawRect(f * FRAME_WIDTH, d * FRAME_HEIGHT, FRAME_WIDTH, 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); - boolean selected = false; - if (cursor != null) { - if (f == cursor.x && d == cursor.y) { - selected = true; - } - } - if (selected) { - g.setColor(selectedColor); - g.fillRect(f * FRAME_WIDTH + 1, d * FRAME_HEIGHT + 1, FRAME_WIDTH - 1, FRAME_HEIGHT - 1); - } - - if (fl == null) { - 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 * FRAME_WIDTH, d * FRAME_HEIGHT, num_frames * FRAME_WIDTH, FRAME_HEIGHT); - - if (selected) { - g.setColor(selectedColor); - g.fillRect(draw_f * FRAME_WIDTH, d * FRAME_HEIGHT, FRAME_WIDTH, FRAME_HEIGHT); - } - - g.setColor(borderColor); - g.drawRect(draw_f * FRAME_WIDTH, d * FRAME_HEIGHT, num_frames * FRAME_WIDTH, FRAME_HEIGHT); - g.setColor(keyColor); - g.fillOval(draw_f * FRAME_WIDTH + FRAME_WIDTH / 4, d * FRAME_HEIGHT + FRAME_HEIGHT / 2 - FRAME_WIDTH / 2, FRAME_WIDTH / 2, FRAME_WIDTH / 2); - - } - } - } - - if (cursor != null && cursor.x >= start_f && cursor.x <= end_f) { - g.setColor(timeColor); - g.drawLine(cursor.x * FRAME_WIDTH + FRAME_WIDTH / 2, 0, cursor.x * FRAME_WIDTH + FRAME_WIDTH / 2, getHeight()); - } - } - - @Override - public void mouseClicked(MouseEvent e) { - - } - - @Override - public void mousePressed(MouseEvent e) { - Point p = e.getPoint(); - p.x = p.x / FRAME_WIDTH; - p.y = p.y / FRAME_HEIGHT; - if (p.x >= timeLine.getFrameCount()) { - p.x = timeLine.getFrameCount() - 1; - } - if (p.y > timeLine.getMaxDepth()) { - p.y = timeLine.getMaxDepth(); - } - cursor = p; - repaint(); - } - - @Override - public void mouseReleased(MouseEvent e) { - - } - - @Override - public void mouseEntered(MouseEvent e) { - - } - - @Override - public void mouseExited(MouseEvent e) { - - } - -} diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/View.java b/trunk/src/com/jpexs/decompiler/flash/gui/View.java index 1eedb87ce..9b72b43f3 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/View.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/View.java @@ -36,6 +36,7 @@ import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.Icon; import javax.swing.ImageIcon; +import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JFrame; @@ -50,11 +51,14 @@ import javax.swing.UnsupportedLookAndFeelException; import javax.swing.plaf.FontUIResource; import javax.swing.plaf.basic.BasicColorChooserUI; import org.pushingpixels.flamingo.api.common.icon.ImageWrapperResizableIcon; +import org.pushingpixels.substance.api.ComponentState; +import org.pushingpixels.substance.api.SubstanceColorScheme; import org.pushingpixels.substance.api.SubstanceConstants; import org.pushingpixels.substance.api.SubstanceLookAndFeel; import org.pushingpixels.substance.api.fonts.FontPolicy; import org.pushingpixels.substance.api.fonts.FontSet; import org.pushingpixels.substance.api.skin.SubstanceOfficeBlue2007LookAndFeel; +import org.pushingpixels.substance.internal.utils.SubstanceColorSchemeUtilities; /** * Contains methods for GUI @@ -342,4 +346,8 @@ public class View { }); return ret[0]; } -} + + public static SubstanceColorScheme getColorScheme() { + return SubstanceColorSchemeUtilities.getActiveColorScheme(new JButton(), ComponentState.ENABLED); + } +} \ No newline at end of file diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/graphics/loadcache32.png b/trunk/src/com/jpexs/decompiler/flash/gui/graphics/loadcache32.png new file mode 100644 index 0000000000000000000000000000000000000000..c10b2fb3f058979ac67f623b3c3cb63ca448522e GIT binary patch literal 1714 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 delta 1620 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 diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/graphics/search32.png b/trunk/src/com/jpexs/decompiler/flash/gui/graphics/search32.png index 1d68522248137043925f43f147d57c4fc1d14625..790c54a26a5e9249b79db50101c1a0e194ed65cc 100644 GIT binary patch delta 1335 zcmV-71<3li3hoM!NPh(oNklz*TBw>vMTi6?BvIm$R&DN% zV|#bKUVAxb>~%NmwH-T*bTqs6cV@mlbIvz24qexQn#17$Q-AZEJ@;`;jj5oEmvj=>pIdbGc1=^FR&wTXf!B-B#Bh}R~GcyBob8`>~+=1Sn zZ=b>c7tq2b;xjqm%n<<@ZIb}Bw$vNXkm9?U#*~UL7y(!3$x|bG0-7a70##MhA$5=k z#MStvp~1e_@rOhj&vl*ra3q=3TO`?ncj}<2+K+<+y?=z)c3TBrx7*Wv>_j_=Vg)FY z0->!Cgu>gnp4-sVH_(C@pDCn1x5v}c-hMP2kJj5i)J$Vqmmpsf^2Bax>Tjs2c??3K z5G+4fhUMjyQD||!x3?o_EYU>sO<`C68dj_KOXWL9&z zTrf5|1`$-cm>dIHk)ihS+AN$+au-K{<2Z1;-OOlGV+pAL?9)&D2#Xs^c;@W6%Y-K! z89fsYSe5CyqiR!z-0}B2hOv@cV<@RqQb|2i&wmUTjYcnD`eCFCUqfjh@#wMRpYtBx zuf!D4G%cljG^7&=;{$F|7yEj?d&5+^wq?k5bao9_idC(z`Co;KvNCYxCIapa z5F{V;t*j`AhK6V1=FRceH{Uw^J&IDRAxh>!yd39jdcLuNg*+0KQ(B#)6s-j8643Bn zx_ghkKfQlH`8TCSDXTUGN(av6gw?h69e;UY9o)zp`{aczUn0G@7{J8LOefe8U_J|r z|DuB)OidW21oG&V764tScQbMB^2~C_8SVBPl|K-=G^tH1SW1xFsF&}an?^xPJgoB z=jZ2kNby%+esQ3?`|AS({XKqT@-5XxjKsQwI@J>w7uJgdd@RF zm$AeoNoJP|8B2}Md$i{L1B15ZS$~S}4gwU~?r+XRH6E)gF~cQvj$o}vBT;tC2}iLH zNAU}N*=t#%Zx#X0>B5@~4+8FLbk5VXIB0Q=UANq74EK7@$N~62e9Z)OWO~CZ_!{rt zTY|uyK<0u;n-d+gv7p%c;#%IYoH9!GH6KXmcJl<6?ybie%BgH1~f33;-m9eEt+E=>Y%$002ovPDHLkV1g9}e*^#k delta 1280 zcmV+b1^@c)3b+c8NPh&{NklPbsdr?(=9UhNI@9yorOZzEi&sRfFdk6?7r=}Sr2^ny#=qQ{$J!rUm8C8{) zmz=%5{SEc?pU`w5-g-IolmzXvEOSv5C9Vivz5zW~R=vo{$w5^`#YaC64b9Nc7PA11 z!K`PSvS&OIdVhQ!qtRx=!r~Hgb8}I8?p$vF;NVm|5K#dnDq`4d79`p228i~85P!vY1WL^}>$OT1Fk(_Ktio;>JqoTAlj{Hr6+Bx}=0lw11%mjkCsPU{?&7W`J}zxBkKg zi3rB9`huM7EQ4KB0OSM#gi!2P;7k{y12Yhd88aaE0#GC)u>P+R%b=((fLQ<%)0d;t z&qT~As+x!k6w?XFYKGNng-QnqE9pjr&*$R+ES6yECnwnxWxz!Gk)Dl8@3k9W@T}k2 z*@17{2Y;{Ei-!;H^VDm)ej^y5^nT^)HILu#$DPi08!hm~3_?@(i%UyY@Mh6*C{_io z=PuZ`>@-L05JMJXr|8I0SZ!8}jgLVJ@Vy=30QTMmwAhTuip*Wm+Hwo??s=4zmf`G~ zGm!>pI?Bq+`2DcGwT;e>wzHhdk zYSVRo@Ie0nw=kdwp!s#wR9^^w6C;(CWq9`hP*@F* zlm7xp^Vc_#mYxnTH6N?1D_CAxMO$k--hVw^!ma-8_b2$K`6dpf9U`6Aq_Ya|YcIO) zbk~SDNH`0^=byXAke{E6SF^7$Ju{7&*%|Ktj*d<&E-oT7GZU^CV%=f}03H*OjjX8sEDo3(G)>>56V~v^5kV+|Bwir?>k2stnum3VFoa*`%@{7}#Y0%1Gu+-oz+^oFO4uAeoS{vfv-*T>N2TLdQo!2nqf+z|s{c zVWX=pn`Laa+ip5m+SRtV-TmafjUpP}o0EH=``+id=Y7t3DBp$4&=*BfU>F9p!GN); zN$kGTf7(&!>XZrsQpx!nBE{}vnZ-qxw)ChJs$@kuLeVr>yliQzW-|aaM~?w4h1dAm zmgt3FN=1IgU)|zv(vtI-{3F^+Q`7_cznN4Qr6Fq~O#E-S!JlkH@#0V5#z)|4d=KVT z<|Z*6hrRx7*f`^ms%if+AV-+Z<#Nu1J)`>QZ7Bw$PDFqilZ zRB{&U8r(}p1O9%-^Zp0r_E~ zUa~|YPqkA1^@(ihIxULQaUuYk8r?7&jp*p;fGkU>dc}cN&Xo`>Hq3SQVdLj*Fo^=p zYu0;q4#z+H;sM{X_fE8(R#nAVQBi@Kni^>2>gx7l_rCr3w(AUfyk0D=FyZdtO;`y- zi^&L-1l#wQu09TC^8R4+hBz(DGV}uXfl|-N@;Qpr7GP_s=s~0el%I?NSENVoJ@emmA&zS6P2abJHR;Zz&0YUPE>_P^r ztPr0RF?jS8G$OZNKqNimo~F}SR#^$=?3a*6L(uBp1XK+SIo9?aI}i$mFgu+9!%x!{i{`3-ck8<_+}!*xO5jXeyQRIUJ7G=ez%#Lnpxsy*DqsQwin> k_`l<7f+~VxJ$NR-0GZowwAl|sCjbBd07*qoM6N<$g5EgGZ~y=R literal 0 HcmV?d00001 diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/graphics/timeline32.png b/trunk/src/com/jpexs/decompiler/flash/gui/graphics/timeline32.png new file mode 100644 index 0000000000000000000000000000000000000000..eb27b9d5e355096b7754221482f929603429e43d GIT binary patch literal 2686 zcmV-^3W4>BP)%zzeQP$-yy zL!QK-kT+zro9FK4weQEhx97jv&1^C_mdu>FceDS0&iT*zzVH0Y;m-c}Q-wKe3>?a2 zQB<>k$O7N(=Y-c+RWrnDLzgAZ(~Z@V1+ z?v4}S-#&Wmw?E$X+`jysyP*~R;H|AtCnX~&@!+%bG0@q8rqY9O2SPi2z{!v#nNm3U z%iN76(CQ8N=B+*6rIpP|!x*N4YMNqi!&un_V~B}h&(Kxe)VU1m1)**V~O zz}wpgdD@R4<=udHT+|BRnyk!RtVo$?l%t{ zTJzJNJ=r*KUg4~(_4Saca8uU)1dgNcAx`##lc=s*a-N(5Uady(W;4X*M#Rj?$KbWI zP<#3zw_iuFr4f>)15?-h9JX(23l=9EzWh(mfOV|2w+Swk9{%UwCrwH{_1I%;X#odo zrv>fJ&FFD^k@(^cSUo&K&Jp;!yW#8agDN2b+9^}P1%2Qzl_OSTfREY~kb_k35WIdj zJmse`bIs$(icz1V7@F^^fN-ev-O?13Y18V}D^XTfhT~tX7!rxeq$( z>2Q553?Uz6I)W-DmMW1<9FW0@GE_kcF29pPix7B$+9W`7xnYP;1RtNIUa1OA`N(QN zt&k|X?62+KyEZj7b$4;`!#Hx}0}Kod;`!%(2b0N!w7c&{MMVWwM8=dAtKqJzg6Oaz zHt40aRZzvpLv1incSTA-q-uz828I=0@*Dw`fyHizY1SN!^mY|2PK-PMS&zdK-GUgS z(Rgyv{CPNW;#2tjemwp3HmFo81cO1Ssn3r-vIeb9O|Z7LAok_m=;d`7_E4F7y5J+@ z)hg&FPa<|0p;jfps5T%NaKRUJ!!P>aWp<+uIR%Bt(rLe+4ojS9)^?9z5L;a5DJCp;B<11Q;ZjQsHoRk ztrp3~WK>tzATco>ljj$~T3e0a)HLi3#$xBb{YXtPK=gPaQ|l6Qa&cDHLQl*WZdwVP z0xsG|cJ6KK{)}P|unK53TJ0)AK5m)KxPNgG;Yd<6iX-rF3V;L(uE9$$zJUJze$1aY zmy$?AdrK>{1WIY+GkDV_W6zFPke!hMF-Xa?))62jzYh--%z?FN1>_^A@x}UQul%Xm z`Vj@_XR0`wfJU<@CME`~0_o}L<4(>D+^Aswe)}J=e%(5hmzQJPwi5L9^x$S&J7!Lw zjulImAUiV)644b=`&l9xgqLAkA9U2xWUXc)xf&$%FdDK1)J)|V(q&p;OiH5D3W^Ct z9iEk68G90@lGyCnu>)I6N^s!7LFnRiFn4sImlBynv<`rzrScPYHF{-NWfgUXc5Y& zGEZ&TfCUQ|js;@AgTa6jYuucVR6r!!X(@o)G`| zDL6}-*{YSr&`{ais2v89WS`HEW>QRs1?I!;b}7C?)WV4sU??(a1S(Fg1?MFvd!B*+^E${g=YR_kXho)!GHHg0&6_u(v$GRz)QSZ~MfmjONrld8 zwFWku1B_)Zw;L>0^sR^`5VYHE6)u`qYSMjccb5VnHas|fGy&e@gm&9<1P^{e!3!vO zNVyM$*{Pf=*=WSl2bZ9=r3HO`eOR!lNMQwA(?LvO>|oWkJM0xKW^@Anx88XDu!jH@ zAS#XwJ25moq=1Mc_2X28;4MoLdYi_0oSw!l1t$h6zziEf79kRy;uXu8sEoFP?g(CL zMRiRzd{nIfwV1Kst^NBBM_Owe1UqIJTqPx&l~%O3-9!Oh$tu1oM}YW0JTyq--Eon{icUa?++Z(Xs;F7G zsHh}1R!4mk;3vdRo-}Ecu#A!lC`T2JwP>tO-1uu{EL~2VPA8gZSTT7wCL7V#+J+IQ z3x9s)kB`%mzKID$lu1rVNa#*XOe&_~pp=wVBPGQIAu0$9%Iw003%GUb7P7Lk#(l>U znwgu6&rg3&?*ek^-EQkAQL5W@t)U@O0qJ%Lh)s<*dS}nh%cPw-DwSHHrjvjZPt>A$ zG48|+SnNGBGjnuWhQIUDZ-u7j7GhK^zP;8!avg`f{CvXJ(7pdXe|{Hj^^Us(M!mDE za;U2EO5KdyS!tpu<}ipbhkgQ+%k5Ms6{FQCO3DH=i>Tf3h>H}_42z{3ofZpm-$OH^ z7eUhgB$_X&sU}TEMn(!<>rO}0aN?zuMi~OtRh2cwTZ>+=e~59}MMC1H`93r>49CC_ z1_lR7FKmit*yx62?dqYxR`gK7uC6W`**1Fb!KI4w?Se{`M}7?1({tc)y9+Wh($7^_ zS6jwO@q{X{9*Jj8pDH8!`k7~+|EtNAvN$fz2E9HGIsz%XoJ1s*m0hAFJzfu(mXOfE z;c#4jbN}C7rmsiL=8kp(z$Xw*;H}p(;>X*NI zG9@K-zTRNCXQH07BwS8s139lc`oWQ7;d#%{?(Xa~4>dJ4eH^dX{i6BCcWf=AzAlo$ z5B@Y`%p%j1C6L93Hw(8(+7nKkRnQd%n;70ZjooR(KS)?|x5Cf=|HmmCXkk;|W}h6E sSAW=~2|#Cuh>1u)t4z4U_@4j+09-(~@lHaTG5`Po07*qoM6N<$f;?>vvj6}9 literal 0 HcmV?d00001 diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index d33ed0c8b..c431d1994 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -437,3 +437,6 @@ node.others = others #after version 1.8.1 menu.tools.search = Text Search + +#after version 1.8.1u1 +menu.tools.timeline = Timeline \ No newline at end of file diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties b/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties index 6685b98e4..5f4bd9d5e 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties +++ b/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties @@ -437,4 +437,7 @@ open.error.cannotOpen = Soubor nelze otev\u0159\u00edt node.others = ostatn\u00ed #after version 1.8.1 -menu.tools.search = Hled\u00e1n\u00ed Textu \ No newline at end of file +menu.tools.search = Hled\u00e1n\u00ed Textu + +#after version 1.8.1u1 +menu.tools.timeline = \u010casov\u00e1 osa \ No newline at end of file diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/locales/TimeLineFrame.properties b/trunk/src/com/jpexs/decompiler/flash/gui/locales/timeline/TimelineFrame.properties similarity index 100% rename from trunk/src/com/jpexs/decompiler/flash/gui/locales/TimeLineFrame.properties rename to trunk/src/com/jpexs/decompiler/flash/gui/locales/timeline/TimelineFrame.properties diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/timeline/FrameSelectionListener.java b/trunk/src/com/jpexs/decompiler/flash/gui/timeline/FrameSelectionListener.java new file mode 100644 index 000000000..06d2c3130 --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/gui/timeline/FrameSelectionListener.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.gui.timeline; + +/** + * + * @author JPEXS + */ +public interface FrameSelectionListener { + + public void frameSelected(int frame, int depth); +} diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/timeline/TimelineBodyPanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/timeline/TimelineBodyPanel.java new file mode 100644 index 000000000..39f29092c --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/gui/timeline/TimelineBodyPanel.java @@ -0,0 +1,270 @@ +/* + * 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.SWF; +import com.jpexs.decompiler.flash.gui.View; +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 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; + } + + 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; + } + if (p.y > timeLine.getMaxDepth()) { + p.y = timeLine.getMaxDepth(); + } + frameSelect(p.x, p.y); + } + + @Override + public void mouseReleased(MouseEvent e) { + + } + + @Override + public void mouseEntered(MouseEvent e) { + + } + + @Override + public void mouseExited(MouseEvent e) { + + } + +} diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/timeline/TimelineDepthPanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/timeline/TimelineDepthPanel.java new file mode 100644 index 000000000..68a158b5f --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/gui/timeline/TimelineDepthPanel.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.gui.timeline; + +import com.jpexs.decompiler.flash.timeline.Timeline; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Rectangle; +import javax.swing.JPanel; + +/** + * + * @author JPEXS + */ +public class TimelineDepthPanel extends JPanel { + + private int maxDepth; + public static final int padding = 5; + public static final float fontSize = 10.0f; + private int scrollOffset = 0; + public static final Color borderColor = Color.lightGray; + public static final Color fontColor = Color.black; + + public TimelineDepthPanel(Timeline timeline) { + maxDepth = timeline.getMaxDepth(); + String maxDepthStr = "" + maxDepth; + setFont(getFont().deriveFont(fontSize)); + int maxDepthW = getFontMetrics(getFont()).stringWidth(maxDepthStr); + Dimension dim = new Dimension(maxDepthW + 2 * padding, Integer.MAX_VALUE); + setSize(dim); + setPreferredSize(dim); + } + + public void scroll(int offset) { + this.scrollOffset = offset; + repaint(); + } + + @Override + protected void paintComponent(Graphics g) { + Rectangle clip = g.getClipBounds(); + int yofs = TimelinePanel.FRAME_HEIGHT - (scrollOffset % TimelinePanel.FRAME_HEIGHT); + int start_d = (scrollOffset + clip.y) / TimelinePanel.FRAME_HEIGHT; + int end_d = (scrollOffset + clip.y + clip.height) / TimelinePanel.FRAME_HEIGHT; + int d_count = end_d - start_d; + g.setColor(TimelinePanel.backgroundColor); + g.fillRect(0, 0, getWidth(), getHeight()); + for (int d = 0; d < d_count; d++) { + g.setColor(borderColor); + g.drawLine(0, yofs + d * TimelinePanel.FRAME_HEIGHT + 1, getWidth(), yofs + d * TimelinePanel.FRAME_HEIGHT + 1); + int curr_d = start_d + d; + g.setColor(fontColor); + g.drawString("" + (start_d + d == 0 ? "a" : curr_d), padding, yofs + d * TimelinePanel.FRAME_HEIGHT - padding); + } + } + +} diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/timeline/TimelineFrame.java b/trunk/src/com/jpexs/decompiler/flash/gui/timeline/TimelineFrame.java new file mode 100644 index 000000000..81b0b8d77 --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/gui/timeline/TimelineFrame.java @@ -0,0 +1,49 @@ +/* + * 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.SWF; +import com.jpexs.decompiler.flash.gui.AppFrame; +import com.jpexs.decompiler.flash.gui.View; +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.Image; +import java.util.ArrayList; + +/** + * + * @author JPEXS + */ +public class TimelineFrame extends AppFrame { + + public TimelinePanel timeline; + + public TimelineFrame(SWF swf) { + 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(swf), BorderLayout.CENTER); + + java.util.List images = new ArrayList<>(); + images.add(View.loadImage("timeline16")); + images.add(View.loadImage("timeline32")); + setIconImages(images); + } +} diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/timeline/TimelinePanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/timeline/TimelinePanel.java new file mode 100644 index 000000000..71a725c4c --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/gui/timeline/TimelinePanel.java @@ -0,0 +1,113 @@ +/* + * 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.SWF; +import com.jpexs.decompiler.flash.gui.View; +import com.jpexs.decompiler.flash.timeline.Timeline; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JButton; +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(SWF swf) { + timeline = new Timeline(swf); + 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); + } + }); + + } +} diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/timeline/TimelineTimePanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/timeline/TimelineTimePanel.java new file mode 100644 index 000000000..22110568f --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/gui/timeline/TimelineTimePanel.java @@ -0,0 +1,126 @@ +/* + * 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 java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Rectangle; +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 TimelineTimePanel extends JPanel implements MouseListener { + + public static final Color borderColor = Color.black; + public static final int lineLength = 3; + public static final int lineTextSpace = 3; + public static final Color fontColor = Color.black; + public float fontSize = 10.0f; + private int scrollOffset = 0; + private int selectedFrame = -1; + private List listeners = new ArrayList<>(); + + public TimelineTimePanel() { + Dimension dim = new Dimension(Integer.MAX_VALUE, TimelinePanel.FRAME_HEIGHT); + setSize(dim); + setPreferredSize(dim); + addMouseListener(this); + } + + public void addFrameSelectionListener(FrameSelectionListener l) { + listeners.add(l); + } + + public void removeFrameSelectionListener(FrameSelectionListener l) { + listeners.remove(l); + } + + public void frameSelect(int frame) { + if (selectedFrame == frame) { + return; + } + for (FrameSelectionListener l : listeners) { + l.frameSelected(frame, -1); + } + selectedFrame = frame; + repaint(); + } + + public void scroll(int offset) { + this.scrollOffset = offset; + repaint(); + } + + @Override + protected void paintComponent(Graphics g) { + Rectangle clip = g.getClipBounds(); + int start_f = (scrollOffset + clip.x) / TimelinePanel.FRAME_WIDTH; + int end_f = (scrollOffset + clip.x + clip.width) / TimelinePanel.FRAME_WIDTH; + g.setColor(TimelinePanel.backgroundColor); + g.fillRect(0, 0, getWidth(), getHeight()); + g.setColor(borderColor); + int xofs = TimelinePanel.FRAME_WIDTH - scrollOffset % TimelinePanel.FRAME_WIDTH - 1; + for (int f = 0; f <= end_f; f++) { + g.drawLine(xofs + f * TimelinePanel.FRAME_WIDTH + 1, TimelinePanel.FRAME_HEIGHT - 1, xofs + f * TimelinePanel.FRAME_WIDTH + 1, TimelinePanel.FRAME_HEIGHT - lineLength); + } + g.setFont(g.getFont().deriveFont(fontSize)); + for (int f = 0; f <= end_f; f++) { + int cur_f = start_f + f; + if (selectedFrame == cur_f) { + g.setColor(TimelinePanel.selectedColor); + g.fillRect(xofs + (f - 1) * TimelinePanel.FRAME_WIDTH + 1, 0, TimelinePanel.FRAME_WIDTH, TimelinePanel.FRAME_HEIGHT - 1); + g.setColor(TimelinePanel.selectedBorderColor); + g.drawRect(xofs + (f - 1) * TimelinePanel.FRAME_WIDTH + 1, 0, TimelinePanel.FRAME_WIDTH, TimelinePanel.FRAME_HEIGHT - 1); + } + g.setColor(fontColor); + if ((cur_f + 1) % 5 == 0 || cur_f == 0) { + String timeStr = "" + (cur_f + 1); + int w = g.getFontMetrics().stringWidth(timeStr); + g.drawString(timeStr, xofs + (f - 1) * TimelinePanel.FRAME_WIDTH + TimelinePanel.FRAME_WIDTH / 2 - w / 2, TimelinePanel.FRAME_HEIGHT - lineLength - lineTextSpace); + } + } + } + + @Override + public void mouseClicked(MouseEvent e) { + } + + @Override + public void mousePressed(MouseEvent e) { + frameSelect((scrollOffset + e.getX()) / TimelinePanel.FRAME_WIDTH); + } + + @Override + public void mouseReleased(MouseEvent e) { + } + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + } + +} diff --git a/trunk/src/com/jpexs/decompiler/flash/timeline/DepthState.java b/trunk/src/com/jpexs/decompiler/flash/timeline/DepthState.java index 765adcbd6..4c3d39d19 100644 --- a/trunk/src/com/jpexs/decompiler/flash/timeline/DepthState.java +++ b/trunk/src/com/jpexs/decompiler/flash/timeline/DepthState.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 JPEXS + * 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 diff --git a/trunk/src/com/jpexs/decompiler/flash/timeline/Frame.java b/trunk/src/com/jpexs/decompiler/flash/timeline/Frame.java index 20f64d900..23dcf5ed7 100644 --- a/trunk/src/com/jpexs/decompiler/flash/timeline/Frame.java +++ b/trunk/src/com/jpexs/decompiler/flash/timeline/Frame.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 JPEXS + * 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 @@ -16,6 +16,7 @@ */ package com.jpexs.decompiler.flash.timeline; +import com.jpexs.decompiler.flash.tags.DoActionTag; import java.util.HashMap; import java.util.Map; @@ -26,6 +27,7 @@ import java.util.Map; public class Frame { public Map layers = new HashMap<>(); + public DoActionTag action; public Frame() { diff --git a/trunk/src/com/jpexs/decompiler/flash/timeline/TimeLine.java b/trunk/src/com/jpexs/decompiler/flash/timeline/TimeLine.java index f4163177c..dff866bef 100644 --- a/trunk/src/com/jpexs/decompiler/flash/timeline/TimeLine.java +++ b/trunk/src/com/jpexs/decompiler/flash/timeline/TimeLine.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 JPEXS + * 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 @@ -17,6 +17,7 @@ package com.jpexs.decompiler.flash.timeline; import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.tags.DoActionTag; import com.jpexs.decompiler.flash.tags.ShowFrameTag; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag; @@ -33,11 +34,11 @@ import java.util.List; * * @author JPEXS */ -public class TimeLine { +public class Timeline { public List frames = new ArrayList<>(); - public TimeLine() { + public Timeline() { } public int getMaxDepth() { @@ -56,7 +57,7 @@ public class TimeLine { return frames.size(); } - public TimeLine(SWF swf) { + public Timeline(SWF swf) { Frame frame = new Frame(); for (Tag t : swf.tags) { if (t instanceof PlaceObjectTypeTag) { @@ -126,6 +127,9 @@ public class TimeLine { int depth = r.getDepth(); frame.layers.remove(depth); } + if (t instanceof DoActionTag) { + frame.action = (DoActionTag) t; + } if (t instanceof ShowFrameTag) { frames.add(frame); frame = new Frame(frame);