-
tjc authored
git-svn-id: svn+ssh://svn.internal.sanger.ac.uk/repos/svn/pathsoft/artemis/trunk@10790 ee4ac58c-ac51-4696-9907-e4b3aa274f04
tjc authoredgit-svn-id: svn+ssh://svn.internal.sanger.ac.uk/repos/svn/pathsoft/artemis/trunk@10790 ee4ac58c-ac51-4696-9907-e4b3aa274f04
FeatureEdit.java 61.17 KiB
/* FeatureEdit.java
*
* created: Tue Dec 1 1998
*
* This file is part of Artemis
*
* Copyright (C) 1998,1999,2000,2001,2002 Genome Research Limited
*
* 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 (at your option) 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.
*
* $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/components/FeatureEdit.java,v 1.69 2009-05-13 10:43:07 tjc Exp $
**/
package uk.ac.sanger.artemis.components;
import uk.ac.sanger.artemis.util.*;
import uk.ac.sanger.artemis.*;
import uk.ac.sanger.artemis.sequence.MarkerRange;
import uk.ac.sanger.artemis.io.ChadoCanonicalGene;
import uk.ac.sanger.artemis.io.DatabaseDocumentEntry;
import uk.ac.sanger.artemis.io.DocumentEntry;
import uk.ac.sanger.artemis.io.GFFDocumentEntry;
import uk.ac.sanger.artemis.io.GFFStreamFeature;
import uk.ac.sanger.artemis.io.OutOfDateException;
import uk.ac.sanger.artemis.io.LocationParseException;
import uk.ac.sanger.artemis.io.PartialSequence;
import uk.ac.sanger.artemis.io.QualifierLazyLoading;
import uk.ac.sanger.artemis.io.QualifierParseException;
import uk.ac.sanger.artemis.io.Range;
import uk.ac.sanger.artemis.io.RangeVector;
import uk.ac.sanger.artemis.io.Key;
import uk.ac.sanger.artemis.io.KeyVector;
import uk.ac.sanger.artemis.io.Location;
import uk.ac.sanger.artemis.io.Qualifier;
import uk.ac.sanger.artemis.io.QualifierVector;
import uk.ac.sanger.artemis.io.EntryInformation;
import uk.ac.sanger.artemis.io.EntryInformationException;
import uk.ac.sanger.artemis.io.StreamQualifier;
import uk.ac.sanger.artemis.io.QualifierInfo;
import uk.ac.sanger.artemis.components.ProgressThread;
import uk.ac.sanger.artemis.components.genebuilder.GeneBuilderFrame;
import uk.ac.sanger.artemis.components.genebuilder.GeneEditorPanel;
import uk.ac.sanger.artemis.components.genebuilder.GeneUtils;
import uk.ac.sanger.artemis.components.genebuilder.ProteinMapPanel;
import uk.ac.sanger.artemis.components.genebuilder.cv.CVPanel;
import uk.ac.sanger.artemis.components.genebuilder.gff.PropertiesPanel;
import uk.ac.sanger.artemis.components.genebuilder.ortholog.MatchPanel;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.Date;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
import java.util.Collections;
import java.util.Comparator;
import javax.swing.*;
/**
* FeatureEdit class
*
* @author Kim Rutherford
* @version $Id: FeatureEdit.java,v 1.69 2009-05-13 10:43:07 tjc Exp $
**/
public class FeatureEdit extends JPanel
implements EntryChangeListener, FeatureChangeListener
{
/**
*
*/
private static final long serialVersionUID = 1L;
/** The choice of feature keys - created in createComponents(). */
private KeyChoice key_choice;
/** The choice of qualifiers - created in createComponents(). */
private QualifierChoice qualifier_choice = null;
private final static int LOCATION_TEXT_WIDTH = 80;
/** The location text - set by updateLocation(). */
private JTextField location_text = new JTextField(LOCATION_TEXT_WIDTH);
/** When pressed - apply changes and dispose of the component. */
private JButton ok_button = new JButton("OK");
/** When pressed - discard changes and dispose of the component. */
private JButton cancel_button = new JButton("Cancel");
/** When pressed - apply changes and keep the component open. */
private JButton apply_button = new JButton("Apply");
/** Edit area for qualifiers - created by createComponents(). */
private QualifierTextArea qualifier_text_area;
/** The Feature this object is displaying. */
private Feature edit_feature;
/**
* The GotoEventSource that was passed to the constructor - used for the
* "Goto Feature" button.
**/
private GotoEventSource goto_event_source;
/** Entry containing the Feature this object is displaying. */
private Entry edit_entry;
/** EntryGroup that contains this Feature (passed to the constructor). */
private EntryGroup entry_group;
/**
* The datestamp of the RWCorbaFeature when updateFromFeature() was last
* called or null if this is not a RWCorbaFeature.
**/
private Date datestamp = null;
/** The Selection that was passed to the constructor. */
private Selection selection;
/**
* The contents of the QualifierTextArea before the user edits anything.
* This is used to work out if anything has changed since the creation of
* the FeatureEdit.
**/
final String orig_qualifier_text;
private JFrame frame;
/** controlled vocabulary tab */
private CVPanel cvForm;
/** GFF tab */
private PropertiesPanel propertiesPanel;
/** similarity/ortholog/paralog tab */
private MatchPanel matchForm;
private EntryInformation entry_information;
private static boolean isTabbedView = false;
private GeneEditorPanel editorPanel;
/**
* Create a new FeatureEdit object from the given Feature.
* @param entry_group The EntryGroup that contains this Feature.
* @param selection The Selection operate on. The operations are "Remove
* Range" and "Grab Range"
* @param goto_event_source The object the we will call gotoBase() on.
**/
public FeatureEdit(final Feature edit_feature,
final EntryGroup entry_group,
final Selection selection,
final GotoEventSource goto_event_source,
final JFrame frame)
{
this(edit_feature, entry_group, selection,
goto_event_source, frame,
edit_feature.getEntry().getEntryInformation());
}
public FeatureEdit(final Feature edit_feature,
final EntryGroup entry_group,
final Selection selection,
final GotoEventSource goto_event_source,
final JFrame frame, final EntryInformation entry_information)
{
this.entry_information = entry_information;
this.frame = frame;
this.edit_feature = edit_feature;
this.edit_entry = edit_feature.getEntry();
this.entry_group = entry_group;
this.selection = selection;
this.goto_event_source = goto_event_source;
setLayout(new BorderLayout());
createComponents();
updateFromFeature();
orig_qualifier_text = qualifier_text_area.getText();
if(edit_feature.getEntry() != null)
{
edit_feature.getEntry().addEntryChangeListener(this);
edit_feature.addFeatureChangeListener(this);
frame.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent event)
{
stopListening();
frame.dispose();
}
});
}
qualifier_text_area.requestFocus();
}
private boolean isPartialSequence()
{
return edit_feature.getEmblFeature().getEntry().getSequence() instanceof PartialSequence;
}
/**
* Set the feature to edit
* @param edit_feature
* @param isSet
*/
public void setActiveFeature(final Feature edit_feature,
final boolean isSet)
{
if(!isPartialSequence() && isSet)
setFeature();
this.edit_feature = edit_feature;
this.edit_entry = edit_feature.getEntry();
updateFromFeature();
}
/**
* Remove this object as a feature and entry change listener.
**/
public void stopListening()
{
getEntry().removeEntryChangeListener(this);
getFeature().removeFeatureChangeListener(this);
if(cvForm != null)
getFeature().removeFeatureChangeListener(cvForm);
if(propertiesPanel != null)
getFeature().removeFeatureChangeListener(propertiesPanel);
if(matchForm != null)
getFeature().removeFeatureChangeListener(matchForm);
}
/**
* Implementation of the EntryChangeListener interface. We listen to
* EntryChange events so we can notify the user if of this component if the
* feature gets deleted.
**/
public void entryChanged(EntryChangeEvent event)
{
switch(event.getType())
{
case EntryChangeEvent.FEATURE_DELETED:
if(event.getFeature() == edit_feature)
{
stopListening();
frame.dispose();
}
break;
default:
// do nothing;
break;
}
}
/**
* Add an ActionListener to the Cancel JButton of this FeatureEdit.
**/
public void addCancelActionListener(final ActionListener l)
{
cancel_button.addActionListener(l);
}
/**
* Remove an ActionListener from the Cancel JButton of this FeatureEdit.
**/
public void removeCancelActionListener(final ActionListener l)
{
cancel_button.removeActionListener(l);
}
/**
* Add an ActionListener to the Apply JButton of this FeatureEdit.
**/
public void addApplyActionListener(final ActionListener l)
{
apply_button.addActionListener(l);
}
/**
* Remove an ActionListener from the Apply JButton of this FeatureEdit.
**/
public void removeApplyActionListener(final ActionListener l)
{
apply_button.removeActionListener(l);
}
/**
* Implementation of the FeatureChangeListener interface. We need to
* listen to feature change events from the Features in this object so that
* we can update the display.
* @param event The change event.
**/
public void featureChanged(FeatureChangeEvent event)
{
getFeature().resetColour();
// re-read the information from the feature
switch(event.getType())
{
case FeatureChangeEvent.LOCATION_CHANGED:
updateLocation();
break;
case FeatureChangeEvent.SEGMENT_CHANGED:
updateLocation();
break;
case FeatureChangeEvent.KEY_CHANGED:
updateKey();
break;
case FeatureChangeEvent.QUALIFIER_CHANGED:
if(qualifier_text_area.getText().equals(orig_qualifier_text))
updateFromFeature();
else
{
if(!event.getFeature().getIDString().equals(getFeature().getIDString()))
break;
final String message =
"warning: the qualifiers have changed outside the editor - " +
"view now?";
final YesNoDialog yes_no_dialog =
new YesNoDialog(frame, message);
if(yes_no_dialog.getResult())
new FeatureViewer(getFeature());
}
break;
default:
updateFromFeature();
break;
}
}
/**
* Create all the components for this FeatureEdit component.
**/
private void createComponents()
{
qualifier_text_area = new QualifierTextArea();
//qualifier_text_area.setWrapStyleWord(true);
FlowLayout flowLayoutZeroHVgap = new FlowLayout(FlowLayout.LEADING, 0, 0);
key_choice =
new KeyChoice(getEntryInformation(),getFeature().getKey());
key_choice.setLayout(flowLayoutZeroHVgap);
final JPanel key_and_qualifier_panel = new JPanel();
location_text.setBackground(Color.white);
final JPanel key_panel = new JPanel(flowLayoutZeroHVgap);
final JLabel locLabel = new JLabel("Location: ");
final JLabel keyLabel = new JLabel("Key: ");
keyLabel.setHorizontalAlignment(SwingConstants.RIGHT);
keyLabel.setPreferredSize(locLabel.getPreferredSize());
key_panel.add(keyLabel);
key_panel.add(key_choice);
key_and_qualifier_panel.setLayout(new BorderLayout());
key_and_qualifier_panel.add(key_panel, "West");
boolean isGFF = false;
if(edit_feature.getEmblFeature().getEntry() instanceof GFFDocumentEntry)
isGFF = true;
qualifier_choice = new QualifierChoice(getEntryInformation(),
key_choice.getSelectedItem(),null,
isGFF);
final JPanel qualifier_panel = new JPanel(new FlowLayout(FlowLayout.TRAILING,0,0));
final JButton qualifier_add_button = new JButton("Add Qualifier:");
qualifier_panel.add(qualifier_add_button);
qualifier_panel.add(qualifier_choice);
key_and_qualifier_panel.add(qualifier_panel, "East");
key_choice.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent _)
{
qualifier_choice.setKey(key_choice.getSelectedItem());
}
});
qualifier_add_button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
final String qualifier_name =
(String)qualifier_choice.getSelectedItem();
QualifierInfo qualifier_info =
getEntryInformation().getQualifierInfo(qualifier_name);
if(qualifier_info == null)
qualifier_info = new QualifierInfo(qualifier_name,
QualifierInfo.OPTIONAL_QUOTED_TEXT,
null, null, false);
qualifier_text_area.append("/" + qualifier_name);
switch(qualifier_info.getType())
{
case QualifierInfo.QUOTED_TEXT:
if(qualifier_name.equals("GO"))
{
// special case for /GO
final java.util.Calendar calendar =
java.util.Calendar.getInstance();
final Date current_time = calendar.getTime();
final java.text.SimpleDateFormat date_format =
new java.text.SimpleDateFormat("yyyyMMdd");
final StringBuffer result_buffer = new StringBuffer();
date_format.format(current_time, result_buffer,
new java.text.FieldPosition(java.text.DateFormat.DATE_FIELD));
final String go_string = "aspect=; term=; GOid=GO:; "+
"evidence=ISS; db_xref=GOC:unpublished; " +
"with=UniProtKB:; date=" + result_buffer;
qualifier_text_area.append("=\"" + go_string + "\"");
}
else if(qualifier_name.equals("controlled_curation"))
{
final java.util.Calendar calendar =
java.util.Calendar.getInstance();
final Date current_time = calendar.getTime();
final java.text.SimpleDateFormat date_format =
new java.text.SimpleDateFormat("yyyyMMdd");
final StringBuffer result_buffer = new StringBuffer();
date_format.format(current_time, result_buffer,
new java.text.FieldPosition(java.text.DateFormat.DATE_FIELD));
final String cc_string = "term=; db_xref=; date="+ result_buffer;
qualifier_text_area.append("=\"" + cc_string + "\"");
}
else
qualifier_text_area.append ("=\"\"");
break;
case QualifierInfo.NO_VALUE:
case QualifierInfo.OPTIONAL_QUOTED_TEXT:
break;
default:
qualifier_text_area.append("=");
}
qualifier_text_area.append("\n");
}
});
final JPanel middle_panel = new JPanel();
middle_panel.setLayout(new BorderLayout(0,0));
final JPanel lower_panel = new JPanel();
lower_panel.setLayout(new BorderLayout(0,0));
//final JPanel outer_location_button_panel = new JPanel(flowLayoutZeroHgap);
//outer_location_button_panel.setLayout(new BorderLayout(0,0));
final JToolBar location_button_panel = new JToolBar();
location_button_panel.setRollover(true);
//outer_location_button_panel.add(location_button_panel, "West");
lower_panel.add(location_button_panel, "North");
final JPanel location_panel = new JPanel(new BorderLayout(0,0));
location_panel.add(locLabel, "West");
location_panel.add(location_text, "Center");
final JButton complement_button = new JButton("Complement");
location_button_panel.add(complement_button);
complement_button.addActionListener(new ActionListener ()
{
public void actionPerformed(ActionEvent e)
{
complementLocation();
}
});
if(GeneUtils.isDatabaseEntry(getFeature().getEmblFeature()))
{
final JButton refresh_button = new JButton("Refresh");
location_button_panel.add(refresh_button);
refresh_button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
refresh();
}
});
}
final JButton grab_button = new JButton("Grab Range");
location_button_panel.add(grab_button);
grab_button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
grabSelectedRange();
}
});
final JButton remove_button = new JButton("Remove Range");
location_button_panel.add(remove_button);
remove_button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
removeSelectedRange();
}
});
final JButton goto_button = new JButton("Goto Feature");
location_button_panel.add(goto_button);
goto_button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
goto_event_source.gotoBase(getFeature().getFirstBaseMarker());
}
});
final JButton select_button = new JButton("Select Feature");
location_button_panel.add(select_button);
select_button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
getSelection().set(getFeature());
}
});
if(Options.getOptions().getPropertyTruthValue("sanger_options"))
{
// a PSU only hack
final JButton tidy_button = new JButton("Tidy");
location_button_panel.add(tidy_button);
tidy_button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
try
{
tidy();
tidyGO();
}
catch(QualifierParseException exception)
{
final String error_string = exception.getMessage();
new MessageDialog(frame,
"Cannot tidy - qualifier error: " +
error_string);
}
}
});
}
final JButton transferAnnotationBbutton = new JButton("TAT");
location_button_panel.add(transferAnnotationBbutton);
transferAnnotationBbutton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
java.util.List geneNames = null;
if(matchForm != null)
geneNames = matchForm.getGeneNameList();
new TransferAnnotationTool(getFeature(), entry_group, geneNames);
}
});
/*if(Options.getOptions().getProperty("external_editor") != null)
{
final JButton external_fasta_edit_button = new JButton("MESS/FASTA");
location_button_panel.add(external_fasta_edit_button);
external_fasta_edit_button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
try
{
if(getFeature().getQualifierByName("fasta_file") != null)
{
final String DEFAULT_MAX_EUK_FASTA_HITS = "10";
final String max_fasta_hits;
final String max_fasta_hits_from_options =
Options.getOptions().getProperty("mess_fasta_hits");
if(Options.getOptions().isEukaryoticMode())
{
if (max_fasta_hits_from_options == null)
max_fasta_hits = DEFAULT_MAX_EUK_FASTA_HITS;
else
max_fasta_hits = max_fasta_hits_from_options;
externalEdit(new String[] { "-fasta", "-maxhits",
max_fasta_hits, "-euk" });
}
else
{
if(max_fasta_hits_from_options == null)
{
externalEdit(new String[] { "-fasta" });
}
else
{
externalEdit(new String[] { "-fasta", "-maxhits",
max_fasta_hits_from_options });
}
}
return;
}
} catch(InvalidRelationException _) {}
new MessageDialog(frame,
"nothing to edit - no /fasta_file qualifier");
}
});
final JButton external_blastp_edit_button = new JButton("MESS/BLASTP");
location_button_panel.add(external_blastp_edit_button);
external_blastp_edit_button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
try
{
if(getFeature().getQualifierByName("blastp_file") != null)
{
final String DEFAULT_MAX_BLASTP_HITS = "10";
final String max_blastp_hits;
final String max_blastp_hits_from_options =
Options.getOptions().getProperty("mess_blastp_hits");
if(max_blastp_hits_from_options == null)
max_blastp_hits = DEFAULT_MAX_BLASTP_HITS;
else
max_blastp_hits = max_blastp_hits_from_options;
if(Options.getOptions().isEukaryoticMode())
{
externalEdit(new String[] { "-blastp", "-maxhits",
max_blastp_hits, "-euk" });
}
else
{
externalEdit(new String[] { "-blastp", "-maxhits",
max_blastp_hits });
}
return;
}
} catch(InvalidRelationException _) {}
new MessageDialog(frame,
"nothing to edit - no /blastp_file qualifier");
}
});
final JButton external_go_edit_button = new JButton("MESS/GO");
location_button_panel.add(external_go_edit_button);
external_go_edit_button.addActionListener(new ActionListener ()
{
public void actionPerformed(ActionEvent e)
{
try
{
if(getFeature().getQualifierByName("blastp+go_file") != null)
{
final String DEFAULT_MAX_GO_BLAST_HITS = "10";
final String max_go_blast_hits;
final String max_go_blast_hits_from_options =
Options.getOptions ().getProperty ("mess_blast_go_hits");
if (max_go_blast_hits_from_options == null)
max_go_blast_hits = DEFAULT_MAX_GO_BLAST_HITS;
else
max_go_blast_hits = max_go_blast_hits_from_options;
if(Options.getOptions().isEukaryoticMode())
{
externalEdit(new String[] { "-blastp+go", "-maxhits",
max_go_blast_hits, "-euk" });
}
else
{
externalEdit(new String[] { "-blastp+go", "-maxhits",
max_go_blast_hits });
}
return;
}
} catch(InvalidRelationException _) {}
new MessageDialog(frame,
"nothing to edit - no /blastp+go_file qualifier");
}
});
}*/
if(Options.isUnixHost())
{
JButton oo_edit_button = new JButton("ObjectEdit");
location_button_panel.add(oo_edit_button);
final uk.ac.sanger.artemis.editor.BigPane bp =
new uk.ac.sanger.artemis.editor.BigPane(getEntryInformation());
oo_edit_button.addActionListener(new ActionListener ()
{
public void actionPerformed(ActionEvent e)
{
String qualifier_txt = qualifier_text_area.getText();
File base_dir = getBaseDirectoryFromEntry(edit_entry);
String baseDirStr = "";
if(base_dir != null)
baseDirStr = base_dir.getAbsolutePath() +
System.getProperty("file.separator");
StringReader strRead = new StringReader(qualifier_txt);
BufferedReader buff = new BufferedReader(strRead);
String line;
final Hashtable dataFile = new Hashtable();
try
{
int ind;
while((line = buff.readLine()) != null)
{
if(line.startsWith("/fasta_file="))
{
if((ind = line.indexOf(':'))>-1)
line = baseDirStr+line.substring(ind+1);
else
line = baseDirStr+line.substring(13);
ind = line.lastIndexOf("\"");
if(ind > -1)
line = line.substring(0, ind);
Vector v;
if(dataFile.containsKey("fasta"))
v = (Vector)dataFile.get("fasta");
else
v = new Vector();
v.add(line);
dataFile.put("fasta",v);
}
else if(line.startsWith("/blastp_file="))
{
if((ind = line.indexOf(':'))>-1)
line = baseDirStr+line.substring(ind+1);
else
line = baseDirStr+line.substring(14);
ind = line.lastIndexOf("\"");
if(ind > -1)
line = line.substring(0, ind);
Vector v;
if(dataFile.containsKey("blastp"))
v = (Vector)dataFile.get("blastp");
else
v = new Vector();
v.add(line);
dataFile.put("blastp",v);
}
else if(line.startsWith("/blastp+go_file="))
{
if((ind = line.indexOf(':'))>-1)
line = line.substring(ind+1);
else
line = baseDirStr+line.substring(17);
ind = line.lastIndexOf("\"");
if(ind > -1)
line = line.substring(0, ind);
Vector v;
if(dataFile.containsKey("blastp+go"))
v = (Vector)dataFile.get("blastp+go");
else
v = new Vector();
v.add(line);
dataFile.put("blastp+go",v);
}
}
}
catch(IOException ioe){}
FeatureEdit.this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
final ProgressThread progress = new ProgressThread(null,
"Loading Data....");
progress.start();
SwingWorker ooEd = new SwingWorker()
{
public Object construct()
{
// find overlaping features
final Location this_loc = edit_feature.getLocation();
final int this_start = this_loc.getFirstBase();
final int this_end = this_loc.getLastBase();
FeaturePredicate predicate = new FeaturePredicate()
{
public boolean testPredicate (final Feature feature)
{
final Location loc = feature.getLocation();
final int start = loc.getFirstBase();
final int end = loc.getLastBase();
if((start > this_start &&
start < this_end) ||
(end > this_start &&
end < this_end))
{
final String note = feature.getNote();
if(note != null &&
note.indexOf("Pfam")>-1)
return true;
}
return false;
}
};
final FeatureVector overlapFeatures = new FeatureVector();
final FeatureEnumeration featureEnum = entry_group.features();
while(featureEnum.hasMoreFeatures())
{
Feature this_feature = featureEnum.nextFeature();
if(predicate.testPredicate(this_feature))
overlapFeatures.add(this_feature);
}
// show object editor
try
{
if(dataFile.size() > 0)
bp.set(dataFile, qualifier_text_area, overlapFeatures,
edit_feature, matchForm, cvForm);
else
JOptionPane.showMessageDialog(null,"No results files.",
"Warning",
JOptionPane.WARNING_MESSAGE);
}
catch(ArrayIndexOutOfBoundsException e)
{
JOptionPane.showMessageDialog(null,"No results files.",
"Warning",
JOptionPane.WARNING_MESSAGE);
}
progress.finished();
FeatureEdit.this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
return null;
}
};
ooEd.start();
}
});
}
middle_panel.add(location_panel, "North");
add(key_and_qualifier_panel, "North");
cancel_button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if(edit_feature.getEntry() != null)
stopListening();
frame.dispose();
}
});
if(!getFeature().isReadOnly())
{
ok_button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if(setFeature())
{
stopListening();
if(propertiesPanel != null)
propertiesPanel.updateObsoleteSettings();
frame.dispose();
}
}
});
apply_button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
setFeature();
}
});
}
final FlowLayout flow_layout =
new FlowLayout(FlowLayout.CENTER, 18, 1);
final JPanel ok_cancel_update_panel = new JPanel(flow_layout);
Box fillerBox = Box.createHorizontalBox();
if(GeneUtils.isDatabaseEntry(getFeature().getEmblFeature()))
{
cvForm = new CVPanel(getFeature());
cvForm.setBackground(Color.WHITE);
matchForm = new MatchPanel(this,
(DocumentEntry)getFeature().getEmblFeature().getEntry());
matchForm.setBackground(Color.WHITE);
propertiesPanel = new PropertiesPanel(getFeature());
propertiesPanel.setBackground(Color.WHITE);
addGffAnnotationView(lower_panel);
final JCheckBox tabbedView = new JCheckBox("Tabbed View", isTabbedView);
tabbedView.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent e)
{
isTabbedView = tabbedView.isSelected();
addGffAnnotationView(lower_panel);
lower_panel.revalidate();
lower_panel.repaint();
}
});
ok_cancel_update_panel.add(tabbedView);
fillerBox.add(Box.createHorizontalStrut(
tabbedView.getPreferredSize().width ));
}
else
lower_panel.add(new JScrollPane(qualifier_text_area), "Center");
if(!getFeature().isReadOnly())
ok_cancel_update_panel.add(ok_button);
ok_cancel_update_panel.add(cancel_button);
if(!getFeature().isReadOnly())
ok_cancel_update_panel.add(apply_button);
ok_cancel_update_panel.add(fillerBox);
add(ok_cancel_update_panel, "South");
middle_panel.add(lower_panel, "Center");
add(middle_panel, "Center");
}
/**
* Refresh the annotation for the active feature
*/
private void refresh()
{
// refresh from the database
final DatabaseDocument originalDocument =
(DatabaseDocument)((DocumentEntry)edit_feature.getEmblFeature().getEntry()).getDocument();
final Set uniquenames = ((GFFStreamFeature)edit_feature.getEmblFeature()).getSegmentRangeStore().keySet();
final Iterator it = uniquenames.iterator();
final String uniquename = (String)it.next();
final DatabaseDocument newDocument = new DatabaseDocument(originalDocument,
uniquename, null, true, null);
newDocument.setLazyFeatureLoad(false);
newDocument.setReadChildren(false);
try
{
DatabaseDocumentEntry dbentry = new DatabaseDocumentEntry(newDocument, null);
uk.ac.sanger.artemis.io.Feature databaseFeature = dbentry.getAllFeatures().featureAt(0);
// compare timelastmodified
Qualifier qualifier = edit_feature.getQualifierByName("timelastmodified");
String active_timelastmodified = (String)qualifier.getValues().get(0);
qualifier = databaseFeature.getQualifierByName("timelastmodified");
String database_timelastmodified = (String)qualifier.getValues().get(0);
if(active_timelastmodified.equals(database_timelastmodified))
{
JOptionPane.showMessageDialog(this,
"No new changes found for the feature\n"+
uniquename+"\n"+
"in the database since:\n"+database_timelastmodified,
"No Updates", JOptionPane.INFORMATION_MESSAGE);
return;
}
else
{
JOptionPane.showMessageDialog(this,
"Changes found for the feature\n"+
uniquename+"\n"+
"in the database at:\n"+database_timelastmodified,
"Changes Found", JOptionPane.INFORMATION_MESSAGE);
}
final QualifierVector db_qv = databaseFeature.getQualifiers();
final QualifierVector qv = edit_feature.getQualifiers();
final QualifierVector new_qv = new QualifierVector();
for(int i=0; i<qv.size(); i++)
{
Qualifier q = (Qualifier)qv.get(i);
if(q.getName().equals("Parent") ||
q.getName().equals("Derives_from") ||
q.getName().equals("ID") )
new_qv.addQualifierValues(q);
}
for(int i=0; i<db_qv.size(); i++)
{
Qualifier q = (Qualifier)db_qv.get(i);
if(q.getName().equals("Parent") ||
q.getName().equals("Derives_from") ||
q.getName().equals("ID") )
continue;
new_qv.add(q);
}
edit_feature.getQualifiers().removeAllElements();
edit_feature.getQualifiers().addAll(new_qv);
updateQualifiers();
}
catch(EntryInformationException e) {}
catch(IOException e) {}
}
/**
* Add the annotation view as tabbed or in a single pane
* @param lower_panel
*/
private void addGffAnnotationView(final JPanel lower_panel)
{
Component c[] = lower_panel.getComponents();
if(isTabbedView)
{
for(int i=0; i<c.length; i++)
{
if(c[i] instanceof JScrollPane)
lower_panel.remove(c[i]);
}
// tabbed pane of core and cv annotaion
JTabbedPane tabbedPane = new JTabbedPane();
JScrollPane jspGff = new JScrollPane(propertiesPanel);
propertiesPanel.setVisible(true); // ensure visible
//jspGff.setPreferredSize(jspCore.getPreferredSize());
tabbedPane.add("Properties", jspGff);
JScrollPane jspCore = new JScrollPane(qualifier_text_area);
tabbedPane.add("Core", jspCore);
JScrollPane jspCV = new JScrollPane(cvForm);
cvForm.setVisible(true); // ensure visible
jspCV.setPreferredSize(jspCore.getPreferredSize());
tabbedPane.add("CV", jspCV);
JScrollPane jspOrtholog = new JScrollPane(matchForm);
matchForm.setVisible(true); // ensure visible
jspOrtholog.setPreferredSize(getPreferredSize());
tabbedPane.add("Match", jspOrtholog);
lower_panel.add(tabbedPane, "Center");
}
else
{
for(int i=0; i<c.length; i++)
{
if(c[i] instanceof JTabbedPane)
lower_panel.remove(c[i]);
}
editorPanel = new GeneEditorPanel(qualifier_text_area, cvForm,
matchForm, propertiesPanel);
JScrollPane jsp = new JScrollPane(editorPanel);
jsp.setPreferredSize(
new Dimension(qualifier_text_area.getPreferredSize().width,
(int)(qualifier_text_area.getPreferredSize().height*1.5)));
// single panel containing annotation forms
lower_panel.add(jsp, "Center");
}
}
/**
* Return the dirtectory that the given entry was read from.
**/
private File getBaseDirectoryFromEntry(final Entry entry)
{
final uk.ac.sanger.artemis.io.Entry embl_entry = entry.getEMBLEntry();
if(embl_entry instanceof DocumentEntry)
{
final DocumentEntry document_entry =(DocumentEntry) embl_entry;
if(document_entry.getDocument() instanceof FileDocument)
{
final FileDocument file_document =
(FileDocument) document_entry.getDocument();
if(file_document.getFile().getParent() != null)
return new File(file_document.getFile().getParent());
}
}
return null;
}
/**
* Read the key, location and qualifier information from the feature and
* update the components.
**/
private void updateFromFeature()
{
datestamp = getFeature().getDatestamp();
updateKey();
updateLocation();
updateQualifiers();
}
/**
* Read the location from the feature and update the location field.
**/
private void updateLocation()
{
location_text.setText(getFeature().getLocation().toStringShort());
}
/**
* Complement the current location_text.
**/
private void complementLocation()
{
if(GeneUtils.isDatabaseEntry(getFeature().getEmblFeature()))
{
final ChadoCanonicalGene chadoGene =
((GFFStreamFeature)getFeature().getEmblFeature()).getChadoGene();
GeneUtils.complementGeneModel(chadoGene);
((GeneBuilderFrame)frame).dispose(true);
return;
}
if(rationalizeLocation())
{
if(location_text.getText().startsWith("complement("))
{
final String new_text = location_text.getText().substring(11);
if (new_text.endsWith(")"))
{
final String new_text2 =
new_text.substring(0, new_text.length () - 1);
location_text.setText(new_text2);
}
else
location_text.setText(new_text);
}
else
{
final String new_text = location_text.getText ();
location_text.setText("complement(" + new_text + ")");
}
}
else
new MessageDialog(frame, "complement failed - " +
"current location cannot be parsed");
}
/**
* Tidy the qualifiers by removing any indication that the annotation has
* been transferred from another gene. Remove the "transferred_" part of
* all qualifier names and the "[[FROM sc_001234 abc1]]" bit of each
* corresponding qualifier value.
**/
private void tidy() throws QualifierParseException
{
final StringBuffer buffer = new StringBuffer();
final QualifierVector qualifiers =
qualifier_text_area.getParsedQualifiers(getEntryInformation());
for(int qualifier_index = 0; qualifier_index < qualifiers.size();
++qualifier_index)
{
final Qualifier this_qualifier = (Qualifier)qualifiers.elementAt(qualifier_index);
final QualifierInfo qualifier_info =
getEntryInformation().getQualifierInfo(this_qualifier.getName());
final StringVector qualifier_strings =
StreamQualifier.toStringVector(qualifier_info, this_qualifier);
for(int value_index = 0; value_index < qualifier_strings.size();
++value_index)
{
final String qualifier_string =
(String)qualifier_strings.elementAt(value_index);
buffer.append(tidyHelper(qualifier_string) + "\n");
}
}
qualifier_text_area.setText(buffer.toString());
}
private void tidyGO() throws QualifierParseException
{
String qualifier_txt = qualifier_text_area.getText();
StringReader strRead = new StringReader(qualifier_txt);
BufferedReader buff = new BufferedReader(strRead);
String line;
final Vector qual_str = new Vector();
try
{
while((line = buff.readLine()) != null)
qual_str.add(line);
}
catch(IOException ioe){}
Comparator comparator = new Comparator()
{
public int compare (Object fst, Object snd)
{
if( !((String)fst).startsWith("/GO") ||
!((String)snd).startsWith("/GO") )
return 0;
return ((String)fst).compareTo((String)snd);
}
};
Collections.sort(qual_str, comparator);
StringBuffer buffer = new StringBuffer();
for(int i = 0; i < qual_str.size(); i++)
{
final String qualifier_string =
(String)qual_str.elementAt(i);
buffer.append(tidyHelper(qualifier_string) + "\n");
}
qualifier_text_area.setText(buffer.toString());
}
/**
* Perform the action of tidy() on the String version of one qualifier.
**/
private String tidyHelper(final String qualifier_string)
{
final String temp_string;
if (qualifier_string.startsWith("/transferred_"))
temp_string = "/" + qualifier_string.substring(13);
else
temp_string = qualifier_string;
final int start_index = temp_string.indexOf ("<<FROM ");
final int end_index = temp_string.indexOf (">>");
if(start_index != -1 && end_index != -1)
{
if(temp_string.length() > end_index + 2 &&
temp_string.charAt(end_index + 2) == ' ')
return temp_string.substring(0, start_index) +
temp_string.substring(end_index + 3);
else
return temp_string.substring(0, start_index) +
temp_string.substring(end_index + 2);
}
else
return temp_string;
}
/**
* Add the currently selected range to location_text.
**/
private void grabSelectedRange()
{
if(!rationalizeLocation ())
{
new MessageDialog(frame,
"grab failed - current location cannot be parsed");
return;
}
final Range selected_range = getSelection().getSelectionRange();
if(selected_range == null)
{
new MessageDialog(frame, "grab failed - nothing is selected");
return;
}
// save it in case it gets mangled
final String old_location_text = location_text.getText();
if (old_location_text.endsWith ("))"))
{
final String new_text =
old_location_text.substring(0, old_location_text.length () - 2);
location_text.setText(new_text + "," + selected_range.getStart () +
".." + selected_range.getEnd () + "))");
}
else
{
if(old_location_text.endsWith (")"))
{
final String new_text =
old_location_text.substring(0, old_location_text.length () - 1);
location_text.setText(new_text + "," + selected_range.getStart () +
".." + selected_range.getEnd () + ")");
}
else
location_text.setText(old_location_text + "," +
selected_range.getStart () +
".." + selected_range.getEnd ());
}
if(!rationalizeLocation())
{
location_text.setText (old_location_text);
new MessageDialog(frame, "grab failed - location cannot be parsed after " +
"grabbing");
}
}
/**
* Remove the currently selected range of bases from location_text.
**/
private void removeSelectedRange()
{
if(!rationalizeLocation())
{
new MessageDialog(frame,
"grab failed - current location cannot be parsed");
return;
}
final MarkerRange selected_marker_range =
getSelection().getMarkerRange();
if(selected_marker_range == null)
{
new MessageDialog(frame, "remove range failed - no bases are selected");
return;
}
final Range selected_range = selected_marker_range.getRawRange();
if (selected_marker_range.getStrand() != getFeature().getStrand())
{
new MessageDialog(frame, "remove range failed - you need to select " +
"some bases on the other strand");
return;
}
final Location location;
try
{
location = new Location(location_text.getText ());
}
catch (LocationParseException e)
{
// this shouldn't happen because we called rationalizeLocation ()
throw new Error("internal error - unexpected exception: " + e);
}
final Range location_total_range = location.getTotalRange();
if(!selected_range.overlaps(location_total_range))
{
new MessageDialog(frame, "remove range failed - the range you " +
"selected does not overlap the feature");
return;
}
if(selected_range.contains(location_total_range))
{
new MessageDialog(frame, "remove range failed - the range you " +
"selected overlaps the whole feature");
return;
}
final RangeVector location_ranges = location.getRanges();
final boolean location_is_complemented = location.isComplement();
final RangeVector new_ranges = new RangeVector();
// if the selected_range completely covers a range remove the
// range. otherwise if the selected_range is completely within one of the
// ranges two new ranges are created. if the selected_range is not
// completely contained then the appropriate end of the range is truncated
for(int i = 0; i < location_ranges.size(); ++i)
{
final Range this_range = (Range)location_ranges.elementAt(i);
if(selected_range.overlaps(this_range))
{
try
{
if(this_range.contains(selected_range) &&
this_range.getStart() != selected_range.getStart() &&
this_range.getEnd() != selected_range.getEnd())
{
// chop a piece out of the middle and make two new ranges
final Range new_start_range =
this_range.change(selected_range.getEnd() + 1,
this_range.getEnd());
new_ranges.add(new_start_range);
final Range new_end_range =
this_range.change(this_range.getStart(),
selected_range.getStart() - 1);
new_ranges.add(new_end_range);
}
else
{
if(selected_range.contains(this_range)) {
// delete (ie. don't copy) the range
}
else
{
if(this_range.getStart() < selected_range.getStart())
{
// truncate the end of the range
final Range new_start_range =
this_range.change(this_range.getStart(),
selected_range.getStart() - 1);
new_ranges.add(new_start_range);
}
else
{
if(this_range.getEnd() > selected_range.getEnd())
{
// truncate the start of the range
final Range new_end_range =
this_range.change(selected_range.getEnd() + 1,
this_range.getEnd());
new_ranges.add(new_end_range);
}
else
throw new Error ("internal error - can't remove range");
}
}
}
}
catch(OutOfRangeException e)
{
throw new Error ("internal error - unexpected exception: " + e);
}
}
else
new_ranges.add(this_range); // copy it unchanged
}
final Location new_location =
new Location(new_ranges, location_is_complemented);
location_text.setText(new_location.toStringShort());
}
/**
* Attempt to parse the current location_text as a Location. If it can be
* parsed it will be canonicalized (ie. the complement, if any, will be
* outermost). Returns true if and only if the location_text could be
* parsed.
**/
private boolean rationalizeLocation()
{
try
{
final Location location = new Location(location_text.getText());
location_text.setText(location.toStringShort());
return true;
}
catch(LocationParseException e)
{
return false;
}
}
/**
* Edit the qualifiers of this Feature in an external editor. The
* qualifiers will be set when the editor finishes. This method works by
* writing the qualifiers to a temporary file and the sequence of the
* feature to a different file.
* @param editor_extra_args Extra arguments to pass to the editor. null
* means there are no extra args.
**/
/*private void externalEdit(final String[] editor_extra_args)
{
try
{
final String pre_edit_text = qualifier_text_area.getText();
// write to a temporary file
final Date current_time = calendar.getTime();
final String temp_file_name =
"/tmp/artemis_temp." + current_time.getTime();
final File temp_file = new File(temp_file_name);
final FileWriter out_writer = new FileWriter(temp_file);
final PrintWriter print_writer = new PrintWriter(out_writer);
print_writer.write(qualifier_text_area.getText());
print_writer.close();
out_writer.close();
final File sequence_temp_file = new File(temp_file_name + ".seq");
final FileWriter sequence_out_writer =
new FileWriter(sequence_temp_file);
final PrintWriter sequence_print_writer =
new PrintWriter(sequence_out_writer);
getFeature().writeBasesOfFeature(sequence_print_writer);
sequence_print_writer.close();
sequence_out_writer.close();
final String editor_path =
Options.getOptions().getProperty("external_editor");
final String[] process_args;
if(editor_extra_args == null)
{
process_args = new String[1];
process_args[0] = temp_file.getCanonicalPath();
}
else
{
process_args = new String[editor_extra_args.length + 1];
System.arraycopy(editor_extra_args, 0, process_args, 0,
editor_extra_args.length);
process_args[process_args.length - 1] = temp_file.getCanonicalPath();
}
System.out.println(editor_path);
for(int i=0;i<process_args.length;i++)
System.out.println(process_args[i]);
final Process process =
ExternalProgram.startProgram(editor_path, process_args);
final ProcessWatcher process_watcher =
new ProcessWatcher(process, "editor", false);
final Thread watcher_thread = new Thread(process_watcher);
watcher_thread.start();
final ProcessWatcherListener listener = new ProcessWatcherListener()
{
public void processFinished(final ProcessWatcherEvent event)
{
try
{
final FileReader file_reader = new FileReader(temp_file);
final BufferedReader buffered_reader =
new BufferedReader(file_reader);
final StringBuffer buffer = new StringBuffer();
String line;
while((line = buffered_reader.readLine()) != null)
buffer.append(line + "\n");
//ensure current qualifier text has not changed
if(!qualifier_text_area.getText().equals(pre_edit_text))
{
final String message =
"the qualifiers have changed - apply changes from the " +
"external editor?";
final YesNoDialog yes_no_dialog =
new YesNoDialog(frame, message);
if(!yes_no_dialog.getResult())
return;
}
qualifier_text_area.setText(buffer.toString());
temp_file.delete();
sequence_temp_file.delete();
return;
}
catch(IOException e)
{
new MessageDialog(frame, "an error occured while " +
"reading from the editor: " + e);
}
}
};
process_watcher.addProcessWatcherListener(listener);
}
catch(IOException e)
{
new MessageDialog(frame, "error while starting editor: " + e);
}
catch(ExternalProgramException e)
{
new MessageDialog(frame, "error while starting editor: " + e);
}
}*/
/**
* Read the qualifiers from the feature and update the qualifier JTextArea.
**/
private void updateQualifiers()
{
if(GeneUtils.isDatabaseEntry(getFeature().getEmblFeature()))
GeneUtils.addLazyQualifiers((GFFStreamFeature)getFeature().getEmblFeature());
qualifier_text_area.setText(getQualifierString());
if(GeneUtils.isDatabaseEntry(getFeature().getEmblFeature()))
{
// load synonym
if(cvForm != null)
cvForm.updateFromFeature(getFeature());
if(propertiesPanel != null)
propertiesPanel.updateFromFeature(getFeature());
if(matchForm != null)
matchForm.updateFromFeature(getFeature());
if(!isTabbedView && editorPanel != null)
editorPanel.updatePanelState();
}
}
/**
* Return a string containing one qualifier per line. These are the
* original qualifiers, not the qualifiers from the qualifier_text_area.
**/
private String getQualifierString()
{
final StringBuffer buffer = new StringBuffer();
final QualifierVector qualifiers = getFeature().getQualifiers();
for(int qualifier_index = 0; qualifier_index < qualifiers.size();
++qualifier_index)
{
final Qualifier this_qualifier = (Qualifier)qualifiers.elementAt(qualifier_index);
//
// strip out CV qualifiers
//
if( (cvForm != null && cvForm.isCvTag(this_qualifier)) ||
(propertiesPanel != null && propertiesPanel.isPropertiesTag(this_qualifier, getFeature())) ||
(matchForm != null && matchForm.isMatchTag(this_qualifier)) ||
(propertiesPanel != null && ProteinMapPanel.isProteinMapElement(this_qualifier)) )
continue;
if(this_qualifier instanceof QualifierLazyLoading)
((QualifierLazyLoading)this_qualifier).setForceLoad(true);
final QualifierInfo qualifier_info =
getEntryInformation().getQualifierInfo(this_qualifier.getName());
final StringVector qualifier_strings =
StreamQualifier.toStringVector(qualifier_info, this_qualifier);
for(int value_index = 0; value_index < qualifier_strings.size();
++value_index)
{
final String qualifier_string = (String)qualifier_strings.elementAt(value_index);
buffer.append(qualifier_string + "\n");
}
}
return buffer.toString();
}
/**
* Set the key, location and qualifiers of the feature to be the same as
* what values currently shown in the components.
* @return true if and only if action succeeds. It may fail because of an
* illegal location or qualifier, in which case a message will be
* displayed before returning.
**/
private boolean setFeature()
{
final Key key = key_choice.getSelectedItem();
final KeyVector possible_keys = getEntryInformation().getValidKeys();
if(possible_keys != null && !possible_keys.contains(key))
{
final YesNoDialog dialog =
new YesNoDialog(frame, "Add this new key: " + key + "?");
if(dialog.getResult()) // yes
getEntryInformation ().addKey (key);
else
return false;
}
final Location location;
try
{
location = new Location(location_text.getText());
}
catch(LocationParseException exception)
{
final String error_string = exception.getMessage ();
System.out.println(error_string);
new MessageDialog(frame, "Cannot apply changes because of location error: " +
error_string);
return false;
}
final QualifierVector qualifiers;
try
{
qualifiers =
qualifier_text_area.getParsedQualifiers(getEntryInformation ());
// if using controlled vocab form
if(cvForm != null)
{
QualifierVector cvQualifiers = cvForm.getCvQualifiers();
if(cvQualifiers != null && cvQualifiers.size() > 0)
qualifiers.addAll(cvQualifiers);
}
if(propertiesPanel != null)
{
QualifierVector gffQualifiers = propertiesPanel.getGffQualifiers(getFeature());
if(gffQualifiers != null && gffQualifiers.size() > 0)
qualifiers.addAll(gffQualifiers);
QualifierVector mapQualifiers = ProteinMapPanel.getProteinMapQualifiers(getFeature());
if(mapQualifiers != null && mapQualifiers.size() > 0)
qualifiers.addAll(mapQualifiers);
}
if(matchForm != null)
{
QualifierVector orthologQualifiers = matchForm.getMatchQualifiers();
if(orthologQualifiers != null && orthologQualifiers.size() > 0)
qualifiers.addAll(orthologQualifiers);
}
//if(similarityTextArea != null)
// similarityTextArea.checkForChanges();
}
catch(QualifierParseException exception)
{
final String error_string = exception.getMessage();
System.out.println(error_string);
new MessageDialog(frame, "Cannot apply changes because of a qualifier " +
"error: " + error_string);
return false;
}
try
{
entry_group.getActionController().startAction();
try
{
getFeature().set(datestamp, key, location, qualifiers);
}
catch(OutOfDateException e)
{
final YesNoDialog dialog =
new YesNoDialog(frame, "the feature has changed since the edit " +
"window was opened, continue?");
if(dialog.getResult()) // yes - ignore the datestamp
getFeature().set(key, location, qualifiers);
else
return false;
}
catch(java.lang.Error err)
{
err.printStackTrace();
if(err.getMessage().indexOf("InvalidRelationException")>-1)
{
JScrollPane jsp = new JScrollPane(new JLabel(err.getMessage()));
jsp.setPreferredSize(new Dimension(200,100));
JOptionPane.showMessageDialog(null, jsp,
"Error", JOptionPane.ERROR_MESSAGE);
}
return false;
}
}
catch(EntryInformationException e)
{
final String error_string = e.getMessage();
new MessageDialog(frame, "Cannot apply changes: " + error_string);
return false;
}
catch(OutOfRangeException e)
{
new MessageDialog(frame, "Cannot apply changes - the location is out of " +
"range for this sequence");
return false;
}
catch(ReadOnlyException e)
{
new MessageDialog(frame, "Cannot apply changes - the feature is " +
"read only");
return false;
}
finally
{
entry_group.getActionController ().endAction ();
}
dribble();
return true;
}
/**
* Return the Feature we are editing as passed to the constructor.
**/
public Feature getFeature()
{
return edit_feature;
}
/**
* On Unix machines this method will append the text of the feature to a
* file in a current directory called .dribble + <the entry name>
**/
private void dribble()
{
if(!Options.isUnixHost())
return;
final String dribble_file_name;
if(getEntry().getName() != null)
dribble_file_name = ".dribble." + getEntry().getName();
else
dribble_file_name = ".dribble.no_name";
try
{
final Writer writer = new FileWriter(dribble_file_name, true);
getFeature().writeNative(writer);
writer.flush();
writer.close();
}
catch(IOException e)
{
System.err.println("IO exception while accessing " + dribble_file_name +
": " + e.getMessage());
}
}
/**
* Return the Entry that contains the Feature this object is displaying.
**/
private Entry getEntry()
{
return edit_entry;
}
/**
* Read the key from the feature and update the key chooser.
**/
private void updateKey()
{
final Key feature_key = getFeature().getKey();
key_choice.setKey(feature_key);
}
/**
* Return the EntryInformation object of the entry containing the feature.
**/
public EntryInformation getEntryInformation()
{
if(entry_information == null)
entry_information = getEntry().getEntryInformation();
return entry_information;
}
/**
* Return the Selection that was passed to the constructor.
**/
private Selection getSelection()
{
return selection;
}
public static boolean isTabbedView()
{
return isTabbedView;
}
public static void setTabbedView(boolean isTabbedView)
{
FeatureEdit.isTabbedView = isTabbedView;
}
/**
* Set whether the feature is obsolete (database mode).
* @param obsoleteChanged
*/
public void setObsoleteChanged(boolean obsoleteChanged)
{
propertiesPanel.setObsoleteChanged(obsoleteChanged);
}
}