X-Git-Url: http://source.jalview.org/gitweb/?p=jalview.git;a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FPopupMenu.java;h=abe9835d3911bc5b89bc82b33191f77108e220c1;hp=3de7c3c81e77349f71843ab2c85678a6432024df;hb=c6018dc0dc12720e13b75850a5303279ac7094b7;hpb=268dfe33ea14bbcdfb0671a1ec8acc5e9c423426 diff --git a/src/jalview/gui/PopupMenu.java b/src/jalview/gui/PopupMenu.java index 3de7c3c..abe9835 100644 --- a/src/jalview/gui/PopupMenu.java +++ b/src/jalview/gui/PopupMenu.java @@ -20,21 +20,46 @@ */ package jalview.gui; +import java.awt.Color; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.BitSet; +import java.util.Collection; +import java.util.Collections; +import java.util.Hashtable; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.Vector; + +import javax.swing.ButtonGroup; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JColorChooser; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.JRadioButtonMenuItem; + import jalview.analysis.AAFrequency; import jalview.analysis.AlignmentAnnotationUtils; import jalview.analysis.AlignmentUtils; import jalview.analysis.Conservation; +import jalview.api.AlignViewportI; import jalview.bin.Cache; import jalview.commands.ChangeCaseCommand; import jalview.commands.EditCommand; import jalview.commands.EditCommand.Action; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AlignmentI; -import jalview.datamodel.Annotation; import jalview.datamodel.DBRefEntry; import jalview.datamodel.HiddenColumns; +import jalview.datamodel.MappedFeatures; import jalview.datamodel.PDBEntry; -import jalview.datamodel.Sequence; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; @@ -47,40 +72,39 @@ import jalview.schemes.Blosum62ColourScheme; import jalview.schemes.ColourSchemeI; import jalview.schemes.ColourSchemes; import jalview.schemes.PIDColourScheme; +import jalview.schemes.ResidueColourScheme; +import jalview.util.Comparison; import jalview.util.GroupUrlLink; import jalview.util.GroupUrlLink.UrlStringTooLongException; import jalview.util.MessageManager; +import jalview.util.StringUtils; import jalview.util.UrlLink; - -import java.awt.Color; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Hashtable; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.SortedMap; -import java.util.TreeMap; -import java.util.Vector; - -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JColorChooser; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JPopupMenu; +import jalview.viewmodel.seqfeatures.FeatureRendererModel; /** - * DOCUMENT ME! - * - * @author $author$ - * @version $Revision: 1.118 $ + * The popup menu that is displayed on right-click on a sequence id, or in the + * sequence alignment. */ public class PopupMenu extends JPopupMenu implements ColourChangeListener { + /* + * maximum length of feature description to include in popup menu item text + */ + private static final int FEATURE_DESC_MAX = 40; + + /* + * true for ID Panel menu, false for alignment panel menu + */ + private final boolean forIdPanel; + + private final AlignmentPanel ap; + + /* + * the sequence under the cursor when clicked + * (additional sequences may be selected) + */ + private final SequenceI sequence; + JMenu groupMenu = new JMenu(); JMenuItem groupName = new JMenuItem(); @@ -91,30 +115,18 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener protected JCheckBoxMenuItem conservationMenuItem = new JCheckBoxMenuItem(); - protected JMenuItem modifyConservation = new JMenuItem(); + protected JRadioButtonMenuItem annotationColour; - AlignmentPanel ap; + protected JMenuItem modifyConservation = new JMenuItem(); JMenu sequenceMenu = new JMenu(); - JMenuItem sequenceName = new JMenuItem(); - - JMenuItem sequenceDetails = new JMenuItem(); - - JMenuItem sequenceSelDetails = new JMenuItem(); - JMenuItem makeReferenceSeq = new JMenuItem(); - JMenuItem chooseAnnotations = new JMenuItem(); - - SequenceI sequence; - JMenuItem createGroupMenuItem = new JMenuItem(); JMenuItem unGroupMenuItem = new JMenuItem(); - JMenuItem outline = new JMenuItem(); - JMenu colourMenu = new JMenu(); JCheckBoxMenuItem showBoxes = new JCheckBoxMenuItem(); @@ -127,18 +139,12 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener JMenu editMenu = new JMenu(); - JMenuItem cut = new JMenuItem(); - - JMenuItem copy = new JMenuItem(); - JMenuItem upperCase = new JMenuItem(); JMenuItem lowerCase = new JMenuItem(); JMenuItem toggle = new JMenuItem(); - JMenu pdbMenu = new JMenu(); - JMenu outputMenu = new JMenu(); JMenu seqShowAnnotationsMenu = new JMenu(); @@ -155,52 +161,246 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener JMenuItem groupAddReferenceAnnotations = new JMenuItem( MessageManager.getString("label.add_reference_annotations")); - JMenuItem sequenceFeature = new JMenuItem(); - JMenuItem textColour = new JMenuItem(); - JMenu jMenu1 = new JMenu(); + JMenu editGroupMenu = new JMenu(); - JMenuItem pdbStructureDialog = new JMenuItem(); + JMenuItem chooseStructure = new JMenuItem(); JMenu rnaStructureMenu = new JMenu(); - JMenuItem editSequence = new JMenuItem(); + /** + * Constructs a menu with sub-menu items for any hyperlinks for the sequence + * and/or features provided. Hyperlinks may include a lookup by sequence id, + * or database cross-references, depending on which links are enabled in user + * preferences. + * + * @param seq + * @param features + * @return + */ + protected static JMenu buildLinkMenu(final SequenceI seq, + List features) + { + JMenu linkMenu = new JMenu(MessageManager.getString("action.link")); + + List nlinks = null; + if (seq != null) + { + nlinks = Preferences.sequenceUrlLinks.getLinksForMenu(); + UrlLink.sort(nlinks); + } + else + { + nlinks = new ArrayList<>(); + } + + if (features != null) + { + for (SequenceFeature sf : features) + { + if (sf.links != null) + { + for (String link : sf.links) + { + nlinks.add(link); + } + } + } + } + + /* + * instantiate the hyperlinklink templates from sequence data; + * note the order of the templates is preserved in the map + */ + Map> linkset = new LinkedHashMap<>(); + for (String link : nlinks) + { + UrlLink urlLink = null; + try + { + urlLink = new UrlLink(link); + } catch (Exception foo) + { + Cache.log.error("Exception for URLLink '" + link + "'", foo); + continue; + } + + if (!urlLink.isValid()) + { + Cache.log.error(urlLink.getInvalidMessage()); + continue; + } + + urlLink.createLinksFromSeq(seq, linkset); + } + + /* + * construct menu items for the hyperlinks (still preserving + * the order of the sorted templates) + */ + addUrlLinks(linkMenu, linkset.values()); + + return linkMenu; + } + + /** + * A helper method that builds menu items from the given links, with action + * handlers to open the link URL, and adds them to the linkMenu. Each provided + * link should be a list whose second item is the menu text, and whose fourth + * item is the URL to open when the menu item is selected. + * + * @param linkMenu + * @param linkset + */ + static private void addUrlLinks(JMenu linkMenu, + Collection> linkset) + { + for (List linkstrset : linkset) + { + final String url = linkstrset.get(3); + JMenuItem item = new JMenuItem(linkstrset.get(1)); + item.setToolTipText(MessageManager + .formatMessage("label.open_url_param", new Object[] + { url })); + item.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + new Thread(new Runnable() + { + @Override + public void run() + { + showLink(url); + } + }).start(); + } + }); + linkMenu.add(item); + } + } + + /** + * Opens the provided url in the default web browser, or shows an error + * message if this fails + * + * @param url + */ + static void showLink(String url) + { + try + { + jalview.util.BrowserLauncher.openURL(url); + } catch (Exception ex) + { + JvOptionPane.showInternalMessageDialog(Desktop.desktop, + MessageManager.getString("label.web_browser_not_found_unix"), + MessageManager.getString("label.web_browser_not_found"), + JvOptionPane.WARNING_MESSAGE); + + ex.printStackTrace(); + } + } + + /** + * add a late bound groupURL item to the given linkMenu + * + * @param linkMenu + * @param label + * - menu label string + * @param urlgenerator + * GroupURLLink used to generate URL + * @param urlstub + * Object array returned from the makeUrlStubs function. + */ + static void addshowLink(JMenu linkMenu, String label, + final GroupUrlLink urlgenerator, final Object[] urlstub) + { + JMenuItem item = new JMenuItem(label); + item.setToolTipText(MessageManager + .formatMessage("label.open_url_seqs_param", new Object[] + { urlgenerator.getUrl_prefix(), + urlgenerator.getNumberInvolved(urlstub) })); + // TODO: put in info about what is being sent. + item.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + new Thread(new Runnable() + { + + @Override + public void run() + { + try + { + showLink(urlgenerator.constructFrom(urlstub)); + } catch (UrlStringTooLongException e2) + { + } + } - JMenu groupLinksMenu; + }).start(); + } + }); - JMenuItem hideInsertions = new JMenuItem(); + linkMenu.add(item); + } /** - * Creates a new PopupMenu object. + * Constructor for a PopupMenu for a click in the alignment panel (on a residue) * * @param ap - * DOCUMENT ME! + * the panel in which the mouse is clicked * @param seq - * DOCUMENT ME! + * the sequence under the mouse + * @throws NullPointerException + * if seq is null */ - public PopupMenu(final AlignmentPanel ap, Sequence seq, List links) + public PopupMenu(final AlignmentPanel ap, SequenceI seq, int column) { - this(ap, seq, links, null); + this(false, ap, seq, column, null); } /** + * Constructor for a PopupMenu for a click in the sequence id panel * - * @param ap + * @param alignPanel + * the panel in which the mouse is clicked + * @param seq + * the sequence under the mouse click + * @param groupLinks + * templates for sequence external links + * @throws NullPointerException + * if seq is null + */ + public PopupMenu(final AlignmentPanel alignPanel, final SequenceI seq, + List groupLinks) + { + this(true, alignPanel, seq, -1, groupLinks); + } + + /** + * Private constructor that constructs a popup menu for either sequence ID + * Panel, or alignment context + * + * @param fromIdPanel + * @param alignPanel * @param seq - * @param links + * @param column + * aligned column position (0...) * @param groupLinks */ - public PopupMenu(final AlignmentPanel ap, final SequenceI seq, - List links, List groupLinks) + private PopupMenu(boolean fromIdPanel, + final AlignmentPanel alignPanel, + final SequenceI seq, final int column, List groupLinks) { - // ///////////////////////////////////////////////////////// - // If this is activated from the sequence panel, the user may want to - // edit or annotate a particular residue. Therefore display the residue menu - // - // If from the IDPanel, we must display the sequence menu - // //////////////////////////////////////////////////////// - this.ap = ap; + Objects.requireNonNull(seq); + this.forIdPanel = fromIdPanel; + this.ap = alignPanel; sequence = seq; for (String ff : FileFormats.getInstance().getWritableFormats(true)) @@ -224,8 +424,9 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener * 'reference annotations' that may be added to the alignment. First for the * currently selected sequence (if there is one): */ - final List selectedSequence = (seq == null ? Collections - . emptyList() : Arrays.asList(seq)); + final List selectedSequence = (forIdPanel && seq != null + ? Arrays.asList(seq) + : Collections. emptyList()); buildAnnotationTypesMenus(seqShowAnnotationsMenu, seqHideAnnotationsMenu, selectedSequence); configureReferenceAnnotationsMenu(seqAddReferenceAnnotations, @@ -234,9 +435,9 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener /* * And repeat for the current selection group (if there is one): */ - final List selectedGroup = (ap.av.getSelectionGroup() == null ? Collections - . emptyList() : ap.av.getSelectionGroup() - .getSequences()); + final List selectedGroup = (alignPanel.av.getSelectionGroup() == null + ? Collections. emptyList() + : alignPanel.av.getSelectionGroup().getSequences()); buildAnnotationTypesMenus(groupShowAnnotationsMenu, groupHideAnnotationsMenu, selectedGroup); configureReferenceAnnotationsMenu(groupAddReferenceAnnotations, @@ -250,22 +451,22 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener e.printStackTrace(); } - JMenuItem menuItem; - if (seq != null) + if (forIdPanel) { + JMenuItem menuItem; sequenceMenu.setText(sequence.getName()); - if (seq == ap.av.getAlignment().getSeqrep()) + if (seq == alignPanel.av.getAlignment().getSeqrep()) { - makeReferenceSeq.setText(MessageManager - .getString("action.unmark_as_reference")); + makeReferenceSeq.setText( + MessageManager.getString("action.unmark_as_reference")); } else { - makeReferenceSeq.setText(MessageManager - .getString("action.set_as_reference")); + makeReferenceSeq.setText( + MessageManager.getString("action.set_as_reference")); } - if (!ap.av.getAlignment().isNucleotide()) + if (!alignPanel.av.getAlignment().isNucleotide()) { remove(rnaStructureMenu); } @@ -276,7 +477,7 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener * add menu items to 2D-render any alignment or sequence secondary * structure annotation */ - AlignmentAnnotation[] aas = ap.av.getAlignment() + AlignmentAnnotation[] aas = alignPanel.av.getAlignment() .getAlignmentAnnotation(); if (aas != null) { @@ -289,14 +490,14 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener */ menuItem = new JMenuItem(); menuItem.setText(MessageManager.formatMessage( - "label.2d_rna_structure_line", - new Object[] { aa.label })); + "label.2d_rna_structure_line", new Object[] + { aa.label })); menuItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - new AppVarna(seq, aa, ap); + new AppVarna(seq, aa, alignPanel); } }); rnaStructureMenu.add(menuItem); @@ -317,15 +518,15 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener // TODO: make rnastrucF a bit more nice menuItem = new JMenuItem(); menuItem.setText(MessageManager.formatMessage( - "label.2d_rna_sequence_name", - new Object[] { seq.getName() })); + "label.2d_rna_sequence_name", new Object[] + { seq.getName() })); menuItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO: VARNA does'nt print gaps in the sequence - new AppVarna(seq, aa, ap); + new AppVarna(seq, aa, alignPanel); } }); rnaStructureMenu.add(menuItem); @@ -350,12 +551,12 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener }); add(menuItem); - if (ap.av.getSelectionGroup() != null - && ap.av.getSelectionGroup().getSize() > 1) + if (alignPanel.av.getSelectionGroup() != null + && alignPanel.av.getSelectionGroup().getSize() > 1) { - menuItem = new JMenuItem(MessageManager.formatMessage( - "label.represent_group_with", - new Object[] { seq.getName() })); + menuItem = new JMenuItem(MessageManager + .formatMessage("label.represent_group_with", new Object[] + { seq.getName() })); menuItem.addActionListener(new ActionListener() { @Override @@ -367,12 +568,12 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener sequenceMenu.add(menuItem); } - if (ap.av.hasHiddenRows()) + if (alignPanel.av.hasHiddenRows()) { - final int index = ap.av.getAlignment().findIndex(seq); + final int index = alignPanel.av.getAlignment().findIndex(seq); - if (ap.av.adjustForHiddenSeqs(index) - - ap.av.adjustForHiddenSeqs(index - 1) > 1) + if (alignPanel.av.adjustForHiddenSeqs(index) + - alignPanel.av.adjustForHiddenSeqs(index - 1) > 1) { menuItem = new JMenuItem( MessageManager.getString("action.reveal_sequences")); @@ -381,10 +582,10 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener @Override public void actionPerformed(ActionEvent e) { - ap.av.showSequence(index); - if (ap.overviewPanel != null) + alignPanel.av.showSequence(index); + if (alignPanel.overviewPanel != null) { - ap.overviewPanel.updateOverviewImage(); + alignPanel.overviewPanel.updateOverviewImage(); } } }); @@ -392,32 +593,43 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener } } } - // for the case when no sequences are even visible - if (ap.av.hasHiddenRows()) + + /* + * offer 'Reveal All' + * - in the IdPanel (seq not null) if any sequence is hidden + * - in the IdPanel or SeqPanel if all sequences are hidden (seq is null) + */ + if (alignPanel.av.hasHiddenRows()) { + boolean addOption = seq != null; + if (!addOption && alignPanel.av.getAlignment().getHeight() == 0) { - menuItem = new JMenuItem( + addOption = true; + } + if (addOption) + { + JMenuItem menuItem = new JMenuItem( MessageManager.getString("action.reveal_all")); menuItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - ap.av.showAllHiddenSeqs(); - if (ap.overviewPanel != null) + alignPanel.av.showAllHiddenSeqs(); + if (alignPanel.overviewPanel != null) { - ap.overviewPanel.updateOverviewImage(); + alignPanel.overviewPanel.updateOverviewImage(); } } }); - add(menuItem); } } - SequenceGroup sg = ap.av.getSelectionGroup(); - boolean isDefinedGroup = (sg != null) ? ap.av.getAlignment() - .getGroups().contains(sg) : false; + SequenceGroup sg = alignPanel.av.getSelectionGroup(); + boolean isDefinedGroup = (sg != null) + ? alignPanel.av.getAlignment().getGroups().contains(sg) + : false; if (sg != null && sg.getSize() > 0) { @@ -451,9 +663,10 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener buildGroupURLMenu(sg, groupLinks); } // Add a 'show all structures' for the current selection - Hashtable pdbe = new Hashtable(), reppdb = new Hashtable(); + Hashtable pdbe = new Hashtable<>(), reppdb = new Hashtable<>(); + SequenceI sqass = null; - for (SequenceI sq : ap.av.getSequenceSelection()) + for (SequenceI sq : alignPanel.av.getSequenceSelection()) { Vector pes = sq.getDatasetSequence().getAllPDBEntries(); if (pes != null && pes.size() > 0) @@ -471,9 +684,9 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener } if (pdbe.size() > 0) { - final PDBEntry[] pe = pdbe.values().toArray( - new PDBEntry[pdbe.size()]), pr = reppdb.values().toArray( - new PDBEntry[reppdb.size()]); + final PDBEntry[] pe = pdbe.values() + .toArray(new PDBEntry[pdbe.size()]), + pr = reppdb.values().toArray(new PDBEntry[reppdb.size()]); final JMenuItem gpdbview, rpdbview; } } @@ -487,81 +700,242 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener { createGroupMenuItem.setVisible(true); unGroupMenuItem.setVisible(false); - jMenu1.setText(MessageManager.getString("action.edit_new_group")); + editGroupMenu.setText(MessageManager.getString("action.edit_new_group")); } else { createGroupMenuItem.setVisible(false); unGroupMenuItem.setVisible(true); - jMenu1.setText(MessageManager.getString("action.edit_group")); + editGroupMenu.setText(MessageManager.getString("action.edit_group")); } - if (seq == null) + if (!forIdPanel) { sequenceMenu.setVisible(false); - pdbStructureDialog.setVisible(false); + chooseStructure.setVisible(false); rnaStructureMenu.setVisible(false); } - if (links != null && links.size() > 0) - { - addFeatureLinks(seq, links); - } + addLinksAndFeatures(seq, column); } /** - * Adds a 'Link' menu item with a sub-menu item for each hyperlink provided. + * Adds + *
    + *
  • configured sequence database links (ID panel popup menu)
  • + *
  • non-positional feature links (ID panel popup menu)
  • + *
  • positional feature links (alignment panel popup menu)
  • + *
  • feature details links (alignment panel popup menu)
  • + *
