diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/PlaceObjectTypeTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/PlaceObjectTypeTag.java index 47916cf57..b93443a3a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/PlaceObjectTypeTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/PlaceObjectTypeTag.java @@ -27,6 +27,7 @@ import com.jpexs.decompiler.flash.types.RGBA; import com.jpexs.decompiler.flash.types.filters.FILTER; import com.jpexs.helpers.ByteArrayRange; import java.io.IOException; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -258,6 +259,10 @@ public abstract class PlaceObjectTypeTag extends Tag implements CharacterIdTag, @Override public Map getNameProperties() { + SWF swf = getSwf(); + if (swf == null) { + return new HashMap<>(); + } Map ret = super.getNameProperties(); int charId = getCharacterId(); String charClassName = getClassName(); diff --git a/src/com/jpexs/decompiler/flash/easygui/EasySwfPanel.java b/src/com/jpexs/decompiler/flash/easygui/EasySwfPanel.java index 2734390d1..893bd4017 100644 --- a/src/com/jpexs/decompiler/flash/easygui/EasySwfPanel.java +++ b/src/com/jpexs/decompiler/flash/easygui/EasySwfPanel.java @@ -28,6 +28,7 @@ import com.jpexs.decompiler.flash.gui.TimelinedMaker; import com.jpexs.decompiler.flash.gui.TransformPanel; import com.jpexs.decompiler.flash.gui.View; import com.jpexs.decompiler.flash.gui.controls.JPersistentSplitPane; +import com.jpexs.decompiler.flash.gui.player.ZoomPanel; import com.jpexs.decompiler.flash.tags.DefineSpriteTag; import com.jpexs.decompiler.flash.tags.PlaceObject2Tag; import com.jpexs.decompiler.flash.tags.RemoveObject2Tag; @@ -291,7 +292,7 @@ public class EasySwfPanel extends JPanel { JPanel topPanel = new JPanel(new BorderLayout()); - JPanel toolbarPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); + undoButton = new JButton(View.getIcon("rotateanticlockwise16")); //undoButton.setToolTipText("Undo"); @@ -342,9 +343,17 @@ public class EasySwfPanel extends JPanel { undoManager.addChangeListener(undoChangeListener); - toolbarPanel.add(undoButton); - toolbarPanel.add(redoButton); - + + JPanel toolbarPanel = new JPanel(new BorderLayout()); + JPanel leftToolbar = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); + leftToolbar.add(undoButton); + leftToolbar.add(redoButton); + + toolbarPanel.add(leftToolbar, BorderLayout.WEST); + + ZoomPanel zoomPanel = new ZoomPanel(stagePanel); + toolbarPanel.add(zoomPanel, BorderLayout.EAST); + topPanel.add(toolbarPanel, BorderLayout.NORTH); topPanel.add(stagePanel, BorderLayout.CENTER); diff --git a/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java b/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java index 3853fd6e2..37118fb3d 100644 --- a/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java +++ b/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java @@ -96,9 +96,9 @@ public class PlayerControls extends JPanel implements MediaDisplayListener { private static final Icon resampleIcon = View.getIcon("resample16"); - private final JLabel percentLabel = new JLabel("100%"); + //private final JLabel percentLabel = new JLabel("100%"); - private final JPanel zoomPanel; + private final ZoomPanel zoomPanel; private final JPanel graphicControls; @@ -106,11 +106,11 @@ public class PlayerControls extends JPanel implements MediaDisplayListener { private final JPanel frameControls; - private boolean zoomToFit = false; +// private boolean zoomToFit = false; - private double realZoom = 1.0; +// private double realZoom = 1.0; - private final JButton zoomFitButton; + //private final JButton zoomFitButton; private final JButton snapshotButton; @@ -134,10 +134,10 @@ public class PlayerControls extends JPanel implements MediaDisplayListener { private static Font notUnderlinedFont = null; - private final int zeroCharacterWidth; - - private final double MAX_ZOOM = 1.0e6; //in larger zooms, flash viewer stops working - + private final int zeroCharacterWidth; + + private JButton selectColorButton; + static { Font font = new JLabel().getFont(); notUnderlinedFont = font; @@ -160,41 +160,22 @@ public class PlayerControls extends JPanel implements MediaDisplayListener { graphicControls = new JPanel(new BorderLayout()); JPanel graphicButtonsPanel = new JPanel(new FlowLayout()); - JButton selectColorButton = new JButton(View.getIcon("color16")); + selectColorButton = new JButton(View.getIcon("color16")); selectColorButton.addActionListener(this::selectBkColorButtonActionPerformed); selectColorButton.setToolTipText(AppStrings.translate("button.selectbkcolor.hint")); - JButton zoomInButton = new JButton(View.getIcon("zoomin16")); - zoomInButton.addActionListener(this::zoomInButtonActionPerformed); - zoomInButton.setToolTipText(AppStrings.translate("button.zoomin.hint")); - - JButton zoomOutButton = new JButton(View.getIcon("zoomout16")); - zoomOutButton.addActionListener(this::zoomOutButtonActionPerformed); - zoomOutButton.setToolTipText(AppStrings.translate("button.zoomout.hint")); - - zoomFitButton = new JButton(View.getIcon("zoomfit16")); - zoomFitButton.addActionListener(this::zoomFitButtonActionPerformed); - zoomFitButton.setToolTipText(AppStrings.translate("button.zoomfit.hint")); - - JButton zoomNoneButton = new JButton(View.getIcon("zoomnone16")); - zoomNoneButton.addActionListener(this::zoomNoneButtonActionPerformed); - zoomNoneButton.setToolTipText(AppStrings.translate("button.zoomnone.hint")); - + zoomPanel = new ZoomPanel(display); + zoomPanel.setVisible(false); + snapshotButton = new JButton(View.getIcon("snapshot16")); snapshotButton.addActionListener(this::snapShotButtonActionPerformed); snapshotButton.setToolTipText(AppStrings.translate("button.snapshot.hint")); snapshotButton.setVisible(false); - zoomPanel = new JPanel(new FlowLayout()); - zoomPanel.add(percentLabel); - zoomPanel.add(zoomInButton); - zoomPanel.add(zoomOutButton); - zoomPanel.add(zoomNoneButton); - zoomPanel.add(zoomFitButton); - zoomPanel.add(selectColorButton); - zoomPanel.setVisible(false); + graphicButtonsPanel.add(zoomPanel); + graphicButtonsPanel.add(selectColorButton); graphicButtonsPanel.add(snapshotButton); JPanel displayButtonsPanel = new JPanel(new FlowLayout()); @@ -403,21 +384,12 @@ public class PlayerControls extends JPanel implements MediaDisplayListener { currentFrame = totalFrames; } float frameRate = display.getFrameRate(); - Zoom zoom = display.getZoom(); - zoomFitButton.setVisible(zoom != null); - percentLabel.setVisible(zoom != null); - Zoom currentZoom = new Zoom(); - currentZoom.fit = zoomToFit; - currentZoom.value = realZoom; - if (zoom != null && !Objects.equals(zoom, currentZoom)) { - zoomToFit = zoom.fit; - realZoom = zoom.value; - updateZoomDisplay(); - } + zoomPanel.update(); zoomPanel.setVisible(display.zoomAvailable()); boolean screenAvailable = display.screenAvailable(); showButton.setVisible(!display.alwaysDisplay() && screenAvailable); + selectColorButton.setVisible(screenAvailable); if (!display.alwaysDisplay()) { showButton.setSelected(display.isDisplayed()); } @@ -464,44 +436,7 @@ public class PlayerControls extends JPanel implements MediaDisplayListener { } }); - } - - private static double roundZoom(double realZoom, int mantisa) { - double l10 = Math.log10(realZoom); - int lg = (int) (-Math.floor(l10) + mantisa - 1); - if (lg < 0) { - lg = 0; - } - BigDecimal bd = new BigDecimal(String.valueOf(realZoom)).setScale(lg, RoundingMode.HALF_UP); - return bd.doubleValue(); - } - - private void updateZoomDisplay() { - double pctzoom = roundZoom(getRealZoom() * 100, 3); - String r = Double.toString(pctzoom); - if (r.endsWith(".0")) { - r = r.substring(0, r.length() - 2); - } - - r += "%"; - - if (zoomToFit) { - percentLabel.setText(AppStrings.translate("fit") + " (" + r + ")"); - } else { - percentLabel.setText(r); - } - - } - - private void updateZoom() { - updateZoomDisplay(); - double pctzoom = roundZoom(getRealZoom() * 100, 3); - double zoom = pctzoom / 100.0; - Zoom zoomObj = new Zoom(); - zoomObj.value = zoom; - zoomObj.fit = zoomToFit; - display.zoom(zoomObj); - } + } private void pauseButtonActionPerformed(ActionEvent evt) { if (display.isPlaying()) { @@ -586,33 +521,7 @@ public class PlayerControls extends JPanel implements MediaDisplayListener { } } - private void zoomInButtonActionPerformed(ActionEvent evt) { - double currentRealZoom = getRealZoom(); - if (currentRealZoom >= MAX_ZOOM) { - return; - } - realZoom = currentRealZoom * ZOOM_MULTIPLIER; - zoomToFit = false; - updateZoom(); - } - - private void zoomOutButtonActionPerformed(ActionEvent evt) { - realZoom = getRealZoom() / ZOOM_MULTIPLIER; - zoomToFit = false; - updateZoom(); - } - - private void zoomNoneButtonActionPerformed(ActionEvent evt) { - realZoom = 1.0; - zoomToFit = false; - updateZoom(); - } - - private void zoomFitButtonActionPerformed(ActionEvent evt) { - realZoom = 1.0; - zoomToFit = true; - updateZoom(); - } + private void snapShotButtonActionPerformed(ActionEvent evt) { putImageToClipBoard(display.printScreen()); @@ -640,13 +549,7 @@ public class PlayerControls extends JPanel implements MediaDisplayListener { Configuration.playFrameSounds.set(!muteButton.isSelected()); } - private double getRealZoom() { - if (zoomToFit) { - return display.getZoomToFit(); - } - - return realZoom; - } + @Override public void mediaDisplayStateChanged(MediaDisplay source) { diff --git a/src/com/jpexs/decompiler/flash/gui/player/ZoomPanel.java b/src/com/jpexs/decompiler/flash/gui/player/ZoomPanel.java new file mode 100644 index 000000000..649ffbc70 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/gui/player/ZoomPanel.java @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2024 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.gui.player; + +import com.jpexs.decompiler.flash.gui.AppStrings; +import com.jpexs.decompiler.flash.gui.View; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Objects; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; + +/** + * + * @author JPEXS + */ +public class ZoomPanel extends JPanel implements MediaDisplayListener { + + private MediaDisplay display; + private JButton zoomFitButton; + private final JLabel percentLabel = new JLabel("100%"); + private boolean zoomToFit = false; + private double realZoom = 1.0; + private final double MAX_ZOOM = 1.0e6; //in larger zooms, flash viewer stops working + + public ZoomPanel(MediaDisplay display) { + this.display = display; + JButton zoomInButton = new JButton(View.getIcon("zoomin16")); + zoomInButton.addActionListener(this::zoomInButtonActionPerformed); + zoomInButton.setToolTipText(AppStrings.translate("button.zoomin.hint")); + + JButton zoomOutButton = new JButton(View.getIcon("zoomout16")); + zoomOutButton.addActionListener(this::zoomOutButtonActionPerformed); + zoomOutButton.setToolTipText(AppStrings.translate("button.zoomout.hint")); + + zoomFitButton = new JButton(View.getIcon("zoomfit16")); + zoomFitButton.addActionListener(this::zoomFitButtonActionPerformed); + zoomFitButton.setToolTipText(AppStrings.translate("button.zoomfit.hint")); + + JButton zoomNoneButton = new JButton(View.getIcon("zoomnone16")); + zoomNoneButton.addActionListener(this::zoomNoneButtonActionPerformed); + zoomNoneButton.setToolTipText(AppStrings.translate("button.zoomnone.hint")); + + setLayout(new FlowLayout()); + add(percentLabel); + add(zoomInButton); + add(zoomOutButton); + add(zoomNoneButton); + add(zoomFitButton); + + display.addEventListener(this); + } + + private void zoomInButtonActionPerformed(ActionEvent evt) { + double currentRealZoom = getRealZoom(); + if (currentRealZoom >= MAX_ZOOM) { + return; + } + realZoom = currentRealZoom * PlayerControls.ZOOM_MULTIPLIER; + zoomToFit = false; + updateZoom(); + } + + private void zoomOutButtonActionPerformed(ActionEvent evt) { + realZoom = getRealZoom() / PlayerControls.ZOOM_MULTIPLIER; + zoomToFit = false; + updateZoom(); + } + + private void zoomNoneButtonActionPerformed(ActionEvent evt) { + realZoom = 1.0; + zoomToFit = false; + updateZoom(); + } + + private void zoomFitButtonActionPerformed(ActionEvent evt) { + realZoom = 1.0; + zoomToFit = true; + updateZoom(); + } + + private double getRealZoom() { + if (zoomToFit) { + return display.getZoomToFit(); + } + + return realZoom; + } + + private void updateZoom() { + updateZoomDisplay(); + double pctzoom = roundZoom(getRealZoom() * 100, 3); + double zoom = pctzoom / 100.0; + Zoom zoomObj = new Zoom(); + zoomObj.value = zoom; + zoomObj.fit = zoomToFit; + display.zoom(zoomObj); + } + + private void updateZoomDisplay() { + double pctzoom = roundZoom(getRealZoom() * 100, 3); + String r = Double.toString(pctzoom); + if (r.endsWith(".0")) { + r = r.substring(0, r.length() - 2); + } + + r += "%"; + + if (zoomToFit) { + percentLabel.setText(AppStrings.translate("fit") + " (" + r + ")"); + } else { + percentLabel.setText(r); + } + } + + private static double roundZoom(double realZoom, int mantisa) { + double l10 = Math.log10(realZoom); + int lg = (int) (-Math.floor(l10) + mantisa - 1); + if (lg < 0) { + lg = 0; + } + BigDecimal bd = new BigDecimal(String.valueOf(realZoom)).setScale(lg, RoundingMode.HALF_UP); + return bd.doubleValue(); + } + + public void update() { + if (!display.isLoaded()) { + return; + } + + View.execInEventDispatchLater(() -> { + Zoom zoom = display.getZoom(); + zoomFitButton.setVisible(zoom != null); + percentLabel.setVisible(zoom != null); + Zoom currentZoom = new Zoom(); + currentZoom.fit = zoomToFit; + currentZoom.value = realZoom; + if (zoom != null && !Objects.equals(zoom, currentZoom)) { + zoomToFit = zoom.fit; + realZoom = zoom.value; + updateZoomDisplay(); + } + }); + } + + public void setMedia(MediaDisplay media) { + if (this.display != null) { + this.display.removeEventListener(this); + } + + this.display = media; + this.display.addEventListener(this); + + update(); + } + + @Override + public void mediaDisplayStateChanged(MediaDisplay source) { + if (display != source) { + return; + } + + update(); + } + + @Override + public void playingFinished(MediaDisplay source) { + } + + @Override + public void statusChanged(String status) { + } +}