/**
*
*/
package cz.cuni.mff.peckam.java.origamist.gui.editor;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.Permission;
import java.util.Date;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.ResourceBundle;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.InputVerifier;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.border.TitledBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.origamist.JFileInput;
import javax.swing.origamist.JImage;
import javax.swing.origamist.JLocalizedButton;
import javax.swing.origamist.JLocalizedLabel;
import javax.swing.origamist.JMultilineLabel;
import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import com.toedter.calendar.JDateChooser;
import com.toedter.calendar.JSpinnerDateEditor;
import cz.cuni.mff.peckam.java.origamist.configuration.Configuration;
import cz.cuni.mff.peckam.java.origamist.gui.common.DefaultLangStringListTextArea;
import cz.cuni.mff.peckam.java.origamist.gui.common.JDiagramPaperInput;
import cz.cuni.mff.peckam.java.origamist.gui.common.JLangStringListTextField;
import cz.cuni.mff.peckam.java.origamist.gui.common.JModelPaperInput;
import cz.cuni.mff.peckam.java.origamist.model.ObjectFactory;
import cz.cuni.mff.peckam.java.origamist.model.Origami;
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.StepThumbnailGenerator;
import cz.cuni.mff.peckam.java.origamist.services.TooltipFactory;
import cz.cuni.mff.peckam.java.origamist.services.interfaces.ConfigurationManager;
import cz.cuni.mff.peckam.java.origamist.utils.PermissionConverter;
import cz.cuni.mff.peckam.java.origamist.utils.UniversalDocumentListener;
/**
* A frame for editing metadata of an tempOrigami. It can also be used to fill metadata for a just-created tempOrigami.
*
* @author Martin Pecka
*/
public class OrigamiPropertiesFrame extends JDialog
{
/** */
private static final long serialVersionUID = -8222843108896744313L;
/**
* If <code>null</code>, indicates that the dialog should display texts for creating a model metadata, otherwise it
* displays texts for editing an existing model's metadata.
*/
protected Origami origami;
/**
* The origami we will store the current settings in. These values will be copied to <code>origami</code> when this
* dialog is closed with the {@link OKAction}.
*/
protected Origami tempOrigami;
/**
* If <code>true</code>, show texts for creating a model, otherwise display texts for editing an existing model's
* metadata.
*/
protected boolean isCreating;
/** Input for model names. */
protected JLangStringListTextField<JTextField> name;
/** Input for model creation date. */
protected JDateChooser creationDate;
/** Input for short description. */
protected JLangStringListTextField<JTextField> shortDesc;
/** Input for long description. */
protected JLangStringListTextField<JTextArea> description;
/** Input for author's name. */
protected JTextField authorName;
/** Input for author's homepage. */
protected JTextField authorHomepage;
/** Input for license name. */
protected JTextField licenseName;
/** Input for license homepage. */
protected JTextField licenseHomepage;
/** List of predefined licenses. */
protected List<JRadioButton> predefinedLicenses = new LinkedList<JRadioButton>();
/** The button group of predefined licenses. */
protected ButtonGroup predefinedLicensesGroup = new ButtonGroup();
/** Input for license content. */
protected JTextArea licenseContent;
/** RadioButton that signalizes that license homepage will be filled and content not. */
protected JRadioButton licenseChooseHomepage;
/** RadioButton that signalizes that license homepage will not be filled and content will be. */
protected JRadioButton licenseChooseContent;
/** Checkbox that signalizes the Do nothing license permission. */
protected JCheckBox licensePermissionDoNothing;
/** Checkbox that signalizes the Edit license permission. */
protected JCheckBox licensePermissionEdit;
/** Checkbox that signalizes the Export license permission. */
protected JCheckBox licensePermissionExport;
/** Checkbox that signalizes the Distribute license permission. */
protected JCheckBox licensePermissionDistribute;
/** Input for the original's URL. */
protected JTextField original;
/** RadioButton that signalizes that the thumbnail should be generated from the model. */
protected JRadioButton thumbnailLoadFromModel;
/** RadioButton that signalizes that the thumbnail should be generated from a file. */
protected JRadioButton thumbnailLoadFromFile;
/** Input for selecting the thumbnail. */
protected JFileInput thumbnailFileInput;
/** Component that shows a preview of the thumbnail. */
protected JThumbnail thumbnailPreview;
/** Input for configuring diagram paper. */
protected JDiagramPaperInput diagramPaper;
/** Input for configuring model paper. */
protected JModelPaperInput modelPaper;
/** Dialog button. */
protected JButton okButton, cancelButton;
/** Label. */
protected JLabel dialogTitle, nameLabel, creationDateLabel, shortDescLabel,
authorNameLabel, authorHomepageLabel, licenseNameLabel, licenseHomepageLabel, licenseContentLabel,
originalLabel, thumbnailFileInputLabel, thumbnailPreviewLabel;
protected String imageFileType = null;
protected Image generatedThumbnail = null, fromFileThumbnail = null;
/**
* @param tempOrigami If <code>null</code>, indicates that the dialog should display texts for creating a model
* metadata, otherwise it displays texts for editing an existing model's metadata.
*/
public OrigamiPropertiesFrame(Origami origami)
{
setOrigami(origami);
final ComponentListener resizeListener = new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e)
{
maybePack();
}
};
getContentPane().addContainerListener(new ContainerListener() {
@Override
public void componentRemoved(ContainerEvent e)
{
e.getChild().removeComponentListener(resizeListener);
}
@Override
public void componentAdded(ContainerEvent e)
{
e.getChild().addComponentListener(resizeListener);
}
});
createComponents();
buildLayout();
if (isCreating)
fillDefaults();
setModalityType(ModalityType.APPLICATION_MODAL);
String titleKey = (isCreating ? "OrigamiPropertiesFrame.title.create" : "OrigamiPropertiesFrame.title.edit");
ServiceLocator.get(ConfigurationManager.class).get()
.addAndRunResourceBundleListener(new Configuration.LocaleListener("application", titleKey) {
@Override
protected void updateText(String text)
{
setTitle(text);
}
});
}
/**
* Create all GUI components.
*/
protected void createComponents()
{
Configuration conf = ServiceLocator.get(ConfigurationManager.class).get();
String titleKey = (isCreating ? "OrigamiPropertiesFrame.title.create" : "OrigamiPropertiesFrame.title.edit");
dialogTitle = new JLocalizedLabel("application", titleKey);
dialogTitle.setFont(dialogTitle.getFont().deriveFont(Font.BOLD, 20f));
nameLabel = new JLocalizedLabel("application", "OrigamiPropertiesFrame.nameLabel");
creationDateLabel = new JLocalizedLabel("application", "OrigamiPropertiesFrame.creationDateLabel");
shortDescLabel = new JLocalizedLabel("application", "OrigamiPropertiesFrame.shortDescLabel");
authorNameLabel = new JLocalizedLabel("application", "OrigamiPropertiesFrame.authorNameLabel");
authorHomepageLabel = new JLocalizedLabel("application", "OrigamiPropertiesFrame.authorHomepageLabel");
licenseNameLabel = new JLocalizedLabel("application", "OrigamiPropertiesFrame.licenseNameLabel");
licenseHomepageLabel = new JLocalizedLabel("application", "OrigamiPropertiesFrame.licenseHomepageLabel");
licenseContentLabel = new JLocalizedLabel("application", "OrigamiPropertiesFrame.licenseContentLabel");
originalLabel = new JLocalizedLabel("application", "OrigamiPropertiesFrame.originalLabel");
thumbnailFileInputLabel = new JLocalizedLabel("application", "OrigamiPropertiesFrame.thumbnailFileInputLabel");
thumbnailPreviewLabel = new JLocalizedLabel("application", "OrigamiPropertiesFrame.thumbnailPreviewLabel");
name = new JLangStringListTextField<JTextField>(tempOrigami.getName(), new JTextField(20));
// in creating mode, the 0 will be replaced in fillDefaults()
creationDate = new JDateChooser(null, tempOrigami.getCreationDate() != null ? tempOrigami.getCreationDate()
: new Date(), null, new JSpinnerDateEditor());
creationDate.setMaxSelectableDate(new Date());
creationDate.setLocale(conf.getLocale());
creationDate.addPropertyChangeListener("date", new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt)
{
tempOrigami.setCreationDate(creationDate.getDate());
}
});
shortDesc = new JLangStringListTextField<JTextField>(tempOrigami.getShortdesc(), new JTextField(20));
description = new DefaultLangStringListTextArea(tempOrigami.getDescription());
final TitledBorder descriptionBorder = BorderFactory.createTitledBorder(description.getBorder(), "");
description.setBorder(descriptionBorder);
conf.addAndRunResourceBundleListener(new Configuration.LocaleListener("application",
"OrigamiPropertiesFrame.descriptionLabel") {
@Override
protected void updateText(String text)
{
descriptionBorder.setTitle(text);
}
});
authorName = new JTextField(tempOrigami.getAuthor().getName(), 20);
authorName.getDocument().addDocumentListener(new UniversalDocumentListener() {
@Override
protected void update(DocumentEvent e)
{
tempOrigami.getAuthor().setName(authorName.getText());
}
});
authorHomepage = new JTextField(tempOrigami.getAuthor().getHomepage() != null ? tempOrigami.getAuthor()
.getHomepage().toString() : "", 20);
authorHomepage.setInputVerifier(new URIInputVerifier());
authorHomepage.getDocument().addDocumentListener(new UniversalDocumentListener() {
@Override
protected void update(DocumentEvent e)
{
URI value = null;
try {
value = new URL(authorHomepage.getText()).toURI();
} catch (MalformedURLException e1) {} catch (URISyntaxException e1) {}
tempOrigami.getAuthor().setHomepage(value);
}
});
licenseName = new JTextField(tempOrigami.getLicense().getName(), 20);
licenseName.getDocument().addDocumentListener(new UniversalDocumentListener() {
@Override
protected void update(DocumentEvent e)
{
tempOrigami.getLicense().setName(licenseName.getText());
}
});
licenseHomepage = new JTextField(tempOrigami.getLicense().getHomepage() != null ? tempOrigami.getLicense()
.getHomepage().toString() : "", 20);
licenseHomepage.setInputVerifier(new URIInputVerifier());
licenseHomepage.getDocument().addDocumentListener(new UniversalDocumentListener() {
@Override
protected void update(DocumentEvent e)
{
URI value = null;
try {
value = new URL(licenseHomepage.getText()).toURI();
} catch (MalformedURLException e1) {} catch (URISyntaxException e1) {}
tempOrigami.getLicense().setHomepage(value);
}
});
licenseContent = new JTextArea(tempOrigami.getLicense().getContent(), 5, 20);
licenseContent.setLineWrap(true);
licenseContent.setWrapStyleWord(true);
licenseContent.getDocument().addDocumentListener(new UniversalDocumentListener() {
@Override
protected void update(DocumentEvent e)
{
tempOrigami.getLicense().setContent(licenseContent.getText());
}
});
ButtonGroup licenseChooseGroup = new ButtonGroup();
licenseChooseHomepage = new JRadioButton();
conf.addAndRunResourceBundleListener(new Configuration.LocaleListener("application",
"OrigamiPropertiesFrame.licenseChooseHomepageLabel") {
@Override
protected void updateText(String text)
{
licenseChooseHomepage.setText(text);
}
});
licenseChooseHomepage.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e)
{
if (e.getStateChange() == ItemEvent.SELECTED) {
licenseHomepage.setVisible(true);
licenseContent.setVisible(false);
tempOrigami.getLicense().setContent(null);
predefinedLicensesGroup.clearSelection();
}
}
});
licenseChooseGroup.add(licenseChooseHomepage);
licenseChooseContent = new JRadioButton();
conf.addAndRunResourceBundleListener(new Configuration.LocaleListener("application",
"OrigamiPropertiesFrame.licenseChooseContentLabel") {
@Override
protected void updateText(String text)
{
licenseChooseContent.setText(text);
}
});
licenseChooseContent.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e)
{
if (e.getStateChange() == ItemEvent.SELECTED) {
licenseHomepage.setVisible(false);
licenseContent.setVisible(true);
tempOrigami.getLicense().setHomepage(null);
predefinedLicensesGroup.clearSelection();
}
}
});
licenseChooseGroup.add(licenseChooseContent);
if (tempOrigami.getLicense().getHomepage() != null)
licenseChooseHomepage.setSelected(true);
else
licenseChooseContent.setSelected(true);
ResourceBundle bundle = ResourceBundle.getBundle("application", conf.getLocale());
Enumeration<String> keys = bundle.getKeys();
while (keys.hasMoreElements()) {
String key = keys.nextElement();
String prefix = "license.";
if (key.startsWith(prefix)) {
final String name = key.substring(prefix.length());
final URL homepage;
try {
homepage = new URL(bundle.getString(key));
} catch (MalformedURLException e) {
continue;
}
JRadioButton btn = new JRadioButton();
predefinedLicenses.add(btn);
predefinedLicensesGroup.add(btn);
btn.setAction(new AbstractAction() {
/** */
private static final long serialVersionUID = 1120375629573349833L;
@Override
public void actionPerformed(ActionEvent e)
{
licenseChooseHomepage.doClick();
licenseName.setText(name);
licenseHomepage.setText(homepage.toString());
}
});
btn.setText(name);
}
}
List<String> selectedPermissions = new LinkedList<String>();
for (Permission p : tempOrigami.getLicense().getPermission())
selectedPermissions.add(p.getName());
licensePermissionDoNothing = new JCheckBox();
licensePermissionDoNothing.setSelected(selectedPermissions.contains("doNothing"));
conf.addAndRunResourceBundleListener(new Configuration.LocaleListener("application", "permission.doNothing") {
@Override
protected void updateText(String text)
{
licensePermissionDoNothing.setText(text);
}
});
licensePermissionDoNothing.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e)
{
if (e.getStateChange() == ItemEvent.SELECTED) {
if (licensePermissionEdit.isSelected() == licensePermissionDoNothing.isSelected())
licensePermissionEdit.setSelected(!licensePermissionDoNothing.isSelected());
if (licensePermissionExport.isSelected() == licensePermissionDoNothing.isSelected())
licensePermissionExport.setSelected(!licensePermissionDoNothing.isSelected());
if (licensePermissionDistribute.isSelected() == licensePermissionDoNothing.isSelected())
licensePermissionDistribute.setSelected(!licensePermissionDoNothing.isSelected());
}
Permission perm = PermissionConverter.parse("doNothing");
List<Permission> perms = tempOrigami.getLicense().getPermission();
if (licensePermissionDoNothing.isSelected()) {
if (!perms.contains(perm))
perms.add(perm);
} else {
perms.remove(perm);
}
}
});
licensePermissionEdit = new JCheckBox();
licensePermissionEdit.setSelected(selectedPermissions.contains("edit"));
conf.addAndRunResourceBundleListener(new Configuration.LocaleListener("application", "permission.edit") {
@Override
protected void updateText(String text)
{
licensePermissionEdit.setText(text);
}
});
licensePermissionEdit.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e)
{
if (e.getStateChange() == ItemEvent.SELECTED) {
if (licensePermissionEdit.isSelected() == licensePermissionDoNothing.isSelected())
licensePermissionDoNothing.setSelected(!licensePermissionEdit.isSelected());
}
Permission perm = PermissionConverter.parse("edit");
List<Permission> perms = tempOrigami.getLicense().getPermission();
if (licensePermissionEdit.isSelected()) {
if (!perms.contains(perm))
perms.add(perm);
} else {
perms.remove(perm);
}
}
});
licensePermissionExport = new JCheckBox();
licensePermissionExport.setSelected(selectedPermissions.contains("export"));
conf.addAndRunResourceBundleListener(new Configuration.LocaleListener("application", "permission.export") {
@Override
protected void updateText(String text)
{
licensePermissionExport.setText(text);
}
});
licensePermissionExport.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e)
{
if (e.getStateChange() == ItemEvent.SELECTED) {
if (licensePermissionExport.isSelected() == licensePermissionDoNothing.isSelected())
licensePermissionDoNothing.setSelected(!licensePermissionExport.isSelected());
}
Permission perm = PermissionConverter.parse("export");
List<Permission> perms = tempOrigami.getLicense().getPermission();
if (licensePermissionExport.isSelected()) {
if (!perms.contains(perm))
perms.add(perm);
} else {
perms.remove(perm);
}
}
});
licensePermissionDistribute = new JCheckBox();
licensePermissionDistribute.setSelected(selectedPermissions.contains("distribute"));
conf.addAndRunResourceBundleListener(new Configuration.LocaleListener("application", "permission.distribute") {
@Override
protected void updateText(String text)
{
licensePermissionDistribute.setText(text);
}
});
licensePermissionDistribute.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e)
{
if (e.getStateChange() == ItemEvent.SELECTED) {
if (licensePermissionDistribute.isSelected() == licensePermissionDoNothing.isSelected())
licensePermissionDoNothing.setSelected(!licensePermissionDistribute.isSelected());
}
Permission perm = PermissionConverter.parse("distribute");
List<Permission> perms = tempOrigami.getLicense().getPermission();
if (licensePermissionDistribute.isSelected()) {
if (!perms.contains(perm))
perms.add(perm);
} else {
perms.remove(perm);
}
}
});
original = new JTextField(tempOrigami.getOriginal() != null ? tempOrigami.getOriginal().toString() : "", 20);
original.setInputVerifier(new URIInputVerifier());
original.getDocument().addDocumentListener(new UniversalDocumentListener() {
@Override
protected void update(DocumentEvent e)
{
URI value = null;
try {
value = new URL(original.getText()).toURI();
} catch (MalformedURLException e1) {} catch (URISyntaxException e1) {}
tempOrigami.setOriginal(value);
}
});
ButtonGroup thumbnailChooseGroup = new ButtonGroup();
thumbnailLoadFromModel = new JRadioButton();
conf.addAndRunResourceBundleListener(new Configuration.LocaleListener("application",
"OrigamiPropertiesFrame.thumbnailLoadFromModelLabel") {
@Override
protected void updateText(String text)
{
thumbnailLoadFromModel.setText(text);
}
});
thumbnailLoadFromModel.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e)
{
if (e.getStateChange() == ItemEvent.SELECTED) {
thumbnailFileInput.setEnabled(false);
thumbnailPreview.setGenerated(true);
imageFileType = tempOrigami.getThumbnail().getImage().getType();
tempOrigami.getThumbnail().getImage().setType("jpg");
tempOrigami.getThumbnail().setGenerated(true);
if (generatedThumbnail != null)
tempOrigami.getThumbnail().getImage().setImageIcon(new ImageIcon(generatedThumbnail));
}
}
});
thumbnailChooseGroup.add(thumbnailLoadFromModel);
imageFileType = tempOrigami.getThumbnail().getImage().getType();
thumbnailLoadFromFile = new JRadioButton();
conf.addAndRunResourceBundleListener(new Configuration.LocaleListener("application",
"OrigamiPropertiesFrame.thumbnailLoadFromFileLabel") {
@Override
protected void updateText(String text)
{
thumbnailLoadFromFile.setText(text);
}
});
thumbnailLoadFromFile.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e)
{
if (e.getStateChange() == ItemEvent.SELECTED) {
thumbnailFileInput.setEnabled(true);
thumbnailPreview.setGenerated(false);
tempOrigami.getThumbnail().getImage().setType(imageFileType);
tempOrigami.getThumbnail().setGenerated(false);
if (fromFileThumbnail != null)
tempOrigami.getThumbnail().getImage().setImageIcon(new ImageIcon(fromFileThumbnail));
}
}
});
thumbnailChooseGroup.add(thumbnailLoadFromFile);
thumbnailFileInput = new JFileInput(ServiceLocator.get(ConfigurationManager.class).get().getLastOpenPath()
.toString(), 20);
thumbnailFileInput.getFileChooser().setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
conf.addAndRunResourceBundleListener(new Configuration.LocaleListener("application", "fileFilter.images") {
@Override
protected void updateText(String text)
{
thumbnailFileInput.getFileChooser().setFileFilter(
new FileNameExtensionFilter(text, "BMP", "JPG", "PNG", "GIF"));
}
});
thumbnailFileInput.getFileChooser().setDialogType(JFileChooser.OPEN_DIALOG);
conf.addAndRunResourceBundleListener(new Configuration.LocaleListener("application",
"OrigamiPropertiesFrame.thumbnailFileDialog.approve.text") {
@Override
protected void updateText(String text)
{
String mnemonic = bundle.getString("OrigamiPropertiesFrame.thumbnailFileDialog.approve.mnemonic");
String tooltip = bundle.getString("OrigamiPropertiesFrame.thumbnailFileDialog.approve.tooltip");
thumbnailFileInput.getFileChooser().setApproveButtonText(text);
thumbnailFileInput.getFileChooser().setApproveButtonMnemonic(
KeyStroke.getKeyStroke(mnemonic).getKeyCode());
thumbnailFileInput.getFileChooser().setApproveButtonToolTipText(
ServiceLocator.get(TooltipFactory.class).getDecorated(tooltip, text, "open-file-32.png",
KeyStroke.getKeyStroke("alt " + mnemonic)));
}
});
thumbnailFileInput.getTextField().getDocument().addDocumentListener(new UniversalDocumentListener() {
@Override
protected void update(DocumentEvent e)
{
File selected = thumbnailFileInput.getFileChooser().getSelectedFile();
ServiceLocator.get(ConfigurationManager.class).get().setLastOpenPath(selected);
tempOrigami.getThumbnail().getImage()
.setType(selected.toString().substring(selected.toString().lastIndexOf('.') + 1));
imageFileType = tempOrigami.getThumbnail().getImage().getType();
tempOrigami.getThumbnail().getImage().setImageIcon(new ImageIcon(selected.toString()));
tempOrigami.getThumbnail().setGenerated(false);
fromFileThumbnail = tempOrigami.getThumbnail().getImage().getImageIcon().getImage();
if (tempOrigami.getThumbnail().getImage().getImageIcon() != null)
thumbnailPreview.setImage(tempOrigami.getThumbnail().getImage().getImageIcon().getImage());
else
thumbnailPreview.setImage(null);
}
});
thumbnailPreview = new JThumbnail(tempOrigami.getThumbnail().getImage().getValue() != null
&& tempOrigami.getThumbnail().getImage().getValue().length > 0 ? tempOrigami.getThumbnail().getImage()
.getImageIcon().getImage() : null);
if (tempOrigami.getThumbnail().isGenerated()) {
if (tempOrigami.getThumbnail().getImage().isImageNonEmpty())
generatedThumbnail = tempOrigami.getThumbnail().getImage().getImageIcon().getImage();
thumbnailLoadFromModel.doClick();
} else {
fromFileThumbnail = tempOrigami.getThumbnail().getImage().getImageIcon().getImage();
thumbnailLoadFromFile.doClick();
}
diagramPaper = new JDiagramPaperInput(tempOrigami.getPaper());
modelPaper = new JModelPaperInput(tempOrigami.getModel().getPaper());
if (!isCreating)
// TODO maybe allow changes not affecting aspect ratio
modelPaper.lockSize();
String okKey = "OrigamiPropertiesFrame.okButton." + (isCreating ? "create" : "edit");
okButton = new JLocalizedButton("application", okKey);
okButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e)
{
if (verifyForm()) {
if (isCreating)
saveDefaults();
setVisible(false);
}
}
});
cancelButton = new JLocalizedButton("application", "buttons.cancel");
cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e)
{
tempOrigami = null;
setVisible(false);
}
});
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e)
{
tempOrigami = null;
}
});
}
/**
* Add all components to a layout.
*/
protected void buildLayout()
{
Configuration conf = ServiceLocator.get(ConfigurationManager.class).get();
CellConstraints cc = new CellConstraints();
final JTabbedPane tabPane = new JTabbedPane();
int tabIndex = 0;
JPanel basicPanel = new JPanel(new FormLayout("$dmargin,right:pref,$lcgap,pref:grow,$dmargin",
"$dmargin,pref,$lgap,pref,$lgap,pref,$lgap,pref,$lgap,pref,$lgap,pref,$lgap,pref,$dmargin"));
final int basicPanelTabIndex = tabIndex++;
tabPane.addTab("", basicPanel);
conf.addAndRunResourceBundleListener(new Configuration.LocaleListener("application",
"OrigamiPropertiesFrame.basicPanelTitle") {
@Override
protected void updateText(String text)
{
tabPane.setTitleAt(basicPanelTabIndex, text);
}
});
basicPanel.add(nameLabel, cc.xy(2, 2));
basicPanel.add(name, cc.xy(4, 2));
basicPanel.add(creationDateLabel, cc.xy(2, 4));
basicPanel.add(creationDate, cc.xy(4, 4));
basicPanel.add(authorNameLabel, cc.xy(2, 6));
basicPanel.add(authorName, cc.xy(4, 6));
basicPanel.add(authorHomepageLabel, cc.xy(2, 8));
basicPanel.add(authorHomepage, cc.xy(4, 8));
basicPanel.add(shortDescLabel, cc.xy(2, 10));
basicPanel.add(shortDesc, cc.xy(4, 10));
basicPanel.add(originalLabel, cc.xy(2, 12));
basicPanel.add(original, cc.xy(4, 12));
basicPanel.add(description, cc.xywh(2, 14, 3, 1));
JPanel thumbnailPanel = new JPanel(new FormLayout(
"$dmargin,center:min(pref;50dlu),$ugap,pref,$ugap,pref,$dmargin", "$dmargin,pref,$lgap,pref,$dmargin"));
final int thumbnailPanelTabIndex = tabIndex++;
tabPane.addTab("", thumbnailPanel);
conf.addAndRunResourceBundleListener(new Configuration.LocaleListener("application",
"OrigamiPropertiesFrame.thumbnailPanelTitle") {
@Override
protected void updateText(String text)
{
tabPane.setTitleAt(thumbnailPanelTabIndex, text);
}
});
thumbnailPanel.add(thumbnailPreviewLabel, cc.xy(2, 2));
thumbnailPanel.add(thumbnailPreview, cc.xy(2, 4));
thumbnailPanel.add(thumbnailLoadFromModel, cc.xy(4, 2));
thumbnailPanel.add(thumbnailLoadFromFile, cc.xy(6, 2));
thumbnailPanel.add(thumbnailFileInputLabel, cc.xy(4, 4));
thumbnailPanel.add(thumbnailFileInput, cc.xy(6, 4));
final JScrollPane licenseContentScrollPane = new JScrollPane(licenseContent,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
JPanel licenseNamePanel = new JPanel(new FormLayout("pref,$lcgap,pref:grow", "pref"));
licenseNamePanel.add(licenseNameLabel, cc.xy(1, 1));
licenseNamePanel.add(licenseName, cc.xy(3, 1));
licenseChooseContent.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e)
{
if (e.getStateChange() == ItemEvent.SELECTED) {
licenseHomepageLabel.setVisible(false);
licenseContentLabel.setVisible(true);
licenseContentScrollPane.setVisible(true);
}
}
});
licenseChooseHomepage.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e)
{
if (e.getStateChange() == ItemEvent.SELECTED) {
licenseContentLabel.setVisible(false);
licenseHomepageLabel.setVisible(true);
licenseContentScrollPane.setVisible(false);
}
}
});
licenseHomepageLabel.setVisible(licenseHomepage.isVisible());
licenseContentLabel.setVisible(licenseContent.isVisible());
licenseContentScrollPane.setVisible(licenseContent.isVisible());
JPanel licenseContentPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
licenseContentPanel.add(licenseChooseContent);
licenseContentPanel.add(licenseChooseHomepage);
JPanel licenseHomepagePanel = new JPanel(new FormLayout("pref,$lcgap,pref:grow", "pref"));
licenseHomepagePanel.add(licenseHomepageLabel, cc.xy(1, 1));
licenseHomepagePanel.add(licenseHomepage, cc.xy(3, 1));
JPanel licensePermissionPanel = new JPanel(new GridLayout(0, 1));
licensePermissionPanel.add(licensePermissionDoNothing);
licensePermissionPanel.add(licensePermissionEdit);
licensePermissionPanel.add(licensePermissionExport);
licensePermissionPanel.add(licensePermissionDistribute);
JPanel licensePanel = new JPanel(new FormLayout("$dmargin,min(pref;500px):grow,$dmargin",
"$dmargin,pref,$lgap,pref,$lgap,pref,$rgap,pref,$lgap,pref,$lgap,pref,$lgap,pref,$lgap,pref,$dmargin"));
final int licensePanelTabIndex = tabIndex++;
tabPane.addTab("", licensePanel);
conf.addAndRunResourceBundleListener(new Configuration.LocaleListener("application",
"OrigamiPropertiesFrame.licensePanelTitle") {
@Override
protected void updateText(String text)
{
tabPane.setTitleAt(licensePanelTabIndex, text);
}
});
JPanel predefinedLicensesPanel = new JPanel(new FormLayout("pref"));
PanelBuilder builder = new PanelBuilder((FormLayout) predefinedLicensesPanel.getLayout(),
predefinedLicensesPanel);
for (JRadioButton b : predefinedLicenses) {
builder.appendRow("$lgap");
builder.appendRow("pref");
builder.nextLine();
builder.add(b);
builder.nextLine();
}
JLabel licenseChooseLabel = new JLocalizedLabel("application", "OrigamiPropertiesFrame.licenseChooseLabel");
licensePanel.add(licenseNamePanel, cc.xy(2, 2));
licensePanel.add(predefinedLicensesPanel, cc.xy(2, 4));
licensePanel.add(licenseChooseLabel, cc.xy(2, 6));
licensePanel.add(licenseContentPanel, cc.xy(2, 8));
licensePanel.add(licenseContentLabel, cc.xy(2, 10));
licensePanel.add(licenseContentScrollPane, cc.xy(2, 12));
licensePanel.add(licenseHomepagePanel, cc.xy(2, 14));
licensePanel.add(licensePermissionPanel, cc.xy(2, 16));
final int diagramPaperTabIndex = tabIndex++;
JPanel diagramPaperPanel = new JPanel(new FormLayout("$dmargin,default,$dmargin", "$dmargin,default,$dmargin"));
diagramPaperPanel.add(diagramPaper, cc.xy(2, 2));
tabPane.addTab("", diagramPaperPanel);
conf.addAndRunResourceBundleListener(new Configuration.LocaleListener("application",
"OrigamiPropertiesFrame.diagramPaperLabel") {
@Override
protected void updateText(String text)
{
tabPane.setTitleAt(diagramPaperTabIndex, text);
}
});
final int modelPaperTabIndex = tabIndex++;
JPanel modelPaperPanel = new JPanel(new FormLayout("$dmargin,default,$dmargin", "$dmargin,default,$dmargin"));
modelPaperPanel.add(modelPaper, cc.xy(2, 2));
tabPane.addTab("", modelPaperPanel);
conf.addAndRunResourceBundleListener(new Configuration.LocaleListener("application",
"OrigamiPropertiesFrame.modelPaperLabel") {
@Override
protected void updateText(String text)
{
tabPane.setTitleAt(modelPaperTabIndex, text);
}
});
JPanel dialogButtonsPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
dialogButtonsPanel.add(cancelButton);
dialogButtonsPanel.add(okButton);
setLayout(new FormLayout("default", "default,$lgap,default"));
add(tabPane, cc.xy(1, 1));
add(dialogButtonsPanel, cc.xy(1, 3));
pack();
}
/**
* @return the origami that was set to this frame (or a new one if <code>null</code> was specified) with the
* metadata copied from this dialog's inputs' values. <code>null</code> can be returned only if the user
* cancelled the dialog for creating a new origami.
*/
public Origami getOrigami()
{
if (tempOrigami != null) {
tempOrigami.setPaper(diagramPaper.getPaper());
tempOrigami.getModel().setPaper(modelPaper.getPaper());
}
if (origami != null && tempOrigami != null) {
origami.getMetadataFrom(tempOrigami);
return origami;
} else if (origami != null) {
return origami;
}
return tempOrigami;
}
/**
* @param origami The origami that should be edited by the dialog.
*/
protected void setOrigami(Origami origami)
{
this.origami = origami;
tempOrigami = (Origami) new ObjectFactory().createOrigami();
tempOrigami.initStructure(false);
if (origami != null) {
tempOrigami.getMetadataFrom(origami);
}
isCreating = (origami == null);
}
/**
* Where applicable, fills or selects a default value. Empty default values are not filled.
*/
protected void fillDefaults()
{
Configuration conf = ServiceLocator.get(ConfigurationManager.class).get();
creationDate.setDate(new Date());
String authorName = conf.getDefaultAuthorName();
this.authorName.setText(authorName);
thumbnailLoadFromModel.doClick();
String authorHomepage = conf.getDefaultAuthorHomepage();
this.authorHomepage.setText(authorHomepage);
this.diagramPaper.selectFirstNonCustom();
this.modelPaper.selectFirstNonCustom();
pack();
}
/**
* Save all values that can be further used as default values.
*/
protected void saveDefaults()
{
Configuration conf = ServiceLocator.get(ConfigurationManager.class).get();
conf.setDefaultAuthorName(this.authorName.getText());
conf.setDefaultAuthorHomepage(this.authorHomepage.getText());
}
/**
* Pack the window if it is smaller than it needs.
*/
protected void maybePack()
{
Dimension layoutSize = getLayout().preferredLayoutSize(this);
Dimension currentSize = getSize();
if (layoutSize.width > currentSize.width || layoutSize.height > currentSize.height)
pack();
}
/**
* @return Whether all the fields are filled correctly and required fields are filled.
*/
protected boolean verifyForm()
{
ResourceBundle messages = ResourceBundle.getBundle("application", ServiceLocator
.get(ConfigurationManager.class).get().getLocale());
List<String> errors = new LinkedList<String>();
if (name.getStrings().size() == 0)
errors.add(messages.getString("OrigamiPropertiesFrame.errors.nameEmpty"));
if (shortDesc.getStrings().size() == 0)
errors.add(messages.getString("OrigamiPropertiesFrame.errors.shortDescEmpty"));
if (authorName.getText().length() == 0)
errors.add(messages.getString("OrigamiPropertiesFrame.errors.authorNameEmpty"));
if (licenseName.getText().length() == 0)
errors.add(messages.getString("OrigamiPropertiesFrame.errors.licenseNameEmpty"));
if (licenseChooseHomepage.isSelected() && licenseHomepage.getText().length() == 0)
errors.add(messages.getString("OrigamiPropertiesFrame.errors.licenseHomepageEmpty"));
if (licenseChooseContent.isSelected() && licenseContent.getText().length() == 0)
errors.add(messages.getString("OrigamiPropertiesFrame.errors.licenseContentEmpty"));
if (thumbnailLoadFromFile.isSelected() && !new File(thumbnailFileInput.getTextField().getText()).exists())
errors.add(messages.getString("OrigamiPropertiesFrame.errors.thumbnailFileNotExists"));
UnitDimension dSize = diagramPaper.getPaper().getSize();
if (dSize.getWidth() == 0d || dSize.getHeight() == 0d
|| (dSize.getUnit() == Unit.REL && dSize.getReferenceLength() == 0d))
errors.add(messages.getString("OrigamiPropertiesFrame.errors.diagramPaperSizeZero"));
UnitDimension mSize = modelPaper.getPaper().getSize();
if (mSize.getWidth() == 0d || mSize.getHeight() == 0d
|| (mSize.getUnit() == Unit.REL && mSize.getReferenceLength() == 0d))
errors.add(messages.getString("OrigamiPropertiesFrame.errors.modelPaperSizeZero"));
if (!errors.isEmpty()) {
StringBuilder errMessage = new StringBuilder();
for (String err : errors) {
errMessage.append(err).append("\n");
}
JOptionPane.showMessageDialog(this, errMessage.toString(),
messages.getString("OrigamiPropertiesFrame.errors.title"), JOptionPane.ERROR_MESSAGE);
return false;
} else {
return true;
}
}
/**
* Input verifier that verifies the content is a URI.
*
* @author Martin Pecka
*/
protected class URIInputVerifier extends InputVerifier
{
@Override
public boolean verify(JComponent input)
{
if (!(input instanceof JTextField))
return false;
JTextField field = (JTextField) input;
if (field.getText().length() == 0)
return true;
try {
new URL(field.getText()).toURI();
return true;
} catch (MalformedURLException e) {
return false;
} catch (URISyntaxException e) {
return false;
}
}
}
/**
* A thumbnail that allows its generation from model.
*
* @author Martin Pecka
*/
protected class JThumbnail extends JImage
{
/** */
private static final long serialVersionUID = 5195157249274834168L;
protected boolean generated = false;
protected JMultilineLabel label = new JMultilineLabel("");
/**
* @param image
*/
public JThumbnail(Image image)
{
super(image);
final ResourceBundle messages = ResourceBundle.getBundle("application",
ServiceLocator.get(ConfigurationManager.class).get().getLocale());
setLayout(new GridLayout());
label.setText("<html><body><center>" + messages.getString("OrigamiPropertiesFrame.pendingThumbnail")
+ "</center></body></html>");
label.setVisible(false);
label.setBackground(Color.WHITE);
add(label);
setToolTipText(messages.getString("OrigamiPropertiesFrame.doubleClickToReloadThumbnail"));
java.awt.event.MouseListener listener = new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e)
{
if (generated && origami != null && (e.getClickCount() > 1 || e.getSource() == label)) {
setImage(null);
label.setVisible(true);
label.setText("<html><body><center>"
+ messages.getString("OrigamiPropertiesFrame.generatingThumbnail")
+ "</center></body></html>");
new Thread(new Runnable() {
@Override
public void run()
{
generatedThumbnail = ServiceLocator.get(StepThumbnailGenerator.class).getThumbnail(
origami, 150, 150);
if (generatedThumbnail != null)
tempOrigami.getThumbnail().getImage()
.setImageIcon(new ImageIcon(generatedThumbnail));
else
tempOrigami.getThumbnail().getImage().setImageIcon(null);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run()
{
setImage(generatedThumbnail);
label.setVisible(false);
label.setText("<html><body><center>"
+ messages.getString("OrigamiPropertiesFrame.pendingThumbnail")
+ "</center></body></html>");
repaint();
}
});
}
}).start();
}
}
};
label.addMouseListener(listener);
addMouseListener(listener);
}
/**
* If you change this property to true, then a message will be displayed that the user should click the
* thumbnail to generate it from model. If you set it to false, the loaded image will be displayed.
*
* @param generated
*/
public void setGenerated(boolean generated)
{
this.generated = generated;
if (origami == null)
return;
if (generated) {
if (generatedThumbnail != null) {
setImage(generatedThumbnail);
label.setVisible(false);
} else {
setImage(null);
label.setVisible(true);
}
} else {
setImage(fromFileThumbnail);
label.setVisible(false);
}
repaint();
}
@Override
public Dimension getMinimumSize()
{
return new Dimension(60, 60);
}
@Override
public Dimension getPreferredSize()
{
return new Dimension(60, 60);
}
}
}