package apes.views;
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.util.HashMap;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import apes.controllers.ChannelController;
import apes.lib.SampleHelper;
import apes.models.InternalFormat;
import apes.models.Player;
/**
* Panel with information about the internal format and some controls for it.
*
* @author Johan Andersson (johandy@student.chalmers.se)
*/
public class InternalFormatStatusPanel extends JPanel
{
/**
* Text field for the start mark.
*/
private JTextField startTextField;
/**
* Text field for the stop mark.
*/
private JTextField stopTextField;
/**
* Text field for the player mark.
*/
private JTextField playerTextField;
/**
* Combo box for the start mark.
*/
private ApesComboBox startUnitList;
/**
* Combo box for the stop mark.
*/
private ApesComboBox stopUnitList;
/**
* Combo box for the player mark.
*/
private ApesComboBox playerUnitList;
/**
* The channel controller.
*/
private ChannelController channelController;
/**
* The player.
*/
private Player player;
/**
* Contains a mark as key and a combo box as value. Used to be able to write
* more dynamic code.
*/
private Map<Mark, JComboBox> unitMap;
/**
* Contains a mark as key and a text field as value. Used to be able to write
* more dynamic code.
*/
private Map<Mark, JTextField> valueMap;
/**
* Locale tags to all different units.
*/
private String[] units = { "channel.unit.samples", "channel.unit.milliseconds", "channel.unit.seconds", "channel.unit.minutes" };
/**
* The different marks.
*/
private enum Mark
{
START, STOP, PLAYER
};
/**
* The sample rate.
*/
private int sampleRate;
/**
* The internal format.
*/
private InternalFormat internalFormat;
/**
* Creates a new <code>InternalFormatStatusPanel</code> instance.
*
* @param channelController The channel controller.
*/
public InternalFormatStatusPanel(InternalFormat internalFormat, ChannelController channelController, Player player)
{
setLayout(new BorderLayout());
this.channelController = channelController;
this.player = player;
this.internalFormat = internalFormat;
this.sampleRate = internalFormat.getSampleRate();
unitMap = new HashMap<Mark, JComboBox>();
valueMap = new HashMap<Mark, JTextField>();
JPanel topPanel = topPanel();
add(topPanel, BorderLayout.NORTH);
JPanel centerPanel = centerPanel();
add(centerPanel, BorderLayout.CENTER);
JPanel bottomPanel = bottomPanel();
add(bottomPanel, BorderLayout.SOUTH);
}
/**
* Returns a top panel with a header and status information on it.
*
* @return The top panel.
*/
public JPanel topPanel()
{
// How many items there are to add.
int amount = 5;
JPanel wrapper = new JPanel();
wrapper.setLayout(new BorderLayout());
JPanel top = new JPanel();
JPanel status = new JPanel();
status.setLayout(new GridLayout(amount, 2));
status.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0));
JLabel header = new JLabel(internalFormat.getFileStatus().getFileName());
header.setFont(new Font("verdana", 1, 20));
top.add(header);
String[] labels = { "sample_rate", "num_channels", "num_samples", "bytes_per_sample", "bits_per_sample" };
int[] values = { internalFormat.getSampleRate(), internalFormat.getNumChannels(), internalFormat.getSampleAmount(), internalFormat.bytesPerSample, internalFormat.bitsPerSample };
// Add all labels and values.
for(int i = 0; i < labels.length; i++)
{
JLabel label = new ApesLabel("channel.information." + labels[i]);
label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10));
JLabel value = new JLabel("" + values[i]);
status.add(label);
status.add(value);
}
wrapper.add(top, BorderLayout.NORTH);
wrapper.add(status, BorderLayout.CENTER);
return wrapper;
}
/**
* Returns a panel with fields and boxes.
*
* @return The center panel.
*/
public JPanel centerPanel()
{
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(3, 3));
// Start
JLabel startLabel = new ApesLabel("channel.start");
startTextField = new JTextField();
startUnitList = new ApesComboBox(units);
unitMap.put(Mark.START, startUnitList);
valueMap.put(Mark.START, startTextField);
panel.add(startLabel);
panel.add(startTextField);
panel.add(startUnitList);
// Stop
JLabel stopLabel = new ApesLabel("channel.stop");
stopTextField = new JTextField();
stopUnitList = new ApesComboBox(units);
unitMap.put(Mark.STOP, stopUnitList);
valueMap.put(Mark.STOP, stopTextField);
panel.add(stopLabel);
panel.add(stopTextField);
panel.add(stopUnitList);
// Player
JLabel playerLabel = new ApesLabel("channel.player");
playerTextField = new JTextField();
playerUnitList = new ApesComboBox(units);
unitMap.put(Mark.PLAYER, playerUnitList);
valueMap.put(Mark.PLAYER, playerTextField);
panel.add(playerLabel);
panel.add(playerTextField);
panel.add(playerUnitList);
return panel;
}
/**
* Returns a panel with a refresh button on it.
*
* @return The bottom panel.
*/
public JPanel bottomPanel()
{
JPanel panel = new JPanel();
JButton refresh = new ApesButton("channel.refresh");
refresh.addActionListener(channelController);
refresh.setName("refresh");
panel.add(refresh);
return panel;
}
/**
* I called when something has been changed in the player. This then updates
* the fields.
*/
public void updatePlayer()
{
setStartValue(player.getStart());
setStopValue(player.getStop());
setPlayerValue(player.getCurrentSample());
}
/**
* Returns the start value in samples.
*
* @return The start value.
*/
public int getStartValue()
{
return getValue(Mark.START);
}
/**
* Sets the start value.
*
* @param samples The start value.
*/
public void setStartValue(int samples)
{
setValue(Mark.START, samples);
}
/**
* Returns the stop value in samples.
*
* @return The stop value.
*/
public int getStopValue()
{
return getValue(Mark.STOP);
}
/**
* Sets the stop value.
*
* @param samples The stop value.
*/
public void setStopValue(int samples)
{
setValue(Mark.STOP, samples);
}
/**
* Returns the player value in samples.
*
* @return The player value.
*/
public int getPlayerValue()
{
return getValue(Mark.PLAYER);
}
/**
* Sets the player value.
*
* @param samples The player value.
*/
public void setPlayerValue(int samples)
{
setValue(Mark.PLAYER, samples);
}
/**
* Generic helper for getting a value.
*
* @param mark The mark.
* @return The value for mark in samples.
*/
private int getValue(Mark mark)
{
JTextField textField = valueMap.get(mark);
int value = getTextFieldValue(textField);
if(isSamples(mark))
{
return value;
}
else if(isMilliseconds(mark))
{
return SampleHelper.millisecondsToSamples(sampleRate, value);
}
else if(isSeconds(mark))
{
return SampleHelper.secondsToSamples(sampleRate, value);
}
else if(isMinutes(mark))
{
return SampleHelper.minutesToSamples(sampleRate, value);
}
return value;
}
/**
* Generic helper for setting a value.
*
* @param mark The mark.
* @param samples The new value for mark.
*/
private void setValue(Mark mark, int samples)
{
JTextField textField = valueMap.get(mark);
int value = getTextFieldValue(textField);
if(isSamples(mark))
{
value = samples;
}
else if(isMilliseconds(mark))
{
value = SampleHelper.samplesToMilliseconds(sampleRate, samples);
}
else if(isSeconds(mark))
{
value = SampleHelper.samplesToSeconds(sampleRate, samples);
}
else if(isMinutes(mark))
{
value = SampleHelper.samplesToMinutes(sampleRate, samples);
}
textField.setText("" + value);
}
/**
* Returns true if <code>mark</code> is in samples. False otherwise.
*
* @param mark The mark.
* @return True if in samples. False otherwise.
*/
private boolean isSamples(Mark mark)
{
return isUnit(mark, 0);
}
/**
* Returns true if <code>mark</code> is in milliseconds. False otherwise.
*
* @param mark The mark.
* @return True if in milliseconds. False otherwise.
*/
private boolean isMilliseconds(Mark mark)
{
return isUnit(mark, 1);
}
/**
* Returns true if <code>mark</code> is in seconds. False otherwise.
*
* @param mark The mark.
* @return True if in seconds. False otherwise.
*/
private boolean isSeconds(Mark mark)
{
return isUnit(mark, 2);
}
/**
* Returns true if <code>mark</code> is in minutes. False otherwise.
*
* @param mark The mark.
* @return True if in minutes. False otherwise.
*/
private boolean isMinutes(Mark mark)
{
return isUnit(mark, 3);
}
/**
* Generic helper for checking what unit is selected for a mark.
*
* @param mark The mark.
* @param index The combo box index.
* @return True if the combo box index is the same as <code>index</code>.
* False otherwise.
*/
private boolean isUnit(Mark mark, int index)
{
return unitMap.get(mark).getSelectedIndex() == index;
}
/**
* Fetches the value from <code>textField</code>. If a valid number, that is
* returned. Otherwise zero is returned.
*
* @param textField The text field.
* @return The text field value, or zero if not valid.
*/
private int getTextFieldValue(JTextField textField)
{
int value = 0;
try
{
value = Integer.parseInt(textField.getText());
}
catch(NumberFormatException e)
{}
return value;
}
}