From 3a71ad6ec979846d531b8a1cf9abaf64c873cac4 Mon Sep 17 00:00:00 2001 From: "honfika@gmail.com" Date: Sun, 26 Apr 2015 12:59:54 +0200 Subject: [PATCH 1/4] small fixes --- src/com/jpexs/decompiler/flash/gui/PreviewPanel.java | 6 +++--- .../jpexs/decompiler/flash/gui/player/FlashPlayerPanel.java | 4 +--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java index 5af40bfde..36e009b8b 100644 --- a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java @@ -942,7 +942,7 @@ public class PreviewPanel extends JSplitPane implements ActionListener { doa = new DoActionTag(swf, null); actions = ASMParser.parse(0, false, - "ActionConstantPool \"_root\" \"my_sound\" \"Sound\" \"my_define_sound\" \"attachSound\"\n" + "ConstantPool \"_root\" \"my_sound\" \"Sound\" \"my_define_sound\" \"attachSound\"\n" + "Push \"_root\"\n" + "GetVariable\n" + "Push \"my_sound\" 0.0 \"Sound\"\n" @@ -961,7 +961,7 @@ public class PreviewPanel extends JSplitPane implements ActionListener { new ShowFrameTag(swf).writeTag(sos2); actions = ASMParser.parse(0, false, - "ActionConstantPool \"_root\" \"my_sound\" \"Sound\" \"my_define_sound\" \"attachSound\" \"start\"\n" + "ConstantPool \"_root\" \"my_sound\" \"Sound\" \"my_define_sound\" \"attachSound\" \"start\"\n" + "StopSounds\n" + "Push \"_root\"\n" + "GetVariable\n" @@ -988,7 +988,7 @@ public class PreviewPanel extends JSplitPane implements ActionListener { new ShowFrameTag(swf).writeTag(sos2); actions = ASMParser.parse(0, false, - "ActionConstantPool \"_root\" \"my_sound\" \"Sound\" \"my_define_sound\" \"attachSound\" \"onSoundComplete\" \"start\" \"execParam\"\n" + "ConstantPool \"_root\" \"my_sound\" \"Sound\" \"my_define_sound\" \"attachSound\" \"onSoundComplete\" \"start\" \"execParam\"\n" + "StopSounds\n" + "Push \"_root\"\n" + "GetVariable\n" diff --git a/src/com/jpexs/decompiler/flash/gui/player/FlashPlayerPanel.java b/src/com/jpexs/decompiler/flash/gui/player/FlashPlayerPanel.java index ad46f14de..811246699 100644 --- a/src/com/jpexs/decompiler/flash/gui/player/FlashPlayerPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/player/FlashPlayerPanel.java @@ -186,9 +186,6 @@ public final class FlashPlayerPanel extends Panel implements Closeable, MediaDis try { ShockwaveFlash flash1 = flash; - if (flash1 == null) { - return; - } boolean changed = false; @@ -208,6 +205,7 @@ public final class FlashPlayerPanel extends Panel implements Closeable, MediaDis } } catch (Exception ex) { // ignore + cancel(); } } }, 100, 100); From 7803fb78b4948ab8007d288c300c329983792425 Mon Sep 17 00:00:00 2001 From: "honfika@gmail.com" Date: Sun, 26 Apr 2015 15:50:26 +0200 Subject: [PATCH 2/4] #841 Loop control for sound preview --- .../flash/configuration/Configuration.java | 4 + .../flash/gui/AdvancedSettingsDialog.java | 16 +- .../decompiler/flash/gui/ErrorLogFrame.java | 203 ++++++------- .../flash/gui/FolderPreviewPanel.java | 8 +- .../decompiler/flash/gui/GenericTagPanel.java | 14 +- .../decompiler/flash/gui/ImagePanel.java | 43 ++- src/com/jpexs/decompiler/flash/gui/Main.java | 57 ++-- .../flash/gui/MainFrameStatusPanel.java | 17 +- .../jpexs/decompiler/flash/gui/MainPanel.java | 86 ++---- .../decompiler/flash/gui/PreviewPanel.java | 1 + .../decompiler/flash/gui/SearchPanel.java | 9 +- .../flash/gui/SearchResultsDialog.java | 9 +- .../flash/gui/SelectLanguageDialog.java | 14 +- .../decompiler/flash/gui/SoundTagPlayer.java | 66 +++- .../jpexs/decompiler/flash/gui/TextPanel.java | 8 +- src/com/jpexs/decompiler/flash/gui/View.java | 286 ++++++++---------- .../decompiler/flash/gui/abc/ABCPanel.java | 29 +- .../flash/gui/abc/DecompiledEditorPane.java | 7 +- .../decompiler/flash/gui/abc/DetailPanel.java | 54 ++-- .../flash/gui/abc/UndoFixedEditorPane.java | 8 +- .../flash/gui/action/ActionPanel.java | 100 +++--- .../flash/gui/graphics/loopoff16.png | Bin 0 -> 422 bytes .../flash/gui/graphics/loopon16.png | Bin 0 -> 750 bytes .../locales/AdvancedSettingsDialog.properties | 3 + .../AdvancedSettingsDialog_hu.properties | 3 + .../flash/gui/locales/MainFrame.properties | 3 + .../flash/gui/locales/MainFrame_hu.properties | 3 + .../flash/gui/player/FlashPlayerPanel.java | 18 ++ .../flash/gui/player/MediaDisplay.java | 6 + .../flash/gui/player/PlayerControls.java | 151 +++++---- .../flash/gui/tagtree/TagTreeModel.java | 23 ++ 31 files changed, 628 insertions(+), 621 deletions(-) create mode 100644 src/com/jpexs/decompiler/flash/gui/graphics/loopoff16.png create mode 100644 src/com/jpexs/decompiler/flash/gui/graphics/loopon16.png diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java index 2f2038a8d..9e8e63137 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java @@ -436,6 +436,10 @@ public class Configuration { public static final ConfigurationItem lastSessionData = null; + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("ui") + public static final ConfigurationItem loopMedia = null; + @ConfigurationDefaultBoolean(true) @ConfigurationCategory("ui") public static final ConfigurationItem allowOnlyOneInstance = null; diff --git a/src/com/jpexs/decompiler/flash/gui/AdvancedSettingsDialog.java b/src/com/jpexs/decompiler/flash/gui/AdvancedSettingsDialog.java index 790785944..d7502b143 100644 --- a/src/com/jpexs/decompiler/flash/gui/AdvancedSettingsDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/AdvancedSettingsDialog.java @@ -364,17 +364,13 @@ public class AdvancedSettingsDialog extends AppDialog implements ActionListener private void showRestartConfirmDialod() { if (View.showConfirmDialog(this, translate("advancedSettings.restartConfirmation"), AppStrings.translate("message.warning"), JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { - View.execInEventDispatchLater(new Runnable() { - - @Override - public void run() { - try { - Thread.sleep(1000); - } catch (InterruptedException ex) { - Logger.getLogger(AdvancedSettingsDialog.class.getName()).log(Level.SEVERE, null, ex); - } - SelectLanguageDialog.reloadUi(); + View.execInEventDispatchLater(() -> { + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + Logger.getLogger(AdvancedSettingsDialog.class.getName()).log(Level.SEVERE, null, ex); } + SelectLanguageDialog.reloadUi(); }); } diff --git a/src/com/jpexs/decompiler/flash/gui/ErrorLogFrame.java b/src/com/jpexs/decompiler/flash/gui/ErrorLogFrame.java index d4a92442a..cd31a8fa0 100644 --- a/src/com/jpexs/decompiler/flash/gui/ErrorLogFrame.java +++ b/src/com/jpexs/decompiler/flash/gui/ErrorLogFrame.java @@ -85,12 +85,9 @@ public class ErrorLogFrame extends AppFrame { public static ErrorLogFrame getInstance() { if (instance == null) { instance = new ErrorLogFrame(); - View.execInEventDispatch(new Runnable() { - @Override - public void run() { - Logger logger = Logger.getLogger(""); - logger.addHandler(instance.getHandler()); - } + View.execInEventDispatch(() -> { + Logger logger = Logger.getLogger(""); + logger.addHandler(instance.getHandler()); }); } return instance; @@ -98,12 +95,9 @@ public class ErrorLogFrame extends AppFrame { public static ErrorLogFrame createNewInstance() { if (instance != null) { - View.execInEventDispatch(new Runnable() { - @Override - public void run() { - Logger logger = Logger.getLogger(""); - logger.removeHandler(instance.getHandler()); - } + View.execInEventDispatch(() -> { + Logger logger = Logger.getLogger(""); + logger.removeHandler(instance.getHandler()); }); instance.setVisible(false); instance.dispose(); @@ -210,110 +204,107 @@ public class ErrorLogFrame extends AppFrame { private void log(final Level level, final String msg, final String detail) { if (logItemCount.getAndIncrement() < MAX_LOG_ITEM_COUNT) { - View.execInEventDispatchLater(new Runnable() { - @Override - public void run() { - notifyMainFrame(level); + View.execInEventDispatchLater(() -> { + notifyMainFrame(level); - JPanel pan = new JPanel(); - pan.setBackground(Color.white); - pan.setLayout(new BoxLayout(pan, BoxLayout.Y_AXIS)); + JPanel pan = new JPanel(); + pan.setBackground(Color.white); + pan.setLayout(new BoxLayout(pan, BoxLayout.Y_AXIS)); - JComponent detailComponent; - if (detail == null) { - detailComponent = null; - } else { - final JTextArea detailTextArea = new JTextArea(detail); - detailTextArea.setEditable(false); - detailTextArea.setOpaque(false); - detailTextArea.setFont(new JLabel().getFont()); - detailTextArea.setBackground(Color.white); - detailComponent = detailTextArea; + JComponent detailComponent; + if (detail == null) { + detailComponent = null; + } else { + final JTextArea detailTextArea = new JTextArea(detail); + detailTextArea.setEditable(false); + detailTextArea.setOpaque(false); + detailTextArea.setFont(new JLabel().getFont()); + detailTextArea.setBackground(Color.white); + detailComponent = detailTextArea; + } + JPanel header = new JPanel(); + header.setLayout(new BoxLayout(header, BoxLayout.X_AXIS)); + header.setBackground(Color.white); + + SimpleDateFormat format = new SimpleDateFormat("dd/MM/YYYY HH:mm:ss"); + final String dateStr = format.format(new Date()); + + JToggleButton copyButton = new JToggleButton(View.getIcon("copy16")); + copyButton.setFocusPainted(false); + copyButton.setBorderPainted(false); + copyButton.setFocusable(false); + copyButton.setContentAreaFilled(false); + copyButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + copyButton.setMargin(new Insets(2, 2, 2, 2)); + copyButton.setToolTipText(translate("copy")); + copyButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + StringSelection stringSelection = new StringSelection(dateStr + " " + level.toString() + " " + msg + "\r\n" + detail); + clipboard.setContents(stringSelection, null); } - JPanel header = new JPanel(); - header.setLayout(new BoxLayout(header, BoxLayout.X_AXIS)); - header.setBackground(Color.white); + }); - SimpleDateFormat format = new SimpleDateFormat("dd/MM/YYYY HH:mm:ss"); - final String dateStr = format.format(new Date()); + final JToggleButton expandButton = new JToggleButton(collapseIcon); + expandButton.setFocusPainted(false); + expandButton.setBorderPainted(false); + expandButton.setFocusable(false); + expandButton.setContentAreaFilled(false); + expandButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + expandButton.setMargin(new Insets(2, 2, 2, 2)); + expandButton.setToolTipText(translate("details")); - JToggleButton copyButton = new JToggleButton(View.getIcon("copy16")); - copyButton.setFocusPainted(false); - copyButton.setBorderPainted(false); - copyButton.setFocusable(false); - copyButton.setContentAreaFilled(false); - copyButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - copyButton.setMargin(new Insets(2, 2, 2, 2)); - copyButton.setToolTipText(translate("copy")); - copyButton.addActionListener(new ActionListener() { + final JScrollPane scrollPane; + if (detailComponent != null) { + scrollPane = new JScrollPane(detailComponent); + scrollPane.setAlignmentX(0f); + } else { + scrollPane = null; + } + + if (detailComponent != null) { + expandButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); - StringSelection stringSelection = new StringSelection(dateStr + " " + level.toString() + " " + msg + "\r\n" + detail); - clipboard.setContents(stringSelection, null); + expandButton.setIcon(expandButton.isSelected() ? expandIcon : collapseIcon); + scrollPane.setVisible(expandButton.isSelected()); + revalidate(); + repaint(); } }); - - final JToggleButton expandButton = new JToggleButton(collapseIcon); - expandButton.setFocusPainted(false); - expandButton.setBorderPainted(false); - expandButton.setFocusable(false); - expandButton.setContentAreaFilled(false); - expandButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - expandButton.setMargin(new Insets(2, 2, 2, 2)); - expandButton.setToolTipText(translate("details")); - - final JScrollPane scrollPane; - if (detailComponent != null) { - scrollPane = new JScrollPane(detailComponent); - scrollPane.setAlignmentX(0f); - } else { - scrollPane = null; - } - - if (detailComponent != null) { - expandButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - expandButton.setIcon(expandButton.isSelected() ? expandIcon : collapseIcon); - scrollPane.setVisible(expandButton.isSelected()); - revalidate(); - repaint(); - } - }); - } - - if (detailComponent != null) { - header.add(expandButton); - } - JLabel dateLabel = new JLabel(dateStr); - dateLabel.setPreferredSize(new Dimension(200, (int) dateLabel.getPreferredSize().getHeight())); - dateLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); - header.add(dateLabel); - - JLabel levelLabel = new JLabel(level.getName()); - levelLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); - header.add(levelLabel); - JTextArea msgLabel = new JTextArea(msg); - msgLabel.setEditable(false); - msgLabel.setOpaque(false); - msgLabel.setFont(levelLabel.getFont()); - - msgLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); - header.add(msgLabel); - header.setAlignmentX(0f); - - header.add(copyButton); - pan.add(header); - if (detailComponent != null) { - pan.add(scrollPane); - scrollPane.setVisible(false); - } - pan.setAlignmentX(0f); - logViewInner.add(pan); - revalidate(); - repaint(); } + + if (detailComponent != null) { + header.add(expandButton); + } + JLabel dateLabel = new JLabel(dateStr); + dateLabel.setPreferredSize(new Dimension(200, (int) dateLabel.getPreferredSize().getHeight())); + dateLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + header.add(dateLabel); + + JLabel levelLabel = new JLabel(level.getName()); + levelLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + header.add(levelLabel); + JTextArea msgLabel = new JTextArea(msg); + msgLabel.setEditable(false); + msgLabel.setOpaque(false); + msgLabel.setFont(levelLabel.getFont()); + + msgLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + header.add(msgLabel); + header.setAlignmentX(0f); + + header.add(copyButton); + pan.add(header); + if (detailComponent != null) { + pan.add(scrollPane); + scrollPane.setVisible(false); + } + pan.setAlignmentX(0f); + logViewInner.add(pan); + revalidate(); + repaint(); }); } } diff --git a/src/com/jpexs/decompiler/flash/gui/FolderPreviewPanel.java b/src/com/jpexs/decompiler/flash/gui/FolderPreviewPanel.java index 367d6ee52..20ec7bd65 100644 --- a/src/com/jpexs/decompiler/flash/gui/FolderPreviewPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/FolderPreviewPanel.java @@ -254,12 +254,8 @@ public class FolderPreviewPanel extends JPanel { cachedPreviews.put(index, renderImage(treeItem.getSwf(), treeItem)); if (!repaintQueued) { repaintQueued = true; - View.execInEventDispatchLater(new Runnable() { - - @Override - public void run() { - repaint(); - } + View.execInEventDispatchLater(() -> { + repaint(); }); } return null; diff --git a/src/com/jpexs/decompiler/flash/gui/GenericTagPanel.java b/src/com/jpexs/decompiler/flash/gui/GenericTagPanel.java index 136304ee0..a7c6c73f0 100644 --- a/src/com/jpexs/decompiler/flash/gui/GenericTagPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/GenericTagPanel.java @@ -313,11 +313,8 @@ public class GenericTagPanel extends JPanel implements ChangeListener { } catch (InterruptedException ex) { Logger.getLogger(GenericTagPanel.class.getName()).log(Level.SEVERE, null, ex); } - View.execInEventDispatch(new Runnable() { - @Override - public void run() { - genericTagPropertiesEditPanelScrollPanel.getVerticalScrollBar().setValue(val); - } + View.execInEventDispatch(() -> { + genericTagPropertiesEditPanelScrollPanel.getVerticalScrollBar().setValue(val); }); } @@ -362,11 +359,8 @@ public class GenericTagPanel extends JPanel implements ChangeListener { } catch (InterruptedException ex) { Logger.getLogger(GenericTagPanel.class.getName()).log(Level.SEVERE, null, ex); } - View.execInEventDispatch(new Runnable() { - @Override - public void run() { - genericTagPropertiesEditPanelScrollPanel.getVerticalScrollBar().setValue(val); - } + View.execInEventDispatch(() -> { + genericTagPropertiesEditPanelScrollPanel.getVerticalScrollBar().setValue(val); }); } diff --git a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java index 75efb4802..3af8c1bcf 100644 --- a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java +++ b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java @@ -83,6 +83,8 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis private int frame = -1; + private boolean loop; + private boolean zoomAvailable = false; private int counter = 0; @@ -363,6 +365,7 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis setOpaque(true); setBackground(View.getDefaultBackgroundColor()); + loop = true; iconPanel = new IconPanel(); //labelPan.add(label, new GridBagConstraints()); add(iconPanel, BorderLayout.CENTER); @@ -529,7 +532,7 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis public void setTimelined(final Timelined drawable, final SWF swf, int frame) { synchronized (ImagePanel.class) { - pause(); + stopInternal(); if (drawable instanceof ButtonTag) { frame = ButtonTag.FRAME_UP; } @@ -650,7 +653,13 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis @Override public void pause() { - stop(); + stopInternal(); + } + + @Override + public void stop() { + stopInternal(); + rewind(); } private void stopAllSounds() { @@ -677,7 +686,17 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis synchronized (ImagePanel.class) { if (timelined != null && counter == this.counter) { int frameCount = timelined.getTimeline().getFrameCount(); - int newframe = frameCount > 0 ? (frame + 1) % frameCount : frame; + int newframe; + if (frameCount > 0) { + if (frame + 1 >= frameCount && !loop) { + newframe = frame; + } else { + newframe = (frame + 1) % frameCount; + } + } else { + newframe = frame; + } + if (stillFrame) { newframe = frame; } @@ -904,7 +923,7 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis } public synchronized void clearAll() { - stop(); + stopInternal(); clearImagePanel(); timelined = null; swf = null; @@ -912,14 +931,14 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis fireMediaDisplayStateChanged(); } - public synchronized void stop() { + private synchronized void stopInternal() { clear(); stopAllSounds(); } @Override public synchronized void play() { - pause(); + stopInternal(); if (timelined != null) { Timeline timeline = timelined.getTimeline(); int frameRate = timeline.frameRate; @@ -992,6 +1011,11 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis return (timelined.getTimeline().getFrameCount() <= 1) || (timer != null); } + @Override + public void setLoop(boolean loop) { + this.loop = loop; + } + @Override public synchronized void gotoFrame(int frame) { if (timelined == null) { @@ -1006,7 +1030,7 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis } this.frame = frame; - stop(); + stopInternal(); shouldDraw.set(true); startTimer(counter, true, 0); fireMediaDisplayStateChanged(); @@ -1028,6 +1052,11 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis return loaded; } + @Override + public boolean loopAvailable() { + return false; + } + @Override public boolean screenAvailable() { return true; diff --git a/src/com/jpexs/decompiler/flash/gui/Main.java b/src/com/jpexs/decompiler/flash/gui/Main.java index 4d6bccd27..33a5caaf7 100644 --- a/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/src/com/jpexs/decompiler/flash/gui/Main.java @@ -179,12 +179,9 @@ public class Main { } public static void startProxy(int port) { - View.execInEventDispatch(new Runnable() { - @Override - public void run() { - if (proxyFrame == null) { - proxyFrame = new ProxyFrame(mainFrame); - } + View.execInEventDispatch(() -> { + if (proxyFrame == null) { + proxyFrame = new ProxyFrame(mainFrame); } }); proxyFrame.setPort(port); @@ -235,15 +232,12 @@ public class Main { public static void stopWork() { working = false; - View.execInEventDispatchLater(new Runnable() { - @Override - public void run() { - if (mainFrame != null) { - mainFrame.getPanel().setWorkStatus("", null); - } - if (loadingDialog != null) { - loadingDialog.setDetail(""); - } + View.execInEventDispatchLater(() -> { + if (mainFrame != null) { + mainFrame.getPanel().setWorkStatus("", null); + } + if (loadingDialog != null) { + loadingDialog.setDetail(""); } }); } @@ -478,12 +472,9 @@ public class Main { } try { Main.startWork(AppStrings.translate("work.creatingwindow") + "..."); - View.execInEventDispatch(new Runnable() { - @Override - public void run() { - ensureMainFrame(); - mainFrame.getPanel().load(swfs1, first1); - } + View.execInEventDispatch(() -> { + ensureMainFrame(); + mainFrame.getPanel().load(swfs1, first1); }); } catch (Exception ex) { @@ -846,31 +837,21 @@ public class Main { logger.log(Level.SEVERE, null, ex); } } - View.execInEventDispatch(new Runnable() { - - @Override - public void run() { - ErrorLogFrame.createNewInstance(); - } + View.execInEventDispatch(() -> { + ErrorLogFrame.createNewInstance(); }); autoCheckForUpdates(); offerAssociation(); - View.execInEventDispatch(new Runnable() { - @Override - public void run() { - loadingDialog = new LoadingDialog(); - } + View.execInEventDispatch(() -> { + loadingDialog = new LoadingDialog(); }); } public static void showModeFrame() { - View.execInEventDispatch(new Runnable() { - @Override - public void run() { - ensureMainFrame(); - mainFrame.setVisible(true); - } + View.execInEventDispatch(() -> { + ensureMainFrame(); + mainFrame.setVisible(true); }); } diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameStatusPanel.java b/src/com/jpexs/decompiler/flash/gui/MainFrameStatusPanel.java index b248d0bfd..21a2ea0ae 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameStatusPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameStatusPanel.java @@ -169,16 +169,13 @@ public class MainFrameStatusPanel extends JPanel implements ActionListener { blinkTimer.schedule(new TimerTask() { @Override public void run() { - View.execInEventDispatch(new Runnable() { - @Override - public void run() { - blinkPos++; - if ((blinkPos % 2) == 0 || (blinkPos >= 4)) { - errorNotificationButton.setIcon(currentIcon); - } else { - errorNotificationButton.setIcon(null); - errorNotificationButton.setSize(16, 16); - } + View.execInEventDispatch(() -> { + blinkPos++; + if ((blinkPos % 2) == 0 || (blinkPos >= 4)) { + errorNotificationButton.setIcon(currentIcon); + } else { + errorNotificationButton.setIcon(null); + errorNotificationButton.setSize(16, 16); } }); diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index fdbdc5cf6..a261bd55d 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -695,12 +695,9 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec private void ensureActionPanel() { if (actionPanel == null) { - View.execInEventDispatch(new Runnable() { - @Override - public void run() { - actionPanel = new ActionPanel(MainPanel.this); - displayPanel.add(actionPanel, CARDACTIONSCRIPTPANEL); - } + View.execInEventDispatch(() -> { + actionPanel = new ActionPanel(MainPanel.this); + displayPanel.add(actionPanel, CARDACTIONSCRIPTPANEL); }); } } @@ -854,11 +851,8 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec refreshTree(null); if (updateNeeded) { - View.execInEventDispatch(new Runnable() { - @Override - public void run() { - tagTree.updateUI(); - } + View.execInEventDispatch(() -> { + tagTree.updateUI(); }); } } @@ -887,21 +881,18 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec actionPanel.initSplits(); } - View.execInEventDispatchLater(new Runnable() { - @Override - public void run() { - splitPane1.setDividerLocation(Configuration.guiSplitPane1DividerLocation.get(getWidth() / 3)); - int confDivLoc = Configuration.guiSplitPane2DividerLocation.get(splitPane2.getHeight() * 3 / 5); - if (confDivLoc > splitPane2.getHeight() - 10) { //In older releases, divider location was saved when detailPanel was invisible too - confDivLoc = splitPane2.getHeight() * 3 / 5; - } - splitPane2.setDividerLocation(confDivLoc); - previewPanel.setDividerLocation(Configuration.guiPreviewSplitPaneDividerLocation.get(previewPanel.getWidth() / 2)); - - splitPos = splitPane2.getDividerLocation(); - splitsInited = true; - previewPanel.setSplitsInited(); + View.execInEventDispatchLater(() -> { + splitPane1.setDividerLocation(Configuration.guiSplitPane1DividerLocation.get(getWidth() / 3)); + int confDivLoc = Configuration.guiSplitPane2DividerLocation.get(splitPane2.getHeight() * 3 / 5); + if (confDivLoc > splitPane2.getHeight() - 10) { //In older releases, divider location was saved when detailPanel was invisible too + confDivLoc = splitPane2.getHeight() * 3 / 5; } + splitPane2.setDividerLocation(confDivLoc); + previewPanel.setDividerLocation(Configuration.guiPreviewSplitPaneDividerLocation.get(previewPanel.getWidth() / 2)); + + splitPos = splitPane2.getDividerLocation(); + splitsInited = true; + previewPanel.setSplitsInited(); }); } @@ -1310,22 +1301,16 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec if (swf.isAS3()) { if (abcPanel != null && abcPanel.search(txt, searchDialog.ignoreCaseCheckBox.isSelected(), searchDialog.regexpCheckBox.isSelected())) { found = true; - View.execInEventDispatch(new Runnable() { - @Override - public void run() { - showDetail(DETAILCARDAS3NAVIGATOR); - showCard(CARDACTIONSCRIPT3PANEL); - } + View.execInEventDispatch(() -> { + showDetail(DETAILCARDAS3NAVIGATOR); + showCard(CARDACTIONSCRIPT3PANEL); }); } } else { if (getActionPanel().search(txt, searchDialog.ignoreCaseCheckBox.isSelected(), searchDialog.regexpCheckBox.isSelected())) { found = true; - View.execInEventDispatch(new Runnable() { - @Override - public void run() { - showCard(CARDACTIONSCRIPTPANEL); - } + View.execInEventDispatch(() -> { + showCard(CARDACTIONSCRIPTPANEL); }); } } @@ -1970,14 +1955,10 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec Main.stopWork(); View.showMessageDialog(null, translate("work.deobfuscating.complete")); - View.execInEventDispatch(new Runnable() { - - @Override - public void run() { - clearAllScriptCache(); - getABCPanel().reload(); - updateClassesList(); - } + View.execInEventDispatch(() -> { + clearAllScriptCache(); + getABCPanel().reload(); + updateClassesList(); }); } }.execute(); @@ -2077,12 +2058,8 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec ignoreMissingCharacters ? JOptionPane.OK_OPTION : JOptionPane.CANCEL_OPTION) == JOptionPane.OK_OPTION; return false; } - View.execInEventDispatch(new Runnable() { - - @Override - public void run() { - font.addCharacter(character, f); - } + View.execInEventDispatch(() -> { + font.addCharacter(character, f); }); return true; @@ -2533,9 +2510,10 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec return; } - TreeItem treeItem = (TreeItem) tagTree.getLastSelectedPathComponent(); - if (treeItem == null) { - return; + TreeItem treeItem = null; + TreePath treePath = tagTree.getSelectionPath(); + if (treePath != null && tagTree.getModel().treePathExists(treePath)) { + treeItem = (TreeItem) treePath.getLastPathComponent(); } if (!forceReload && (treeItem == oldItem)) { @@ -2693,7 +2671,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec previewPanel.showImagePanel(new SerializableImage(View.loadImage("sound32"))); previewPanel.setImageReplaceButtonVisible(treeItem instanceof DefineSoundTag); try { - SoundTagPlayer soundThread = new SoundTagPlayer((SoundTag) treeItem, Integer.MAX_VALUE, true); + SoundTagPlayer soundThread = new SoundTagPlayer((SoundTag) treeItem, Configuration.loopMedia.get() ? Integer.MAX_VALUE : 1, true); previewPanel.setMedia(soundThread); } catch (LineUnavailableException | IOException | UnsupportedAudioFileException ex) { logger.log(Level.SEVERE, null, ex); diff --git a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java index 36e009b8b..ee7245ad5 100644 --- a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java @@ -395,6 +395,7 @@ public class PreviewPanel extends JSplitPane implements ActionListener { JPanel previewCnt = new JPanel(new BorderLayout()); imagePanel = new ImagePanel(); + imagePanel.setLoop(Configuration.loopMedia.get()); previewCnt.add(imagePanel, BorderLayout.CENTER); previewCnt.add(imagePlayControls = new PlayerControls(mainPanel, imagePanel), BorderLayout.SOUTH); imagePlayControls.setMedia(imagePanel); diff --git a/src/com/jpexs/decompiler/flash/gui/SearchPanel.java b/src/com/jpexs/decompiler/flash/gui/SearchPanel.java index f8f060180..6c6a5e5fd 100644 --- a/src/com/jpexs/decompiler/flash/gui/SearchPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/SearchPanel.java @@ -124,12 +124,9 @@ public class SearchPanel extends JPanel implements ActionListener { } private void doUpdate() { - View.execInEventDispatchLater(new Runnable() { - @Override - public void run() { - searchPos.setText((foundPos + 1) + "/" + found.size()); - listener.updateSearchPos(found.get(foundPos)); - } + View.execInEventDispatchLater(() -> { + searchPos.setText((foundPos + 1) + "/" + found.size()); + listener.updateSearchPos(found.get(foundPos)); }); } diff --git a/src/com/jpexs/decompiler/flash/gui/SearchResultsDialog.java b/src/com/jpexs/decompiler/flash/gui/SearchResultsDialog.java index 2e77a0062..a712c911c 100644 --- a/src/com/jpexs/decompiler/flash/gui/SearchResultsDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/SearchResultsDialog.java @@ -112,13 +112,8 @@ public class SearchResultsDialog extends AppDialog implements ActionListener private void gotoElement() { if (resultsList.getSelectedIndex() != -1) { - View.execInEventDispatchLater(new Runnable() { - - @Override - public void run() { - listener.updateSearchPos(resultsList.getSelectedValue()); - } - + View.execInEventDispatchLater(() -> { + listener.updateSearchPos(resultsList.getSelectedValue()); }); } } diff --git a/src/com/jpexs/decompiler/flash/gui/SelectLanguageDialog.java b/src/com/jpexs/decompiler/flash/gui/SelectLanguageDialog.java index eaf42bfb8..13ecb96ca 100644 --- a/src/com/jpexs/decompiler/flash/gui/SelectLanguageDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/SelectLanguageDialog.java @@ -128,15 +128,11 @@ public class SelectLanguageDialog extends AppDialog implements ActionListener { } public static void reloadUi() { - View.execInEventDispatchLater(new Runnable() { - - @Override - public void run() { - Locale.setDefault(Locale.forLanguageTag(Configuration.locale.get())); - DefaultSyntaxKit.reloadConfigs(); - Main.initLang(); - Main.reloadApp(); - } + View.execInEventDispatchLater(() -> { + Locale.setDefault(Locale.forLanguageTag(Configuration.locale.get())); + DefaultSyntaxKit.reloadConfigs(); + Main.initLang(); + Main.reloadApp(); }); } diff --git a/src/com/jpexs/decompiler/flash/gui/SoundTagPlayer.java b/src/com/jpexs/decompiler/flash/gui/SoundTagPlayer.java index ee7015e29..3ee757274 100644 --- a/src/com/jpexs/decompiler/flash/gui/SoundTagPlayer.java +++ b/src/com/jpexs/decompiler/flash/gui/SoundTagPlayer.java @@ -30,6 +30,8 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Timer; +import java.util.TimerTask; import java.util.logging.Level; import java.util.logging.Logger; import javax.sound.sampled.AudioSystem; @@ -56,8 +58,12 @@ public class SoundTagPlayer implements MediaDisplay { private final SoundTag tag; + private final Timer timer; + private final List listeners = new ArrayList<>(); + private boolean rewindAfterStop = false; + @Override public void addEventListener(MediaDisplayListener listener) { listeners.add(listener); @@ -68,6 +74,12 @@ public class SoundTagPlayer implements MediaDisplay { listeners.remove(listener); } + public void fireMediaDisplayStateChanged() { + for (MediaDisplayListener l : listeners) { + l.mediaDisplayStateChanged(this); + } + } + private void firePlayingFinished() { for (MediaDisplayListener l : listeners) { l.playingFinished(this); @@ -85,7 +97,6 @@ public class SoundTagPlayer implements MediaDisplay { @Override public void update(LineEvent event) { if (event.getType() == LineEvent.Type.STOP) { - //clip.close(); synchronized (playLock) { if (!paused) { decreaseLoopCount(); @@ -98,10 +109,32 @@ public class SoundTagPlayer implements MediaDisplay { } } } + + if (rewindAfterStop) { + rewind(); + rewindAfterStop = false; + } } + + fireMediaDisplayStateChanged(); } }); + timer = new Timer(); + timer.schedule(new TimerTask() { + + @Override + public void run() { + + try { + fireMediaDisplayStateChanged(); + } catch (Exception ex) { + // ignore + cancel(); + } + } + }, 100, 100); + if (!async) { paused = true; openSound(tag); @@ -168,6 +201,13 @@ public class SoundTagPlayer implements MediaDisplay { } } + @Override + public void stop() { + rewindAfterStop = true; + pause(); + rewind(); + } + @Override public void play() { synchronized (playLock) { @@ -181,6 +221,8 @@ public class SoundTagPlayer implements MediaDisplay { clip.start(); } } + + fireMediaDisplayStateChanged(); } @Override @@ -195,6 +237,11 @@ public class SoundTagPlayer implements MediaDisplay { } } + @Override + public boolean loopAvailable() { + return true; + } + @Override public boolean screenAvailable() { return false; @@ -219,19 +266,18 @@ public class SoundTagPlayer implements MediaDisplay { return null; } + @Override + public void setLoop(boolean loop) { + loopCount = loop ? Integer.MAX_VALUE : 1; + } + @Override public void gotoFrame(int frame) { synchronized (playLock) { - boolean active = clip.isActive(); - if (active) { - clip.stop(); - } clip.setMicrosecondPosition((long) frame * FRAME_DIVISOR); - - if (active) { - clip.start(); - } } + + fireMediaDisplayStateChanged(); } @Override @@ -257,6 +303,8 @@ public class SoundTagPlayer implements MediaDisplay { @Override protected void finalize() throws Throwable { try { + timer.cancel(); + if (clip != null) { clip.close(); } diff --git a/src/com/jpexs/decompiler/flash/gui/TextPanel.java b/src/com/jpexs/decompiler/flash/gui/TextPanel.java index 86112dc4b..cc6f5f09e 100644 --- a/src/com/jpexs/decompiler/flash/gui/TextPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/TextPanel.java @@ -313,12 +313,8 @@ public class TextPanel extends JPanel { public void updateSearchPos() { textValue.setCaretPosition(0); - View.execInEventDispatchLater(new Runnable() { - - @Override - public void run() { - textSearchPanel.showQuickFindDialog(textValue); - } + View.execInEventDispatchLater(() -> { + textSearchPanel.showQuickFindDialog(textValue); }); } diff --git a/src/com/jpexs/decompiler/flash/gui/View.java b/src/com/jpexs/decompiler/flash/gui/View.java index bd3776004..5d2a8b0eb 100644 --- a/src/com/jpexs/decompiler/flash/gui/View.java +++ b/src/com/jpexs/decompiler/flash/gui/View.java @@ -150,109 +150,105 @@ public class View { } catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException ignored) { } - execInEventDispatch(new Runnable() { - @Override - public void run() { + execInEventDispatch(() -> { + try { + UIManager.setLookAndFeel(new SubstanceOfficeBlue2007LookAndFeel()); + SubstanceLookAndFeel.setSkin(Configuration.guiSkin.get()); + UIManager.put(SubstanceLookAndFeel.COLORIZATION_FACTOR, 0.999);//This works for not changing labels color and not changing Dialogs title + UIManager.put("Tree.expandedIcon", getIcon("expand16")); + UIManager.put("Tree.collapsedIcon", getIcon("collapse16")); + UIManager.put("ColorChooserUI", BasicColorChooserUI.class.getName()); + UIManager.put("ColorChooser.swatchesRecentSwatchSize", new Dimension(20, 20)); + UIManager.put("ColorChooser.swatchesSwatchSize", new Dimension(20, 20)); + UIManager.put("RibbonApplicationMenuPopupPanelUI", MyRibbonApplicationMenuPopupPanelUI.class.getName()); + UIManager.put("RibbonApplicationMenuButtonUI", MyRibbonApplicationMenuButtonUI.class.getName()); + UIManager.put("ProgressBarUI", MyProgressBarUI.class.getName()); + UIManager.put("TextField.background", Color.white); + UIManager.put("FormattedTextField.background", Color.white); + UIManager.put("CommandButtonUI", MyCommandButtonUI.class.getName()); - try { - UIManager.setLookAndFeel(new SubstanceOfficeBlue2007LookAndFeel()); - SubstanceLookAndFeel.setSkin(Configuration.guiSkin.get()); - UIManager.put(SubstanceLookAndFeel.COLORIZATION_FACTOR, 0.999);//This works for not changing labels color and not changing Dialogs title - UIManager.put("Tree.expandedIcon", getIcon("expand16")); - UIManager.put("Tree.collapsedIcon", getIcon("collapse16")); - UIManager.put("ColorChooserUI", BasicColorChooserUI.class.getName()); - UIManager.put("ColorChooser.swatchesRecentSwatchSize", new Dimension(20, 20)); - UIManager.put("ColorChooser.swatchesSwatchSize", new Dimension(20, 20)); - UIManager.put("RibbonApplicationMenuPopupPanelUI", MyRibbonApplicationMenuPopupPanelUI.class.getName()); - UIManager.put("RibbonApplicationMenuButtonUI", MyRibbonApplicationMenuButtonUI.class.getName()); - UIManager.put("ProgressBarUI", MyProgressBarUI.class.getName()); - UIManager.put("TextField.background", Color.white); - UIManager.put("FormattedTextField.background", Color.white); - UIManager.put("CommandButtonUI", MyCommandButtonUI.class.getName()); + FontPolicy pol = SubstanceLookAndFeel.getFontPolicy(); + final FontSet fs = pol.getFontSet("Substance", null); - FontPolicy pol = SubstanceLookAndFeel.getFontPolicy(); - final FontSet fs = pol.getFontSet("Substance", null); + //Restore default font for chinese characters + SubstanceLookAndFeel.setFontPolicy(new FontPolicy() { - //Restore default font for chinese characters - SubstanceLookAndFeel.setFontPolicy(new FontPolicy() { + private final FontSet fontSet = new FontSet() { - private final FontSet fontSet = new FontSet() { + private FontUIResource controlFont; - private FontUIResource controlFont; + private FontUIResource menuFont; - private FontUIResource menuFont; + private FontUIResource titleFont; - private FontUIResource titleFont; + private FontUIResource windowTitleFont; - private FontUIResource windowTitleFont; + private FontUIResource smallFont; - private FontUIResource smallFont; - - private FontUIResource messageFont; - - @Override - public FontUIResource getControlFont() { - if (controlFont == null) { - FontUIResource f = fs.getControlFont(); - controlFont = new FontUIResource(defaultFont.getName(), f.getStyle(), f.getSize()); - } - return controlFont; - } - - @Override - public FontUIResource getMenuFont() { - if (menuFont == null) { - FontUIResource f = fs.getMenuFont(); - menuFont = new FontUIResource(defaultFont.getName(), f.getStyle(), f.getSize()); - } - return menuFont; - } - - @Override - public FontUIResource getTitleFont() { - if (titleFont == null) { - FontUIResource f = fs.getTitleFont(); - titleFont = new FontUIResource(defaultFont.getName(), f.getStyle(), f.getSize()); - } - return titleFont; - } - - @Override - public FontUIResource getWindowTitleFont() { - if (windowTitleFont == null) { - FontUIResource f = fs.getWindowTitleFont(); - windowTitleFont = new FontUIResource(defaultFont.getName(), f.getStyle(), f.getSize()); - } - return windowTitleFont; - } - - @Override - public FontUIResource getSmallFont() { - if (smallFont == null) { - FontUIResource f = fs.getSmallFont(); - smallFont = new FontUIResource(defaultFont.getName(), f.getStyle(), f.getSize()); - } - return smallFont; - } - - @Override - public FontUIResource getMessageFont() { - if (messageFont == null) { - FontUIResource f = fs.getMessageFont(); - messageFont = new FontUIResource(defaultFont.getName(), f.getStyle(), f.getSize()); - } - return messageFont; - } - }; + private FontUIResource messageFont; @Override - public FontSet getFontSet(String string, UIDefaults uid) { - return fontSet; + public FontUIResource getControlFont() { + if (controlFont == null) { + FontUIResource f = fs.getControlFont(); + controlFont = new FontUIResource(defaultFont.getName(), f.getStyle(), f.getSize()); + } + return controlFont; } - }); - } catch (UnsupportedLookAndFeelException ex) { - Logger.getLogger(View.class.getName()).log(Level.SEVERE, null, ex); - } + + @Override + public FontUIResource getMenuFont() { + if (menuFont == null) { + FontUIResource f = fs.getMenuFont(); + menuFont = new FontUIResource(defaultFont.getName(), f.getStyle(), f.getSize()); + } + return menuFont; + } + + @Override + public FontUIResource getTitleFont() { + if (titleFont == null) { + FontUIResource f = fs.getTitleFont(); + titleFont = new FontUIResource(defaultFont.getName(), f.getStyle(), f.getSize()); + } + return titleFont; + } + + @Override + public FontUIResource getWindowTitleFont() { + if (windowTitleFont == null) { + FontUIResource f = fs.getWindowTitleFont(); + windowTitleFont = new FontUIResource(defaultFont.getName(), f.getStyle(), f.getSize()); + } + return windowTitleFont; + } + + @Override + public FontUIResource getSmallFont() { + if (smallFont == null) { + FontUIResource f = fs.getSmallFont(); + smallFont = new FontUIResource(defaultFont.getName(), f.getStyle(), f.getSize()); + } + return smallFont; + } + + @Override + public FontUIResource getMessageFont() { + if (messageFont == null) { + FontUIResource f = fs.getMessageFont(); + messageFont = new FontUIResource(defaultFont.getName(), f.getStyle(), f.getSize()); + } + return messageFont; + } + }; + + @Override + public FontSet getFontSet(String string, UIDefaults uid) { + return fontSet; + } + }); + } catch (UnsupportedLookAndFeelException ex) { + Logger.getLogger(View.class.getName()).log(Level.SEVERE, null, ex); } }); @@ -389,11 +385,8 @@ public class View { public static int showOptionDialog(final Component parentComponent, final Object message, final String title, final int optionType, final int messageType, final Icon icon, final Object[] options, final Object initialValue) { final int[] ret = new int[1]; - execInEventDispatch(new Runnable() { - @Override - public void run() { - ret[0] = JOptionPane.showOptionDialog(parentComponent, message, title, optionType, messageType, icon, options, initialValue); - } + execInEventDispatch(() -> { + ret[0] = JOptionPane.showOptionDialog(parentComponent, message, title, optionType, messageType, icon, options, initialValue); }); return ret[0]; } @@ -404,11 +397,8 @@ public class View { public static int showConfirmDialog(final Component parentComponent, final Object message, final String title, final int optionType, final int messageTyp) { final int ret[] = new int[1]; - execInEventDispatch(new Runnable() { - @Override - public void run() { - ret[0] = JOptionPane.showConfirmDialog(parentComponent, message, title, optionType, messageTyp); - } + execInEventDispatch(() -> { + ret[0] = JOptionPane.showConfirmDialog(parentComponent, message, title, optionType, messageTyp); }); return ret[0]; } @@ -431,11 +421,8 @@ public class View { } final int ret[] = new int[1]; - execInEventDispatch(new Runnable() { - @Override - public void run() { - ret[0] = JOptionPane.showConfirmDialog(parentComponent, warPanel, title, optionType, messageTyp); - } + execInEventDispatch(() -> { + ret[0] = JOptionPane.showConfirmDialog(parentComponent, warPanel, title, optionType, messageTyp); }); showAgainConfig.set(!donotShowAgainCheckBox.isSelected()); return ret[0]; @@ -471,21 +458,15 @@ public class View { } public static void showMessageDialog(final Component parentComponent, final Object message) { - execInEventDispatch(new Runnable() { - @Override - public void run() { - JOptionPane.showMessageDialog(parentComponent, message); - } + execInEventDispatch(() -> { + JOptionPane.showMessageDialog(parentComponent, message); }); } public static String showInputDialog(final Object message, final Object initialSelection) { final String[] ret = new String[1]; - execInEventDispatch(new Runnable() { - @Override - public void run() { - ret[0] = JOptionPane.showInputDialog(message, initialSelection); - } + execInEventDispatch(() -> { + ret[0] = JOptionPane.showInputDialog(message, initialSelection); }); return ret[0]; } @@ -623,52 +604,49 @@ public class View { } public static JTable autoResizeColWidth(final JTable table, final TableModel model) { - View.execInEventDispatch(new Runnable() { - @Override - public void run() { - table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); - table.setModel(model); + View.execInEventDispatch(() -> { + table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + table.setModel(model); - int margin = 5; + int margin = 5; - for (int i = 0; i < table.getColumnCount(); i++) { - int vColIndex = i; - DefaultTableColumnModel colModel = (DefaultTableColumnModel) table.getColumnModel(); - TableColumn col = colModel.getColumn(vColIndex); - int width; + for (int i = 0; i < table.getColumnCount(); i++) { + int vColIndex = i; + DefaultTableColumnModel colModel = (DefaultTableColumnModel) table.getColumnModel(); + TableColumn col = colModel.getColumn(vColIndex); + int width; - // Get width of column header - TableCellRenderer renderer = col.getHeaderRenderer(); + // Get width of column header + TableCellRenderer renderer = col.getHeaderRenderer(); - if (renderer == null) { - renderer = table.getTableHeader().getDefaultRenderer(); - } - - Component comp = renderer.getTableCellRendererComponent(table, col.getHeaderValue(), false, false, 0, 0); - - width = comp.getPreferredSize().width; - - // Get maximum width of column data - for (int r = 0; r < table.getRowCount(); r++) { - renderer = table.getCellRenderer(r, vColIndex); - comp = renderer.getTableCellRendererComponent(table, table.getValueAt(r, vColIndex), false, false, - r, vColIndex); - width = Math.max(width, comp.getPreferredSize().width); - } - - // Add margin - width += 2 * margin; - - // Set the width - col.setPreferredWidth(width); + if (renderer == null) { + renderer = table.getTableHeader().getDefaultRenderer(); } - ((DefaultTableCellRenderer) table.getTableHeader().getDefaultRenderer()).setHorizontalAlignment( - SwingConstants.LEFT); + Component comp = renderer.getTableCellRendererComponent(table, col.getHeaderValue(), false, false, 0, 0); - // table.setAutoCreateRowSorter(true); - table.getTableHeader().setReorderingAllowed(false); + width = comp.getPreferredSize().width; + + // Get maximum width of column data + for (int r = 0; r < table.getRowCount(); r++) { + renderer = table.getCellRenderer(r, vColIndex); + comp = renderer.getTableCellRendererComponent(table, table.getValueAt(r, vColIndex), false, false, + r, vColIndex); + width = Math.max(width, comp.getPreferredSize().width); + } + + // Add margin + width += 2 * margin; + + // Set the width + col.setPreferredWidth(width); } + + ((DefaultTableCellRenderer) table.getTableHeader().getDefaultRenderer()).setHorizontalAlignment( + SwingConstants.LEFT); + + // table.setAutoCreateRowSorter(true); + table.getTableHeader().setReorderingAllowed(false); }); return table; diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java index f71d92876..33c7b2327 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java @@ -219,14 +219,10 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Se searchPanel.setSearchText(txt); - View.execInEventDispatch(new Runnable() { - - @Override - public void run() { - SearchResultsDialog sr = new SearchResultsDialog<>(ABCPanel.this.mainPanel.getMainFrame().getWindow(), txt, ABCPanel.this); - sr.setResults(found); - sr.setVisible(true); - } + View.execInEventDispatch(() -> { + SearchResultsDialog sr = new SearchResultsDialog<>(ABCPanel.this.mainPanel.getMainFrame().getWindow(), txt, ABCPanel.this); + sr.setResults(found); + sr.setVisible(true); }); return true; @@ -703,12 +699,9 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Se public void hilightScript(ScriptPack pack) { TagTreeModel ttm = (TagTreeModel) mainPanel.tagTree.getModel(); final TreePath tp = ttm.getTreePath(pack); - View.execInEventDispatchLater(new Runnable() { - @Override - public void run() { - mainPanel.tagTree.setSelectionPath(tp); - mainPanel.tagTree.scrollPathToVisible(tp); - } + View.execInEventDispatchLater(() -> { + mainPanel.tagTree.setSelectionPath(tp); + mainPanel.tagTree.scrollPathToVisible(tp); }); } @@ -721,12 +714,8 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Se hilightScript(pack); decompiledTextArea.setCaretPosition(0); - View.execInEventDispatchLater(new Runnable() { - - @Override - public void run() { - searchPanel.showQuickFindDialog(decompiledTextArea); - } + View.execInEventDispatchLater(() -> { + searchPanel.showQuickFindDialog(decompiledTextArea); }); } diff --git a/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java b/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java index 9790969f5..935b87b78 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java @@ -499,11 +499,8 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL @Override public void caretUpdate(final CaretEvent e) { if (!SwingUtilities.isEventDispatchThread()) { - View.execInEventDispatch(new Runnable() { - @Override - public void run() { - caretUpdate(e); - } + View.execInEventDispatch(() -> { + caretUpdate(e); }); return; } diff --git a/src/com/jpexs/decompiler/flash/gui/abc/DetailPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/DetailPanel.java index e569c0b3c..97d141bc3 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/DetailPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/DetailPanel.java @@ -159,39 +159,35 @@ public class DetailPanel extends JPanel implements ActionListener { } public void showCard(final String name, final Trait trait) { - View.execInEventDispatch(new Runnable() { + View.execInEventDispatch(() -> { + CardLayout layout = (CardLayout) innerPanel.getLayout(); + layout.show(innerPanel, name); + boolean b = cardMap.get(name) instanceof TraitDetail; + buttonsPanel.setVisible(b); - @Override - public void run() { - CardLayout layout = (CardLayout) innerPanel.getLayout(); - layout.show(innerPanel, name); - boolean b = cardMap.get(name) instanceof TraitDetail; - buttonsPanel.setVisible(b); - - TraitDetail newDetail = null; - if (b) { - newDetail = (TraitDetail) cardMap.get(name); - } - for (JComponent v : cardMap.values()) { - if (v instanceof TraitDetail) { - if (v != newDetail) { - TraitDetail oldDetail = (TraitDetail) v; - oldDetail.setActive(false); - } + TraitDetail newDetail = null; + if (b) { + newDetail = (TraitDetail) cardMap.get(name); + } + for (JComponent v : cardMap.values()) { + if (v instanceof TraitDetail) { + if (v != newDetail) { + TraitDetail oldDetail = (TraitDetail) v; + oldDetail.setActive(false); } } - if (newDetail != null) { - newDetail.setActive(true); - } + } + if (newDetail != null) { + newDetail.setActive(true); + } - selectedCard = name; - selectedLabel.setText(selectedCard); - if (trait == null) { - traitNameLabel.setText("-"); - } else { - if (abcPanel != null) { - traitNameLabel.setText(trait.getName(abcPanel.abc).getName(abcPanel.abc.constants, new ArrayList<>(), false)); - } + selectedCard = name; + selectedLabel.setText(selectedCard); + if (trait == null) { + traitNameLabel.setText("-"); + } else { + if (abcPanel != null) { + traitNameLabel.setText(trait.getName(abcPanel.abc).getName(abcPanel.abc.constants, new ArrayList<>(), false)); } } }); diff --git a/src/com/jpexs/decompiler/flash/gui/abc/UndoFixedEditorPane.java b/src/com/jpexs/decompiler/flash/gui/abc/UndoFixedEditorPane.java index 3a1254fe2..96c072c42 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/UndoFixedEditorPane.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/UndoFixedEditorPane.java @@ -42,12 +42,8 @@ public class UndoFixedEditorPane extends JEditorPane { @Override public void setText(final String t) { - View.execInEventDispatch(new Runnable() { - - @Override - public void run() { - setText(t, getContentType()); - } + View.execInEventDispatch(() -> { + setText(t, getContentType()); }); } diff --git a/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java b/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java index ae92aeac1..23ffff714 100644 --- a/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java @@ -277,14 +277,10 @@ public class ActionPanel extends JPanel implements ActionListener, SearchListene Main.stopWork(); searchPanel.setSearchText(txt); - View.execInEventDispatch(new Runnable() { - - @Override - public void run() { - SearchResultsDialog sr = new SearchResultsDialog<>(ActionPanel.this.mainPanel.getMainFrame().getWindow(), txt, ActionPanel.this); - sr.setResults(found); - sr.setVisible(true); - } + View.execInEventDispatch(() -> { + SearchResultsDialog sr = new SearchResultsDialog<>(ActionPanel.this.mainPanel.getMainFrame().getWindow(), txt, ActionPanel.this); + sr.setResults(found); + sr.setVisible(true); }); return true; //return searchPanel.setResults(found); @@ -293,52 +289,40 @@ public class ActionPanel extends JPanel implements ActionListener, SearchListene } private void setDecompiledText(final String text) { - View.execInEventDispatch(new Runnable() { - - @Override - public void run() { - ignoreCarret = true; - decompiledEditor.setText(text); - ignoreCarret = false; - } + View.execInEventDispatch(() -> { + ignoreCarret = true; + decompiledEditor.setText(text); + ignoreCarret = false; }); } private void setEditorText(final String text, final String contentType) { - View.execInEventDispatch(new Runnable() { - - @Override - public void run() { - ignoreCarret = true; - editor.setContentType(contentType); - editor.setText(text); - ignoreCarret = false; - } + View.execInEventDispatch(() -> { + ignoreCarret = true; + editor.setContentType(contentType); + editor.setText(text); + ignoreCarret = false; }); } private void setText(final HighlightedText text, final String contentType) { - View.execInEventDispatch(new Runnable() { - - @Override - public void run() { - int pos = editor.getCaretPosition(); - Highlighting lastH = null; - for (Highlighting h : disassembledHilights) { - if (pos < h.startPos) { - break; - } - lastH = h; + View.execInEventDispatch(() -> { + int pos = editor.getCaretPosition(); + Highlighting lastH = null; + for (Highlighting h : disassembledHilights) { + if (pos < h.startPos) { + break; } - Long offset = lastH == null ? 0 : lastH.getProperties().offset; - disassembledHilights = text.instructionHilights; - String stripped = text.text; - setEditorText(stripped, contentType); - Highlighting h = Highlighting.searchOffset(disassembledHilights, offset); - if (h != null) { - if (h.startPos <= editor.getDocument().getLength()) { - editor.setCaretPosition(h.startPos); - } + lastH = h; + } + Long offset = lastH == null ? 0 : lastH.getProperties().offset; + disassembledHilights = text.instructionHilights; + String stripped = text.text; + setEditorText(stripped, contentType); + Highlighting h = Highlighting.searchOffset(disassembledHilights, offset); + if (h != null) { + if (h.startPos <= editor.getDocument().getLength()) { + editor.setCaretPosition(h.startPos); } } }); @@ -468,17 +452,13 @@ public class ActionPanel extends JPanel implements ActionListener, SearchListene setSourceWorker = null; Main.stopWork(); - View.execInEventDispatch(new Runnable() { - - @Override - public void run() { - try { - get(); - } catch (CancellationException ex) { - setEditorText("; " + AppStrings.translate("work.canceled"), "text/flasm"); - } catch (Exception ex) { - setDecompiledText("// " + AppStrings.translate("decompilationError") + ": " + ex); - } + View.execInEventDispatch(() -> { + try { + get(); + } catch (CancellationException ex) { + setEditorText("; " + AppStrings.translate("work.canceled"), "text/flasm"); + } catch (Exception ex) { + setDecompiledText("// " + AppStrings.translate("decompilationError") + ": " + ex); } }); } @@ -839,12 +819,8 @@ public class ActionPanel extends JPanel implements ActionListener, SearchListene mainPanel.tagTree.scrollPathToVisible(tp); decompiledEditor.setCaretPosition(0); - View.execInEventDispatchLater(new Runnable() { - - @Override - public void run() { - searchPanel.showQuickFindDialog(decompiledEditor); - } + View.execInEventDispatchLater(() -> { + searchPanel.showQuickFindDialog(decompiledEditor); }); } } diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/loopoff16.png b/src/com/jpexs/decompiler/flash/gui/graphics/loopoff16.png new file mode 100644 index 0000000000000000000000000000000000000000..1c4f57a16126b203bfa12caf50f4b3fe725f9bc1 GIT binary patch literal 422 zcmV;X0a^ZuP)2#b| zLX6^UF84fh?wy$kBLC~BD2js0>zp+XR}r`}LU#$3n|fVSTQ&_fqK z-dP1W_0w_)Fx(96Hd?S$6Ag!Gb0{2;SA#|hQKxxo4lC@GkWvoF>433OT)ML_c*YrK zxk(GV+5xw=j}C#*d_)ZQm|^vSE$e_Rfi{EB*{sr@#u0%!GuA`kT6eip5)*9h(VoI2 z7I~jC*1{1PRmB(0C&t&XN#G6@eBuONxMW%!n+~_GQB^!(14SOFz%!m0KGcES_nU0K zx*VUU%kcb!9C_-b+%XxB2spb0jf9EGvCrBTt7=&<*|?4A1r-;+e)BJV19u#CG)&jc Qk^lez07*qoM6N<$f+7R3%K!iX literal 0 HcmV?d00001 diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/loopon16.png b/src/com/jpexs/decompiler/flash/gui/graphics/loopon16.png new file mode 100644 index 0000000000000000000000000000000000000000..406ec333bc036690d4639cbec70e8f586e977699 GIT binary patch literal 750 zcmV`dI4bfJkF0x@cXCL|Igq$5O2KprVjQ%O+X7O;#( z4BD1bI(<+cEez0UoerJ8pvUZH<2j7y zcZNUt)xrxJYFpmPCdcPpZrKy&*VZ>ApFbcitp@qg#TeIQPnn2A+}{k&#TSQNduHE8 zR1lLg6t#%bX_+CDEg*4_f_v33^v*=h#I2ZA3~EX24{j>CdV}A=`*V zT4vz!`I!OrPI2eFNk)w9XPLPE(JbD&MP{&ll+#ia(bqqy8yG)*4e)6tkBnME*Ypl9 z-y3DbfrSJUUwt@@D-R}c|4op+OgNr~#cI=AsIxgE+;$>~av4mxb*QrFQBlRSu^2P( z#4-pavM8REG5;k1bN7TkM8nPocv)tTbCDe=Sn=D!1EK%memuVc8qO zwkWfiP|txa2~#c~+AY08Q|E`jSGoE#-RjvgwZ5L>o_F>0mY3bqi%w2z>#*|89S-gW g7yS2U`k(Lo6ZXgk;$VJhmjD0&07*qoM6N<$g5UmA*#H0l literal 0 HcmV?d00001 diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties index e18297b1a..e5dba47c1 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties @@ -344,3 +344,6 @@ config.description.gui.skin = Look and feel skin config.name.lastSessionData = Last session data config.description.lastSessionData = Contains the opened files from the last session + +config.name.loopMedia = Loop sounds and sprites +config.description.lastSessionData = Automatically restarts the playing of the sounds and sprites diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_hu.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_hu.properties index 0d87dfd36..4e53911cf 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_hu.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_hu.properties @@ -344,3 +344,6 @@ config.description.gui.skin = Kin\u00e9zet config.name.lastSessionData = Utols\u00f3 munkamenet adatai config.description.lastSessionData = Az legut\u00f3bbi munkamenetben megnyitott f\u00e1jlokat tartalmazza + +config.name.loopMedia = Zen\u00e9k \u00e9s szpr\u00e1jtok +config.description.lastSessionData = Aut\u00f3matikusan \u00fajraind\u00edtja a zen\u00e9k \u00e9s szpr\u00e1jtok lej\u00e1tsz\u00e1s\u00e1t diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index 0f4cb1c26..cca6578b3 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -577,3 +577,6 @@ selectNextTag = Select next tag button.ignoreAll = Ignore All menu.file.import.symbolClass = Import Symbol-Class text.toggleCase = Toggle case + +#after version 5.0.2 +preview.loop = Loop diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties index 020325957..79bcadaec 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties @@ -576,3 +576,6 @@ selectNextTag = K\u00f6vetkez\u0151 tag kiv\u00e1laszt\u00e1sa button.ignoreAll = Mell\u0151z mindet menu.file.import.symbolClass = Szimb\u00f3lum oszt\u00e1ly import\u00e1l\u00e1s text.toggleCase = Kis- nagybet\u0171 v\u00e1ltoztat\u00e1s + +#after version 5.0.2 +preview.loop = Ism\u00e9tl\u00e9s diff --git a/src/com/jpexs/decompiler/flash/gui/player/FlashPlayerPanel.java b/src/com/jpexs/decompiler/flash/gui/player/FlashPlayerPanel.java index 811246699..d36c7745b 100644 --- a/src/com/jpexs/decompiler/flash/gui/player/FlashPlayerPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/player/FlashPlayerPanel.java @@ -56,6 +56,11 @@ public final class FlashPlayerPanel extends Panel implements Closeable, MediaDis private int frameRate; + @Override + public boolean loopAvailable() { + return false; + } + @Override public boolean screenAvailable() { return true; @@ -261,6 +266,15 @@ public final class FlashPlayerPanel extends Panel implements Closeable, MediaDis } } + @Override + public void stop() { + try { + flash.Stop(); + flash.Rewind(); + } catch (ActiveXException ex) { // Can be "Data not available yet exception" + } + } + @Override public void rewind() { try { @@ -286,6 +300,10 @@ public final class FlashPlayerPanel extends Panel implements Closeable, MediaDis } } + @Override + public void setLoop(boolean loop) { + } + @Override public void gotoFrame(int frame) { if (frame < 0) { diff --git a/src/com/jpexs/decompiler/flash/gui/player/MediaDisplay.java b/src/com/jpexs/decompiler/flash/gui/player/MediaDisplay.java index 4596ae4b2..1bca6866d 100644 --- a/src/com/jpexs/decompiler/flash/gui/player/MediaDisplay.java +++ b/src/com/jpexs/decompiler/flash/gui/player/MediaDisplay.java @@ -33,12 +33,16 @@ public interface MediaDisplay { public void pause(); + public void stop(); + public void play(); public void rewind(); public boolean isPlaying(); + public void setLoop(boolean loop); + public void gotoFrame(int frame); public void setBackground(Color color); @@ -49,6 +53,8 @@ public interface MediaDisplay { public BufferedImage printScreen(); + public boolean loopAvailable(); + public boolean screenAvailable(); public boolean zoomAvailable(); diff --git a/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java b/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java index 36bb36000..5c732140b 100644 --- a/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java +++ b/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java @@ -16,6 +16,7 @@ */ package com.jpexs.decompiler.flash.gui.player; +import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.gui.AppStrings; import com.jpexs.decompiler.flash.gui.MainPanel; import com.jpexs.decompiler.flash.gui.View; @@ -67,6 +68,8 @@ public class PlayerControls extends JPanel implements ActionListener, MediaDispl private static final String ACTION_STOP = "STOP"; + private static final String ACTION_LOOP = "LOOP"; + private static final String ACTION_SELECT_BKCOLOR = "SELECTCOLOR"; private static final String ACTION_ZOOMIN = "ZOOMIN"; @@ -87,6 +90,8 @@ public class PlayerControls extends JPanel implements ActionListener, MediaDispl private final JButton pauseButton; + private final JButton loopButton; + private boolean paused = false; private MediaDisplay display; @@ -105,6 +110,10 @@ public class PlayerControls extends JPanel implements ActionListener, MediaDispl private static final Icon playIcon = View.getIcon("play16"); + private static final Icon loopIcon = View.getIcon("loopon16"); + + private static final Icon noLoopIcon = View.getIcon("loopoff16"); + private final JLabel percentLabel = new JLabel("100%"); private final JPanel zoomPanel; @@ -121,6 +130,8 @@ public class PlayerControls extends JPanel implements ActionListener, MediaDispl private final JButton zoomFitButton; + private final JButton snapshotButton; + public static final int ZOOM_DECADE_STEPS = 10; public static final double ZOOM_MULTIPLIER = Math.pow(10, 1.0 / ZOOM_DECADE_STEPS); @@ -172,7 +183,7 @@ public class PlayerControls extends JPanel implements ActionListener, MediaDispl zoomNoneButton.setActionCommand(ACTION_ZOOMNONE); zoomNoneButton.setToolTipText(AppStrings.translate("button.zoomnone.hint")); - JButton snapshotButton = new JButton(View.getIcon("snapshot16")); + snapshotButton = new JButton(View.getIcon("snapshot16")); snapshotButton.addActionListener(this); snapshotButton.setActionCommand(ACTION_SNAPSHOT); snapshotButton.setToolTipText(AppStrings.translate("button.snapshot.hint")); @@ -287,8 +298,16 @@ public class PlayerControls extends JPanel implements ActionListener, MediaDispl stopButton.setMargin(new Insets(4, 2, 2, 2)); stopButton.setActionCommand(ACTION_STOP); stopButton.addActionListener(this); + loopButton = new JButton(pauseIcon); + loopButton.setToolTipText(AppStrings.translate("preview.loop")); + loopButton.setMargin(new Insets(4, 2, 2, 2)); + loopButton.setActionCommand(ACTION_LOOP); + loopButton.addActionListener(this); + boolean loop = Configuration.loopMedia.get(); + loopButton.setIcon(loop ? loopIcon : noLoopIcon); buttonsPanel.add(pauseButton); buttonsPanel.add(stopButton); + buttonsPanel.add(loopButton); controlPanel.add(buttonsPanel, BorderLayout.CENTER); progress = new JProgressBar(); @@ -339,6 +358,8 @@ public class PlayerControls extends JPanel implements ActionListener, MediaDispl this.display = media; this.display.addEventListener(this); + + update(); } private void update() { @@ -346,53 +367,51 @@ public class PlayerControls extends JPanel implements ActionListener, MediaDispl return; } - View.execInEventDispatch(new Runnable() { - @Override - public void run() { - updateZoom(); - Zoom zoom = display.getZoom(); - zoomFitButton.setVisible(zoom != null); - percentLabel.setVisible(zoom != null); - zoomPanel.setVisible(display.zoomAvailable()); - boolean screenAvailable = display.screenAvailable(); - graphicControls.setVisible(screenAvailable); - totalFrameLabel.setVisible(screenAvailable); - frameLabel.setVisible(screenAvailable); - frameControls.setVisible(screenAvailable); - int totalFrames = display.getTotalFrames(); - int currentFrame = display.getCurrentFrame(); - if (currentFrame >= totalFrames) { - currentFrame = totalFrames - 1; - } - int frameRate = display.getFrameRate(); - if (totalFrames == 0) { - progress.setIndeterminate(true); - } else { - progress.setMaximum(totalFrames - 1); - progress.setMinimum(0); - progress.setValue(currentFrame); - progress.setIndeterminate(false); - } - frameLabel.setText(("" + (currentFrame + 1))); - totalFrameLabel.setText("" + totalFrames); - if (frameRate != 0) { - timeLabel.setText("(" + formatMs((currentFrame * 1000) / frameRate) + ")"); - totalTimeLabel.setText("(" + formatMs(((totalFrames - 1) * 1000) / frameRate) + ")"); - } - if (totalFrames <= 1 && playbackControls.isVisible()) { - playbackControls.setVisible(false); - } - if (totalFrames > 1 && !playbackControls.isVisible()) { - playbackControls.setVisible(true); - } - boolean paused = !display.isPlaying(); - if (paused) { - pauseButton.setToolTipText(AppStrings.translate("preview.play")); - pauseButton.setIcon(playIcon); - } else { - pauseButton.setToolTipText(AppStrings.translate("preview.pause")); - pauseButton.setIcon(pauseIcon); - } + View.execInEventDispatchLater(() -> { + updateZoom(); + Zoom zoom = display.getZoom(); + zoomFitButton.setVisible(zoom != null); + percentLabel.setVisible(zoom != null); + zoomPanel.setVisible(display.zoomAvailable()); + boolean screenAvailable = display.screenAvailable(); + snapshotButton.setVisible(screenAvailable); + graphicControls.setVisible(screenAvailable); + totalFrameLabel.setVisible(screenAvailable); + frameLabel.setVisible(screenAvailable); + frameControls.setVisible(screenAvailable); + int totalFrames = display.getTotalFrames(); + int currentFrame = display.getCurrentFrame(); + if (currentFrame >= totalFrames) { + currentFrame = totalFrames - 1; + } + int frameRate = display.getFrameRate(); + if (totalFrames == 0) { + progress.setIndeterminate(true); + } else { + progress.setMaximum(totalFrames - 1); + progress.setMinimum(0); + progress.setValue(currentFrame); + progress.setIndeterminate(false); + } + frameLabel.setText(("" + (currentFrame + 1))); + totalFrameLabel.setText("" + totalFrames); + if (frameRate != 0) { + timeLabel.setText("(" + formatMs((currentFrame * 1000) / frameRate) + ")"); + totalTimeLabel.setText("(" + formatMs(((totalFrames - 1) * 1000) / frameRate) + ")"); + } + if (totalFrames <= 1 && playbackControls.isVisible()) { + playbackControls.setVisible(false); + } + if (totalFrames > 1 && !playbackControls.isVisible()) { + playbackControls.setVisible(true); + } + boolean paused1 = !display.isPlaying(); + if (paused1) { + pauseButton.setToolTipText(AppStrings.translate("preview.play")); + pauseButton.setIcon(playIcon); + } else { + pauseButton.setToolTipText(AppStrings.translate("preview.pause")); + pauseButton.setIcon(pauseIcon); } }); @@ -441,6 +460,13 @@ public class PlayerControls extends JPanel implements ActionListener, MediaDispl } break; + case ACTION_LOOP: + boolean loop = !Configuration.loopMedia.get(); + Configuration.loopMedia.set(loop); + loopButton.setIcon(loop ? loopIcon : noLoopIcon); + display.setLoop(loop); + break; + case ACTION_GOTOFRAME: final JPanel gotoPanel = new JPanel(new BorderLayout()); final JTextField frameField = new JTextField("" + display.getCurrentFrame()); @@ -451,15 +477,10 @@ public class PlayerControls extends JPanel implements ActionListener, MediaDispl @Override public void ancestorAdded(AncestorEvent event) { final AncestorListener al = this; - View.execInEventDispatchLater(new Runnable() { - - @Override - public void run() { - frameField.selectAll(); - frameField.requestFocusInWindow(); - gotoPanel.removeAncestorListener(al); - - } + View.execInEventDispatchLater(() -> { + frameField.selectAll(); + frameField.requestFocusInWindow(); + gotoPanel.removeAncestorListener(al); }); } @@ -495,18 +516,14 @@ public class PlayerControls extends JPanel implements ActionListener, MediaDispl display.gotoFrame(display.getCurrentFrame() - 1); break; case ACTION_STOP: - display.pause(); - display.rewind(); + display.stop(); break; case ACTION_SELECT_BKCOLOR: - View.execInEventDispatch(new Runnable() { - @Override - public void run() { - Color newColor = JColorChooser.showDialog(null, AppStrings.translate("dialog.selectbkcolor.title"), View.getSwfBackgroundColor()); - if (newColor != null) { - View.setSwfBackgroundColor(newColor); - display.setBackground(newColor); - } + View.execInEventDispatch(() -> { + Color newColor = JColorChooser.showDialog(null, AppStrings.translate("dialog.selectbkcolor.title"), View.getSwfBackgroundColor()); + if (newColor != null) { + View.setSwfBackgroundColor(newColor); + display.setBackground(newColor); } }); break; diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeModel.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeModel.java index 9ade6a7cf..ad31a8578 100644 --- a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeModel.java +++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeModel.java @@ -724,6 +724,29 @@ public class TagTreeModel implements TreeModel { throw new Error("Unsupported parent type: " + parentNode.getClass().getName()); } + public boolean treePathExists(TreePath treePath) { + TreeItem current = null; + for (Object o : treePath.getPath()) { + TreeItem item = (TreeItem) o; + if (current == null) { + if (item != getRoot()) { + return false; + } + + current = item; + } else { + int idx = getIndexOfChild(current, item); + if (idx == -1) { + return false; + } + + current = item; + } + } + + return true; + } + @Override public void addTreeModelListener(TreeModelListener l) { listeners.add(l); From d28d72c096b34602b467c55fd57d3b9cea5a54c3 Mon Sep 17 00:00:00 2001 From: "honfika@gmail.com" Date: Sun, 26 Apr 2015 16:46:04 +0200 Subject: [PATCH 3/4] morphshape animation fix --- src/com/jpexs/decompiler/flash/gui/ImagePanel.java | 7 +++---- src/com/jpexs/decompiler/flash/gui/MainPanel.java | 2 ++ .../jpexs/decompiler/flash/gui/player/PlayerControls.java | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java index 3af8c1bcf..63989674b 100644 --- a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java +++ b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java @@ -688,10 +688,9 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis int frameCount = timelined.getTimeline().getFrameCount(); int newframe; if (frameCount > 0) { - if (frame + 1 >= frameCount && !loop) { - newframe = frame; - } else { - newframe = (frame + 1) % frameCount; + newframe = (frame + 1) % frameCount; + if (newframe == 0 && !loop) { + stop(); } } else { newframe = frame; diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index a261bd55d..9c2e9a1cb 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -2825,6 +2825,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec ds.matrix = new MATRIX(); ds.ratio = i * 65535 / framesCnt; f.layers.put(1, ds); + f.layersChanged = true; tim.addFrame(f); } } else if (tag instanceof FontTag) { @@ -2836,6 +2837,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec ds.matrix = new MATRIX(); ds.time = i; f.layers.put(1, ds); + f.layersChanged = true; tim.addFrame(f); } } else { diff --git a/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java b/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java index 5c732140b..84ed0426b 100644 --- a/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java +++ b/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java @@ -397,7 +397,7 @@ public class PlayerControls extends JPanel implements ActionListener, MediaDispl totalFrameLabel.setText("" + totalFrames); if (frameRate != 0) { timeLabel.setText("(" + formatMs((currentFrame * 1000) / frameRate) + ")"); - totalTimeLabel.setText("(" + formatMs(((totalFrames - 1) * 1000) / frameRate) + ")"); + totalTimeLabel.setText("(" + formatMs((totalFrames * 1000) / frameRate) + ")"); } if (totalFrames <= 1 && playbackControls.isVisible()) { playbackControls.setVisible(false); From 92712a723357499797fa321570b5eed3bb06fb70 Mon Sep 17 00:00:00 2001 From: "honfika@gmail.com" Date: Sun, 26 Apr 2015 21:06:54 +0200 Subject: [PATCH 4/4] #845 Import exported AS1/2 (DefineButton2&DefineSprite) button --- .../src/com/jpexs/decompiler/flash/SWF.java | 144 +----------------- .../flash/exporters/TextExporter.java | 2 - .../exporters/script/AS2ScriptExporter.java | 5 + .../exporters/script/AS3ScriptExporter.java | 104 +++++++++++++ .../exporters/script/ExportPackTask.java | 98 ++++++++++++ .../settings/ScriptExportSettings.java | 2 + .../settings/TextExportSettings.java | 2 + .../flash/importers/ScriptImporter.java | 61 ++++++++ .../flash/importers/TextImporter.java | 4 +- .../console/CommandLineArgumentParser.java | 4 +- .../decompiler/flash/gui/MainFrameMenu.java | 4 + .../flash/gui/MainFrameRibbonMenu.java | 13 ++ .../jpexs/decompiler/flash/gui/MainPanel.java | 29 +++- .../flash/gui/locales/MainFrame.properties | 1 + .../flash/gui/locales/MainFrame_hu.properties | 1 + 15 files changed, 321 insertions(+), 153 deletions(-) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/AS3ScriptExporter.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/ExportPackTask.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/ScriptImporter.java diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index 546fcc5e1..9d92e6d59 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -65,6 +65,7 @@ import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter; import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; import com.jpexs.decompiler.flash.exporters.script.AS2ScriptExporter; +import com.jpexs.decompiler.flash.exporters.script.AS3ScriptExporter; import com.jpexs.decompiler.flash.exporters.settings.ScriptExportSettings; import com.jpexs.decompiler.flash.helpers.HighlightedText; import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; @@ -130,7 +131,6 @@ import com.jpexs.decompiler.graph.TranslateStack; import com.jpexs.decompiler.graph.model.LocalData; import com.jpexs.helpers.ByteArrayRange; import com.jpexs.helpers.Cache; -import com.jpexs.helpers.CancellableWorker; import com.jpexs.helpers.Helper; import com.jpexs.helpers.NulStream; import com.jpexs.helpers.ProgressListener; @@ -161,14 +161,6 @@ import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.Stack; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import java.util.logging.Logger; import java.util.zip.DeflaterOutputStream; @@ -1204,136 +1196,6 @@ public final class SWF implements SWFContainerItem, Timelined { return displayRect; } - private class ExportPackTask implements Callable { - - ScriptPack pack; - - String directory; - - ScriptExportSettings exportSettings; - - ClassPath path; - - AtomicInteger index; - - int count; - - boolean parallel; - - AbortRetryIgnoreHandler handler; - - long startTime; - - long stopTime; - - EventListener eventListener; - - public ExportPackTask(AbortRetryIgnoreHandler handler, AtomicInteger index, int count, ClassPath path, ScriptPack pack, String directory, ScriptExportSettings exportSettings, boolean parallel, EventListener evl) { - this.pack = pack; - this.directory = directory; - this.exportSettings = exportSettings; - this.path = path; - this.index = index; - this.count = count; - this.parallel = parallel; - this.handler = handler; - this.eventListener = evl; - } - - @Override - public File call() throws Exception { - RunnableIOExResult rio = new RunnableIOExResult() { - @Override - public void run() throws IOException { - startTime = System.currentTimeMillis(); - this.result = pack.export(directory, exportSettings, parallel); - stopTime = System.currentTimeMillis(); - } - }; - int currentIndex = index.getAndIncrement(); - if (eventListener != null) { - synchronized (ABC.class) { - eventListener.handleExportingEvent("script", currentIndex, count, path); - } - } - new RetryTask(rio, handler).run(); - if (eventListener != null) { - synchronized (ABC.class) { - long time = stopTime - startTime; - eventListener.handleExportedEvent("script", currentIndex, count, path + ", " + Helper.formatTimeSec(time)); - } - } - return rio.result; - } - } - - private List exportActionScript2(AbortRetryIgnoreHandler handler, String outdir, ScriptExportSettings exportSettings, boolean parallel, EventListener evl) throws IOException { - List ret = new ArrayList<>(); - - if (!outdir.endsWith(File.separator)) { - outdir += File.separator; - } - - ret.addAll(new AS2ScriptExporter().exportAS2ScriptsTimeout(handler, outdir, getASMs(true), exportSettings, evl)); - return ret; - } - - private List exportActionScript3(final AbortRetryIgnoreHandler handler, final String outdir, final ScriptExportSettings exportSettings, final boolean parallel, final EventListener evl) { - final AtomicInteger cnt = new AtomicInteger(1); - - final List ret = new ArrayList<>(); - final List packs = getAS3Packs(); - - if (!parallel || packs.size() < 2) { - try { - CancellableWorker.call(new Callable() { - @Override - public Void call() throws Exception { - for (ScriptPack item : packs) { - ExportPackTask task = new ExportPackTask(handler, cnt, packs.size(), item.getClassPath(), item, outdir, exportSettings, parallel, evl); - ret.add(task.call()); - } - return null; - } - }, Configuration.exportTimeout.get(), TimeUnit.SECONDS); - } catch (TimeoutException ex) { - logger.log(Level.SEVERE, Helper.formatTimeToText(Configuration.exportTimeout.get()) + " ActionScript export limit reached", ex); - } catch (Exception ex) { - logger.log(Level.SEVERE, "Error during ABC export", ex); - } - } else { - ExecutorService executor = Executors.newFixedThreadPool(Configuration.getParallelThreadCount()); - List> futureResults = new ArrayList<>(); - for (ScriptPack item : packs) { - Future future = executor.submit(new ExportPackTask(handler, cnt, packs.size(), item.getClassPath(), item, outdir, exportSettings, parallel, evl)); - futureResults.add(future); - } - - try { - executor.shutdown(); - if (!executor.awaitTermination(Configuration.exportTimeout.get(), TimeUnit.SECONDS)) { - logger.log(Level.SEVERE, Helper.formatTimeToText(Configuration.exportTimeout.get()) + " ActionScript export limit reached"); - } - } catch (InterruptedException ex) { - } finally { - executor.shutdownNow(); - } - - for (int f = 0; f < futureResults.size(); f++) { - try { - if (futureResults.get(f).isDone()) { - ret.add(futureResults.get(f).get()); - } - } catch (InterruptedException ex) { - } catch (ExecutionException ex) { - logger.log(Level.SEVERE, "Error during ABC export", ex); - } - } - } - - return ret; - } - public EventListener getExportEventListener() { EventListener evl = new EventListener() { @Override @@ -1363,9 +1225,9 @@ public final class SWF implements SWFContainerItem, Timelined { List ret = new ArrayList<>(); if (isAS3()) { - ret.addAll(exportActionScript3(handler, outdir, exportSettings, parallel, evl)); + ret.addAll(new AS3ScriptExporter().exportActionScript3(this, handler, outdir, exportSettings, parallel, evl)); } else { - ret.addAll(exportActionScript2(handler, outdir, exportSettings, parallel, evl)); + ret.addAll(new AS2ScriptExporter().exportAS2ScriptsTimeout(handler, outdir, getASMs(true), exportSettings, evl)); } return ret; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/TextExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/TextExporter.java index a69faa124..e74fb0a50 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/TextExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/TextExporter.java @@ -43,8 +43,6 @@ import java.util.List; */ public class TextExporter { - public static final String TEXT_EXPORT_FOLDER = "texts"; - public static final String TEXT_EXPORT_FILENAME_FORMATTED = "textsformatted.txt"; public static final String TEXT_EXPORT_FILENAME_PLAIN = "textsplain.txt"; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/AS2ScriptExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/AS2ScriptExporter.java index a0fa961b1..3fad0d23e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/AS2ScriptExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/AS2ScriptExporter.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.exporters.script; import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler; import com.jpexs.decompiler.flash.EventListener; +import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; @@ -51,6 +52,10 @@ public class AS2ScriptExporter { private static final Logger logger = Logger.getLogger(AS2ScriptExporter.class.getName()); + public List exportActionScript2(SWF swf, AbortRetryIgnoreHandler handler, String outdir, ScriptExportSettings exportSettings, boolean parallel, EventListener evl) throws IOException { + return exportAS2ScriptsTimeout(handler, outdir, swf.getASMs(true), exportSettings, evl); + } + public List exportAS2ScriptsTimeout(final AbortRetryIgnoreHandler handler, final String outdir, final Map asms, final ScriptExportSettings exportSettings, final EventListener evl) throws IOException { try { List result = CancellableWorker.call(new Callable>() { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/AS3ScriptExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/AS3ScriptExporter.java new file mode 100644 index 000000000..6f8a86c5a --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/AS3ScriptExporter.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.exporters.script; + +import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler; +import com.jpexs.decompiler.flash.EventListener; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.abc.ScriptPack; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.exporters.settings.ScriptExportSettings; +import com.jpexs.helpers.CancellableWorker; +import com.jpexs.helpers.Helper; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author JPEXS + */ +public class AS3ScriptExporter { + + private static final Logger logger = Logger.getLogger(AS3ScriptExporter.class.getName()); + + public List exportActionScript3(SWF swf, final AbortRetryIgnoreHandler handler, final String outdir, final ScriptExportSettings exportSettings, final boolean parallel, final EventListener evl) { + final AtomicInteger cnt = new AtomicInteger(1); + + final List ret = new ArrayList<>(); + final List packs = swf.getAS3Packs(); + + if (!parallel || packs.size() < 2) { + try { + CancellableWorker.call(new Callable() { + @Override + public Void call() throws Exception { + for (ScriptPack item : packs) { + ExportPackTask task = new ExportPackTask(handler, cnt, packs.size(), item.getClassPath(), item, outdir, exportSettings, parallel, evl); + ret.add(task.call()); + } + return null; + } + }, Configuration.exportTimeout.get(), TimeUnit.SECONDS); + } catch (TimeoutException ex) { + logger.log(Level.SEVERE, Helper.formatTimeToText(Configuration.exportTimeout.get()) + " ActionScript export limit reached", ex); + } catch (Exception ex) { + logger.log(Level.SEVERE, "Error during ABC export", ex); + } + } else { + ExecutorService executor = Executors.newFixedThreadPool(Configuration.getParallelThreadCount()); + List> futureResults = new ArrayList<>(); + for (ScriptPack item : packs) { + Future future = executor.submit(new ExportPackTask(handler, cnt, packs.size(), item.getClassPath(), item, outdir, exportSettings, parallel, evl)); + futureResults.add(future); + } + + try { + executor.shutdown(); + if (!executor.awaitTermination(Configuration.exportTimeout.get(), TimeUnit.SECONDS)) { + logger.log(Level.SEVERE, Helper.formatTimeToText(Configuration.exportTimeout.get()) + " ActionScript export limit reached"); + } + } catch (InterruptedException ex) { + } finally { + executor.shutdownNow(); + } + + for (int f = 0; f < futureResults.size(); f++) { + try { + if (futureResults.get(f).isDone()) { + ret.add(futureResults.get(f).get()); + } + } catch (InterruptedException ex) { + } catch (ExecutionException ex) { + logger.log(Level.SEVERE, "Error during ABC export", ex); + } + } + } + + return ret; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/ExportPackTask.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/ExportPackTask.java new file mode 100644 index 000000000..e4898be16 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/ExportPackTask.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.exporters.script; + +import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler; +import com.jpexs.decompiler.flash.EventListener; +import com.jpexs.decompiler.flash.RetryTask; +import com.jpexs.decompiler.flash.RunnableIOExResult; +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.ClassPath; +import com.jpexs.decompiler.flash.abc.ScriptPack; +import com.jpexs.decompiler.flash.exporters.settings.ScriptExportSettings; +import com.jpexs.helpers.Helper; +import java.io.File; +import java.io.IOException; +import java.util.concurrent.Callable; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * + * @author JPEXS + */ +public class ExportPackTask implements Callable { + + ScriptPack pack; + + String directory; + + ScriptExportSettings exportSettings; + + ClassPath path; + + AtomicInteger index; + + int count; + + boolean parallel; + + AbortRetryIgnoreHandler handler; + + long startTime; + + long stopTime; + + EventListener eventListener; + + public ExportPackTask(AbortRetryIgnoreHandler handler, AtomicInteger index, int count, ClassPath path, ScriptPack pack, String directory, ScriptExportSettings exportSettings, boolean parallel, EventListener evl) { + this.pack = pack; + this.directory = directory; + this.exportSettings = exportSettings; + this.path = path; + this.index = index; + this.count = count; + this.parallel = parallel; + this.handler = handler; + this.eventListener = evl; + } + + @Override + public File call() throws Exception { + RunnableIOExResult rio = new RunnableIOExResult() { + @Override + public void run() throws IOException { + startTime = System.currentTimeMillis(); + this.result = pack.export(directory, exportSettings, parallel); + stopTime = System.currentTimeMillis(); + } + }; + int currentIndex = index.getAndIncrement(); + if (eventListener != null) { + synchronized (ABC.class) { + eventListener.handleExportingEvent("script", currentIndex, count, path); + } + } + new RetryTask(rio, handler).run(); + if (eventListener != null) { + synchronized (ABC.class) { + long time = stopTime - startTime; + eventListener.handleExportedEvent("script", currentIndex, count, path + ", " + Helper.formatTimeSec(time)); + } + } + return rio.result; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/settings/ScriptExportSettings.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/settings/ScriptExportSettings.java index d3b5c7bd7..adc967174 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/settings/ScriptExportSettings.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/settings/ScriptExportSettings.java @@ -25,6 +25,8 @@ import com.jpexs.decompiler.flash.helpers.FileTextWriter; */ public class ScriptExportSettings { + public static final String EXPORT_FOLDER_NAME = "scripts"; + public ScriptExportMode mode; public boolean singleFile; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/settings/TextExportSettings.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/settings/TextExportSettings.java index df7aca902..eac51a037 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/settings/TextExportSettings.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/settings/TextExportSettings.java @@ -24,6 +24,8 @@ import com.jpexs.decompiler.flash.exporters.modes.TextExportMode; */ public class TextExportSettings { + public static final String EXPORT_FOLDER_NAME = "texts"; + public TextExportMode mode; public boolean singleFile; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/ScriptImporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/ScriptImporter.java new file mode 100644 index 000000000..c318c2150 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/ScriptImporter.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.importers; + +import com.jpexs.decompiler.flash.action.parser.ActionParseException; +import com.jpexs.decompiler.flash.tags.base.ASMSource; +import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.helpers.Helper; +import com.jpexs.helpers.Path; +import java.io.File; +import java.io.IOException; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author JPEXS + */ +public class ScriptImporter { + + private static final Logger logger = Logger.getLogger(ScriptImporter.class.getName()); + + public void importScripts(String scriptsFolder, Map asms) { + + for (String key : asms.keySet()) { + String fileName = Path.combine(scriptsFolder, key) + ".as"; + if (new File(fileName).exists()) { + ASMSource src = asms.get(key); + String as = Helper.readTextFile(fileName); + + com.jpexs.decompiler.flash.action.parser.script.ActionScriptParser par = new com.jpexs.decompiler.flash.action.parser.script.ActionScriptParser(src.getSwf().version); + try { + src.setActions(par.actionsFromString(as)); + } catch (ActionParseException ex) { + logger.log(Level.SEVERE, "%error% on line %line%, file: %file%".replace("%error%", ex.text).replace("%line%", Long.toString(ex.line)).replace("%file%", fileName), ex); + } catch (CompilationException ex) { + logger.log(Level.SEVERE, "%error% on line %line%, file: %file%".replace("%error%", ex.text).replace("%line%", Long.toString(ex.line)).replace("%file%", fileName), ex); + } catch (IOException ex) { + logger.log(Level.SEVERE, "error during script import, file: %file%".replace("%file%", fileName), ex); + } + + src.setModified(); + } + } + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/TextImporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/TextImporter.java index bc888a41f..2e57ea0c1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/TextImporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/TextImporter.java @@ -18,7 +18,7 @@ package com.jpexs.decompiler.flash.importers; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.exporters.TextExporter; +import com.jpexs.decompiler.flash.exporters.settings.TextExportSettings; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.MissingCharacterHandler; import com.jpexs.decompiler.flash.tags.base.TextImportErrorHandler; @@ -111,7 +111,7 @@ public class TextImporter { } public void importTextsMultipleFiles(String folder, SWF swf) { - File textsFolder = new File(Path.combine(folder, TextExporter.TEXT_EXPORT_FOLDER)); + File textsFolder = new File(Path.combine(folder, TextExportSettings.EXPORT_FOLDER_NAME)); String[] files = textsFolder.list(new FilenameFilter() { private final Pattern pat = Pattern.compile("\\d+\\.txt", Pattern.CASE_INSENSITIVE); diff --git a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java index 2613a2314..7aa7e193f 100644 --- a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java +++ b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java @@ -1041,7 +1041,7 @@ public class CommandLineArgumentParser { if (singleTextFile == null) { singleTextFile = Configuration.textExportSingleFile.get(); } - new TextExporter().exportTexts(handler, outDir + (multipleExportTypes ? File.separator + "texts" : ""), extags, new TextExportSettings(enumFromStr(formats.get("text"), TextExportMode.class), singleTextFile, zoom), evl); + new TextExporter().exportTexts(handler, outDir + (multipleExportTypes ? File.separator + TextExportSettings.EXPORT_FOLDER_NAME : ""), extags, new TextExportSettings(enumFromStr(formats.get("text"), TextExportMode.class), singleTextFile, zoom), evl); } if (exportAll || exportFormats.contains("frame")) { @@ -1056,7 +1056,7 @@ public class CommandLineArgumentParser { } boolean parallel = Configuration.parallelSpeedUp.get(); - String scriptsFolder = Path.combine(outDir, "scripts"); + String scriptsFolder = Path.combine(outDir, ScriptExportSettings.EXPORT_FOLDER_NAME); Path.createDirectorySafe(new File(scriptsFolder)); Boolean singleScriptFile = parseBooleanConfigValue(formats.get("singlescript")); if (singleScriptFile == null) { diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java b/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java index 888d29dec..da952343b 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java @@ -162,6 +162,10 @@ public abstract class MainFrameMenu { mainFrame.getPanel().importText(swf); } + protected void importScript() { + mainFrame.getPanel().importScript(swf); + } + protected void importSymbolClass() { mainFrame.getPanel().importSymbolClass(swf); } diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java index ae601f3ce..cf96079f3 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java @@ -139,6 +139,8 @@ public class MainFrameRibbonMenu extends MainFrameMenu implements ActionListener private static final String ACTION_IMPORT_TEXT = "IMPORTTEXT"; + private static final String ACTION_IMPORT_SCRIPT = "IMPORTSCRIPT"; + private static final String ACTION_IMPORT_SYMBOL_CLASS = "IMPORTSYMBOLCLASS"; private static final String ACTION_CHECK_UPDATES = "CHECKUPDATES"; @@ -199,6 +201,8 @@ public class MainFrameRibbonMenu extends MainFrameMenu implements ActionListener private JCommandButton importTextCommandButton; + private JCommandButton importScriptCommandButton; + private JCommandButton importSymbolClassCommandButton; private JCommandButton importXmlCommandButton; @@ -448,6 +452,10 @@ public class MainFrameRibbonMenu extends MainFrameMenu implements ActionListener importTextCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.import.text")), View.getResizableIcon("importtext32")); assignListener(importTextCommandButton, ACTION_IMPORT_TEXT); + // todo: icon + importScriptCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.import.script")), View.getResizableIcon("importtext32")); + assignListener(importScriptCommandButton, ACTION_IMPORT_SCRIPT); + importSymbolClassCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.import.symbolClass")), View.getResizableIcon("importsymbolclass32")); assignListener(importSymbolClassCommandButton, ACTION_IMPORT_SYMBOL_CLASS); @@ -456,6 +464,7 @@ public class MainFrameRibbonMenu extends MainFrameMenu implements ActionListener importBand.addCommandButton(importXmlCommandButton, RibbonElementPriority.TOP); importBand.addCommandButton(importTextCommandButton, RibbonElementPriority.MEDIUM); + importBand.addCommandButton(importScriptCommandButton, RibbonElementPriority.MEDIUM); importBand.addCommandButton(importSymbolClassCommandButton, RibbonElementPriority.MEDIUM); JRibbonBand viewBand = new JRibbonBand(translate("menu.view"), null); @@ -782,6 +791,7 @@ public class MainFrameRibbonMenu extends MainFrameMenu implements ActionListener exportXmlCommandButton.setEnabled(swfLoaded); exportSelectionCommandButton.setEnabled(swfLoaded); importTextCommandButton.setEnabled(swfLoaded); + importScriptCommandButton.setEnabled(swfLoaded); importSymbolClassCommandButton.setEnabled(swfLoaded); importXmlCommandButton.setEnabled(swfLoaded); reloadCommandButton.setEnabled(swfLoaded); @@ -994,6 +1004,9 @@ public class MainFrameRibbonMenu extends MainFrameMenu implements ActionListener case ACTION_IMPORT_TEXT: importText(); break; + case ACTION_IMPORT_SCRIPT: + importScript(); + break; case ACTION_IMPORT_SYMBOL_CLASS: importSymbolClass(); break; diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index 9c2e9a1cb..d549db92c 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -80,6 +80,7 @@ import com.jpexs.decompiler.flash.helpers.FileTextWriter; import com.jpexs.decompiler.flash.helpers.Freed; import com.jpexs.decompiler.flash.importers.BinaryDataImporter; import com.jpexs.decompiler.flash.importers.ImageImporter; +import com.jpexs.decompiler.flash.importers.ScriptImporter; import com.jpexs.decompiler.flash.importers.ShapeImporter; import com.jpexs.decompiler.flash.importers.SwfXmlImporter; import com.jpexs.decompiler.flash.importers.SymbolClassImporter; @@ -1090,7 +1091,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec new ShapeExportSettings(export.getValue(ShapeExportMode.class), export.getZoom()), evl)); ret.addAll(new MorphShapeExporter().exportMorphShapes(handler, selFile + File.separator + "morphshapes", morphshapes, new MorphShapeExportSettings(export.getValue(MorphShapeExportMode.class), export.getZoom()), evl)); - ret.addAll(new TextExporter().exportTexts(handler, selFile + File.separator + "texts", texts, + ret.addAll(new TextExporter().exportTexts(handler, selFile + File.separator + TextExportSettings.EXPORT_FOLDER_NAME, texts, new TextExportSettings(export.getValue(TextExportMode.class), Configuration.textExportSingleFile.get(), export.getZoom()), evl)); ret.addAll(new MovieExporter().exportMovies(handler, selFile + File.separator + "movies", movies, new MovieExportSettings(export.getValue(MovieExportMode.class)), evl)); @@ -1120,7 +1121,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec } boolean parallel = Configuration.parallelSpeedUp.get(); - String scriptsFolder = Path.combine(selFile, "scripts"); + String scriptsFolder = Path.combine(selFile, ScriptExportSettings.EXPORT_FOLDER_NAME); Path.createDirectorySafe(new File(scriptsFolder)); ScriptExportSettings scriptExportSettings = new ScriptExportSettings(export.getValue(ScriptExportMode.class), !parallel && Configuration.scriptExportSingleFile.get()); String singleFileName = Path.combine(scriptsFolder, swf.getShortFileName() + scriptExportSettings.getFileExtension()); @@ -1152,7 +1153,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec new ShapeExportSettings(export.getValue(ShapeExportMode.class), export.getZoom()), evl); new MorphShapeExporter().exportMorphShapes(handler, selFile + File.separator + "morphshapes", swf.tags, new MorphShapeExportSettings(export.getValue(MorphShapeExportMode.class), export.getZoom()), evl); - new TextExporter().exportTexts(handler, selFile + File.separator + "texts", swf.tags, + new TextExporter().exportTexts(handler, selFile + File.separator + TextExportSettings.EXPORT_FOLDER_NAME, swf.tags, new TextExportSettings(export.getValue(TextExportMode.class), Configuration.textExportSingleFile.get(), export.getZoom()), evl); new MovieExporter().exportMovies(handler, selFile + File.separator + "movies", swf.tags, new MovieExportSettings(export.getValue(MovieExportMode.class)), evl); @@ -1174,7 +1175,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec } boolean parallel = Configuration.parallelSpeedUp.get(); - String scriptsFolder = Path.combine(selFile, "scripts"); + String scriptsFolder = Path.combine(selFile, ScriptExportSettings.EXPORT_FOLDER_NAME); Path.createDirectorySafe(new File(scriptsFolder)); ScriptExportSettings scriptExportSettings = new ScriptExportSettings(export.getValue(ScriptExportMode.class), !parallel && Configuration.scriptExportSingleFile.get()); String singleFileName = Path.combine(scriptsFolder, swf.getShortFileName() + scriptExportSettings.getFileExtension()); @@ -1629,7 +1630,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec chooser.setAcceptAllFileFilterUsed(false); if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { String selFile = Helper.fixDialogFile(chooser.getSelectedFile()).getAbsolutePath(); - File textsFile = new File(Path.combine(selFile, TextExporter.TEXT_EXPORT_FOLDER, TextExporter.TEXT_EXPORT_FILENAME_FORMATTED)); + File textsFile = new File(Path.combine(selFile, TextExportSettings.EXPORT_FOLDER_NAME, TextExporter.TEXT_EXPORT_FILENAME_FORMATTED)); TextImporter textImporter = new TextImporter(getMissingCharacterHandler(), new TextImportErrorHandler() { // "configuration items" for the current replace only @@ -1665,7 +1666,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec if (textsFile.exists()) { textImporter.importTextsSingleFileFormatted(textsFile, swf); } else { - textsFile = new File(Path.combine(selFile, TextExporter.TEXT_EXPORT_FOLDER, TextExporter.TEXT_EXPORT_FILENAME_PLAIN)); + textsFile = new File(Path.combine(selFile, TextExportSettings.EXPORT_FOLDER_NAME, TextExporter.TEXT_EXPORT_FILENAME_PLAIN)); // try to import plain texts if (textsFile.exists()) { textImporter.importTextsSingleFile(textsFile, swf); @@ -1679,6 +1680,22 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec } } + public void importScript(final SWF swf) { + JFileChooser chooser = new JFileChooser(); + chooser.setCurrentDirectory(new File(Configuration.lastExportDir.get())); + chooser.setDialogTitle(translate("import.select.directory")); + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + chooser.setAcceptAllFileFilterUsed(false); + if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { + String selFile = Helper.fixDialogFile(chooser.getSelectedFile()).getAbsolutePath(); + String scriptsFolder = Path.combine(selFile, ScriptExportSettings.EXPORT_FOLDER_NAME); + + new ScriptImporter().importScripts(scriptsFolder, swf.getASMs(true)); + + reload(true); + } + } + public void importSymbolClass(final SWF swf) { JFileChooser chooser = new JFileChooser(); chooser.setCurrentDirectory(new File(Configuration.lastExportDir.get())); diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index cca6578b3..0d4fb8849 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -580,3 +580,4 @@ text.toggleCase = Toggle case #after version 5.0.2 preview.loop = Loop +menu.file.import.script = Import script diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties index 79bcadaec..e105c1e43 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties @@ -579,3 +579,4 @@ text.toggleCase = Kis- nagybet\u0171 v\u00e1ltoztat\u00e1s #after version 5.0.2 preview.loop = Ism\u00e9tl\u00e9s +menu.file.import.script = Szkript import\u00e1l\u00e1sa