/**
*
*/
package cz.cuni.mff.peckam.java.origamist.gui.common;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.origamist.JLocalizedButton;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import cz.cuni.mff.peckam.java.origamist.configuration.Configuration;
import cz.cuni.mff.peckam.java.origamist.model.UnitDimension;
import cz.cuni.mff.peckam.java.origamist.model.jaxb.Unit;
import cz.cuni.mff.peckam.java.origamist.services.ServiceLocator;
import cz.cuni.mff.peckam.java.origamist.services.interfaces.ConfigurationManager;
import cz.cuni.mff.peckam.java.origamist.utils.ChangeNotification;
import cz.cuni.mff.peckam.java.origamist.utils.Observer;
import cz.cuni.mff.peckam.java.origamist.utils.UnitDimensionWithLabel;
/**
* An input for {@link UnitDimension} which also provides a set of predefined sizes.
*
* @author Martin Pecka
*/
public class JPaperSizeInput extends JUnitDimensionInput
{
/** */
private static final long serialVersionUID = 727058655215687837L;
/** The list of user-defined papers. */
protected List<UnitDimensionWithLabel> userPapers;
/** Combobox for predefined paper sizes. */
protected JComboBox paperSizes;
/** The button for saving a custom paper. */
protected JButton savePaper;
/** The button for removing a saved custom paper. */
protected JButton removePaper;
/** The item that stands for custom size. */
protected UnitDimensionWithLabel customSize;
/**
*
*/
public JPaperSizeInput()
{
ItemEvent evt = new ItemEvent(paperSizes, 0, paperSizes.getSelectedItem(), ItemEvent.SELECTED);
for (ItemListener l : paperSizes.getItemListeners()) {
l.itemStateChanged(evt);
}
}
@Override
protected void createComponents()
{
super.createComponents();
ServiceLocator
.get(ConfigurationManager.class)
.get()
.addAndRunResourceBundleListener(
new Configuration.LocaleListener("application", "JPaperSizeInput.paperSizesLabel") {
@Override
protected void updateText(String text)
{
setBorder(BorderFactory.createTitledBorder(text));
}
});
paperSizes = new JComboBox(getPapers());
ServiceLocator.get(ConfigurationManager.class).get()
.addPropertyChangeListener("locale", new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt)
{
UnitDimensionWithLabel selected = (UnitDimensionWithLabel) paperSizes.getSelectedItem();
Vector<UnitDimensionWithLabel> newItems = getPapers();
UnitDimensionWithLabel newSelected = null;
paperSizes.setModel(new DefaultComboBoxModel(newItems));
if (selected != null) {
for (UnitDimensionWithLabel d : newItems) {
if (d.getDimension() != null && d.getDimension().equals(selected.getDimension())) {
newSelected = d;
break;
}
}
}
if (newSelected != null) {
paperSizes.setSelectedItem(newSelected);
}
}
});
paperSizes.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e)
{
if (e.getStateChange() == ItemEvent.SELECTED) {
UnitDimensionWithLabel newItem = (UnitDimensionWithLabel) e.getItem();
if (newItem.getDimension() != null)
JPaperSizeInput.super.setValue(newItem.getDimension());
JPaperSizeInput.super.setEnabled(newItem.getDimension() == null);
if (newItem.getDimension() == null) {
removePaper.setVisible(false);
savePaper.setVisible(true);
savePaper.setEnabled(true);
} else {
savePaper.setVisible(false);
removePaper.setVisible(true);
removePaper.setEnabled(userPapers.contains(newItem));
}
}
}
});
paperSizes.setRenderer(new DefaultListCellRenderer() {
/** */
private static final long serialVersionUID = 445838703043695244L;
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
boolean cellHasFocus)
{
JLabel cell = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
UnitDimensionWithLabel val = (UnitDimensionWithLabel) value;
if (val.getDimension() != null) {
cell.setText(val.getLabel() + " (" + val.getDimension().toString() + ")");
} else {
cell.setText(val.getLabel());
}
return cell;
}
});
ServiceLocator.get(ConfigurationManager.class).get().getPapers()
.addObserver(new Observer<UnitDimensionWithLabel>() {
@Override
public void changePerformed(ChangeNotification<? extends UnitDimensionWithLabel> change)
{
Object selected = paperSizes.getSelectedItem();
Vector<UnitDimensionWithLabel> papers = getPapers();
paperSizes.setModel(new DefaultComboBoxModel(papers));
if (!papers.contains(selected)) {
selected = paperSizes.getModel().getElementAt(0);
}
paperSizes.setSelectedItem(selected);
ItemEvent evt = new ItemEvent(paperSizes, 0, selected, ItemEvent.SELECTED);
for (ItemListener l : paperSizes.getItemListeners())
l.itemStateChanged(evt);
}
});
Icon saveIcon = new ImageIcon(getClass().getResource("/resources/images/add-24.png"));
savePaper = new JLocalizedButton("application", "JPaperSizeInput.savePaper", saveIcon);
savePaper.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e)
{
ResourceBundle messages = ResourceBundle.getBundle("application",
ServiceLocator.get(ConfigurationManager.class).get().getLocale());
String name = null;
while (true) {
name = (String) JOptionPane.showInputDialog(JPaperSizeInput.this,
messages.getString("JPaperSizeInput.savePaper.message"),
messages.getString("JPaperSizeInput.savePaper.title"), JOptionPane.QUESTION_MESSAGE, null,
null, name != null ? name : "");
if (name == null)
break;
boolean nameExists = false;
for (UnitDimensionWithLabel dim : userPapers) {
if (dim.getLabel().equals(name)) {
nameExists = true;
break;
}
}
if (nameExists) {
JOptionPane.showMessageDialog(JPaperSizeInput.this,
messages.getString("JPaperSizeInput.savePaper.nameExists.message"),
messages.getString("JPaperSizeInput.savePaper.nameExists.title"),
JOptionPane.ERROR_MESSAGE);
} else {
UnitDimension dim = getValue();
UnitDimensionWithLabel newDim = new UnitDimensionWithLabel(dim, name);
userPapers.add(newDim);
UnitDimensionWithLabel selected = null;
for (UnitDimensionWithLabel udim : getPapers()) {
if (udim.equals(newDim)) {
selected = udim;
}
}
if (selected != null)
paperSizes.setSelectedItem(selected);
break;
}
}
}
});
Icon removeIcon = new ImageIcon(getClass().getResource("/resources/images/remove-24.png"));
removePaper = new JLocalizedButton("application", "JPaperSizeInput.removePaper", removeIcon);
removePaper.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e)
{
ResourceBundle messages = ResourceBundle.getBundle("application",
ServiceLocator.get(ConfigurationManager.class).get().getLocale());
if (JOptionPane.showConfirmDialog(JPaperSizeInput.this,
messages.getString("JPaperSizeInput.removePaper.message"),
messages.getString("JPaperSizeInput.removePaper.title"), JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
userPapers.remove(paperSizes.getSelectedItem());
paperSizes.setSelectedItem(customSize);
}
}
});
}
@Override
protected void buildLayout()
{
CellConstraints cc = new CellConstraints();
JPanel paperPanel = new JPanel(new FormLayout("pref,$ugap,pref,pref", "pref"));
paperPanel.add(paperSizes, cc.xy(1, 1));
paperPanel.add(savePaper, cc.xy(3, 1));
paperPanel.add(removePaper, cc.xy(4, 1));
JPanel widthPanel = new JPanel(new FormLayout("pref:grow,$lcgap,pref", "pref"));
widthPanel.add(widthLabel, cc.xy(1, 1));
widthPanel.add(width, cc.xy(3, 1));
JPanel heightPanel = new JPanel(new FormLayout("pref:grow,$lcgap,pref", "pref"));
heightPanel.add(heightLabel, cc.xy(1, 1));
heightPanel.add(height, cc.xy(3, 1));
JPanel unitPanel = new JPanel(new FormLayout("pref:grow,$lcgap,pref", "pref"));
unitPanel.add(unitLabel, cc.xy(1, 1));
unitPanel.add(unit, cc.xy(3, 1));
JPanel unitDimPanel = new JPanel(new FormLayout("pref,$ugap:grow,pref", "pref,$lgap,pref"));
unitDimPanel.add(widthPanel, cc.xy(1, 1));
unitDimPanel.add(heightPanel, cc.xy(1, 3));
unitDimPanel.add(unitPanel, cc.xy(3, 1));
unitDimPanel.add(preserveRatio, cc.xy(3, 3));
JPanel aspectPanel = new JPanel(new FormLayout("pref,$lcgap,pref,0px:grow,pref", "pref"));
aspectPanel.add(aspectRatioLabel, cc.xy(1, 1));
aspectPanel.add(aspectRatioDisplay, cc.xy(3, 1));
aspectPanel.add(rotatePaper, cc.xy(5, 1));
JPanel refDimPanel = new JPanel(new FormLayout("pref,$lcgap,pref,$ugap:grow,pref,$lcgap,pref", "pref"));
refDimPanel.add(refLengthLabel, cc.xy(1, 1));
refDimPanel.add(refLength, cc.xy(3, 1));
refDimPanel.add(refUnitLabel, cc.xy(5, 1));
refDimPanel.add(refUnit, cc.xy(7, 1));
setLayout(new FormLayout("pref", "pref,$lgap,pref,$lgap,pref,$lgap,pref,$lgap,pref"));
add(paperPanel, cc.xy(1, 1));
add(unitDimPanel, cc.xy(1, 3));
add(aspectPanel, cc.xy(1, 5));
add(refLabel, cc.xy(1, 7));
add(refDimPanel, cc.xy(1, 9));
}
@Override
public void setValue(UnitDimension value)
{
super.setValue(value);
if (!setValueWithoutSideEffects && customSize != null)
paperSizes.setSelectedItem(customSize);
}
@Override
public void setEnabled(boolean enabled)
{
super.setEnabled(enabled);
paperSizes.setEnabled(enabled);
rotatePaper.setEnabled(enabled);
savePaper.setEnabled(enabled);
removePaper.setEnabled(enabled);
}
/**
* @return all defined paper sizes (taken from a .properties file).
*/
protected Vector<UnitDimensionWithLabel> getPapers()
{
Vector<UnitDimensionWithLabel> result = new Vector<UnitDimensionWithLabel>();
ResourceBundle bundle = ResourceBundle.getBundle("application", ServiceLocator.get(ConfigurationManager.class)
.get().getLocale());
Enumeration<String> keys = bundle.getKeys();
customSize = null;
while (keys.hasMoreElements()) {
String key = keys.nextElement();
if (key.startsWith("paper.") && key.endsWith(".label")) {
String prefix = key.substring(0, key.lastIndexOf(".label"));
String label = bundle.getString(key);
UnitDimension dim = new UnitDimension();
try {
try {
double width = Double.parseDouble(bundle.getString(prefix + ".width"));
double height = Double.parseDouble(bundle.getString(prefix + ".height"));
Unit unit = Unit.fromValue(bundle.getString(prefix + ".unit"));
Double refLength = null;
try {
refLength = Double.parseDouble(bundle.getString(prefix + ".reference.length"));
} catch (MissingResourceException e) {}
Unit refUnit = null;
try {
refUnit = Unit.fromValue(bundle.getString(prefix + ".reference.unit"));
} catch (MissingResourceException e) {}
dim.setWidth(width);
dim.setHeight(height);
dim.setUnit(unit);
dim.setReference(refUnit, refLength);
} catch (MissingResourceException e) {
// this will happen for the custom paper size
dim = null;
}
UnitDimensionWithLabel newItem = new UnitDimensionWithLabel(dim, label);
// we only want one custom item in the list
if (!(newItem.getDimension() == null && customSize != null)) {
result.add(newItem);
if (newItem.getDimension() == null)
customSize = newItem;
}
} catch (IllegalArgumentException e) {/* For wrongly spelled units. */}
}
}
if (userPapers == null)
userPapers = ServiceLocator.get(ConfigurationManager.class).get().getPapers();
result.addAll(userPapers);
UnitDimensionWithLabel[] items = result.toArray(new UnitDimensionWithLabel[] {});
Arrays.sort(items, new Comparator<UnitDimensionWithLabel>() {
@Override
public int compare(UnitDimensionWithLabel o1, UnitDimensionWithLabel o2)
{
// let the custom dimension be the first
if (o1.getDimension() == null)
return -1;
if (o2.getDimension() == null)
return 1;
return o1.getLabel().compareTo(o2.getLabel());
}
});
result = new Vector<UnitDimensionWithLabel>(Arrays.asList(items));
return result;
}
}