+ * If this panel is also showed complementary (CDS/protein) features, then links + * to their feature details are also added. * * @param seq - * @param links + * @param column */ - void addFeatureLinks(final SequenceI seq, List links) + void addLinksAndFeatures(final SequenceI seq, final int column) { - JMenu linkMenu = new JMenu(MessageManager.getString("action.link")); - Map> linkset = new LinkedHashMap>(); + List features = null; + if (forIdPanel) + { + features = sequence.getFeatures().getNonPositionalFeatures(); + } + else + { + features = ap.getFeatureRenderer().findFeaturesAtColumn(sequence, + column + 1); + } - for (String link : links) + addLinks(seq, features); + + if (!forIdPanel) { - UrlLink urlLink = null; - try - { - urlLink = new UrlLink(link); - } catch (Exception foo) - { - Cache.log.error("Exception for URLLink '" + link + "'", foo); - continue; - } + addFeatureDetails(features, seq, column); + } + } - if (!urlLink.isValid()) + /** + * Add a menu item to show feature details for each sequence feature. Any + * linked 'virtual' features (CDS/protein) are also optionally found and + * included. + * + * @param features + * @param seq + * @param column + */ + protected void addFeatureDetails(List features, + final SequenceI seq, final int column) + { + /* + * add features in CDS/protein complement at the corresponding + * position if configured to do so + */ + MappedFeatures mf = null; + if (ap.av.isShowComplementFeatures()) + { + if (!Comparison.isGap(sequence.getCharAt(column))) { - Cache.log.error(urlLink.getInvalidMessage()); - continue; + AlignViewportI complement = ap.getAlignViewport() + .getCodingComplement(); + AlignFrame af = Desktop.getAlignFrameFor(complement); + FeatureRendererModel fr2 = af.getFeatureRenderer(); + int seqPos = sequence.findPosition(column); + mf = fr2.findComplementFeaturesAtResidue(sequence, seqPos); } + } - urlLink.createLinksFromSeq(seq, linkset); + if (features.isEmpty() && mf == null) + { + /* + * no features to show at this position + */ + return; } - addshowLinks(linkMenu, linkset.values()); + JMenu details = new JMenu( + MessageManager.getString("label.feature_details")); + add(details); - // disable link menu if there are no valid entries - if (linkMenu.getItemCount() > 0) + String name = seq.getName(); + for (final SequenceFeature sf : features) { - linkMenu.setEnabled(true); + addFeatureDetailsMenuItem(details, name, sf, null); } - else + + if (mf != null) { - linkMenu.setEnabled(false); + for (final SequenceFeature sf : mf.features) + { + addFeatureDetailsMenuItem(details, name, sf, mf); + } } + } - if (sequence != null) + /** + * A helper method to add one menu item whose action is to show details for + * one feature. The menu text includes feature description, but this may be + * truncated. + * + * @param details + * @param seqName + * @param sf + * @param mf + */ + void addFeatureDetailsMenuItem(JMenu details, final String seqName, + final SequenceFeature sf, MappedFeatures mf) + { + int start = sf.getBegin(); + int end = sf.getEnd(); + if (mf != null) + { + /* + * show local rather than linked feature coordinates + */ + int[] beginRange = mf.getMappedPositions(start, start); + int[] endRange = mf.getMappedPositions(end, end); + if (beginRange == null || endRange == null) + { + // e.g. variant extending to stop codon so not mappable + return; + } + start = beginRange[0]; + end = endRange[endRange.length - 1]; + int[] localRange = mf.getMappedPositions(start, end); + if (localRange == null) + { + return; + } + start = localRange[0]; + end = localRange[localRange.length - 1]; + } + StringBuilder desc = new StringBuilder(); + desc.append(sf.getType()).append(" ").append(String.valueOf(start)); + if (start != end) { - sequenceMenu.add(linkMenu); + desc.append(sf.isContactFeature() ? ":" : "-"); + desc.append(String.valueOf(end)); } - else + String description = sf.getDescription(); + if (description != null) + { + desc.append(" "); + description = StringUtils.stripHtmlTags(description); + + /* + * truncate overlong descriptions unless they contain an href + * (as truncation could leave corrupted html) + */ + boolean hasLink = description.indexOf("a href") > -1; + if (description.length() > FEATURE_DESC_MAX && !hasLink) + { + description = description.substring(0, FEATURE_DESC_MAX) + "..."; + } + desc.append(description); + } + String featureGroup = sf.getFeatureGroup(); + if (featureGroup != null) { - add(linkMenu); + desc.append(" (").append(featureGroup).append(")"); } + String htmlText = JvSwingUtils.wrapTooltip(true, desc.toString()); + JMenuItem item = new JMenuItem(htmlText); + item.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + showFeatureDetails(sf, seqName, mf); + } + }); + details.add(item); + } + + /** + * Opens a panel showing a text report of feature details + * + * @param sf + * @param seqName + * @param mf + */ + protected void showFeatureDetails(SequenceFeature sf, String seqName, + MappedFeatures mf) + { + CutAndPasteHtmlTransfer cap = new CutAndPasteHtmlTransfer(); + // it appears Java's CSS does not support border-collapse :-( + cap.addStylesheetRule("table { border-collapse: collapse;}"); + cap.addStylesheetRule("table, td, th {border: 1px solid black;}"); + cap.setText(sf.getDetailsReport(seqName, mf)); + + Desktop.addInternalFrame(cap, + MessageManager.getString("label.feature_details"), 500, 500); + } + + /** + * Adds a 'Link' menu item with a sub-menu item for each hyperlink provided. + * When seq is not null, these are links for the sequence id, which may be to + * external web sites for the sequence accession, and/or links embedded in + * non-positional features. When seq is null, only links embedded in the + * provided features are added. If no links are found, the menu is not added. + * + * @param seq + * @param features + */ + void addLinks(final SequenceI seq, List features) + { + JMenu linkMenu = buildLinkMenu(forIdPanel ? seq : null, features); + // only add link menu if it has entries + if (linkMenu.getItemCount() > 0) + { + if (forIdPanel) + { + sequenceMenu.add(linkMenu); + } + else + { + add(linkMenu); + } + } } /** @@ -585,9 +959,11 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener showMenu.removeAll(); hideMenu.removeAll(); - final List all = Arrays.asList(new String[] { MessageManager - .getString("label.all") }); - addAnnotationTypeToShowHide(showMenu, forSequences, "", all, true, true); + final List all = Arrays + .asList(new String[] + { MessageManager.getString("label.all") }); + addAnnotationTypeToShowHide(showMenu, forSequences, "", all, true, + true); addAnnotationTypeToShowHide(hideMenu, forSequences, "", all, true, false); showMenu.addSeparator(); @@ -602,8 +978,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener * the insertion order, which is the order of the annotations on the * alignment. */ - Map>> shownTypes = new LinkedHashMap>>(); - Map>> hiddenTypes = new LinkedHashMap>>(); + Map>> shownTypes = new LinkedHashMap<>(); + Map>> hiddenTypes = new LinkedHashMap<>(); AlignmentAnnotationUtils.getShownHiddenTypes(shownTypes, hiddenTypes, AlignmentAnnotationUtils.asList(annotations), forSequences); @@ -699,7 +1075,7 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener // menu appears asap // sequence only URLs // ID/regex match URLs - groupLinksMenu = new JMenu( + JMenu groupLinksMenu = new JMenu( MessageManager.getString("action.group_link")); // three types of url that might be created. JMenu[] linkMenus = new JMenu[] { null, @@ -709,12 +1085,12 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener SequenceI[] seqs = ap.av.getSelectionAsNewSequence(); String[][] idandseqs = GroupUrlLink.formStrings(seqs); - Hashtable commonDbrefs = new Hashtable(); + Hashtable commonDbrefs = new Hashtable<>(); for (int sq = 0; sq < seqs.length; sq++) { - int start = seqs[sq].findPosition(sg.getStartRes()), end = seqs[sq] - .findPosition(sg.getEndRes()); + int start = seqs[sq].findPosition(sg.getStartRes()), + end = seqs[sq].findPosition(sg.getEndRes()); // just collect ids from dataset sequence // TODO: check if IDs collected from selecton group intersects with the // current selection, too @@ -741,8 +1117,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener if (((String[]) sarray[1])[sq] == null) { - if (!dbr[d].hasMap() - || (dbr[d].getMap().locateMappedRange(start, end) != null)) + if (!dbr[d].hasMap() || (dbr[d].getMap() + .locateMappedRange(start, end) != null)) { ((String[]) sarray[1])[sq] = dbr[d].getAccessionId(); ((int[]) sarray[0])[0]++; @@ -814,9 +1190,10 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener int type = urlLink.getGroupURLType() & 3; // first two bits ofurlLink type bitfield are sequenceids and sequences // TODO: FUTURE: ensure the groupURL menu structure can be generalised - addshowLink(linkMenus[type], label - + (((type & 1) == 1) ? ("(" - + (usingNames ? "Names" : ltarget) + ")") : ""), + addshowLink(linkMenus[type], + label + (((type & 1) == 1) + ? ("(" + (usingNames ? "Names" : ltarget) + ")") + : ""), urlLink, urlset); addMenu = true; } @@ -838,96 +1215,6 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener } } - private void addshowLinks(JMenu linkMenu, Collection> linkset) - { - for (List linkstrset : linkset) - { - // split linkstr into label and url - addshowLink(linkMenu, linkstrset.get(1), linkstrset.get(3)); - } - } - - /** - * add a show URL menu item to the given linkMenu - * - * @param linkMenu - * @param label - * - menu label string - * @param url - * - url to open - */ - private void addshowLink(JMenu linkMenu, String label, final String url) - { - JMenuItem item = new JMenuItem(label); - item.setToolTipText(MessageManager.formatMessage( - "label.open_url_param", new Object[] { url })); - item.addActionListener(new ActionListener() - { - @Override - public void actionPerformed(ActionEvent e) - { - new Thread(new Runnable() - { - - @Override - public void run() - { - showLink(url); - } - - }).start(); - } - }); - - linkMenu.add(item); - } - - /** - * add a late bound groupURL item to the given linkMenu - * - * @param linkMenu - * @param label - * - menu label string - * @param urlgenerator - * GroupURLLink used to generate URL - * @param urlstub - * Object array returned from the makeUrlStubs function. - */ - private void addshowLink(JMenu linkMenu, String label, - final GroupUrlLink urlgenerator, final Object[] urlstub) - { - JMenuItem item = new JMenuItem(label); - item.setToolTipText(MessageManager.formatMessage( - "label.open_url_seqs_param", - new Object[] { urlgenerator.getUrl_prefix(), - urlgenerator.getNumberInvolved(urlstub) })); - // TODO: put in info about what is being sent. - item.addActionListener(new ActionListener() - { - @Override - public void actionPerformed(ActionEvent e) - { - new Thread(new Runnable() - { - - @Override - public void run() - { - try - { - showLink(urlgenerator.constructFrom(urlstub)); - } catch (UrlStringTooLongException e2) - { - } - } - - }).start(); - } - }); - - linkMenu.add(item); - } - /** * DOCUMENT ME! * @@ -947,8 +1234,9 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener } }); sequenceMenu.setText(MessageManager.getString("label.sequence")); - sequenceName.setText(MessageManager - .getString("label.edit_name_description")); + + JMenuItem sequenceName = new JMenuItem( + MessageManager.getString("label.edit_name_description")); sequenceName.addActionListener(new ActionListener() { @Override @@ -957,8 +1245,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener sequenceName_actionPerformed(); } }); - chooseAnnotations.setText(MessageManager - .getString("action.choose_annotations")); + JMenuItem chooseAnnotations = new JMenuItem( + MessageManager.getString("action.choose_annotations")); chooseAnnotations.addActionListener(new ActionListener() { @Override @@ -967,24 +1255,24 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener chooseAnnotations_actionPerformed(e); } }); - sequenceDetails.setText(MessageManager - .getString("label.sequence_details")); + JMenuItem sequenceDetails = new JMenuItem( + MessageManager.getString("label.sequence_details")); sequenceDetails.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - sequenceDetails_actionPerformed(); + createSequenceDetailsReport(new SequenceI[] { sequence }); } }); - sequenceSelDetails.setText(MessageManager - .getString("label.sequence_details")); + JMenuItem sequenceSelDetails = new JMenuItem( + MessageManager.getString("label.sequence_details")); sequenceSelDetails.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - sequenceSelectionDetails_actionPerformed(); + createSequenceDetailsReport(ap.av.getSequenceSelection()); } }); @@ -998,8 +1286,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener unGroupMenuItem_actionPerformed(); } }); - createGroupMenuItem.setText(MessageManager - .getString("action.create_group")); + createGroupMenuItem + .setText(MessageManager.getString("action.create_group")); createGroupMenuItem.addActionListener(new ActionListener() { @Override @@ -1009,7 +1297,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener } }); - outline.setText(MessageManager.getString("action.border_colour")); + JMenuItem outline = new JMenuItem( + MessageManager.getString("action.border_colour")); outline.addActionListener(new ActionListener() { @Override @@ -1047,8 +1336,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener showColourText_actionPerformed(); } }); - displayNonconserved.setText(MessageManager - .getString("label.show_non_conserved")); + displayNonconserved + .setText(MessageManager.getString("label.show_non_conserved")); displayNonconserved.setState(true); displayNonconserved.addActionListener(new ActionListener() { @@ -1059,7 +1348,7 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener } }); editMenu.setText(MessageManager.getString("action.edit")); - cut.setText(MessageManager.getString("action.cut")); + JMenuItem cut = new JMenuItem(MessageManager.getString("action.cut")); cut.addActionListener(new ActionListener() { @Override @@ -1077,7 +1366,7 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener changeCase(e); } }); - copy.setText(MessageManager.getString("action.copy")); + JMenuItem copy = new JMenuItem(MessageManager.getString("action.copy")); copy.addActionListener(new ActionListener() { @Override @@ -1104,18 +1393,18 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener changeCase(e); } }); - outputMenu.setText(MessageManager.getString("label.out_to_textbox") - + "..."); - seqShowAnnotationsMenu.setText(MessageManager - .getString("label.show_annotations")); - seqHideAnnotationsMenu.setText(MessageManager - .getString("label.hide_annotations")); - groupShowAnnotationsMenu.setText(MessageManager - .getString("label.show_annotations")); - groupHideAnnotationsMenu.setText(MessageManager - .getString("label.hide_annotations")); - sequenceFeature.setText(MessageManager - .getString("label.create_sequence_feature")); + outputMenu.setText( + MessageManager.getString("label.out_to_textbox") + "..."); + seqShowAnnotationsMenu + .setText(MessageManager.getString("label.show_annotations")); + seqHideAnnotationsMenu + .setText(MessageManager.getString("label.hide_annotations")); + groupShowAnnotationsMenu + .setText(MessageManager.getString("label.show_annotations")); + groupHideAnnotationsMenu + .setText(MessageManager.getString("label.hide_annotations")); + JMenuItem sequenceFeature = new JMenuItem( + MessageManager.getString("label.create_sequence_feature")); sequenceFeature.addActionListener(new ActionListener() { @Override @@ -1124,10 +1413,10 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener sequenceFeature_actionPerformed(); } }); - jMenu1.setText(MessageManager.getString("label.group")); - pdbStructureDialog.setText(MessageManager - .getString("label.show_pdbstruct_dialog")); - pdbStructureDialog.addActionListener(new ActionListener() + editGroupMenu.setText(MessageManager.getString("label.group")); + chooseStructure.setText( + MessageManager.getString("label.show_pdbstruct_dialog")); + chooseStructure.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) @@ -1141,12 +1430,12 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener } }); - rnaStructureMenu.setText(MessageManager - .getString("label.view_rna_structure")); + rnaStructureMenu + .setText(MessageManager.getString("label.view_rna_structure")); // colStructureMenu.setText("Colour By Structure"); - editSequence.setText(MessageManager.getString("label.edit_sequence") - + "..."); + JMenuItem editSequence = new JMenuItem( + MessageManager.getString("label.edit_sequence") + "..."); editSequence.addActionListener(new ActionListener() { @Override @@ -1155,8 +1444,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener editSequence_actionPerformed(actionEvent); } }); - makeReferenceSeq.setText(MessageManager - .getString("label.mark_as_representative")); + makeReferenceSeq.setText( + MessageManager.getString("label.mark_as_representative")); makeReferenceSeq.addActionListener(new ActionListener() { @@ -1167,25 +1456,25 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener } }); - hideInsertions.setText(MessageManager - .getString("label.hide_insertions")); - hideInsertions.addActionListener(new ActionListener() - { - - @Override - public void actionPerformed(ActionEvent e) - { - hideInsertions_actionPerformed(e); - } - }); groupMenu.add(sequenceSelDetails); add(groupMenu); add(sequenceMenu); add(rnaStructureMenu); - add(pdbStructureDialog); - if (sequence != null) + add(chooseStructure); + if (forIdPanel) { + JMenuItem hideInsertions = new JMenuItem( + MessageManager.getString("label.hide_insertions")); + hideInsertions.addActionListener(new ActionListener() + { + + @Override + public void actionPerformed(ActionEvent e) + { + hideInsertions_actionPerformed(e); + } + }); add(hideInsertions); } // annotations configuration panel suppressed for now @@ -1206,7 +1495,7 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener groupMenu.add(sequenceFeature); groupMenu.add(createGroupMenuItem); groupMenu.add(unGroupMenuItem); - groupMenu.add(jMenu1); + groupMenu.add(editGroupMenu); sequenceMenu.add(sequenceName); sequenceMenu.add(sequenceDetails); sequenceMenu.add(makeReferenceSeq); @@ -1220,19 +1509,15 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener editMenu.add(upperCase); editMenu.add(lowerCase); editMenu.add(toggle); - // JBPNote: These shouldn't be added here - should appear in a generic - // 'apply web service to this sequence menu' - // pdbMenu.add(RNAFold); - // pdbMenu.add(ContraFold); - jMenu1.add(groupName); - jMenu1.add(colourMenu); - jMenu1.add(showBoxes); - jMenu1.add(showText); - jMenu1.add(showColourText); - jMenu1.add(outline); - jMenu1.add(displayNonconserved); + editGroupMenu.add(groupName); + editGroupMenu.add(colourMenu); + editGroupMenu.add(showBoxes); + editGroupMenu.add(showText); + editGroupMenu.add(showColourText); + editGroupMenu.add(outline); + editGroupMenu.add(displayNonconserved); } - + /** * Constructs the entries for the colour menu */ @@ -1249,8 +1534,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener } }); - abovePIDColour.setText(MessageManager - .getString("label.above_identity_threshold")); + abovePIDColour.setText( + MessageManager.getString("label.above_identity_threshold")); abovePIDColour.addActionListener(new ActionListener() { @Override @@ -1260,8 +1545,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener } }); - modifyPID.setText(MessageManager - .getString("label.modify_identity_threshold")); + modifyPID.setText( + MessageManager.getString("label.modify_identity_threshold")); modifyPID.addActionListener(new ActionListener() { @Override @@ -1271,18 +1556,25 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener } }); - conservationMenuItem.setText(MessageManager - .getString("action.by_conservation")); + conservationMenuItem + .setText(MessageManager.getString("action.by_conservation")); conservationMenuItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - conservationMenuItem_actionPerformed(conservationMenuItem - .isSelected()); + conservationMenuItem_actionPerformed( + conservationMenuItem.isSelected()); } }); + annotationColour = new JRadioButtonMenuItem( + MessageManager.getString("action.by_annotation")); + annotationColour.setName(ResidueColourScheme.ANNOTATION_COLOUR); + annotationColour.setEnabled(false); + annotationColour.setToolTipText( + MessageManager.getString("label.by_annotation_tooltip")); + modifyConservation.setText(MessageManager .getString("label.modify_conservation_threshold")); modifyConservation.addActionListener(new ActionListener() @@ -1313,7 +1605,10 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener colourMenu.add(textColour); colourMenu.addSeparator(); - ColourMenuHelper.addMenuItems(colourMenu, this, sg, false); + ButtonGroup bg = ColourMenuHelper.addMenuItems(colourMenu, this, sg, + false); + bg.add(annotationColour); + colourMenu.add(annotationColour); colourMenu.addSeparator(); colourMenu.add(conservationMenuItem); @@ -1340,8 +1635,7 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener // int threshold = SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup() // .getName()); // sg.cs.setThreshold(threshold, ap.av.isIgnoreGapsConsensus()); - SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup() - .getName()); + SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup().getName()); SliderPanel.showPIDSlider(); } } @@ -1368,11 +1662,11 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener * Temporary store to hold distinct calcId / type pairs for the tooltip. * Using TreeMap means calcIds are shown in alphabetical order. */ - SortedMap tipEntries = new TreeMap(); - final Map> candidates = new LinkedHashMap>(); + SortedMap tipEntries = new TreeMap<>(); + final Map> candidates = new LinkedHashMap<>(); AlignmentI al = this.ap.av.getAlignment(); - AlignmentUtils.findAddableReferenceAnnotations(forSequences, - tipEntries, candidates, al); + AlignmentUtils.findAddableReferenceAnnotations(forSequences, tipEntries, + candidates, al); if (!candidates.isEmpty()) { StringBuilder tooltip = new StringBuilder(64); @@ -1444,23 +1738,37 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener protected void hideInsertions_actionPerformed(ActionEvent actionEvent) { - if (sequence != null) + HiddenColumns hidden = ap.av.getAlignment().getHiddenColumns(); + BitSet inserts = new BitSet(); + + boolean markedPopup = false; + // mark inserts in current selection + if (ap.av.getSelectionGroup() != null) { - /* ColumnSelection cs = ap.av.getColumnSelection(); - if (cs == null) - { - cs = new ColumnSelection(); - } - cs.hideInsertionsFor(sequence); - ap.av.setColumnSelection(cs);*/ + // mark just the columns in the selection group to be hidden + inserts.set(ap.av.getSelectionGroup().getStartRes(), + ap.av.getSelectionGroup().getEndRes() + 1); // TODO why +1? - HiddenColumns hidden = ap.av.getAlignment().getHiddenColumns(); - if (hidden == null) + // now clear columns without gaps + for (SequenceI sq : ap.av.getSelectionGroup().getSequences()) { - hidden = new HiddenColumns(); + if (sq == sequence) + { + markedPopup = true; + } + inserts.and(sq.getInsertionsAsBits()); } - hidden.hideInsertionsFor(sequence); - ap.av.getAlignment().setHiddenColumns(hidden); + hidden.clearAndHideColumns(inserts, ap.av.getSelectionGroup().getStartRes(), + ap.av.getSelectionGroup().getEndRes()); + } + + // now mark for sequence under popup if we haven't already done it + else if (!markedPopup && sequence != null) + { + inserts.or(sequence.getInsertionsAsBits()); + + // and set hidden columns accordingly + hidden.hideColumns(inserts); } refresh(); } @@ -1470,41 +1778,30 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener createSequenceDetailsReport(ap.av.getSequenceSelection()); } - protected void sequenceDetails_actionPerformed() - { - createSequenceDetailsReport(new SequenceI[] { sequence }); - } - public void createSequenceDetailsReport(SequenceI[] sequences) { CutAndPasteHtmlTransfer cap = new CutAndPasteHtmlTransfer(); StringBuilder contents = new StringBuilder(128); for (SequenceI seq : sequences) { - contents.append("

" - + MessageManager - .formatMessage( - "label.create_sequence_details_report_annotation_for", - new Object[] { seq.getDisplayId(true) }) - + "

"); - new SequenceAnnotationReport(null) - .createSequenceAnnotationReport( - contents, - seq, - true, - true, - (ap.getSeqPanel().seqCanvas.fr != null) ? ap - .getSeqPanel().seqCanvas.fr.getMinMax() - : null); + contents.append("

" + MessageManager.formatMessage( + "label.create_sequence_details_report_annotation_for", + new Object[] + { seq.getDisplayId(true) }) + "

"); + new SequenceAnnotationReport(false).createSequenceAnnotationReport( + contents, seq, true, true, ap.getSeqPanel().seqCanvas.fr); contents.append("

"); } cap.setText("" + contents.toString() + ""); - Desktop.addInternalFrame(cap, MessageManager.formatMessage( - "label.sequence_details_for", - (sequences.length == 1 ? new Object[] { sequences[0] - .getDisplayId(true) } : new Object[] { MessageManager - .getString("label.selection") })), 500, 400); + Desktop.addInternalFrame(cap, + MessageManager.formatMessage("label.sequence_details_for", + (sequences.length == 1 ? new Object[] + { sequences[0].getDisplayId(true) } + : new Object[] + { MessageManager + .getString("label.selection") })), + 500, 400); } @@ -1520,7 +1817,9 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener void refresh() { ap.updateAnnotation(); - ap.paintAlignment(true); + // removed paintAlignment(true) here: + // updateAnnotation calls paintAlignment already, so don't need to call + // again PaintRefresher.Refresh(this, ap.av.getSequenceSetId()); } @@ -1552,8 +1851,7 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener sg.getStartRes(), sg.getEndRes() + 1)); int threshold = SliderPanel.setPIDSliderSource(ap, - sg.getGroupColourScheme(), getGroup() - .getName()); + sg.getGroupColourScheme(), getGroup().getName()); sg.cs.setThreshold(threshold, ap.av.isIgnoreGapsConsensus()); @@ -1599,9 +1897,9 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener if (selected) { // JBPNote: Conservation name shouldn't be i18n translated - Conservation c = new Conservation("Group", sg.getSequences(ap.av - .getHiddenRepSequences()), sg.getStartRes(), - sg.getEndRes() + 1); + Conservation c = new Conservation("Group", + sg.getSequences(ap.av.getHiddenRepSequences()), + sg.getStartRes(), sg.getEndRes() + 1); c.calculate(); c.verdict(false, ap.av.getConsPercGaps()); @@ -1633,8 +1931,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener SequenceGroup sg = getGroup(); EditNameDialog dialog = new EditNameDialog(sg.getName(), - sg.getDescription(), " " - + MessageManager.getString("label.group_name") + " ", + sg.getDescription(), + " " + MessageManager.getString("label.group_name") + " ", MessageManager.getString("label.group_description") + " ", MessageManager.getString("label.edit_group_name_description"), ap.alignFrame); @@ -1667,10 +1965,9 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener } /** - * DOCUMENT ME! - * - * @param e - * DOCUMENT ME! + * Shows a dialog where the sequence name and description may be edited. If a + * name containing spaces is entered, these are converted to underscores, with a + * warning message. */ void sequenceName_actionPerformed() { @@ -1679,8 +1976,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener " " + MessageManager.getString("label.sequence_name") + " ", MessageManager.getString("label.sequence_description") + " ", - MessageManager - .getString("label.edit_sequence_name_description"), + MessageManager.getString( + "label.edit_sequence_name_description"), ap.alignFrame); if (!dialog.accept) @@ -1688,28 +1985,28 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener return; } - if (dialog.getName() != null) + String name = dialog.getName(); + if (name != null) { - if (dialog.getName().indexOf(" ") > -1) + if (name.indexOf(" ") > -1) { - JvOptionPane - .showMessageDialog( - ap, - MessageManager - .getString("label.spaces_converted_to_backslashes"), - MessageManager - .getString("label.no_spaces_allowed_sequence_name"), - JvOptionPane.WARNING_MESSAGE); + JvOptionPane.showMessageDialog(ap, + MessageManager + .getString("label.spaces_converted_to_backslashes"), + MessageManager + .getString("label.no_spaces_allowed_sequence_name"), + JvOptionPane.WARNING_MESSAGE); + name = name.replace(' ', '_'); } - sequence.setName(dialog.getName().replace(' ', '_')); - ap.paintAlignment(false); + sequence.setName(name); + ap.paintAlignment(false, false); } sequence.setDescription(dialog.getDescription()); - ap.av.firePropertyChange("alignment", null, ap.av.getAlignment() - .getSequences()); + ap.av.firePropertyChange("alignment", null, + ap.av.getAlignment().getSequences()); } @@ -1791,22 +2088,6 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener refresh(); } - public void showLink(String url) - { - try - { - jalview.util.BrowserLauncher.openURL(url); - } catch (Exception ex) - { - JvOptionPane.showInternalMessageDialog(Desktop.desktop, - MessageManager.getString("label.web_browser_not_found_unix"), - MessageManager.getString("label.web_browser_not_found"), - JvOptionPane.WARNING_MESSAGE); - - ex.printStackTrace(); - } - } - void hideSequences(boolean representGroup) { ap.av.hideSequences(sequence, representGroup); @@ -1857,8 +2138,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener ap.alignFrame.addHistoryItem(caseCommand); - ap.av.firePropertyChange("alignment", null, ap.av.getAlignment() - .getSequences()); + ap.av.firePropertyChange("alignment", null, + ap.av.getAlignment().getSequences()); } } @@ -1867,9 +2148,9 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener { CutAndPasteTransfer cap = new CutAndPasteTransfer(); cap.setForInput(null); - Desktop.addInternalFrame(cap, MessageManager.formatMessage( - "label.alignment_output_command", - new Object[] { e.getActionCommand() }), 600, 500); + Desktop.addInternalFrame(cap, MessageManager + .formatMessage("label.alignment_output_command", new Object[] + { e.getActionCommand() }), 600, 500); String[] omitHidden = null; @@ -1877,8 +2158,10 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener // or we simply trust the user wants // wysiwig behaviour - FileFormatI fileFormat = FileFormats.getInstance().forName(e.getActionCommand()); - cap.setText(new FormatAdapter(ap).formatSequences(fileFormat, ap, true)); + FileFormatI fileFormat = FileFormats.getInstance() + .forName(e.getActionCommand()); + cap.setText( + new FormatAdapter(ap).formatSequences(fileFormat, ap, true)); } public void sequenceFeature_actionPerformed() @@ -1889,8 +2172,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener return; } - List seqs = new ArrayList(); - List features = new ArrayList(); + List seqs = new ArrayList<>(); + List features = new ArrayList<>(); /* * assemble dataset sequences, and template new sequence features, @@ -1904,15 +2187,22 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener if (start <= end) { seqs.add(sg.getSequenceAt(i).getDatasetSequence()); - features.add(new SequenceFeature(null, null, null, start, end, null)); + features.add(new SequenceFeature(null, null, start, end, null)); } } - if (ap.getSeqPanel().seqCanvas.getFeatureRenderer().amendFeatures(seqs, - features, true, ap)) + /* + * an entirely gapped region will generate empty lists of sequence / features + */ + if (!seqs.isEmpty()) { - ap.alignFrame.setShowSeqFeatures(true); - ap.highlightSearchResults(null); + if (ap.getSeqPanel().seqCanvas.getFeatureRenderer() + .amendFeatures(seqs, features, true, ap)) + { + ap.alignFrame.setShowSeqFeatures(true); + ap.av.setSearchResults(null); // clear highlighting + ap.repaint(); // draw new/amended features + } } } @@ -1925,40 +2215,22 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener } } - public void colourByStructure(String pdbid) - { - Annotation[] anots = ap.av.getStructureSelectionManager() - .colourSequenceFromStructure(sequence, pdbid); - - AlignmentAnnotation an = new AlignmentAnnotation("Structure", - "Coloured by " + pdbid, anots); - - ap.av.getAlignment().addAnnotation(an); - an.createSequenceMapping(sequence, 0, true); - // an.adjustForAlignment(); - ap.av.getAlignment().setAnnotationIndex(an, 0); - - ap.adjustAnnotationHeight(); - - sequence.addAlignmentAnnotation(an); - - } - public void editSequence_actionPerformed(ActionEvent actionEvent) { SequenceGroup sg = ap.av.getSelectionGroup(); + SequenceI seq = sequence; if (sg != null) { - if (sequence == null) + if (seq == null) { - sequence = sg.getSequenceAt(0); + seq = sg.getSequenceAt(0); } EditNameDialog dialog = new EditNameDialog( - sequence.getSequenceAsString(sg.getStartRes(), - sg.getEndRes() + 1), null, - MessageManager.getString("label.edit_sequence"), null, + seq.getSequenceAsString(sg.getStartRes(), + sg.getEndRes() + 1), + null, MessageManager.getString("label.edit_sequence"), null, MessageManager.getString("label.edit_sequence"), ap.alignFrame); @@ -1966,15 +2238,15 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener { EditCommand editCommand = new EditCommand( MessageManager.getString("label.edit_sequences"), - Action.REPLACE, dialog.getName().replace(' ', - ap.av.getGapCharacter()), + Action.REPLACE, + dialog.getName().replace(' ', ap.av.getGapCharacter()), sg.getSequencesAsArray(ap.av.getHiddenRepSequences()), sg.getStartRes(), sg.getEndRes() + 1, ap.av.getAlignment()); ap.alignFrame.addHistoryItem(editCommand); - ap.av.firePropertyChange("alignment", null, ap.av.getAlignment() - .getSequences()); + ap.av.firePropertyChange("alignment", null, + ap.av.getAlignment().getSequences()); } } } @@ -1993,7 +2265,7 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener * switch to the chosen colour scheme (or null for None) */ ColourSchemeI colourScheme = ColourSchemes.getInstance() - .getColourScheme(colourSchemeName, sg, + .getColourScheme(colourSchemeName, ap.av, sg, ap.av.getHiddenRepSequences()); sg.setColourScheme(colourScheme); if (colourScheme instanceof Blosum62ColourScheme