/* * JAME 6.2.1 * http://jame.sourceforge.net * * Copyright 2001, 2016 Andrea Medeghini * * This file is part of JAME. * * JAME is an application for creating fractals and other graphics artifacts. * * JAME 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. * * JAME 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 JAME. If not, see <http://www.gnu.org/licenses/>. * */ package net.sf.jame.twister.swing.encoder; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.AbstractAction; import javax.swing.Box; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JDialog; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JTextField; import javax.swing.WindowConstants; import javax.swing.border.CompoundBorder; import javax.swing.border.EmptyBorder; import javax.swing.border.LineBorder; import javax.swing.border.TitledBorder; import net.sf.jame.core.extension.ConfigurableExtension; import net.sf.jame.core.extension.Extension; import net.sf.jame.core.extension.ExtensionException; import net.sf.jame.core.extension.ExtensionNotFoundException; import net.sf.jame.core.swing.extension.ExtensionComboBoxModel; import net.sf.jame.core.swing.extension.ExtensionFilter; import net.sf.jame.core.swing.extension.ExtensionListCellRenderer; import net.sf.jame.core.swing.util.GUIFactory; import net.sf.jame.core.swing.util.GUIUtil; import net.sf.jame.core.util.ProgressListener; import net.sf.jame.queue.LibraryService; import net.sf.jame.queue.RenderService; import net.sf.jame.queue.RenderService.ServiceCallback; import net.sf.jame.queue.RenderServiceRegistry; import net.sf.jame.queue.encoder.EncoderHook; import net.sf.jame.queue.encoder.extension.EncoderExtensionConfig; import net.sf.jame.queue.encoder.extension.EncoderExtensionRuntime; import net.sf.jame.queue.profile.RenderProfileDataRow; import net.sf.jame.twister.swing.TwisterSwingResources; /** * @author Andrea Medeghini */ public class EncoderDialog extends JDialog { private static final Logger logger = Logger.getLogger(EncoderDialog.class.getName()); private static final long serialVersionUID = 1L; private static final String STRING_FRAME_TITLE = "encoderFrame.title"; // private static final String STRING_FRAME_WIDTH = "encoderFrame.width"; // private static final String STRING_FRAME_HEIGHT = "encoderFrame.height"; // private static final String STRING_FRAME_ICON = "encoderFrame.icon"; private final JProgressBar progressBar = new JProgressBar(0, 100); private final JFileChooser profileChooser = new JFileChooser(System.getProperty("user.home")); private final JButton profileExportButton = GUIFactory.createButton(new ExportAction(), TwisterSwingResources.getInstance().getString("tooltip.export")); private final JButton chooseButton = GUIFactory.createButton(new ChooseAction(), TwisterSwingResources.getInstance().getString("tooltip.choose")); private final JButton cancelButton = GUIFactory.createButton(new CancelAction(), TwisterSwingResources.getInstance().getString("tooltip.cancel")); private final JButton closeButton = GUIFactory.createButton(new CloseAction(), TwisterSwingResources.getInstance().getString("tooltip.close")); private final JTextField pathTextField = GUIFactory.createTextField((String) null, TwisterSwingResources.getInstance().getString("tooltip.path")); private final ExtensionComboBoxModel model; private RenderProfileDataRow profile; private boolean isInterrupted; private final RenderService service; private final JComboBox combobox; /** * @param frame * @param service * @param profile */ public EncoderDialog(final JFrame frame, final RenderService service) { super(frame); this.service = service; setResizable(true); setUndecorated(false); // setCursor(new Cursor(Cursor.HAND_CURSOR)); setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE); setTitle(TwisterSwingResources.getInstance().getString(EncoderDialog.STRING_FRAME_TITLE)); // final Rectangle bounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds(); // final int width = Math.min(Integer.parseInt(ServiceResources.getInstance().getString(EncoderDialog.STRING_FRAME_WIDTH)), bounds.width); // final int height = Math.min(Integer.parseInt(ServiceResources.getInstance().getString(EncoderDialog.STRING_FRAME_HEIGHT)), bounds.height); final JPanel filePanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); final JPanel encoderPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); final JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); final Dimension textFieldSize = new Dimension(300, 24); pathTextField.setPreferredSize(textFieldSize); pathTextField.setMinimumSize(textFieldSize); pathTextField.setMaximumSize(textFieldSize); encoderPanel.setBorder(new TitledBorder(new EmptyBorder(0, 0, 0, 0), TwisterSwingResources.getInstance().getString("label.encoder"))); filePanel.setBorder(new TitledBorder(new EmptyBorder(0, 0, 0, 0), TwisterSwingResources.getInstance().getString("label.path"))); model = new ExtensionComboBoxModel(RenderServiceRegistry.getInstance().getEncoderRegistry(), false); combobox = GUIFactory.createComboBox(model, TwisterSwingResources.getInstance().getString("tooltip.encoder")); combobox.setRenderer(new ExtensionListCellRenderer()); encoderPanel.add(combobox); buttonsPanel.add(profileExportButton); buttonsPanel.add(closeButton); filePanel.add(pathTextField); filePanel.add(chooseButton); final Box panel = Box.createVerticalBox(); profileChooser.setMultiSelectionEnabled(false); panel.setBorder(new EmptyBorder(8, 8, 8, 8)); panel.add(encoderPanel); panel.add(Box.createVerticalStrut(8)); panel.add(filePanel); panel.add(Box.createVerticalStrut(8)); panel.add(buttonsPanel); getContentPane().setLayout(new BorderLayout()); getContentPane().add(panel); pack(); } /** * @param profile */ @SuppressWarnings("unchecked") public void setProfile(final RenderProfileDataRow profile) { this.profile = profile; model.reload(RenderServiceRegistry.getInstance().getEncoderRegistry(), new ExtensionFilter() { /** * @see net.sf.jame.core.swing.extension.ExtensionFilter#accept(net.sf.jame.core.extension.Extension) */ public boolean accept(final Extension<?> extension) { try { if ((profile.getTotalFrames() > 0) && ((EncoderExtensionRuntime<?>) extension.createExtensionRuntime()).isMovieSupported()) { return true; } if ((profile.getTotalFrames() == 0) && ((EncoderExtensionRuntime<?>) extension.createExtensionRuntime()).isImageSupported()) { return true; } } catch (final ExtensionException e) { e.printStackTrace(); } return false; } }); if ((pathTextField.getText() != null) && (pathTextField.getText().trim().length() > 0)) { try { final Extension<EncoderExtensionRuntime> extension = (Extension<EncoderExtensionRuntime>) model.getRegistry().getExtension("service.encoder" + pathTextField.getText().substring(pathTextField.getText().indexOf("."))); model.setSelectedItemByExtensionId(extension.getExtensionId()); } catch (final ExtensionNotFoundException e) { if (profile.getTotalFrames() == 0) { model.setSelectedItemByExtensionId("service.encoder.tiff"); } else { model.setSelectedItemByExtensionId("service.encoder.mpeg4"); } } } else { if (profile.getTotalFrames() == 0) { model.setSelectedItemByExtensionId("service.encoder.tiff"); } else { model.setSelectedItemByExtensionId("service.encoder.mpeg4"); } } } private class ExportAction extends AbstractAction { private static final long serialVersionUID = 1L; /** * */ public ExportAction() { super(TwisterSwingResources.getInstance().getString("action.export")); } /** * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ public void actionPerformed(final ActionEvent e) { if ((pathTextField.getText() != null) && (pathTextField.getText().trim().length() == 0)) { JOptionPane.showMessageDialog(EncoderDialog.this, TwisterSwingResources.getInstance().getString("message.missingFile"), TwisterSwingResources.getInstance().getString("label.exportProfile"), JOptionPane.WARNING_MESSAGE); } else { final File file = new File(pathTextField.getText()); if (file.exists()) { if (JOptionPane.showConfirmDialog(EncoderDialog.this, TwisterSwingResources.getInstance().getString("message.confirmOverwrite"), TwisterSwingResources.getInstance().getString("label.exportProfile"), JOptionPane.WARNING_MESSAGE) == JOptionPane.OK_OPTION) { final ProgressDialog dialog = new ProgressDialog(); GUIUtil.centerWindow(dialog, getLocationOnScreen(), EncoderDialog.this.getBounds()); dialog.setVisible(true); } } else { final ProgressDialog dialog = new ProgressDialog(); GUIUtil.centerWindow(dialog, getLocationOnScreen(), EncoderDialog.this.getBounds()); dialog.setVisible(true); } } } } private class ChooseAction extends AbstractAction { private static final long serialVersionUID = 1L; /** * */ public ChooseAction() { super(TwisterSwingResources.getInstance().getString("action.choose")); } /** * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ @SuppressWarnings("unchecked") public void actionPerformed(final ActionEvent e) { profileChooser.setDialogTitle(TwisterSwingResources.getInstance().getString("label.exportProfile")); final int returnVal = profileChooser.showSaveDialog(new JFrame()); if (returnVal == JFileChooser.APPROVE_OPTION) { pathTextField.setText(profileChooser.getSelectedFile().getAbsoluteFile().getPath()); try { final EncoderExtensionRuntime encoder = ((ConfigurableExtension<EncoderExtensionRuntime<?>, EncoderExtensionConfig>) combobox.getSelectedItem()).createExtensionRuntime(); if ((pathTextField.getText() != null) && (encoder.isMovieSupported() && !pathTextField.getText().toLowerCase().endsWith(encoder.getMovieSuffix().toLowerCase()))) { pathTextField.setText(pathTextField.getText() + encoder.getMovieSuffix().toLowerCase()); } else if ((pathTextField.getText() != null) && (encoder.isImageSupported() && !pathTextField.getText().toLowerCase().endsWith(encoder.getImageSuffix().toLowerCase()))) { pathTextField.setText(pathTextField.getText() + encoder.getImageSuffix().toLowerCase()); } } catch (final Exception x) { x.printStackTrace(); } } } } private class CancelAction extends AbstractAction { private static final long serialVersionUID = 1L; /** * */ public CancelAction() { super(TwisterSwingResources.getInstance().getString("action.cancel")); } /** * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ public void actionPerformed(final ActionEvent e) { isInterrupted = true; } } private class CloseAction extends AbstractAction { private static final long serialVersionUID = 1L; /** * */ public CloseAction() { super(TwisterSwingResources.getInstance().getString("action.close")); } /** * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ public void actionPerformed(final ActionEvent e) { setVisible(false); } } public class ProgressDialog extends JDialog { private static final long serialVersionUID = 1L; public ProgressDialog() { super(new JFrame()); progressBar.setValue(0); setModal(true); setUndecorated(true); setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); final JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); buttonsPanel.add(cancelButton); final JPanel panel = new JPanel(); panel.setLayout(new BorderLayout()); panel.setBorder(new CompoundBorder(new LineBorder(Color.LIGHT_GRAY), new TitledBorder(new EmptyBorder(40, 40, 40, 40), TwisterSwingResources.getInstance().getString("message.export")))); panel.add(progressBar, BorderLayout.CENTER); panel.add(buttonsPanel, BorderLayout.SOUTH); getContentPane().setLayout(new BorderLayout()); getContentPane().add(panel); pack(); addWindowListener(new Dialoglistener()); } private class Dialoglistener extends WindowAdapter { /** * @see java.awt.event.WindowAdapter#windowOpened(java.awt.event.WindowEvent) */ @SuppressWarnings("unchecked") @Override public void windowOpened(final WindowEvent e) { try { final EncoderExtensionRuntime encoder = ((ConfigurableExtension<EncoderExtensionRuntime<?>, EncoderExtensionConfig>) combobox.getSelectedItem()).createExtensionRuntime(); isInterrupted = false; encoder.setInterruptHook(new EncoderHook() { /** * @see net.sf.jame.service.encoder.EncoderHook#isInterrupted() */ public boolean isInterrupted() { return isInterrupted; } }); final EncoderProgressListener listener = new EncoderProgressListener(); if (encoder != null) { service.execute(new ServiceCallback<Object>() { public void executed(final Object value) { listener.done(); } public void failed(final Throwable throwable) { listener.failed(throwable); } public Object execute(final LibraryService service) throws Exception { service.exportProfile(profile, encoder, listener, new File(pathTextField.getText())); return null; } }); } else { setVisible(false); dispose(); } } catch (final ExtensionException x) { JOptionPane.showMessageDialog(EncoderDialog.this, TwisterSwingResources.getInstance().getString("message.exportFailed"), TwisterSwingResources.getInstance().getString("label.exportProfile"), JOptionPane.ERROR_MESSAGE); EncoderDialog.logger.log(Level.WARNING, "Can't export the profile", x); x.printStackTrace(); } } private class EncoderProgressListener implements ProgressListener { public void done() { GUIUtil.executeTask(new Runnable() { public void run() { setVisible(false); dispose(); } }, true); } public void failed(final Throwable e) { GUIUtil.executeTask(new Runnable() { public void run() { JOptionPane.showMessageDialog(EncoderDialog.this, TwisterSwingResources.getInstance().getString("message.exportFailed"), TwisterSwingResources.getInstance().getString("label.exportProfile"), JOptionPane.ERROR_MESSAGE); EncoderDialog.logger.log(Level.WARNING, "Can't export the profile", e); setVisible(false); dispose(); } }, true); } public void stateChanged(final String message, final int percentage) { GUIUtil.executeTask(new Runnable() { public void run() { progressBar.setValue(percentage); } }, true); } public void stateChanged(final String message) { } } } } }