/*
* Copyright (c) 2009 The Jackson Laboratory
*
* This software was developed by Gary Churchill's Lab at The Jackson
* Laboratory (see http://research.jax.org/faculty/churchill).
*
* This 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.
*
* This software 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 software. If not, see <http://www.gnu.org/licenses/>.
*/
package org.jax.qtl.scan.gui;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.jax.qtl.scan.ScanCommandBuilder;
import org.jax.r.RSyntaxException;
import org.jax.r.RUtilities;
import org.jax.r.gui.RCommandEditorListener;
import org.jax.r.jriutilities.JRIUtilityFunctions;
import org.jax.r.jriutilities.RInterfaceFactory;
import org.jax.util.TextWrapper;
/**
* A panel for editing the permutations and result name of a
* {@link ScanCommandBuilder}
* @author <A HREF="mailto:keith.sheppard@jax.org">Keith Sheppard</A>
*/
public class PermutationsAndResultScanPanel extends ScanCommandEditorPanel
{
/**
* every {@link java.io.Serializable} is supposed to have one of these
*/
private static final long serialVersionUID = 5936966692016099862L;
/**
* the logger
*/
private static final Logger LOG = Logger.getLogger(
PermutationsAndResultScanPanel.class.getName());
private final ScanPermutationsPanel scanPermutationsPanel;
private final ScanCommandBuilder scanCommand;
/**
* Constructor
* @param scanCommand
* the scan command that this panel edits
*/
public PermutationsAndResultScanPanel(ScanCommandBuilder scanCommand)
{
this.scanCommand = scanCommand;
this.scanPermutationsPanel = new ScanPermutationsPanel(scanCommand);
this.initComponents();
this.postGuiInit();
}
/**
* {@inheritDoc}
*/
@Override
public void addRCommandEditorListener(RCommandEditorListener editorListener)
{
super.addRCommandEditorListener(editorListener);
this.scanPermutationsPanel.addRCommandEditorListener(editorListener);
}
/**
* {@inheritDoc}
*/
@Override
public void removeRCommandEditorListener(
RCommandEditorListener editorListener)
{
super.removeRCommandEditorListener(editorListener);
this.scanPermutationsPanel.removeRCommandEditorListener(editorListener);
}
/**
* Take care of the initialization that needs to happen after the
* GUI builder code has run.
*/
private void postGuiInit()
{
this.scanResultTextField.getDocument().addDocumentListener(
new DocumentListener()
{
public void changedUpdate(DocumentEvent e)
{
PermutationsAndResultScanPanel.this.scanResultNameChanged();
}
public void insertUpdate(DocumentEvent e)
{
PermutationsAndResultScanPanel.this.scanResultNameChanged();
}
public void removeUpdate(DocumentEvent e)
{
PermutationsAndResultScanPanel.this.scanResultNameChanged();
}
});
}
/**
* Respond to a change in the scan result name
*/
private void scanResultNameChanged()
{
try
{
// construct the scan result text field from the readable name
String scanResultIdentifier = RUtilities.fromReadableNameToRIdentifier(
this.scanResultTextField.getText().trim());
if(scanResultIdentifier.length() > 0)
{
// append the cross name to the identifier
scanResultIdentifier =
this.scanCommand.getCross().getAccessorExpressionString() + "." +
scanResultIdentifier;
}
this.scanCommand.setScanResultName(
scanResultIdentifier);
this.fireCommandModified();
}
catch(RSyntaxException ex)
{
this.scanCommand.setScanResultName(null);
this.fireCommandModified();
LOG.log(Level.FINE,
"user error: bad syntax for scan result",
ex);
}
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("all")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
scanResultLabel = new javax.swing.JLabel();
scanResultTextField = new javax.swing.JTextField();
permutationsPanelDownCast = this.scanPermutationsPanel;
scanResultLabel.setText("Name Your Scan Result:");
org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(layout.createSequentialGroup()
.addContainerGap()
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(permutationsPanelDownCast, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 363, Short.MAX_VALUE)
.add(layout.createSequentialGroup()
.add(scanResultLabel)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(scanResultTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 140, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(layout.createSequentialGroup()
.addContainerGap()
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(scanResultLabel)
.add(scanResultTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(permutationsPanelDownCast, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 216, Short.MAX_VALUE)
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPanel permutationsPanelDownCast;
private javax.swing.JLabel scanResultLabel;
private javax.swing.JTextField scanResultTextField;
// End of variables declaration//GEN-END:variables
/**
* Validate the data contained in this panel. The user is alerted if
* there is something wrong with the data format
* @return
* true iff the validation succeeds
*/
public boolean validateData()
{
String message = null;
String scanResultIdentifier = this.scanCommand.getScanResultName();
String readableScanResultName =
this.scanResultTextField.getText().trim();
if(scanResultIdentifier == null || scanResultIdentifier.length() == 0)
{
if(this.scanResultTextField.getText().length() == 0)
{
message = "Scan result name cannot be empty";
}
else
{
message = RUtilities.getErrorMessageForReadableName(
readableScanResultName);
if(message == null)
{
message = "Cannot parse scan result name";
}
}
}
else if(JRIUtilityFunctions.isTopLevelObject(
scanResultIdentifier,
RInterfaceFactory.getRInterfaceInstance()))
{
message =
"The name \"" + readableScanResultName + "\" conflicts with " +
"an existing data object. Please choose another name.";
}
if(message != null)
{
JOptionPane.showMessageDialog(
this,
TextWrapper.wrapText(
message,
TextWrapper.DEFAULT_DIALOG_COLUMN_COUNT),
"Validation Failed",
JOptionPane.WARNING_MESSAGE);
return false;
}
else
{
return true;
}
}
/**
* This function tells this panel that a component other than itself
* has edited the {@link ScanCommandBuilder} and that we need to refresh
* our graphics to reflect those changes.
*/
public void refreshGui()
{
String scanResultName = this.scanCommand.getScanResultName();
String crossNamePlusDot =
this.scanCommand.getCross().getAccessorExpressionString() + ".";
if(scanResultName != null && scanResultName.startsWith(crossNamePlusDot))
{
scanResultName = scanResultName.substring(crossNamePlusDot.length());
this.scanResultTextField.setText(RUtilities.fromRIdentifierToReadableName(
scanResultName));
}
else
{
this.scanResultTextField.setText("");
}
this.scanPermutationsPanel.refreshGui();
}
/**
* {@inheritDoc}
*/
@Override
protected ScanCommandBuilder getScanCommand()
{
return this.scanCommand;
}
}