label.automatically_associate_pdb_files_by_name = Automatically Associate PDB files by name
label.ignore_unmatched_dropped_files_info = <html>Do you want to <em>ignore</em> the {0} files whose names did not match any sequence IDs ?</html>
label.ignore_unmatched_dropped_files = Ignore unmatched dropped files?
+label.view_name_original = Original
label.enter_view_name = Enter View Name
label.enter_label = Enter label
label.enter_label_for_the_structure = Enter a label for the structure?
label.cdna_aligned = {0} sequences in {1} alignments were realigned
label.view_as_cdna = Show aligned cDNA
label.view_as_cdna_tip = Open a new alignment of the related cDNA sequences
+label.linked_view_title = {0} and {1}
label.align = Align
label.extract_scores = Extract Scores
label.get_cross_refs = Get Cross References
public Hashtable alignmentProperties;
+ private Set<AlignedCodonFrame> codonFrameList = new LinkedHashSet<AlignedCodonFrame>();
+
private void initAlignment(SequenceI[] seqs)
{
int i = 0;
{
seqs[i] = new Sequence(seqs[i]);
}
+
+ /*
+ * Share the same dataset sequence mappings (if any). TODO: find a better
+ * place for these to live (alignment dataset?).
+ */
+ this.codonFrameList = ((Alignment) al).codonFrameList;
+
initAlignment(seqs);
}
// this(compactAlignment.refCigars);
}
- /**
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
@Override
public List<SequenceI> getSequences()
{
return true;
}
+ /**
+ * Delete all annotations, including auto-calculated if the flag is set true.
+ * Returns true if at least one annotation was deleted, else false.
+ *
+ * @param includingAutoCalculated
+ * @return
+ */
+ @Override
+ public boolean deleteAllAnnotations(boolean includingAutoCalculated)
+ {
+ boolean result = false;
+ for (AlignmentAnnotation alan : getAlignmentAnnotation())
+ {
+ if (!alan.autoCalculated || includingAutoCalculated)
+ {
+ deleteAnnotation(alan);
+ result = true;
+ }
+ }
+ return result;
+ }
+
/*
* (non-Javadoc)
*
return alignmentProperties;
}
- // AlignedCodonFrame[] codonFrameList = null;
-
- LinkedHashSet<AlignedCodonFrame> codonFrameList = new LinkedHashSet<AlignedCodonFrame>();
-
/*
* (non-Javadoc)
*
return cframes;
}
- /*
- * (non-Javadoc)
+ /**
+ * Sets the codon frame mappings (replacing any existing mappings).
+ *
+ * @see jalview.datamodel.AlignmentI#setCodonFrames()
+ */
+ @Override
+ public void setCodonFrames(Set<AlignedCodonFrame> acfs)
+ {
+ this.codonFrameList = acfs;
+ }
+
+ /**
+ * Returns the set of codon frame mappings. Any changes to the returned set
+ * will affect the alignment.
*
* @see jalview.datamodel.AlignmentI#getCodonFrames()
*/
void setAnnotationIndex(AlignmentAnnotation aa, int index);
/**
+ * Delete all annotations, including auto-calculated if the flag is set true.
+ * Returns true if at least one annotation was deleted, else false.
+ *
+ * @param includingAutoCalculated
+ * @return
+ */
+ boolean deleteAllAnnotations(boolean includingAutoCalculated);
+
+ /**
* Deletes a specific AlignmentAnnotation from the alignment, and removes its
* reference from any SequenceI or SequenceGroup object's annotation if and
* only if aa is contained within the alignment's annotation vector.
Set<AlignedCodonFrame> getCodonFrames();
/**
+ * Set the codon frame mappings (replacing any existing set).
+ */
+ void setCodonFrames(Set<AlignedCodonFrame> acfs);
+
+ /**
* get codon frames involving sequenceI
*/
List<AlignedCodonFrame> getCodonFrame(SequenceI seq);
IProgressIndicator, AlignViewControllerGuiI
{
- /** DOCUMENT ME!! */
public static final int DEFAULT_WIDTH = 700;
- /** DOCUMENT ME!! */
public static final int DEFAULT_HEIGHT = 500;
+ /*
+ * The currently displayed panel (selected tabbed view if more than one)
+ */
public AlignmentPanel alignPanel;
AlignViewport viewport;
{
EditCommand editCommand = (EditCommand) command;
al = editCommand.getAlignment();
- Vector comps = (Vector) PaintRefresher.components.get(viewport
+ List<Component> comps = PaintRefresher.components.get(viewport
.getSequenceSetId());
- for (int i = 0; i < comps.size(); i++)
+ for (Component comp : comps)
{
- if (comps.elementAt(i) instanceof AlignmentPanel)
+ if (comp instanceof AlignmentPanel)
{
- if (al == ((AlignmentPanel) comps.elementAt(i)).av.getAlignment())
+ if (al == ((AlignmentPanel) comp).av.getAlignment())
{
- originalSource = ((AlignmentPanel) comps.elementAt(i)).av;
+ originalSource = ((AlignmentPanel) comp).av;
break;
}
}
@Override
public void newView_actionPerformed(ActionEvent e)
{
- newView(true);
- }
+ /*
+ * Note if the current view has a protein/cdna complementary view
+ */
+ AlignViewportI linkedView = this.viewport.getCodingComplement();
- /**
- *
- * @param copyAnnotation
- * if true then duplicate all annnotation, groups and settings
- * @return new alignment panel, already displayed.
- */
- public AlignmentPanel newView(boolean copyAnnotation)
- {
- return newView(null, copyAnnotation);
- }
+ AlignmentPanel newPanel = newView(null, true);
- /**
- *
- * @param viewTitle
- * title of newly created view
- * @return new alignment panel, already displayed.
- */
- public AlignmentPanel newView(String viewTitle)
- {
- return newView(viewTitle, true);
+ /*
+ * If the original view has a protein/cdna linked view, make and link a new
+ * view there also.
+ */
+ // TODO refactor the hell out of this - move to a controller, lose the casts
+ // and direct member access, etc
+ if (linkedView != null)
+ {
+ AlignFrame linkedAlignFrame = ((AlignViewport) linkedView)
+ .getAlignPanel().alignFrame;
+ AlignmentPanel newLinkedPanel = linkedAlignFrame.newView(null, true);
+ newLinkedPanel.av.viewName = newPanel.av.viewName;
+ newPanel.av.setCodingComplement(newLinkedPanel.av);
+ final StructureSelectionManager ssm = StructureSelectionManager
+ .getStructureSelectionManager(Desktop.instance);
+ ssm.addCommandListener(newPanel.av);
+ ssm.addCommandListener(newLinkedPanel.av);
+
+ }
}
/**
+ * Creates and shows a new view of the current alignment.
*
* @param viewTitle
- * title of newly created view
+ * title of newly created view; if null, one will be generated
* @param copyAnnotation
* if true then duplicate all annnotation, groups and settings
* @return new alignment panel, already displayed.
*/
public AlignmentPanel newView(String viewTitle, boolean copyAnnotation)
{
+ /*
+ * Create a new AlignmentPanel (with its own, new Viewport)
+ */
AlignmentPanel newap = new Jalview2XML().copyAlignPanel(alignPanel,
true);
if (!copyAnnotation)
{
- // just remove all the current annotation except for the automatic stuff
+ /*
+ * remove all groups and annotation except for the automatic stuff
+ */
newap.av.getAlignment().deleteAllGroups();
- for (AlignmentAnnotation alan : newap.av.getAlignment()
- .getAlignmentAnnotation())
- {
- if (!alan.autoCalculated)
- {
- newap.av.getAlignment().deleteAnnotation(alan);
- }
- ;
- }
+ newap.av.getAlignment().deleteAllAnnotations(false);
}
newap.av.gatherViewsHere = false;
if (viewport.viewName == null)
{
- viewport.viewName = "Original";
+ viewport.viewName = MessageManager
+ .getString("label.view_name_original");
}
+ /*
+ * Views share the same edits, undo and redo stacks, mappings.
+ */
newap.av.setHistoryList(viewport.getHistoryList());
newap.av.setRedoList(viewport.getRedoList());
+ newap.av.getAlignment().setCodonFrames(
+ viewport.getAlignment().getCodonFrames());
+
+ newap.av.viewName = getNewViewName(viewTitle);
+
+ addAlignmentPanel(newap, true);
+ newap.alignmentChanged();
+
+ if (alignPanels.size() == 2)
+ {
+ viewport.gatherViewsHere = true;
+ }
+ tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
+ return newap;
+ }
+ /**
+ * Make a new name for the view, ensuring it is unique within the current
+ * sequenceSetId. (This used to be essential for Jalview Project archives, but
+ * these now use viewId. Unique view names are still desirable for usability.)
+ *
+ * @param viewTitle
+ * @return
+ */
+ protected String getNewViewName(String viewTitle)
+ {
int index = Desktop.getViewCount(viewport.getSequenceSetId());
- // make sure the new view has a unique name - this is essential for Jalview
- // 2 archives
boolean addFirstIndex = false;
if (viewTitle == null || viewTitle.trim().length() == 0)
{
index = 1;// we count from 1 if given a specific name
}
String newViewName = viewTitle + ((addFirstIndex) ? " " + index : "");
- Vector comps = (Vector) PaintRefresher.components.get(viewport
+
+ List<Component> comps = PaintRefresher.components.get(viewport
.getSequenceSetId());
- Vector existingNames = new Vector();
- for (int i = 0; i < comps.size(); i++)
- {
- if (comps.elementAt(i) instanceof AlignmentPanel)
- {
- AlignmentPanel ap = (AlignmentPanel) comps.elementAt(i);
- if (!existingNames.contains(ap.av.viewName))
- {
- existingNames.addElement(ap.av.viewName);
- }
- }
- }
+
+ List<String> existingNames = getExistingViewNames(comps);
while (existingNames.contains(newViewName))
{
newViewName = viewTitle + " " + (++index);
}
+ return newViewName;
+ }
- newap.av.viewName = newViewName;
-
- addAlignmentPanel(newap, true);
- newap.alignmentChanged();
-
- if (alignPanels.size() == 2)
+ /**
+ * Returns a list of distinct view names found in the given list of
+ * components. View names are held on the viewport of an AlignmentPanel.
+ *
+ * @param comps
+ * @return
+ */
+ protected List<String> getExistingViewNames(List<Component> comps)
+ {
+ List<String> existingNames = new ArrayList<String>();
+ for (Component comp : comps)
{
- viewport.gatherViewsHere = true;
+ if (comp instanceof AlignmentPanel)
+ {
+ AlignmentPanel ap = (AlignmentPanel) comp;
+ if (!existingNames.contains(ap.av.viewName))
+ {
+ existingNames.add(ap.av.viewName);
+ }
+ }
}
- tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
- return newap;
+ return existingNames;
}
+ /**
+ * Explode tabbed views into separate windows.
+ */
@Override
public void expandViews_actionPerformed(ActionEvent e)
{
Desktop.instance.explodeViews(this);
}
+ /**
+ * Gather views in separate windows back into a tabbed presentation.
+ */
@Override
public void gatherViews_actionPerformed(ActionEvent e)
{
{
Component[] menuItems = colourMenu.getMenuComponents();
- int i, iSize = menuItems.length;
- for (i = 0; i < iSize; i++)
+ int iSize = menuItems.length;
+ for (int i = 0; i < iSize; i++)
{
if (menuItems[i].getName() != null
&& menuItems[i].getName().equals("USER_DEFINED"))
@Override
public void averageDistanceTreeMenuItem_actionPerformed(ActionEvent e)
{
- NewTreePanel("AV", "PID", "Average distance tree using PID");
+ newTreePanel("AV", "PID", "Average distance tree using PID");
}
/**
@Override
public void neighbourTreeMenuItem_actionPerformed(ActionEvent e)
{
- NewTreePanel("NJ", "PID", "Neighbour joining tree using PID");
+ newTreePanel("NJ", "PID", "Neighbour joining tree using PID");
}
/**
@Override
protected void njTreeBlosumMenuItem_actionPerformed(ActionEvent e)
{
- NewTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");
+ newTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");
}
/**
@Override
protected void avTreeBlosumMenuItem_actionPerformed(ActionEvent e)
{
- NewTreePanel("AV", "BL", "Average distance tree using BLOSUM62");
+ newTreePanel("AV", "BL", "Average distance tree using BLOSUM62");
}
/**
* @param title
* DOCUMENT ME!
*/
- void NewTreePanel(String type, String pwType, String title)
+ void newTreePanel(String type, String pwType, String title)
{
TreePanel tp;
{
String treecalcnm = MessageManager.getString("label.tree_calc_"
+ type.toLowerCase());
- for (final Object pwtype : ResidueProperties.scoreMatrices.keySet())
+ for (final String pwtype : ResidueProperties.scoreMatrices.keySet())
{
JMenuItem tm = new JMenuItem();
ScoreModelI sm = ResidueProperties.scoreMatrices.get(pwtype);
@Override
public void actionPerformed(ActionEvent e)
{
- NewTreePanel(type, (String) pwtype, title);
+ newTreePanel(type, pwtype, title);
}
});
calculateTree.add(tm);
}
sortByTreeMenu.removeAll();
- Vector comps = (Vector) PaintRefresher.components.get(viewport
+ List<Component> comps = PaintRefresher.components.get(viewport
.getSequenceSetId());
- Vector treePanels = new Vector();
- int i, iSize = comps.size();
- for (i = 0; i < iSize; i++)
+ List<TreePanel> treePanels = new ArrayList<TreePanel>();
+ for (Component comp : comps)
{
- if (comps.elementAt(i) instanceof TreePanel)
+ if (comp instanceof TreePanel)
{
- treePanels.add(comps.elementAt(i));
+ treePanels.add((TreePanel) comp);
}
}
- iSize = treePanels.size();
-
- if (iSize < 1)
+ if (treePanels.size() < 1)
{
sortByTreeMenu.setVisible(false);
return;
sortByTreeMenu.setVisible(true);
- for (i = 0; i < treePanels.size(); i++)
+ for (final TreePanel tp : treePanels)
{
- final TreePanel tp = (TreePanel) treePanels.elementAt(i);
final JMenuItem item = new JMenuItem(tp.getTitle());
item.addActionListener(new java.awt.event.ActionListener()
{
}
}
+ /**
+ * Method invoked by the ChangeListener on the tabbed pane, in other words
+ * when a different tabbed pane is selected by the user or programmatically.
+ */
@Override
public void tabSelectionChanged(int index)
{
}
}
+ /**
+ * On right mouse click on view tab, prompt for and set new view name.
+ */
@Override
public void tabbedPane_mousePressed(MouseEvent e)
{
if (SwingUtilities.isRightMouseButton(e))
{
- String reply = JOptionPane.showInternalInputDialog(this,
- MessageManager.getString("label.enter_view_name"),
- MessageManager.getString("label.enter_view_name"),
+ String msg = MessageManager.getString("label.enter_view_name");
+ String reply = JOptionPane.showInternalInputDialog(this, msg, msg,
JOptionPane.QUESTION_MESSAGE);
if (reply != null)
{
viewport.viewName = reply;
+ // TODO warn if reply is in getExistingViewNames()?
tabbedPane.setTitleAt(tabbedPane.getSelectedIndex(), reply);
}
}
import jalview.structure.StructureSelectionManager;
import jalview.structure.VamsasSource;
import jalview.util.MessageManager;
+import jalview.util.StringUtils;
import jalview.viewmodel.AlignmentViewport;
import jalview.ws.params.AutoCalcSetting;
{
AlignmentPanel[] aps = PaintRefresher.getAssociatedPanels(this
.getSequenceSetId());
- AlignmentPanel ap = null;
for (int p = 0; aps != null && p < aps.length; p++)
{
if (aps[p].av == this)
*/
AlignFrame newAlignFrame = new AlignFrame(al, AlignFrame.DEFAULT_WIDTH,
AlignFrame.DEFAULT_HEIGHT);
+ newAlignFrame.setTitle(title);
/*
* Identify protein and dna alignments. Make a copy of this one if opening
*/
AlignFrame copyMe = new AlignFrame(thisAlignment,
AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
- copyMe.setTitle(""); // TODO would like this AlignFrame.title here
+ copyMe.setTitle(getAlignPanel().alignFrame.getTitle());
final AlignFrame proteinFrame = al.isNucleotide() ? copyMe
: newAlignFrame;
final AlignFrame cdnaFrame = al.isNucleotide() ? newAlignFrame
: copyMe;
- newAlignFrame.setTitle(title);
cdnaFrame.setVisible(true);
proteinFrame.setVisible(true);
+ String proteinShortName = StringUtils.getLastToken(
+ proteinFrame.getTitle(), "/");
+ String dnaShortName = StringUtils.getLastToken(cdnaFrame.getTitle(),
+ "/");
+ String linkedTitle = MessageManager.formatMessage(
+ "label.linked_view_title", dnaShortName, proteinShortName);
JInternalFrame splitFrame = new SplitFrame(cdnaFrame, proteinFrame);
- Desktop.addInternalFrame(splitFrame, title, AlignFrame.DEFAULT_WIDTH,
+ Desktop.addInternalFrame(splitFrame, linkedTitle,
+ AlignFrame.DEFAULT_WIDTH,
AlignFrame.DEFAULT_HEIGHT);
/*
- * Set the frames to list for each other's edit and sort commands.
+ * Set the frames to listen for each other's edit and sort commands.
*/
ssm.addCommandListener(cdnaFrame.getViewport());
ssm.addCommandListener(proteinFrame.getViewport());
/*
- * cDNA view will mirror edits, selection, sorting, show/hide on protein
+ * 'Coding complement' (dna/protein) views will mirror each others' edits,
+ * selections, sorting etc as decided from time to time by the relevant
+ * authorities.
*/
proteinFrame.getViewport().setCodingComplement(cdnaFrame.getViewport());
}
* Creates a new AlignmentPanel object.
*
* @param af
- * DOCUMENT ME!
* @param av
- * DOCUMENT ME!
*/
public AlignmentPanel(AlignFrame af, final AlignViewport av)
{
*/
public void adjustmentValueChanged(AdjustmentEvent evt)
{
-
int oldX = av.getStartRes();
int oldY = av.getStartSeq();
if (alignFrame != null && !headless)
{
alignFrame.setProgressBar(MessageManager.formatMessage(
- "status.saving_file",
- new String[]
+ "status.saving_file", new Object[]
{ type.getLabel() }), progress);
}
try
*/
public static AlignmentViewport[] getViewports(String sequenceSetId)
{
- Vector viewp = new Vector();
+ List<AlignmentViewport> viewp = new ArrayList<AlignmentViewport>();
if (desktop != null)
{
- javax.swing.JInternalFrame[] frames = instance.getAllFrames();
+ AlignFrame[] frames = Desktop.getAlignFrames();
- for (int t = 0; t < frames.length; t++)
+ for (AlignFrame afr : frames)
{
- if (frames[t] instanceof AlignFrame)
+ if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
{
- AlignFrame afr = ((AlignFrame) frames[t]);
- if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
+ if (afr.alignPanels != null)
{
- if (afr.alignPanels != null)
+ for (AlignmentPanel ap : afr.alignPanels)
{
- for (int a = 0; a < afr.alignPanels.size(); a++)
+ if (sequenceSetId.equals(ap.av.getSequenceSetId()))
{
- if (sequenceSetId.equals(afr.alignPanels.get(a).av
- .getSequenceSetId()))
- {
- viewp.addElement(afr.alignPanels.get(a).av);
- }
+ viewp.add(ap.av);
}
}
- else
- {
- viewp.addElement(((AlignFrame) frames[t]).getViewport());
- }
+ }
+ else
+ {
+ viewp.add(afr.getViewport());
}
}
}
if (viewp.size() > 0)
{
- AlignmentViewport[] vp = new AlignmentViewport[viewp.size()];
- viewp.copyInto(vp);
- return vp;
+ return viewp.toArray(new AlignmentViewport[viewp.size()]);
}
}
return null;
/**
* Accessor method to quickly get all the AlignmentFrames loaded.
+ *
+ * @return an array of AlignFrame, or null if none found
*/
public static AlignFrame[] getAlignFrames()
{
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.StringTokenizer;
}
if (seqRefIds == null)
{
- seqRefIds = new Hashtable();
+ seqRefIds = new HashMap<String, SequenceI>();
}
}
* and alignment sequences. Populated as XML reps of sequence objects are
* created.)
*/
- java.util.Hashtable seqRefIds = null; // key->SequenceI resolution
+ Map<String, SequenceI> seqRefIds = null; // key->SequenceI resolution
+ /*
+ * Forward referenced sequences - a holding place for cross-references pending
+ * resolution.
+ */
Vector frefedSequence = null;
boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
{
if (ref[1] instanceof jalview.datamodel.Mapping)
{
- SequenceI seq = (SequenceI) seqRefIds.get(sref);
+ SequenceI seq = seqRefIds.get(sref);
while (seq.getDatasetSequence() != null)
{
seq = seq.getDatasetSequence();
{
if (ref[1] instanceof jalview.datamodel.AlignedCodonFrame)
{
- SequenceI seq = (SequenceI) seqRefIds.get(sref);
+ SequenceI seq = seqRefIds.get(sref);
while (seq.getDatasetSequence() != null)
{
seq = seq.getDatasetSequence();
}
if (seqRefIds == null)
{
- seqRefIds = new Hashtable();
+ seqRefIds = new HashMap<String, SequenceI>();
}
if (viewportsAdded == null)
{
AlcodMap[] maps = alc[i].getAlcodMap();
for (int m = 0; m < maps.length; m++)
{
- SequenceI dnaseq = (SequenceI) seqRefIds
+ SequenceI dnaseq = seqRefIds
.get(maps[m].getDnasq());
// Load Mapping
jalview.datamodel.Mapping mapping = null;
for (int s = 0; s < groups[i].getSeqCount(); s++)
{
String seqId = groups[i].getSeq(s) + "";
- jalview.datamodel.SequenceI ts = (jalview.datamodel.SequenceI) seqRefIds
+ jalview.datamodel.SequenceI ts = seqRefIds
.get(seqId);
if (ts != null)
// Desktop.desktop.getComponentAt(x, y);
// TODO: NOW: check that this recovers the PDB file correctly.
String pdbFile = loadPDBFile(jprovider, ids[p].getId());
- jalview.datamodel.SequenceI seq = (jalview.datamodel.SequenceI) seqRefIds
+ jalview.datamodel.SequenceI seq = seqRefIds
.get(JSEQ[i].getId() + "");
if (sviewid == null)
{
{
// JBP TODO: Check this is called for AlCodonFrames to support recovery of
// xRef Codon Maps
- jalview.datamodel.Sequence sq = (jalview.datamodel.Sequence) seqRefIds
- .get(vamsasSeq.getId());
- jalview.datamodel.SequenceI dsq = null;
+ SequenceI sq = seqRefIds.get(vamsasSeq.getId());
+ SequenceI dsq = null;
if (sq != null && sq.getDatasetSequence() != null)
{
dsq = sq.getDatasetSequence();
// need to create or add a new dataset sequence reference to this sequence
if (sqid != null)
{
- dsq = (jalview.datamodel.SequenceI) seqRefIds.get(sqid);
+ dsq = seqRefIds.get(sqid);
}
// check again
if (dsq == null)
/**
* recover from hash
*/
- jmap.setTo((SequenceI) seqRefIds.get(dsfor));
+ jmap.setTo(seqRefIds.get(dsfor));
}
else
{
* local sequence definition
*/
Sequence ms = mc.getSequence();
- jalview.datamodel.Sequence djs = null;
+ SequenceI djs = null;
String sqid = ms.getDsseqid();
if (sqid != null && sqid.length() > 0)
{
/*
* recover dataset sequence
*/
- djs = (jalview.datamodel.Sequence) seqRefIds.get(sqid);
+ djs = seqRefIds.get(sqid);
}
else
{
viewportsAdded = new Hashtable();
AlignFrame af = LoadFromObject(jm, null, false, null);
+ // next line added in an attempt to copy AlignedCodonFrame list but failed
+ // resolveFrefedSequences();
af.alignPanels.clear();
af.closeMenuItem_actionPerformed(true);
// register sequence object so the XML parser can recover it.
if (seqRefIds == null)
{
- seqRefIds = new Hashtable();
+ seqRefIds = new HashMap<String, SequenceI>();
}
if (seqsToIds == null)
{
seqsToIds = new IdentityHashMap();
}
- seqRefIds.put(jv2vobj.get(jvobj).toString(), jvobj);
+ seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
seqsToIds.put(jvobj, id);
}
else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
+import javax.swing.JScrollBar;
import javax.swing.SwingConstants;
/**
}
}
+ /**
+ * Returns the proportion of its range that a scrollbar's position represents,
+ * as a value between 0 and 1. For example if the whole range is from 0 to
+ * 200, then a position of 40 gives proportion = 0.2.
+ *
+ * @see http://www.javalobby.org/java/forums/t33050.html#91885334
+ *
+ * @param scroll
+ * @return
+ */
+ public static float getScrollBarProportion(JScrollBar scroll)
+ {
+ /*
+ * The extent (scroll handle width) deduction gives the true operating range
+ * of possible positions.
+ */
+ int possibleRange = scroll.getMaximum() - scroll.getMinimum()
+ - scroll.getModel().getExtent();
+ float valueInRange = scroll.getValue()
+ - (scroll.getModel().getExtent() / 2f);
+ float proportion = valueInRange / possibleRange;
+ return proportion;
+ }
+
+ /**
+ * Returns the scroll bar position in its range that would match the given
+ * proportion (between 0 and 1) of the whole. For example if the whole range
+ * is from 0 to 200, then a proportion of 0.25 gives position 50.
+ *
+ * @param scrollbar
+ * @param proportion
+ * @return
+ */
+ public static int getScrollValueForProportion(JScrollBar scrollbar,
+ float proportion)
+ {
+ /*
+ * The extent (scroll handle width) deduction gives the true operating range
+ * of possible positions.
+ */
+ float fraction = proportion
+ * (scrollbar.getMaximum() - scrollbar.getMinimum() - scrollbar
+ .getModel().getExtent())
+ + (scrollbar.getModel().getExtent() / 2f);
+ return Math.min(Math.round(fraction), scrollbar.getMaximum());
+ }
+
}
*/
package jalview.gui;
-import java.util.*;
-import java.util.List;
-
-import java.awt.*;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceI;
-import jalview.datamodel.*;
+import java.awt.Component;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
/**
* Route datamodel/view update events for a sequence set to any display
*/
public class PaintRefresher
{
- static Hashtable components;
+ static Map<String, List<Component>> components = new HashMap<String, List<Component>>();
/**
- * DOCUMENT ME!
+ * Add the given component to those registered under the given sequence set
+ * id. Does nothing if already added.
*
* @param comp
- * DOCUMENT ME!
* @param al
- * DOCUMENT ME!
*/
public static void Register(Component comp, String seqSetId)
{
- if (components == null)
- {
- components = new Hashtable();
- }
-
if (components.containsKey(seqSetId))
{
- Vector comps = (Vector) components.get(seqSetId);
+ List<Component> comps = components.get(seqSetId);
if (!comps.contains(comp))
{
- comps.addElement(comp);
+ comps.add(comp);
}
}
else
{
- Vector vcoms = new Vector();
- vcoms.addElement(comp);
+ List<Component> vcoms = new ArrayList<Component>();
+ vcoms.add(comp);
components.put(seqSetId, vcoms);
}
}
+ /**
+ * Remove this component from all registrations. Also removes a registered
+ * sequence set id if there are no remaining components registered against it.
+ *
+ * @param comp
+ */
public static void RemoveComponent(Component comp)
{
- if (components == null)
- {
- return;
- }
-
- Enumeration en = components.keys();
- while (en.hasMoreElements())
+ List<String> emptied = new ArrayList<String>();
+ for (Entry<String, List<Component>> registered : components.entrySet())
{
- String id = en.nextElement().toString();
- Vector comps = (Vector) components.get(id);
+ String id = registered.getKey();
+ List<Component> comps = components.get(id);
comps.remove(comp);
- if (comps.size() == 0)
+ if (comps.isEmpty())
{
- components.remove(id);
+ emptied.add(id);
}
}
+
+ /*
+ * Remove now empty ids after the above (to avoid
+ * ConcurrentModificationException).
+ */
+ for (String id : emptied)
+ {
+ components.remove(id);
+ }
}
public static void Refresh(Component source, String id)
public static void Refresh(Component source, String id,
boolean alignmentChanged, boolean validateSequences)
{
- if (components == null)
- {
- return;
- }
-
- Component comp;
- Vector comps = (Vector) components.get(id);
+ List<Component> comps = components.get(id);
if (comps == null)
{
return;
}
- Enumeration e = comps.elements();
- while (e.hasMoreElements())
+ for (Component comp : comps)
{
- comp = (Component) e.nextElement();
-
if (comp == source)
{
continue;
static AlignmentPanel[] getAssociatedPanels(String id)
{
- if (components == null)
- {
- return new AlignmentPanel[0];
- }
- ;
- Vector comps = (Vector) components.get(id);
+ List<Component> comps = components.get(id);
if (comps == null)
{
return new AlignmentPanel[0];
}
- ;
- Vector tmp = new Vector();
- int i, iSize = comps.size();
- for (i = 0; i < iSize; i++)
+ List<AlignmentPanel> tmp = new ArrayList<AlignmentPanel>();
+ for (Component comp : comps)
{
- if (comps.elementAt(i) instanceof AlignmentPanel)
+ if (comp instanceof AlignmentPanel)
{
- tmp.addElement(comps.elementAt(i));
+ tmp.add((AlignmentPanel) comp);
}
}
- AlignmentPanel[] result = new AlignmentPanel[tmp.size()];
- tmp.toArray(result);
-
- return result;
+ return tmp.toArray(new AlignmentPanel[tmp.size()]);
}
}
import javax.swing.AbstractAction;
import javax.swing.JComponent;
+import javax.swing.JMenuItem;
import javax.swing.KeyStroke;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;
{
if (getTopComponent() instanceof AlignFrame)
{
- for (Entry<KeyStroke, ActionListener> acc : ((AlignFrame) getTopComponent())
+ for (Entry<KeyStroke, JMenuItem> acc : ((AlignFrame) getTopComponent())
.getAccelerators().entrySet())
{
Component c = getComponentAtMouse();
if (c instanceof AlignFrame)
{
- ((AlignFrame) c).getAccelerators().get(ks)
- .actionPerformed(null);
+ for (ActionListener a : ((AlignFrame) c).getAccelerators()
+ .get(ks).getActionListeners())
+ {
+
+ a.actionPerformed(null);
+ }
}
}
});
* Disable unwanted here
*/
// X expand views - wrecks the split pane view
- this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).remove(
- KeyStroke.getKeyStroke(KeyEvent.VK_X, 0, false));
+ KeyStroke key_X = KeyStroke.getKeyStroke(KeyEvent.VK_X, 0, false);
+ disableAccelerator(key_X);
+ }
+ }
+
+ /**
+ * Ugly hack for Proof of Concept that disables the key binding in this frame
+ * _and_ disables the bound menu item _and_ removes the key accelerator in the
+ * child frames.
+ *
+ * @param key
+ */
+ protected void disableAccelerator(KeyStroke key)
+ {
+ disableAccelerator(key, getTopComponent());
+ disableAccelerator(key, getBottomComponent());
+ this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).remove(key);
+ }
+
+ /**
+ * Disable the menu item for which this key is the accelerator, also removes
+ * its action listeners to prevent key accelerator working.
+ *
+ * @param key
+ * @param comp
+ */
+ private void disableAccelerator(KeyStroke key, JComponent comp)
+ {
+ // HACKED ONLY FOR PROOF OF CONCEPT
+ // Proper solution might involve explicit 'configure menu' method on
+ // AlignFrame, or
+ // changing key listeners to key bindings in AlignFrame, or both
+ if (comp instanceof AlignFrame)
+ {
+ JMenuItem mi = ((AlignFrame) comp).getAccelerators().get(key);
+ if (mi != null)
+ {
+ mi.setEnabled(false);
+ for (ActionListener al : mi.getActionListeners())
+ {
+ mi.removeActionListener(al);
+ }
+ }
}
}
}
private boolean showAutoCalculatedAbove = false;
- private Map<KeyStroke, ActionListener> accelerators = new HashMap<KeyStroke, ActionListener>();
+ private Map<KeyStroke, JMenuItem> accelerators = new HashMap<KeyStroke, JMenuItem>();
public GAlignFrame()
{
JMenuItem menuItem, ActionListener actionListener)
{
menuItem.setAccelerator(keyStroke);
- accelerators.put(keyStroke, actionListener);
+ accelerators.put(keyStroke, menuItem);
menuItem.addActionListener(actionListener);
}
this.annotationSortOrder = annotationSortOrder;
}
- public Map<KeyStroke, ActionListener> getAccelerators()
+ public Map<KeyStroke, JMenuItem> getAccelerators()
{
return this.accelerators;
}
package jalview.util;
+
public class StringUtils
{
}
return tmp;
}
+
+ /**
+ * Returns the last part of 'input' after the last occurrence of 'token'. For
+ * example to extract only the filename from a full path or URL.
+ *
+ * @param input
+ * @param token
+ * a delimiter which must be in regular expression format
+ * @return
+ */
+ public static String getLastToken(String input, String token)
+ {
+ if (input == null)
+ {
+ return null;
+ }
+ if (token == null)
+ {
+ return input;
+ }
+ String[] st = input.split(token);
+ return st[st.length - 1];
+ }
}
assertFalse(iter.hasNext());
}
+ @Test
+ public void testDeleteAllAnnotations_includingAutocalculated()
+ {
+ AlignmentAnnotation aa = new AlignmentAnnotation("Consensus",
+ "Consensus", 0.5);
+ aa.autoCalculated = true;
+ al.addAnnotation(aa);
+ AlignmentAnnotation[] anns = al.getAlignmentAnnotation();
+ assertEquals("Wrong number of annotations before deleting", 4,
+ anns.length);
+ al.deleteAllAnnotations(true);
+ assertEquals("Not all deleted", 0, al.getAlignmentAnnotation().length);
+ }
+
+ @Test
+ public void testDeleteAllAnnotations_excludingAutocalculated()
+ {
+ AlignmentAnnotation aa = new AlignmentAnnotation("Consensus",
+ "Consensus", 0.5);
+ aa.autoCalculated = true;
+ al.addAnnotation(aa);
+ AlignmentAnnotation[] anns = al.getAlignmentAnnotation();
+ assertEquals("Wrong number of annotations before deleting", 4,
+ anns.length);
+ al.deleteAllAnnotations(false);
+ assertEquals("Not just one annotation left", 1,
+ al.getAlignmentAnnotation().length);
+ }
+
/**
* Tests for realigning as per a supplied alignment: Dna as Dna.
*
acf.addMap(al2.getSequenceAt(1), al1.getSequenceAt(1), ml);
al1.addCodonFrame(acf);
- al2.alignAs(al1);
+ ((Alignment) al2).alignAs(al1, false, true);
assertEquals("GC-TC--GUC-GTA-CT", al2.getSequenceAt(0)
.getSequenceAsString());
assertEquals("-GG-GTC--AGG---CAGT", al2.getSequenceAt(1)
String before0 = al2.getSequenceAt(0).getSequenceAsString();
String before1 = al2.getSequenceAt(1).getSequenceAsString();
- al2.alignAs(al1);
+ ((Alignment) al2).alignAs(al1, false, true);
assertEquals(before0, al2.getSequenceAt(0).getSequenceAsString());
assertEquals(before1, al2.getSequenceAt(1).getSequenceAsString());
}
acf.addMap(al1.getSequenceAt(1), al2.getSequenceAt(1), ml);
al2.addCodonFrame(acf);
- al1.alignAs(al2);
- assertEquals("AC-G---G--CUC-CA------A-CT", al1.getSequenceAt(0)
- .getSequenceAsString());
- assertEquals("---CG-T---TA--ACG---A---AGT", al1.getSequenceAt(1)
- .getSequenceAsString());
- }
-
- /**
- * Test aligning cdna (with introns) as per protein alignment.
- *
- * @throws IOException
- */
- @Test
- public void testAlignAs_cdnaAsProteinWithIntrons() throws IOException
- {
/*
- * Load alignments and add mappings for cDNA to protein
+ * Realign DNA; currently keeping existing gaps in introns only
*/
- AlignmentI al1 = loadAlignment(CDNA_SEQS_1, "FASTA");
- AlignmentI al2 = loadAlignment(AA_SEQS_1, "FASTA");
- AlignedCodonFrame acf = new AlignedCodonFrame();
- MapList ml = new MapList(new int[]
- { 1, 12 }, new int[]
- { 1, 4 }, 3, 1);
- acf.addMap(al1.getSequenceAt(0), al2.getSequenceAt(0), ml);
- acf.addMap(al1.getSequenceAt(1), al2.getSequenceAt(1), ml);
- al2.addCodonFrame(acf);
-
- al1.alignAs(al2);
- assertEquals("AC-G---G--CUC-CA------A-CT", al1.getSequenceAt(0)
+ ((Alignment) al1).alignAs(al2, false, true);
+ assertEquals("ACG---GCUCCA------ACT", al1.getSequenceAt(0)
.getSequenceAsString());
- assertEquals("---CG-T---TA--ACG---A---AGT", al1.getSequenceAt(1)
+ assertEquals("---CGT---TAACGA---AGT", al1.getSequenceAt(1)
.getSequenceAsString());
}
((Alignment) al1).alignAs(al2, false, false);
assertEquals("---AAagG------GCCcTTT", al1.getSequenceAt(0)
.getSequenceAsString());
- assertEquals("cCCGgg---TTT------AAA", al1.getSequenceAt(1)
+ // note 1 gap in protein corresponds to 'gg-' in DNA (3 positions)
+ assertEquals("cCCGgg-TTT------AAA", al1.getSequenceAt(1)
.getSequenceAsString());
/*
// assumption: we include 'the greater of' protein/dna gap lengths, not both
assertEquals("---A-Aa-gG------GCC-cT-TT", al1.getSequenceAt(0)
.getSequenceAsString());
- assertEquals("c--CCGgg---TT--T------AA-A", al1.getSequenceAt(1)
+ assertEquals("c--CCGgg-TT--T------AA-A", al1.getSequenceAt(1)
.getSequenceAsString());
}
}
--- /dev/null
+package jalview.gui;
+
+import static org.junit.Assert.assertEquals;
+
+import javax.swing.JScrollBar;
+
+import org.junit.Test;
+
+public class JvSwingUtilsTest
+{
+
+ @Test
+ public void testGetScrollBarProportion()
+ {
+ /*
+ * orientation, value, extent (width), min, max
+ */
+ JScrollBar sb = new JScrollBar(0, 125, 50, 0, 450);
+
+ /*
+ * operating range is 25 - 425 (400 wide) so value 125 is 100/400ths of this
+ * range
+ */
+ assertEquals(0.25f, JvSwingUtils.getScrollBarProportion(sb), 0.001f);
+ }
+
+ @Test
+ public void testGetScrollValueForProportion()
+ {
+ /*
+ * orientation, value, extent (width), min, max
+ */
+ JScrollBar sb = new JScrollBar(0, 125, 50, 0, 450);
+
+ /*
+ * operating range is 25 - 425 (400 wide) so value 125 is a quarter of this
+ * range
+ */
+ assertEquals(125, JvSwingUtils.getScrollValueForProportion(sb, 0.25f));
+ }
+}
--- /dev/null
+package jalview.gui;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import jalview.datamodel.Alignment;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+
+import java.awt.Component;
+import java.util.List;
+import java.util.Map;
+
+import javax.swing.JPanel;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class PaintRefresherTest
+{
+ // TODO would prefer PaintRefresher to be a single rather than static
+ @Before
+ public void setUp()
+ {
+ PaintRefresher.components.clear();
+ }
+
+ @After
+ public void tearDown()
+ {
+ PaintRefresher.components.clear();
+ }
+
+ @Test
+ public void testRegister()
+ {
+ JPanel jp = new JPanel();
+ JPanel jp2 = new JPanel();
+ JPanel jp3 = new JPanel();
+ JPanel jp4 = new JPanel();
+ PaintRefresher.Register(jp, "22");
+ PaintRefresher.Register(jp, "22");
+ PaintRefresher.Register(jp2, "22");
+ PaintRefresher.Register(jp3, "33");
+ PaintRefresher.Register(jp3, "44");
+ PaintRefresher.Register(jp4, "44");
+
+ Map<String, List<Component>> registered = PaintRefresher.components;
+ assertEquals(3, registered.size());
+ assertEquals(2, registered.get("22").size());
+ assertEquals(1, registered.get("33").size());
+ assertEquals(2, registered.get("44").size());
+ assertTrue(registered.get("22").contains(jp));
+ assertTrue(registered.get("22").contains(jp2));
+ assertTrue(registered.get("33").contains(jp3));
+ assertTrue(registered.get("44").contains(jp3));
+ assertTrue(registered.get("44").contains(jp4));
+ }
+
+ @Test
+ public void testRemoveComponent()
+ {
+ Map<String, List<Component>> registered = PaintRefresher.components;
+
+ // no error with an empty PaintRefresher
+ JPanel jp = new JPanel();
+ JPanel jp2 = new JPanel();
+ PaintRefresher.RemoveComponent(jp);
+ assertTrue(registered.isEmpty());
+
+ /*
+ * Add then remove one item
+ */
+ PaintRefresher.Register(jp, "11");
+ PaintRefresher.RemoveComponent(jp);
+ assertTrue(registered.isEmpty());
+
+ /*
+ * Add one item under two ids, then remove it. It is removed from both ids,
+ * and the now empty id is removed.
+ */
+ PaintRefresher.Register(jp, "11");
+ PaintRefresher.Register(jp, "22");
+ PaintRefresher.Register(jp2, "22");
+ PaintRefresher.RemoveComponent(jp);
+ // "11" is removed as now empty, only 22/jp2 left
+ assertEquals(1, registered.size());
+ assertEquals(1, registered.get("22").size());
+ assertTrue(registered.get("22").contains(jp2));
+ }
+
+ @Test
+ public void testGetAssociatedPanels()
+ {
+ SequenceI [] seqs = new SequenceI[]{new Sequence("", "ABC")};
+ Alignment al = new Alignment(seqs);
+
+ /*
+ * AlignFrame constructor has side-effects: AlignmentPanel is constructed,
+ * and SeqCanvas, IdPanel, AlignmentPanel are all registered under the
+ * sequence set id of the viewport.
+ */
+ AlignViewport av = new AlignViewport(al);
+ AlignFrame af = new AlignFrame(al, 4, 1);
+ AlignmentPanel ap1 = af.alignPanel;
+ AlignmentPanel[] panels = PaintRefresher.getAssociatedPanels(av
+ .getSequenceSetId());
+ assertEquals(1, panels.length);
+ assertSame(ap1, panels[0]);
+
+ panels = PaintRefresher.getAssociatedPanels(av.getSequenceSetId() + 1);
+ assertEquals(0, panels.length);
+ }
+}
package jalview.util;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
// out of range deletion is ignore
assertTrue(Arrays.equals(c1, StringUtils.deleteChars(c1, 3, 4)));
}
+
+ @Test
+ public void testGetLastToken()
+ {
+ assertNull(StringUtils.getLastToken(null, null));
+ assertNull(StringUtils.getLastToken(null, "/"));
+ assertEquals("a", StringUtils.getLastToken("a", null));
+
+ assertEquals("abc", StringUtils.getLastToken("abc", "/"));
+ assertEquals("c", StringUtils.getLastToken("abc", "b"));
+ assertEquals("file1.dat", StringUtils.getLastToken(
+ "file://localhost:8080/data/examples/file1.dat", "/"));
+ }
}