mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-05 06:44:52 +00:00
380 lines
14 KiB
Java
380 lines
14 KiB
Java
/*
|
|
* Copyright (C) 2010-2014 JPEXS
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
package com.jpexs.decompiler.flash.gui.player;
|
|
|
|
import com.jpexs.decompiler.flash.gui.AppStrings;
|
|
import com.jpexs.decompiler.flash.gui.View;
|
|
import java.awt.BorderLayout;
|
|
import java.awt.Color;
|
|
import java.awt.Dimension;
|
|
import java.awt.FlowLayout;
|
|
import java.awt.Image;
|
|
import java.awt.Insets;
|
|
import java.awt.Toolkit;
|
|
import java.awt.datatransfer.Clipboard;
|
|
import java.awt.datatransfer.ClipboardOwner;
|
|
import java.awt.datatransfer.DataFlavor;
|
|
import java.awt.datatransfer.Transferable;
|
|
import java.awt.datatransfer.UnsupportedFlavorException;
|
|
import java.awt.event.ActionEvent;
|
|
import java.awt.event.ActionListener;
|
|
import java.awt.event.MouseAdapter;
|
|
import java.awt.event.MouseEvent;
|
|
import java.awt.image.BufferedImage;
|
|
import java.io.IOException;
|
|
import java.math.BigDecimal;
|
|
import java.util.Timer;
|
|
import java.util.TimerTask;
|
|
import javax.swing.BoxLayout;
|
|
import javax.swing.Icon;
|
|
import javax.swing.JButton;
|
|
import javax.swing.JColorChooser;
|
|
import javax.swing.JLabel;
|
|
import javax.swing.JPanel;
|
|
import javax.swing.JProgressBar;
|
|
|
|
/**
|
|
*
|
|
* @author JPEXS
|
|
*/
|
|
public class PlayerControls extends JPanel implements ActionListener {
|
|
|
|
static final String ACTION_PAUSE = "PAUSE";
|
|
static final String ACTION_STOP = "STOP";
|
|
static final String ACTION_SELECT_BKCOLOR = "SELECTCOLOR";
|
|
static final String ACTION_ZOOMIN = "ZOOMIN";
|
|
static final String ACTION_ZOOMOUT = "ZOOMOUT";
|
|
static final String ACTION_ZOOMFIT = "ZOOMFIT";
|
|
static final String ACTION_ZOOMNONE = "ZOOMNONE";
|
|
static final String ACTION_SNAPSHOT = "SNAPSHOT";
|
|
|
|
private final JButton pauseButton;
|
|
private boolean paused = false;
|
|
private MediaDisplay display;
|
|
private JProgressBar progress;
|
|
private final Timer timer;
|
|
private final JLabel timeLabel;
|
|
private final JLabel totalTimeLabel;
|
|
private static final Icon pauseIcon = View.getIcon("pause16");
|
|
private static final Icon playIcon = View.getIcon("play16");
|
|
|
|
private final JLabel percentLabel = new JLabel("100%");
|
|
private final JPanel zoomPanel;
|
|
private final JPanel graphicControls;
|
|
private final JPanel playbackControls;
|
|
private double realZoom = 1.0;
|
|
|
|
private final JButton zoomFitButton;
|
|
|
|
public static final int ZOOM_DECADE_STEPS = 10;
|
|
public static final double ZOOM_MULTIPLIER = Math.pow(10, 1.0 / ZOOM_DECADE_STEPS);
|
|
|
|
public PlayerControls(MediaDisplay display) {
|
|
|
|
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
|
|
|
graphicControls = new JPanel(new BorderLayout());
|
|
JPanel graphicButtonsPanel = new JPanel(new FlowLayout());
|
|
JButton selectColorButton = new JButton(View.getIcon("color16"));
|
|
selectColorButton.addActionListener(this);
|
|
selectColorButton.setActionCommand(ACTION_SELECT_BKCOLOR);
|
|
selectColorButton.setToolTipText(AppStrings.translate("button.selectbkcolor.hint"));
|
|
|
|
JButton zoomInButton = new JButton(View.getIcon("zoomin16"));
|
|
zoomInButton.addActionListener(this);
|
|
zoomInButton.setActionCommand(ACTION_ZOOMIN);
|
|
zoomInButton.setToolTipText(AppStrings.translate("button.zoomin.hint"));
|
|
|
|
JButton zoomOutButton = new JButton(View.getIcon("zoomout16"));
|
|
zoomOutButton.addActionListener(this);
|
|
zoomOutButton.setActionCommand(ACTION_ZOOMOUT);
|
|
zoomOutButton.setToolTipText(AppStrings.translate("button.zoomout.hint"));
|
|
|
|
zoomFitButton = new JButton(View.getIcon("zoomfit16"));
|
|
zoomFitButton.addActionListener(this);
|
|
zoomFitButton.setActionCommand(ACTION_ZOOMFIT);
|
|
zoomFitButton.setToolTipText(AppStrings.translate("button.zoomfit.hint"));
|
|
|
|
JButton zoomNoneButton = new JButton(View.getIcon("zoomnone16"));
|
|
zoomNoneButton.addActionListener(this);
|
|
zoomNoneButton.setActionCommand(ACTION_ZOOMNONE);
|
|
zoomNoneButton.setToolTipText(AppStrings.translate("button.zoomnone.hint"));
|
|
|
|
JButton snapshotButton = new JButton(View.getIcon("snapshot16"));
|
|
snapshotButton.addActionListener(this);
|
|
snapshotButton.setActionCommand(ACTION_SNAPSHOT);
|
|
snapshotButton.setToolTipText(AppStrings.translate("button.snapshot.hint"));
|
|
|
|
zoomPanel = new JPanel(new FlowLayout());
|
|
//updateZoom();
|
|
zoomPanel.add(percentLabel);
|
|
zoomPanel.add(zoomInButton);
|
|
zoomPanel.add(zoomOutButton);
|
|
zoomPanel.add(zoomNoneButton);
|
|
zoomPanel.add(zoomFitButton);
|
|
zoomPanel.add(selectColorButton);
|
|
graphicButtonsPanel.add(zoomPanel);
|
|
graphicButtonsPanel.add(snapshotButton);
|
|
graphicControls.add(graphicButtonsPanel,BorderLayout.EAST);
|
|
|
|
add(graphicControls);
|
|
graphicControls.setVisible(display.screenAvailable());
|
|
|
|
playbackControls = new JPanel();
|
|
this.display = display;
|
|
JPanel controlPanel = new JPanel(new BorderLayout());
|
|
timeLabel = new JLabel("00:00.00");
|
|
totalTimeLabel = new JLabel("00:00.00");
|
|
controlPanel.add(timeLabel, BorderLayout.WEST);
|
|
controlPanel.add(totalTimeLabel, BorderLayout.EAST);
|
|
playbackControls.setLayout(new BoxLayout(playbackControls, BoxLayout.Y_AXIS));
|
|
JPanel buttonsPanel = new JPanel(new FlowLayout());
|
|
|
|
pauseButton = new JButton(AppStrings.translate("preview.pause"), pauseIcon);
|
|
pauseButton.setMargin(new Insets(0, 0, 0, 0));
|
|
pauseButton.setActionCommand(ACTION_PAUSE);
|
|
pauseButton.addActionListener(this);
|
|
JButton stopButton = new JButton(AppStrings.translate("preview.stop"), View.getIcon("stop16"));
|
|
stopButton.setMargin(new Insets(0, 0, 0, 0));
|
|
stopButton.setActionCommand(ACTION_STOP);
|
|
stopButton.addActionListener(this);
|
|
buttonsPanel.add(pauseButton);
|
|
buttonsPanel.add(stopButton);
|
|
controlPanel.add(buttonsPanel, BorderLayout.CENTER);
|
|
|
|
progress = new JProgressBar();
|
|
Dimension pref = progress.getPreferredSize();
|
|
pref.height = 20;
|
|
progress.setPreferredSize(pref);
|
|
final PlayerControls t = this;
|
|
progress.addMouseListener(new MouseAdapter() {
|
|
@Override
|
|
public void mousePressed(MouseEvent e) {
|
|
int frame = (int) Math.floor(e.getX() * t.display.getTotalFrames() / (double) progress.getWidth());
|
|
boolean p = t.display.isPlaying();
|
|
t.display.gotoFrame(frame);
|
|
if (p) {
|
|
t.display.play();
|
|
}
|
|
}
|
|
});
|
|
playbackControls.add(progress);
|
|
playbackControls.add(controlPanel);
|
|
timer = new Timer();
|
|
timer.schedule(new TimerTask() {
|
|
@Override
|
|
public void run() {
|
|
update();
|
|
}
|
|
}, 100, 100);
|
|
add(playbackControls);
|
|
}
|
|
|
|
private String formatMs(long ms) {
|
|
long s = ms / 1000;
|
|
ms %= 1000;
|
|
long m = s / 60;
|
|
s %= 60;
|
|
long h = m / 60;
|
|
m %= 60;
|
|
return "" + (h > 0 ? h + ":" : "") + pad(m) + ":" + pad(s) + "." + pad(ms / 10);
|
|
}
|
|
|
|
private String pad(long t) {
|
|
String ret = "" + t;
|
|
while (ret.length() < 2) {
|
|
ret = "0" + ret;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
public void setMedia(MediaDisplay media) {
|
|
this.display = media;
|
|
}
|
|
|
|
private void update() {
|
|
if (!display.isLoaded()) {
|
|
return;
|
|
}
|
|
|
|
View.execInEventDispatch(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
double zoom = display.getZoom();
|
|
zoomFitButton.setVisible(zoom!=0.0);
|
|
percentLabel.setVisible(zoom!=0.0);
|
|
zoomPanel.setVisible(display.zoomAvailable());
|
|
graphicControls.setVisible(display.screenAvailable());
|
|
int totalFrames = display.getTotalFrames();
|
|
int currentFrame = display.getCurrentFrame();
|
|
int frameRate = display.getFrameRate();
|
|
if (totalFrames == 0) {
|
|
progress.setIndeterminate(true);
|
|
} else {
|
|
progress.setMaximum(totalFrames - 1);
|
|
progress.setMinimum(0);
|
|
progress.setValue(currentFrame);
|
|
progress.setIndeterminate(false);
|
|
}
|
|
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);
|
|
}
|
|
if (display.isPlaying() == paused) {
|
|
paused = !paused;
|
|
|
|
if (paused) {
|
|
pauseButton.setText(AppStrings.translate("preview.play"));
|
|
pauseButton.setIcon(playIcon);
|
|
} else {
|
|
pauseButton.setText(AppStrings.translate("preview.pause"));
|
|
pauseButton.setIcon(pauseIcon);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
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, BigDecimal.ROUND_HALF_UP);
|
|
return bd.doubleValue();
|
|
}
|
|
|
|
private void updateZoom() {
|
|
double pctzoom = roundZoom(realZoom * 100, 3);
|
|
String r = "" + pctzoom;
|
|
double zoom = pctzoom / 100.0;
|
|
if (r.endsWith(".0")) {
|
|
r = r.substring(0, r.length() - 2);
|
|
}
|
|
percentLabel.setText("" + r + "%");
|
|
display.zoom(zoom);
|
|
}
|
|
|
|
@Override
|
|
public void actionPerformed(ActionEvent e) {
|
|
switch (e.getActionCommand()) {
|
|
case ACTION_PAUSE:
|
|
if (paused) {
|
|
display.play();
|
|
} else {
|
|
display.pause();
|
|
}
|
|
break;
|
|
case ACTION_STOP:
|
|
display.pause();
|
|
display.rewind();
|
|
break;
|
|
case ACTION_SELECT_BKCOLOR:
|
|
View.execInEventDispatch(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
Color newColor = JColorChooser.showDialog(null, AppStrings.translate("dialog.selectbkcolor.title"), View.swfBackgroundColor);
|
|
if (newColor != null) {
|
|
View.swfBackgroundColor = newColor;
|
|
display.setBackground(newColor);
|
|
}
|
|
}
|
|
});
|
|
break;
|
|
case ACTION_ZOOMIN:
|
|
realZoom *= ZOOM_MULTIPLIER;
|
|
updateZoom();
|
|
break;
|
|
case ACTION_ZOOMOUT:
|
|
realZoom /= ZOOM_MULTIPLIER;
|
|
updateZoom();
|
|
break;
|
|
case ACTION_ZOOMNONE:
|
|
realZoom = 1.0;
|
|
updateZoom();
|
|
break;
|
|
case ACTION_ZOOMFIT:
|
|
display.zoomToFit();
|
|
//updateZoom();
|
|
break;
|
|
case ACTION_SNAPSHOT:
|
|
putImageToClipBoard(display.printScreen());
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
private class TransferableImage implements Transferable {
|
|
|
|
Image img;
|
|
|
|
public TransferableImage(Image img) {
|
|
this.img = img;
|
|
}
|
|
|
|
@Override
|
|
public Object getTransferData(DataFlavor flavor)
|
|
throws UnsupportedFlavorException, IOException {
|
|
if (flavor.equals(DataFlavor.imageFlavor) && img != null) {
|
|
return img;
|
|
} else {
|
|
throw new UnsupportedFlavorException(flavor);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public DataFlavor[] getTransferDataFlavors() {
|
|
DataFlavor[] flavors = new DataFlavor[1];
|
|
flavors[ 0] = DataFlavor.imageFlavor;
|
|
return flavors;
|
|
}
|
|
|
|
@Override
|
|
public boolean isDataFlavorSupported(DataFlavor flavor) {
|
|
DataFlavor[] flavors = getTransferDataFlavors();
|
|
for (int i = 0; i < flavors.length; i++) {
|
|
if (flavor.equals(flavors[ i])) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private void putImageToClipBoard(BufferedImage img) {
|
|
if (img == null) {
|
|
return;
|
|
}
|
|
TransferableImage trans = new TransferableImage(img);
|
|
Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
|
|
c.setContents(trans, new ClipboardOwner() {
|
|
@Override
|
|
public void lostOwnership(Clipboard clipboard, Transferable contents) {
|
|
}
|
|
});
|
|
}
|
|
}
|