X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FPopupMenu.java;h=2034b3fc0938849fa279766da2900f8a39adec38;hb=71c5a29a58e5505aaf7d63a8c9f1bea3ae93d629;hp=8c87aa0d5e5b60d6307dff8f7c7e246bbac66909;hpb=a82f1e47eef845557e95e61116e6b34bdd3242f3;p=jalview.git diff --git a/src/jalview/gui/PopupMenu.java b/src/jalview/gui/PopupMenu.java index 8c87aa0..2034b3f 100644 --- a/src/jalview/gui/PopupMenu.java +++ b/src/jalview/gui/PopupMenu.java @@ -24,15 +24,16 @@ 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.ResidueCount; import jalview.datamodel.SequenceFeature; @@ -49,11 +50,13 @@ 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 jalview.viewmodel.seqfeatures.FeatureRendererModel; import java.awt.Color; import java.awt.event.ActionEvent; @@ -69,6 +72,7 @@ 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; @@ -87,6 +91,19 @@ import javax.swing.JRadioButtonMenuItem; */ public class PopupMenu extends JPopupMenu implements ColourChangeListener { + /* + * 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(); @@ -101,28 +118,14 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener protected JMenuItem modifyConservation = new JMenuItem(); - AlignmentPanel ap; - 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(); @@ -135,18 +138,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(); @@ -163,23 +160,14 @@ 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(); - - JMenu groupLinksMenu; - - JMenuItem hideInsertions = 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, @@ -190,7 +178,7 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener * @param features * @return */ - static JMenu buildLinkMenu(final SequenceI seq, + protected static JMenu buildLinkMenu(final SequenceI seq, List features) { JMenu linkMenu = new JMenu(MessageManager.getString("action.link")); @@ -362,41 +350,55 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener } /** - * Creates a new PopupMenu object. + * Constructor for a PopupMenu for a click in the alignment panel (on a residue) * * @param ap + * the panel in which the mouse is clicked * @param seq - * @param features - * non-positional features (for seq not null), or positional features - * at residue (for seq equal to null) + * the sequence under the mouse + * @throws NullPointerException + * if seq is null */ - public PopupMenu(final AlignmentPanel ap, SequenceI seq, - List features) + public PopupMenu(final AlignmentPanel ap, SequenceI seq, int column) { - this(ap, seq, features, null); + this(false, ap, seq, column, null); } /** - * Constructor + * Constructor for a PopupMenu for a click in the sequence id panel * * @param alignPanel + * the panel in which the mouse is clicked * @param seq - * the sequence under the cursor if in the Id panel, null if in the - * sequence panel - * @param features - * non-positional features if in the Id panel, features at the - * clicked residue if in the sequence panel + * 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 features, List groupLinks) + 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(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 column + * aligned column position (0...) + * @param groupLinks + */ + private PopupMenu(boolean fromIdPanel, + final AlignmentPanel alignPanel, + final SequenceI seq, final int column, List groupLinks) + { + Objects.requireNonNull(seq); + this.forIdPanel = fromIdPanel; this.ap = alignPanel; sequence = seq; @@ -421,9 +423,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, @@ -448,9 +450,9 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener e.printStackTrace(); } - JMenuItem menuItem; - if (seq != null) + if (forIdPanel) { + JMenuItem menuItem; sequenceMenu.setText(sequence.getName()); if (seq == alignPanel.av.getAlignment().getSeqrep()) { @@ -635,7 +637,7 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener } if (addOption) { - menuItem = new JMenuItem( + JMenuItem menuItem = new JMenuItem( MessageManager.getString("action.reveal_all")); menuItem.addActionListener(new ActionListener() { @@ -728,27 +730,57 @@ 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); } + addLinksAndFeatures(seq, column); + } + + /** + * 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 column + */ + void addLinksAndFeatures(final SequenceI seq, final int column) + { + List features = null; + if (forIdPanel) + { + features = sequence.getFeatures().getNonPositionalFeatures(); + } + else + { + features = ap.getFeatureRenderer().findFeaturesAtColumn(sequence, + column + 1); + } + addLinks(seq, features); - if (seq == null) + if (!forIdPanel) { - addFeatureDetails(features); + addFeatureDetails(features, seq, column); } } @@ -756,75 +788,127 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener * Add a link to show feature details for each sequence feature * * @param features + * @param column + * @param seq */ - protected void addFeatureDetails(List features) + protected void addFeatureDetails(List features, + SequenceI seq, int column) { - if (features == null || features.isEmpty()) + /* + * 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))) + { + AlignViewportI complement = ap.getAlignViewport() + .getCodingComplement(); + AlignFrame af = Desktop.getAlignFrameFor(complement); + FeatureRendererModel fr2 = af.getFeatureRenderer(); + int seqPos = sequence.findPosition(column); + mf = fr2.findComplementFeaturesAtResidue(sequence, seqPos); + } + } + + if (features.isEmpty() && mf == null) { + /* + * no features to show at this position + */ return; } + JMenu details = new JMenu( MessageManager.getString("label.feature_details")); add(details); + String name = seq.getName(); for (final SequenceFeature sf : features) { - int start = sf.getBegin(); - int end = sf.getEnd(); - String desc = null; - if (start == end) + addFeatureDetailsMenuItem(details, name, sf); + } + + if (mf != null) + { + name = mf.fromSeq == seq ? mf.mapping.getTo().getName() + : mf.fromSeq.getName(); + for (final SequenceFeature sf : mf.features) { - desc = String.format("%s %d", sf.getType(), start); + addFeatureDetailsMenuItem(details, name, sf); } - else + } + } + + /** + * A helper method to add one menu item whose action is to show details for one + * feature + * + * @param details + * @param seqName + * @param sf + */ + void addFeatureDetailsMenuItem(JMenu details, final String seqName, + final SequenceFeature sf) + { + int start = sf.getBegin(); + int end = sf.getEnd(); + String desc = null; + if (start == end) + { + desc = String.format("%s %d", sf.getType(), start); + } + else + { + desc = String.format("%s %d-%d", sf.getType(), start, end); + } + String tooltip = desc; + String description = sf.getDescription(); + if (description != null) + { + description = StringUtils.stripHtmlTags(description); + if (description.length() > 12) { - desc = String.format("%s %d-%d", sf.getType(), start, end); + desc = desc + " " + description.substring(0, 12) + ".."; } - String tooltip = desc; - String description = sf.getDescription(); - if (description != null) + else { - description = StringUtils.stripHtmlTags(description); - if (description.length() > 12) - { - desc = desc + " " + description.substring(0, 12) + ".."; - } - else - { - desc = desc + " " + description; - } - tooltip = tooltip + " " + description; + desc = desc + " " + description; } - if (sf.getFeatureGroup() != null) + tooltip = tooltip + " " + description; + } + if (sf.getFeatureGroup() != null) + { + tooltip = tooltip + (" (" + sf.getFeatureGroup() + ")"); + } + JMenuItem item = new JMenuItem(desc); + item.setToolTipText(tooltip); + item.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) { - tooltip = tooltip + (" (" + sf.getFeatureGroup() + ")"); + showFeatureDetails(seqName, sf); } - JMenuItem item = new JMenuItem(desc); - item.setToolTipText(tooltip); - item.addActionListener(new ActionListener() - { - @Override - public void actionPerformed(ActionEvent e) - { - showFeatureDetails(sf); - } - }); - details.add(item); - } + }); + details.add(item); } /** * Opens a panel showing a text report of feature dteails * + * @param seqName + * * @param sf */ - protected void showFeatureDetails(SequenceFeature sf) + protected void showFeatureDetails(String seqName, SequenceFeature sf) { CutAndPasteHtmlTransfer cap = new CutAndPasteHtmlTransfer(); - // it appears Java's CSS does not support border-collaps :-( + // 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()); + cap.setText(sf.getDetailsReport(seqName)); Desktop.addInternalFrame(cap, MessageManager.getString("label.feature_details"), 500, 500); @@ -842,12 +926,12 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener */ void addLinks(final SequenceI seq, List features) { - JMenu linkMenu = buildLinkMenu(seq, features); + JMenu linkMenu = buildLinkMenu(forIdPanel ? seq : null, features); // only add link menu if it has entries if (linkMenu.getItemCount() > 0) { - if (sequence != null) + if (forIdPanel) { sequenceMenu.add(linkMenu); } @@ -995,7 +1079,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, @@ -1154,7 +1238,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener } }); sequenceMenu.setText(MessageManager.getString("label.sequence")); - sequenceName.setText( + + JMenuItem sequenceName = new JMenuItem( MessageManager.getString("label.edit_name_description")); sequenceName.addActionListener(new ActionListener() { @@ -1164,8 +1249,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 @@ -1174,24 +1259,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()); } }); @@ -1216,7 +1301,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 @@ -1266,7 +1352,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 @@ -1284,7 +1370,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 @@ -1321,7 +1407,7 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener .setText(MessageManager.getString("label.show_annotations")); groupHideAnnotationsMenu .setText(MessageManager.getString("label.hide_annotations")); - sequenceFeature.setText( + JMenuItem sequenceFeature = new JMenuItem( MessageManager.getString("label.create_sequence_feature")); sequenceFeature.addActionListener(new ActionListener() { @@ -1331,10 +1417,10 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener sequenceFeature_actionPerformed(); } }); - jMenu1.setText(MessageManager.getString("label.group")); - pdbStructureDialog.setText( + editGroupMenu.setText(MessageManager.getString("label.group")); + chooseStructure.setText( MessageManager.getString("label.show_pdbstruct_dialog")); - pdbStructureDialog.addActionListener(new ActionListener() + chooseStructure.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) @@ -1352,7 +1438,7 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener .setText(MessageManager.getString("label.view_rna_structure")); // colStructureMenu.setText("Colour By Structure"); - editSequence.setText( + JMenuItem editSequence = new JMenuItem( MessageManager.getString("label.edit_sequence") + "..."); editSequence.addActionListener(new ActionListener() { @@ -1374,25 +1460,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 @@ -1413,7 +1499,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); @@ -1427,17 +1513,13 @@ 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); } /** @@ -1700,11 +1782,6 @@ 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(); @@ -1892,10 +1969,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() { @@ -1913,9 +1989,10 @@ 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 @@ -1923,9 +2000,10 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener MessageManager .getString("label.no_spaces_allowed_sequence_name"), JvOptionPane.WARNING_MESSAGE); + name = name.replace(' ', '_'); } - sequence.setName(dialog.getName().replace(' ', '_')); + sequence.setName(name); ap.paintAlignment(false, false); } @@ -2141,38 +2219,20 @@ 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(), + seq.getSequenceAsString(sg.getStartRes(), sg.getEndRes() + 1), null, MessageManager.getString("label.edit_sequence"), null, MessageManager.getString("label.edit_sequence"),