package gui; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSpinner; import javax.swing.SpinnerNumberModel; import javax.swing.SwingUtilities; import javax.swing.filechooser.FileFilter; import javax.swing.filechooser.FileNameExtensionFilter; import kussmaulUtils.ViewUtils; public class SaveFrame extends JFrame { private static final long serialVersionUID = 7593935847720677138L; private static SaveFrame p; private Animation animation; private ProgressDisplay d; private JSpinner widthSpinner; private JSpinner heightSpinner; private JLabel frameDelayLabel; private JSpinner frameDelaySpinner; private JFileChooser chooser; private ActionListener onStart; private ActionListener onFinish; public SaveFrame(Animation animation, ProgressDisplay d) { super("Save"); this.animation = animation; this.d = d; initializeComponents(); addActionListeners(); setLayout(new GridBagLayout()); GridBagConstraints gbc = ViewUtils.createGBC(); JPanel spinPanel = new JPanel(new GridLayout(3,2)); spinPanel.add(new JLabel("Width:")); spinPanel.add(widthSpinner); spinPanel.add(new JLabel("Height:")); spinPanel.add(heightSpinner); spinPanel.add(frameDelayLabel); spinPanel.add(frameDelaySpinner); add(spinPanel, gbc); gbc.gridy++; JLabel noteLabel = new JLabel("Filename conflicts will be resolved automatically"); noteLabel.setFont(noteLabel.getFont().deriveFont(noteLabel.getFont().getSize() - 2f)); add(noteLabel, gbc); gbc.gridy++; add(chooser, gbc); pack(); } public void initializeComponents() { widthSpinner = new JSpinner(new SpinnerNumberModel(1, 1, 99999, 100)); heightSpinner = new JSpinner(new SpinnerNumberModel(1, 1, 99999, 100)); frameDelayLabel = new JLabel("Frame delay (ms):"); frameDelaySpinner = new JSpinner(new SpinnerNumberModel(0, 0, 99999, 1)); chooser = new JFileChooser(); chooser.setDialogType(JFileChooser.SAVE_DIALOG); chooser.setAcceptAllFileFilterUsed(false); //setAnimationMode(true); // chooser.setSelectedFile(StringUtil.resolveConflictName(chooser.getSelectedFile(), "glitch", true)); } public void addActionListeners() { widthSpinner.addChangeListener(ce -> { heightSpinner.setValue(Math.round(((Integer) widthSpinner.getValue()) * (animation.getSourceHeight()/(float) animation.getSourceWidth()))); }); heightSpinner.addChangeListener(ce -> { widthSpinner.setValue(Math.round(((Integer) heightSpinner.getValue()) * (animation.getSourceWidth()/(float) animation.getSourceHeight()))); }); chooser.addActionListener(ae -> { if(ae.getActionCommand().equals(JFileChooser.APPROVE_SELECTION)) { save(); } setVisible(false); }); chooser.addPropertyChangeListener(pcl -> { if(pcl.getPropertyName().equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) { if(getFormatDesc().equals(FileFormat.ANIMATEDGIF.getDescription())) { frameDelaySpinner.setEnabled(true); frameDelaySpinner.setValue(0); frameDelayLabel.setText("Frame delay (ms):"); } else if(getFormatDesc().equals(FileFormat.MP4.getDescription())) { frameDelaySpinner.setEnabled(true); frameDelaySpinner.setValue(30); frameDelayLabel.setText("Frames/second:"); } else { frameDelaySpinner.setEnabled(false); } } }); } private String getFormatDesc() { return chooser.getFileFilter() == null ? "png" : (String) chooser.getFileFilter().getDescription(); } private String getFormatExt() { return chooser.getFileFilter() == null ? "png" : ((FileNameExtensionFilter) chooser.getFileFilter()).getExtensions()[0]; } private void setAnimationMode(boolean animationMode) { for (FileFilter f : chooser.getChoosableFileFilters()) chooser.removeChoosableFileFilter(f); if(animationMode) { for(FileFormat f : FileFormat.getAnimatedFormats()) { chooser.addChoosableFileFilter(new FileNameExtensionFilter(f.getDescription(), f.getExtension())); } } else { for(FileFormat f : FileFormat.getImageFormats()) chooser.addChoosableFileFilter(new FileNameExtensionFilter(f.getDescription(), f.getExtension())); } } private void save() { if(onStart != null) SwingUtilities.invokeLater(() -> onStart.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_FIRST, "save"))); String format = getFormatDesc().toLowerCase(); System.out.println(format); switch (format) { case "png sequence" : animation.savePNGSequence(chooser.getSelectedFile(), (Integer) widthSpinner.getValue(), d, onFinish); break; case "mp4" : animation.saveVid(chooser.getSelectedFile(), (Integer) widthSpinner.getValue(), (Integer) frameDelaySpinner.getValue(), d, onFinish); break; case "animated gif" : animation.saveGIF(chooser.getSelectedFile(), (Integer) widthSpinner.getValue(), (Integer) frameDelaySpinner.getValue(), d, onFinish); break; case "png": case "gif": case "bitmap": case "jpeg": animation.saveImage(chooser.getSelectedFile(), getFormatExt(), (Integer) widthSpinner.getValue(), d, onFinish); break; } } public static void open(Animation animation, boolean animationMode, ActionListener onStart, ProgressDisplay d, ActionListener onFinish) { if(p == null) p = new SaveFrame(animation, d); else { p.animation = animation; p.d = d; } p.widthSpinner.setValue(animation.getSourceWidth()); p.onStart = onStart; p.onFinish = onFinish; //p.chooser.putClientProperty("FileChooser.listViewBorder", BorderFactory.createEmptyBorder()); p.setLocationRelativeTo(null); p.setVisible(true); p.setAnimationMode(animationMode); } }