/*
* Jajuk
* Copyright (C) The Jajuk Team
* http://jajuk.info
*
* 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 2
* of the License, or 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.jajuk.ui.wizard.prepare_party;
import java.awt.Desktop;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingConstants;
import javax.swing.border.BevelBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import net.miginfocom.swing.MigLayout;
import org.jajuk.base.Type;
import org.jajuk.base.TypeManager;
import org.jajuk.ui.helpers.DefaultMouseWheelListener;
import org.jajuk.ui.windows.JajukMainWindow;
import org.jajuk.ui.wizard.prepare_party.PreparePartyWizard.Variable;
import org.jajuk.util.Const;
import org.jajuk.util.Messages;
import org.jajuk.util.UtilPrepareParty;
import org.jajuk.util.log.Log;
import org.qdwizard.ClearPoint;
import org.qdwizard.Screen;
/**
* General options panel.
*/
@ClearPoint
public class PreparePartyWizardGeneralOptionsScreen extends Screen implements ActionListener,
ChangeListener, MouseListener {
/** Constant for MigLayout. */
private static final String GROW = "grow";
/** Constant for MigLayout. */
private static final String GROW_TWO_COL = "[grow][]";
/** Constant for MigLayout. */
private static final String LABEL_WIDTH = "width 40:40:";
/** Generated serialVersionUID. */
private static final long serialVersionUID = 1L;
/** Empty value. */
private static final String NO_VALUE = " ";
/** Enable limit on number of tracks. */
private JCheckBox jcbMaxTracks;
/** The max. number of tracks */
private JSlider jsMaxTracks;
/** The max. number of tracks */
private JLabel jnMaxTracks;
/** Enable limit on max size. */
private JCheckBox jcbMaxSize;
/** Max size (in MB) of party. */
private JSlider jsMaxSize;
/** Max size (in MB) of party. */
private JLabel jnMaxSize;
/** Enable limit on max playing length. */
private JCheckBox jcbMaxLength;
/** Max playing length of party (in minutes). */
private JSlider jsMaxLength;
/** Max playing length of party (in minutes). */
private JLabel jnMaxLength;
/** Enable limit on specific audio type. */
private JCheckBox jcbOneMedia;
/** Limit to one type of audo file. */
@SuppressWarnings("rawtypes")
private JComboBox jcbMedia;
/** Enable conversion to the selected audio type. */
private JCheckBox jcbConvertMedia;
/** Audio conversion. */
private JLabel jlConvertMedia;
/** Button to configure audio conversion. */
private JButton jbConvertConfig;
/** Limit on rate of tracks. */
private JLabel jlRatingLevel;
/** The min. number of stars a track needs to have */
private JSlider jsRatingLevel;
/** Enable normalizing filenames so they can be stored on windows fileshares. */
private JCheckBox jcbNormalizeFilename;
/* (non-Javadoc)
* @see org.qdwizard.Screen#getDescription()
*/
@Override
public String getDescription() {
return Messages.getString("PreparePartyWizard.5");
}
/* (non-Javadoc)
* @see org.qdwizard.Screen#getName()
*/
@Override
public String getName() {
return Messages.getString("PreparePartyWizard.4");
}
/**
* Create panel UI.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public void initUI() {
{ // Max Tracks
jcbMaxTracks = new JCheckBox(Messages.getString("PreparePartyWizard.10"));
jcbMaxTracks.setToolTipText(Messages.getString("PreparePartyWizard.11"));
jsMaxTracks = new JSlider(0, 1000, 100);
jnMaxTracks = new JLabel(NO_VALUE);
jnMaxTracks.setBorder(new BevelBorder(BevelBorder.LOWERED));
jnMaxTracks.setHorizontalAlignment(SwingConstants.RIGHT);
jsMaxTracks.setMajorTickSpacing(100);
jsMaxTracks.setMinorTickSpacing(10);
jsMaxTracks.setPaintTicks(true);
jsMaxTracks.setPaintLabels(true);
jsMaxTracks.setToolTipText(Messages.getString("PreparePartyWizard.11"));
}
{ // Max Size
jcbMaxSize = new JCheckBox(Messages.getString("PreparePartyWizard.12"));
jcbMaxSize.setToolTipText(Messages.getString("PreparePartyWizard.13"));
jsMaxSize = new JSlider(0, 1000, 100);
jnMaxSize = new JLabel(NO_VALUE);
jnMaxSize.setBorder(new BevelBorder(BevelBorder.LOWERED));
jnMaxSize.setHorizontalAlignment(SwingConstants.RIGHT);
jsMaxSize.setMajorTickSpacing(100);
jsMaxSize.setMinorTickSpacing(10);
jsMaxSize.setPaintTicks(true);
jsMaxSize.setPaintLabels(true);
jsMaxSize.setToolTipText(Messages.getString("PreparePartyWizard.13"));
}
{ // Max Length
jcbMaxLength = new JCheckBox(Messages.getString("PreparePartyWizard.14"));
jcbMaxLength.setToolTipText(Messages.getString("PreparePartyWizard.15"));
jsMaxLength = new JSlider(0, 1000, 100);
jnMaxLength = new JLabel(NO_VALUE);
jnMaxLength.setBorder(new BevelBorder(BevelBorder.LOWERED));
jnMaxLength.setHorizontalAlignment(SwingConstants.RIGHT);
jsMaxLength.setMajorTickSpacing(100);
jsMaxLength.setMinorTickSpacing(10);
jsMaxLength.setPaintTicks(true);
jsMaxLength.setPaintLabels(true);
jsMaxLength.setToolTipText(Messages.getString("PreparePartyWizard.15"));
}
{ // Choose Media
jcbOneMedia = new JCheckBox(Messages.getString("PreparePartyWizard.16"));
jcbOneMedia.setToolTipText(Messages.getString("PreparePartyWizard.17"));
jcbMedia = new JComboBox();
List<Type> types = TypeManager.getInstance().getTypes();
// sort the list on extension here
Collections.sort(types, new TypeComparator());
for (Type type : types) {
// exclude playlists and web-radios from selection as we cannot copy
// those.
if (!type.getExtension().equals(Const.EXT_PLAYLIST)
&& !type.getExtension().equals(Const.EXT_RADIO)) {
jcbMedia.addItem(type.getExtension());
}
}
jcbMedia.setToolTipText(Messages.getString("PreparePartyWizard.17"));
jcbConvertMedia = new JCheckBox(Messages.getString("PreparePartyWizard.34"));
jcbConvertMedia.setToolTipText(Messages.getString("PreparePartyWizard.35"));
// to show help and allow clicking for viewing the related web-page
jlConvertMedia = new JLabel(Messages.getString("PreparePartyWizard.37"));
jbConvertConfig = new JButton(Messages.getString("PreparePartyWizard.40"));
}
{ // Rating Level
jlRatingLevel = new JLabel(Messages.getString("DigitalDJWizard.8"));
jlRatingLevel.setToolTipText(Messages.getString("DigitalDJWizard.53"));
jsRatingLevel = new JSlider(0, 4, 0);
jsRatingLevel.setMajorTickSpacing(1);
jsRatingLevel.setMinorTickSpacing(1);
jsRatingLevel.setPaintTicks(true);
jsRatingLevel.setSnapToTicks(true);
jsRatingLevel.setPaintLabels(true);
jsRatingLevel.setToolTipText(Messages.getString("DigitalDJWizard.53"));
}
jcbNormalizeFilename = new JCheckBox(Messages.getString("PreparePartyWizard.26"));
jcbNormalizeFilename.setToolTipText(Messages.getString("PreparePartyWizard.27"));
// populate the UI items with values from the data object
readData();
// add listeners after reading initial data to not overwrite them with
// init-state-change actions
// enable/disable slider depending on checkbox
jcbMaxTracks.addActionListener(this);
jsMaxTracks.addMouseWheelListener(new DefaultMouseWheelListener(jsMaxTracks));
jsMaxTracks.addChangeListener(this);
// enable/disable slider depending on checkbox
jcbMaxSize.addActionListener(this);
jsMaxSize.addMouseWheelListener(new DefaultMouseWheelListener(jsMaxSize));
jsMaxSize.addChangeListener(this);
// enable/disable slider depending on checkbox
jcbMaxLength.addActionListener(this);
jsMaxLength.addMouseWheelListener(new DefaultMouseWheelListener(jsMaxLength));
jsMaxLength.addChangeListener(this);
// enable/disable combobox depending on checkbox
jcbOneMedia.addActionListener(this);
jcbMedia.addActionListener(this);
jcbConvertMedia.addActionListener(this);
jlConvertMedia.addMouseListener(this);
jbConvertConfig.addActionListener(this);
// get informed about rating level slider changes
jsRatingLevel.addMouseWheelListener(new DefaultMouseWheelListener(jsRatingLevel));
jsRatingLevel.addChangeListener(this);
jcbNormalizeFilename.addActionListener(this);
setLayout(new MigLayout("insets 10,gapx 10,gapy 15", "[][grow]"));
add(jcbMaxTracks);
{
JPanel panel = new JPanel();
panel.setLayout(new MigLayout("", GROW_TWO_COL));
panel.add(jsMaxTracks, GROW);
panel.add(jnMaxTracks, LABEL_WIDTH);
add(panel, "grow,wrap");
}
add(jcbMaxSize);
{
JPanel panel = new JPanel();
panel.setLayout(new MigLayout("", GROW_TWO_COL));
panel.add(jsMaxSize, GROW);
panel.add(jnMaxSize, LABEL_WIDTH);
add(panel, "grow,wrap");
}
add(jcbMaxLength);
{
JPanel panel = new JPanel();
panel.setLayout(new MigLayout("", GROW_TWO_COL));
panel.add(jsMaxLength, GROW);
panel.add(jnMaxLength, LABEL_WIDTH);
add(panel, "grow,wrap");
}
add(jcbOneMedia);
add(jcbMedia, "grow,wrap");
// dummy-Label to get the CheckBox for "convert" into the second column
add(new JLabel());
add(jcbConvertMedia, "grow,wrap");
add(new JLabel());
{
JPanel panel = new JPanel();
panel.setLayout(new MigLayout("", GROW_TWO_COL));
panel.add(jlConvertMedia, GROW);
panel.add(jbConvertConfig);
add(panel, "grow,wrap");
}
add(jcbNormalizeFilename, "grow,wrap");
add(jlRatingLevel);
add(jsRatingLevel, "grow,wrap");
// store initial values and adjust values
updateData();
}
/**
* Populate the UI items with values from the data object.
*/
private void readData() {
// set the values from the stored data
// initially these are not set, so we need to query for "containsKey"...
if (isTrue(Variable.MAXTRACKS_ENABLED)) {
jsMaxTracks.setEnabled(true);
jcbMaxTracks.setSelected(true);
} else {
jsMaxTracks.setEnabled(false);
jcbMaxTracks.setSelected(false);
}
if (data.containsKey(Variable.MAXTRACKS)) {
jsMaxTracks.setValue((Integer) data.get(Variable.MAXTRACKS));
}
if (isTrue(Variable.MAXSIZE_ENABLED)) {
jsMaxSize.setEnabled(true);
jcbMaxSize.setSelected(true);
} else {
jsMaxSize.setEnabled(false);
jcbMaxSize.setSelected(false);
}
if (data.containsKey(Variable.MAXSIZE)) {
jsMaxSize.setValue((Integer) data.get(Variable.MAXSIZE));
}
if (isTrue(Variable.MAXLENGTH_ENABLED)) {
jsMaxLength.setEnabled(true);
jcbMaxLength.setSelected(true);
} else {
jsMaxLength.setEnabled(false);
jcbMaxLength.setSelected(false);
}
if (data.containsKey(Variable.MAXLENGTH)) {
jsMaxLength.setValue((Integer) data.get(Variable.MAXLENGTH));
}
if (isTrue(Variable.ONE_MEDIA_ENABLED)) {
jcbMedia.setEnabled(true);
jcbOneMedia.setSelected(true);
jcbConvertMedia.setEnabled(true);
} else {
jcbMedia.setEnabled(false);
jcbOneMedia.setSelected(false);
jcbConvertMedia.setEnabled(false);
}
// Check if pacpl can be used, do it every time the dialog starts as the
// user might have installed it by now
boolean bPACPLAvailable = UtilPrepareParty.checkPACPL((String) data
.get(Variable.CONVERT_COMMAND));
if (!bPACPLAvailable) {
// disable media conversion if pacpl is not found
jcbConvertMedia.setEnabled(false);
}
// don't set Convert to on from data if PACPL became unavailable
if (isTrue(Variable.CONVERT_MEDIA) && bPACPLAvailable) {
jcbConvertMedia.setSelected(true);
} else {
jcbConvertMedia.setSelected(false);
}
if (data.containsKey(Variable.ONE_MEDIA)) {
jcbMedia.setSelectedItem(data.get(Variable.ONE_MEDIA));
} else {
// default to MP3 initially
jcbMedia.setSelectedItem("mp3");
}
if (data.containsKey(Variable.RATING_LEVEL)) {
jsRatingLevel.setValue((Integer) data.get(Variable.RATING_LEVEL));
}
if (isTrue(Variable.NORMALIZE_FILENAME)) {
jcbNormalizeFilename.setSelected(true);
} else {
jcbNormalizeFilename.setSelected(false);
}
}
/**
* Return if the specified element is true in the data-map.
*
* @param key The key to look up in the data-object.
*
* @return true if the value was stored as boolean true, false otherwise.
*/
private final boolean isTrue(final Variable key) {
return data.containsKey(key) && Boolean.TRUE.equals(data.get(key));
}
/**
* Write the data from the UI items to the data object.
*/
private void updateData() {
// store if checkbox is enabled and update the label accordingly
updateOneItem(jcbMaxTracks, jsMaxTracks, jnMaxTracks, Variable.MAXTRACKS,
Variable.MAXTRACKS_ENABLED);
updateOneItem(jcbMaxSize, jsMaxSize, jnMaxSize, Variable.MAXSIZE, Variable.MAXSIZE_ENABLED);
updateOneItem(jcbMaxLength, jsMaxLength, jnMaxLength, Variable.MAXLENGTH,
Variable.MAXLENGTH_ENABLED);
if (jcbOneMedia.isSelected()) {
data.put(Variable.ONE_MEDIA, jcbMedia.getSelectedItem());
data.put(Variable.ONE_MEDIA_ENABLED, Boolean.TRUE);
} else {
// keep old value... data.remove(Variable.KEY_MEDIA);
data.put(Variable.ONE_MEDIA_ENABLED, Boolean.FALSE);
}
data.put(Variable.CONVERT_MEDIA, jcbConvertMedia.isSelected());
data.put(Variable.RATING_LEVEL, jsRatingLevel.getValue());
data.put(Variable.NORMALIZE_FILENAME, jcbNormalizeFilename.isSelected());
}
/**
* Helper to handle a checkbox/slider combination. It also updates an
* associated Label with the value from the Slider.
*
* @param cb The checkbox to check for selected/deselected state
* @param slider The slider to get the value from
* @param label The Label to populate with the current value from the Slider.
* @param key The key in the data object for the value of the Slider.
* @param keyOn The key in the data object to store the enabled/disabled
* state.
*/
private void updateOneItem(JCheckBox cb, JSlider slider, JLabel label, Variable key,
Variable keyOn) {
if (cb.isSelected()) {
if (!slider.getValueIsAdjusting()) {
data.put(key, slider.getValue());
data.put(keyOn, Boolean.TRUE);
}
label.setText(Integer.toString(slider.getValue()));
} else {
if (!slider.getValueIsAdjusting()) {
// keep value... data.remove(key);
data.put(keyOn, Boolean.FALSE);
}
label.setText(NO_VALUE);
}
}
/**
* Return if the specified element is true in the data-map.
*
* @param key The key to look up in the data-object.
*
* @return true if the value was stored as boolean true, false otherwise.
*/
private final boolean isTrue(final String key) {
return data.containsKey(key) && Boolean.TRUE.equals(data.get(key));
}
/*
* (non-Javadoc)
*
* @see
* java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
@Override
public void actionPerformed(ActionEvent ae) {
// if a checkbox is selected/deselected, enable/disable the
// sliders/comboboxes accordingly
if (ae.getSource() == jcbMaxTracks) {
jsMaxTracks.setEnabled(jcbMaxTracks.isSelected());
} else if (ae.getSource() == jcbMaxSize) {
jsMaxSize.setEnabled(jcbMaxSize.isSelected());
} else if (ae.getSource() == jcbMaxLength) {
jsMaxLength.setEnabled(jcbMaxLength.isSelected());
} else if (ae.getSource() == jcbOneMedia) {
jcbMedia.setEnabled(jcbOneMedia.isSelected());
jcbConvertMedia.setEnabled(jcbOneMedia.isSelected());
} else if (ae.getSource() == jbConvertConfig) {
// create the settings dialog, it will display itself and inform us when
// the value is changed with "Ok"
new PreparePartyConvertSettings(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
// no need for re-checking if the same command is chosen as before
if (e.getSource().toString().equals(data.get(Variable.CONVERT_COMMAND))) {
Log.debug("Same pacpl-command as before: " + e.getSource().toString());
return;
}
Log.debug("New pacpl-command: " + e.getSource().toString());
data.put(Variable.CONVERT_COMMAND, e.getSource().toString());
// re-check if pacpl can be called now
boolean bPACPLAvailable = UtilPrepareParty.checkPACPL((String) data
.get(Variable.CONVERT_COMMAND));
// disable media conversion if pacpl is not found
if (bPACPLAvailable) {
Log.debug("Updated settings for media conversion allow pacpl to be used.");
jcbConvertMedia.setEnabled(true);
} else {
Log.warn("Updated settings for media conversion do not allow pacpl to be used!");
jcbConvertMedia.setEnabled(false);
jcbConvertMedia.setSelected(false);
}
}
}, (String) data.get(Variable.CONVERT_COMMAND), JajukMainWindow.getInstance());
}
updateData();
}
/*
* (non-Javadoc)
*
* @see
* javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent
* )
*/
@Override
public void stateChanged(ChangeEvent ie) {
// just update the stored data whenever we receive an interesting
// event
if (ie.getSource() == jsMaxTracks) {
updateData();
} else if (ie.getSource() == jsMaxSize) {
updateData();
} else if (ie.getSource() == jsMaxLength) {
updateData();
} else if (ie.getSource() == jcbMedia) {
updateData();
} else if (ie.getSource() == jsRatingLevel) {
updateData();
}
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
*/
@Override
public void mouseClicked(MouseEvent e) {
if (e.getSource() == jlConvertMedia) {
try {
Desktop.getDesktop().browse(
new URI("http://jajuk.info/index.php/Installing_Perl_Audio_Converter"));
} catch (IOException ex) {
Log.error(ex);
} catch (URISyntaxException ex) {
Log.error(ex);
}
}
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
*/
@Override
public void mouseEntered(MouseEvent e) {
// nothing to do here...
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
*/
@Override
public void mouseExited(MouseEvent e) {
// nothing to do here...
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
*/
@Override
public void mousePressed(MouseEvent e) {
// nothing to do here...
}
/*
* (non-Javadoc)
*
* @see
* java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
*/
@Override
public void mouseReleased(MouseEvent e) {
// nothing to do here...
}
}