X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FPopupMenu.java;h=957ca4645ac6a1dd9215a5e9151b40b2bd563d06;hb=ab43013b7e357b84b4abade0dba949668dfb2a0e;hp=78c159257dda91e618202bc33c82dff99af1a652;hpb=2e7da637a195ff484f92a333675284f071657cd6;p=jalview.git diff --git a/src/jalview/gui/PopupMenu.java b/src/jalview/gui/PopupMenu.java index 78c1592..957ca46 100644 --- a/src/jalview/gui/PopupMenu.java +++ b/src/jalview/gui/PopupMenu.java @@ -1,5 +1,5 @@ /* - * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2) + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2b1) * Copyright (C) 2014 The Jalview Authors * * This file is part of Jalview. @@ -21,10 +21,13 @@ package jalview.gui; import jalview.analysis.AAFrequency; +import jalview.analysis.AlignmentAnnotationUtils; import jalview.analysis.Conservation; 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.PDBEntry; @@ -34,7 +37,6 @@ import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; import jalview.io.FormatAdapter; import jalview.io.SequenceAnnotationReport; -import jalview.renderer.AnnotationRenderer; import jalview.schemes.AnnotationColourGradient; import jalview.schemes.Blosum62ColourScheme; import jalview.schemes.BuriedColourScheme; @@ -60,12 +62,13 @@ 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.HashMap; +import java.util.Collections; import java.util.Hashtable; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.TreeMap; import java.util.Vector; import javax.swing.ButtonGroup; @@ -188,11 +191,17 @@ public class PopupMenu extends JPopupMenu JMenu outputMenu = new JMenu(); - JMenu showAnnotationsMenu = new JMenu(); + JMenu seqShowAnnotationsMenu = new JMenu(); - JMenu hideAnnotationsMenu = new JMenu(); + JMenu seqHideAnnotationsMenu = new JMenu(); - JMenuItem addDatasequenceAnnotations = new JMenuItem(); + JMenuItem seqAddReferenceAnnotations = new JMenuItem(); + + JMenu groupShowAnnotationsMenu = new JMenu(); + + JMenu groupHideAnnotationsMenu = new JMenu(); + + JMenuItem groupAddReferenceAnnotations = new JMenuItem(); JMenuItem sequenceFeature = new JMenuItem(); @@ -279,9 +288,27 @@ public class PopupMenu extends JPopupMenu } /* - * Build menus for annotation types that may be shown or hidden. + * Build menus for annotation types that may be shown or hidden, and for + * 'reference annotations' that may be added to the alignment. First for the + * currently selected sequence (if there is one): */ - buildAnnotationTypesMenus(); + final List selectedSequence = (seq == null ? Collections + . emptyList() : Arrays.asList(seq)); + buildAnnotationTypesMenus(seqShowAnnotationsMenu, + seqHideAnnotationsMenu, selectedSequence); + configureReferenceAnnotationsMenu(seqAddReferenceAnnotations, + selectedSequence); + + /* + * And repeat for the current selection group (if there is one): + */ + final List selectedGroup = (ap.av.getSelectionGroup() == null ? Collections + . emptyList() : ap.av.getSelectionGroup() + .getSequences()); + buildAnnotationTypesMenus(groupShowAnnotationsMenu, + groupHideAnnotationsMenu, selectedGroup); + configureReferenceAnnotationsMenu(groupAddReferenceAnnotations, + selectedGroup); try { @@ -308,18 +335,19 @@ public class PopupMenu extends JPopupMenu menuItem = new JMenuItem(); menuItem.setText(pdb.getId()); - menuItem.addActionListener(new ActionListener() + menuItem.addActionListener(new ActionListener() { @Override - public void actionPerformed(ActionEvent e) { - // TODO re JAL-860: optionally open dialog or provide a menu entry - // allowing user to open just one structure per sequence - // new AppJmol(pdb, ap.av.collateForPDB(new PDBEntry[] - // { pdb })[0], null, ap); - new StructureViewer(ap.getStructureSelectionManager()) - .viewStructures(pdb, - ap.av.collateForPDB(new PDBEntry[] - { pdb })[0], null, ap); + public void actionPerformed(ActionEvent e) + { + // TODO re JAL-860: optionally open dialog or provide a menu entry + // allowing user to open just one structure per sequence + // new AppJmol(pdb, ap.av.collateForPDB(new PDBEntry[] + // { pdb })[0], null, ap); + new StructureViewer(ap.getStructureSelectionManager()) + .viewStructures(pdb, + ap.av.collateForPDB(new PDBEntry[] + { pdb })[0], null, ap); } }); viewStructureMenu.add(menuItem); @@ -346,12 +374,12 @@ public class PopupMenu extends JPopupMenu { AlignmentAnnotation[] aa = ap.av.getAlignment() .getAlignmentAnnotation(); - for (int i = 0; i < aa.length; i++) + for (int i = 0; aa != null && i < aa.length; i++) { - if (aa[i].getRNAStruc() != null) + if (aa[i].isValidStruc() && aa[i].sequenceRef == null) { final String rnastruc = aa[i].getRNAStruc(); - final String structureLine = aa[i].label; + final String structureLine = aa[i].label + " (alignment)"; menuItem = new JMenuItem(); menuItem.setText(MessageManager.formatMessage( "label.2d_rna_structure_line", new String[] @@ -361,15 +389,15 @@ public class PopupMenu extends JPopupMenu @Override public void actionPerformed(ActionEvent e) { - // System.out.println("1:"+structureLine); - System.out.println("1:sname" + seq.getName()); - System.out.println("2:seq" + seq); - - // System.out.println("3:"+seq.getSequenceAsString()); - System.out.println("3:strucseq" + rnastruc); - // System.out.println("4:struc"+seq.getRNA()); - System.out.println("5:name" + seq.getName()); - System.out.println("6:ap" + ap); + // // System.out.println("1:"+structureLine); + // System.out.println("1:sname" + seq.getName()); + // System.out.println("2:seq" + seq); + // + // // System.out.println("3:"+seq.getSequenceAsString()); + // System.out.println("3:strucseq" + rnastruc); + // // System.out.println("4:struc"+seq.getRNA()); + // System.out.println("5:name" + seq.getName()); + // System.out.println("6:ap" + ap); new AppVarna(structureLine, seq, seq.getSequenceAsString(), rnastruc, seq.getName(), ap); // new AppVarna(seq.getName(),seq,rnastruc,seq.getRNA(), @@ -388,7 +416,7 @@ public class PopupMenu extends JPopupMenu AlignmentAnnotation seqAnno[] = seq.getAnnotation(); for (int i = 0; i < seqAnno.length; i++) { - if (seqAnno[i].getRNAStruc() != null) + if (seqAnno[i].isValidStruc()) { final String rnastruc = seqAnno[i].getRNAStruc(); @@ -797,9 +825,10 @@ public class PopupMenu extends JPopupMenu } /** - * Add annotation types to a 'Show annotations' or 'Hide annotations' menu. + * Add annotation types to 'Show annotations' and/or 'Hide annotations' menus. * "All" is added first, followed by a separator. Then add any annotation - * types associated with the current selection. + * types associated with the current selection. Separate menus are built for + * the selected sequence group (if any), and the selected sequence. *

* Some annotation rows are always rendered together - these can be identified * by a common graphGroup property > -1. Only one of each group will be marked @@ -807,230 +836,82 @@ public class PopupMenu extends JPopupMenu * composite type name, e.g. *

* IUPredWS (Long), IUPredWS (Short) + * + * @param seq */ - protected void buildAnnotationTypesMenus() + protected void buildAnnotationTypesMenus(JMenu showMenu, JMenu hideMenu, + List forSequences) { - final SequenceGroup selectionGroup = ap.av.getSelectionGroup(); - if (selectionGroup == null) - { - // this menu option is only for a selection - return; - } + showMenu.removeAll(); + hideMenu.removeAll(); - showAnnotationsMenu.removeAll(); - hideAnnotationsMenu.removeAll(); final List all = Arrays.asList(ALL_ANNOTATIONS); - addAnnotationTypeToShowHide(showAnnotationsMenu, "", all, true, true); - addAnnotationTypeToShowHide(hideAnnotationsMenu, "", all, true, false); - showAnnotationsMenu.addSeparator(); - hideAnnotationsMenu.addSeparator(); + addAnnotationTypeToShowHide(showMenu, forSequences, "", all, true, true); + addAnnotationTypeToShowHide(hideMenu, forSequences, "", all, true, + false); + showMenu.addSeparator(); + hideMenu.addSeparator(); final AlignmentAnnotation[] annotations = ap.getAlignment() .getAlignmentAnnotation(); - BitSet visibleGraphGroups = PopupMenu - .getVisibleLineGraphGroups(annotations); /* * Find shown/hidden annotations types, distinguished by source (calcId), - * and grouped by graphGroup. + * and grouped by graphGroup. Using LinkedHashMap means we will retrieve in + * the insertion order, which is the order of the annotations on the + * alignment. */ - Map>> shownTypes = new HashMap>>(); - Map>> hiddenTypes = new HashMap>>(); - PopupMenu.getAnnotationTypesForShowHide(shownTypes, hiddenTypes, - visibleGraphGroups, annotations, selectionGroup); + Map>> shownTypes = new LinkedHashMap>>(); + Map>> hiddenTypes = new LinkedHashMap>>(); + AlignmentAnnotationUtils.getShownHiddenTypes(shownTypes, + hiddenTypes, + AlignmentAnnotationUtils.asList(annotations), + forSequences); for (String calcId : hiddenTypes.keySet()) { for (List type : hiddenTypes.get(calcId)) { - addAnnotationTypeToShowHide(showAnnotationsMenu, calcId, type, - false, true); + addAnnotationTypeToShowHide(showMenu, forSequences, + calcId, type, false, true); } } + // grey out 'show annotations' if none are hidden + showMenu.setEnabled(!hiddenTypes.isEmpty()); for (String calcId : shownTypes.keySet()) { for (List type : shownTypes.get(calcId)) { - addAnnotationTypeToShowHide(hideAnnotationsMenu, calcId, type, - false, false); + addAnnotationTypeToShowHide(hideMenu, forSequences, + calcId, type, false, false); } } + // grey out 'hide annotations' if none are shown + hideMenu.setEnabled(!shownTypes.isEmpty()); } /** - * Helper method to populate lists of annotation types for the Show/Hide - * Annotations menus. If sequenceGroup is not null, this is restricted to - * annotations which are associated with sequences in the selection group. - *

- * If an annotation row is currently visible, its type (label) is added (once - * only per type), to the shownTypes list. If it is currently hidden, it is - * added to the hiddenTypesList. - *

- * For rows that belong to a line graph group, so are always rendered - * together: - *

    - *
  • Treat all rows in the group as visible, if at least one of them is
  • - *
  • Build a comma-separated label with all the types that belong to the - * group
  • - *
+ * Returns a list of sequences - either the current selection group (if there + * is one), else the specified single sequence. * - * @param shownTypes - * a map, keyed by calcId (annotation source), whose entries are the - * lists of annotation types found for the calcId; each annotation - * type in turn may be a list (in the case of grouped annotations) - * @param hiddenTypes - * a map, similar to shownTypes, but for hidden annotation types - * @param visibleGraphGroups - * a lookup keyed by graphGroup identifier - * @param annotations - * the annotations on the alignment to scan - * @param sequenceGroup - * the sequence group to restrict search to + * @param seq + * @return */ - public static void getAnnotationTypesForShowHide( - Map>> shownTypes, - Map>> hiddenTypes, - BitSet visibleGraphGroups, AlignmentAnnotation[] annotations, - SequenceGroup sequenceGroup) + protected List getSequenceScope(SequenceI seq) { - /* - * Build a lookup, by calcId (annotation source), of all annotation types in - * each graph group. - */ - Map>> groupLabels = new HashMap>>(); - - // trackers for which calcId!label combinations we have dealt with - List addedToShown = new ArrayList(); - List addedToHidden = new ArrayList(); - - for (AlignmentAnnotation aa : annotations) - { - - if (sequenceGroup == null - || (aa.sequenceRef != null && sequenceGroup.getSequences() - .contains(aa.sequenceRef))) - { - String calcId = aa.getCalcId(); - - /* - * Build a 'composite label' for types in line graph groups. - */ - final List labelAsList = new ArrayList(); - final String displayLabel = aa.label; - labelAsList.add(displayLabel); - if (aa.graph == AlignmentAnnotation.LINE_GRAPH - && aa.graphGroup > -1) - { - if (!groupLabels.containsKey(calcId)) - { - groupLabels.put(calcId, new HashMap>()); - } - Map> groupLabelsForCalcId = groupLabels - .get(calcId); - if (groupLabelsForCalcId.containsKey(aa.graphGroup)) - { - if (!groupLabelsForCalcId.get(aa.graphGroup).contains( - displayLabel)) - { - groupLabelsForCalcId.get(aa.graphGroup).add(displayLabel); - } - } - else - { - groupLabelsForCalcId.put(aa.graphGroup, labelAsList); - } - } - else - /* - * 'Simple case' - not a grouped annotation type - list of one label - * only - */ - { - String rememberAs = calcId + "!" + displayLabel; - if (aa.visible && !addedToShown.contains(rememberAs)) - { - if (!shownTypes.containsKey(calcId)) - { - shownTypes.put(calcId, new ArrayList>()); - } - shownTypes.get(calcId).add(labelAsList); - addedToShown.add(rememberAs); - } - else - { - if (!aa.visible && !addedToHidden.contains(rememberAs)) - { - if (!hiddenTypes.containsKey(calcId)) - { - hiddenTypes.put(calcId, new ArrayList>()); - } - hiddenTypes.get(calcId).add(labelAsList); - addedToHidden.add(rememberAs); - } - } - } - } - } - /* - * finally add the 'composite group labels' to the appropriate lists, - * depending on whether the group is identified as visible or hidden - */ - for (String calcId : groupLabels.keySet()) + List forSequences = null; + final SequenceGroup selectionGroup = ap.av.getSelectionGroup(); + if (selectionGroup != null && selectionGroup.getSize() > 0) { - for (int group : groupLabels.get(calcId).keySet()) - { - final List groupLabel = groupLabels.get(calcId).get(group); - if (visibleGraphGroups.get(group)) - { - if (!shownTypes.containsKey(calcId)) - { - shownTypes.put(calcId, new ArrayList>()); - } - shownTypes.get(calcId).add(groupLabel); - } - else - { - if (!hiddenTypes.containsKey(calcId)) - { - hiddenTypes.put(calcId, new ArrayList>()); - } - hiddenTypes.get(calcId).add(groupLabel); - } - } + forSequences = selectionGroup.getSequences(); } - } - - /** - * Returns a BitSet (possibly empty) of those graphGroups for line graph - * annotations, which have at least one member annotation row marked visible. - * The logic is that only one row in the group is marked visible, but when it - * is drawn, so are all the other rows in the same group. - *

- * This lookup set allows us to check whether rows marked not visible are in - * fact shown. - * - * @see AnnotationRenderer#drawComponent - * @param annotations - * @return - */ - public static BitSet getVisibleLineGraphGroups( - AlignmentAnnotation[] annotations) - { - // todo move to a utility class - BitSet result = new BitSet(); - for (AlignmentAnnotation ann : annotations) + else { - if (ann.graph == AlignmentAnnotation.LINE_GRAPH && ann.visible) - { - int gg = ann.graphGroup; - if (gg > -1) - { - result.set(gg); - } - } + forSequences = seq == null ? Collections. emptyList() + : Arrays.asList(seq); } - return result; + return forSequences; } /** @@ -1039,6 +920,8 @@ public class PopupMenu extends JPopupMenu * * @param showOrHideMenu * the menu to add to + * @param forSequences + * the sequences whose annotations may be shown or hidden * @param calcId * @param types * the label to add @@ -1049,7 +932,8 @@ public class PopupMenu extends JPopupMenu * type, else hide */ protected void addAnnotationTypeToShowHide(JMenu showOrHideMenu, - String calcId, final List types, final boolean allTypes, + final List forSequences, String calcId, + final List types, final boolean allTypes, final boolean actionIsShow) { String label = types.toString(); // [a, b, c] @@ -1061,7 +945,8 @@ public class PopupMenu extends JPopupMenu @Override public void actionPerformed(ActionEvent e) { - showHideAnnotation_actionPerformed(types, allTypes, actionIsShow); + showHideAnnotation_actionPerformed(types, forSequences, allTypes, + actionIsShow); } }); showOrHideMenu.add(item); @@ -1069,26 +954,24 @@ public class PopupMenu extends JPopupMenu /** * Action on selecting a list of annotation type (or the 'all types' values) - * to show or hide for the selection. + * to show or hide for the specified sequences. * * @param types + * @param forSequences * @param anyType * @param doShow */ protected void showHideAnnotation_actionPerformed( - Collection types, boolean anyType, boolean doShow) + Collection types, List forSequences, + boolean anyType, boolean doShow) { for (AlignmentAnnotation aa : ap.getAlignment() .getAlignmentAnnotation()) { - // TODO: select by calcId (source of annotation) as well as label - // e.g. by refactoring of buildAnnotationTypeMenus to as - // to construct the actionPerformed methods as the calcId/labels are found if (anyType || types.contains(aa.label)) { if ((aa.sequenceRef != null) - && ap.av.getSelectionGroup().getSequences() - .contains(aa.sequenceRef)) + && forSequences.contains(aa.sequenceRef)) { aa.visible = doShow; } @@ -1582,11 +1465,14 @@ public class PopupMenu extends JPopupMenu }); outputMenu.setText(MessageManager.getString("label.out_to_textbox") + "..."); - showAnnotationsMenu.setText(MessageManager + seqShowAnnotationsMenu.setText(MessageManager .getString("label.show_annotations")); - hideAnnotationsMenu.setText(MessageManager + seqHideAnnotationsMenu.setText(MessageManager + .getString("label.hide_annotations")); + groupShowAnnotationsMenu.setText(MessageManager + .getString("label.show_annotations")); + groupHideAnnotationsMenu.setText(MessageManager .getString("label.hide_annotations")); - configureReferenceAnnotationsMenu(); sequenceFeature.setText(MessageManager .getString("label.create_sequence_feature")); sequenceFeature.addActionListener(new ActionListener() @@ -1632,10 +1518,19 @@ public class PopupMenu extends JPopupMenu add(groupMenu); add(sequenceMenu); this.add(structureMenu); + // annotations configuration panel suppressed for now // groupMenu.add(chooseAnnotations); - groupMenu.add(showAnnotationsMenu); - groupMenu.add(hideAnnotationsMenu); - groupMenu.add(addDatasequenceAnnotations); + + /* + * Add show/hide annotations to the Sequence menu, and to the Selection menu + * (if a selection group is in force). + */ + sequenceMenu.add(seqShowAnnotationsMenu); + sequenceMenu.add(seqHideAnnotationsMenu); + sequenceMenu.add(seqAddReferenceAnnotations); + groupMenu.add(groupShowAnnotationsMenu); + groupMenu.add(groupHideAnnotationsMenu); + groupMenu.add(groupAddReferenceAnnotations); groupMenu.add(editMenu); groupMenu.add(outputMenu); groupMenu.add(sequenceFeature); @@ -1871,40 +1766,46 @@ public class PopupMenu extends JPopupMenu /** * Check for any annotations on the underlying dataset sequences (for the - * current selection group) which are not on the alignment. If any are found, + * current selection group) which are not 'on the alignment'.If any are found, * enable the option to add them to the alignment. The criteria for 'on the - * alignment' is finding an annotation that matches on - * sequenceRef.datasetSequence, calcId and label. + * alignment' is finding an alignment annotation on the alignment, matched on + * calcId, label and sequenceRef. + * + * A tooltip is also constructed that displays the source (calcId) and type + * (label) of the annotations that can be added. + * + * @param menuItem + * @param forSequences */ - protected void configureReferenceAnnotationsMenu() + protected void configureReferenceAnnotationsMenu( + JMenuItem menuItem, List forSequences) { - addDatasequenceAnnotations.setText(MessageManager + menuItem.setText(MessageManager .getString("label.add_reference_annotations")); - addDatasequenceAnnotations.setEnabled(false); + menuItem.setEnabled(false); + if (forSequences == null) + { + return; + } /* - * Temporary store so we can write distinct calcId / type pairs on the - * tooltip. + * Temporary store to hold distinct calcId / type pairs for the tooltip. + * Using TreeMap means calcIds are shown in alphabetical order. */ - Map tipEntries = new HashMap(); + Map tipEntries = new TreeMap(); StringBuilder tooltip = new StringBuilder(64); tooltip.append(MessageManager.getString("label.add_annotations_for")); - // this menu option only applies for a Selection - if (this.ap.av.getSelectionGroup() == null) - { - return; - } - /* * For each sequence selected in the alignment, make a list of any * annotations on the underlying dataset sequence which are not already on - * the sequence in the alignment. + * the alignment. * * Build a map of { alignmentSequence, } */ - final Map> candidates = new HashMap>(); - for (SequenceI seq : this.ap.av.getSelectionGroup().getSequences()) + AlignmentI al = this.ap.av.getAlignment(); + final Map> candidates = new LinkedHashMap>(); + for (SequenceI seq : forSequences) { SequenceI dataset = seq.getDatasetSequence(); if (dataset == null) @@ -1920,11 +1821,12 @@ public class PopupMenu extends JPopupMenu for (AlignmentAnnotation dsann : datasetAnnotations) { /* - * If the sequence has no annotation that matches this one, then add - * this one to the results list. + * Find matching annotations on the alignment. */ - if (seq.getAlignmentAnnotations(dsann.getCalcId(), dsann.label) - .isEmpty()) + final Iterable matchedAlignmentAnnotations = al + .findAnnotations(seq, dsann.getCalcId(), + dsann.label); + if (!matchedAlignmentAnnotations.iterator().hasNext()) { result.add(dsann); tipEntries.put(dsann.getCalcId(), dsann.label); @@ -1944,16 +1846,16 @@ public class PopupMenu extends JPopupMenu * Found annotations that could be added. Enable the menu item, and * configure its tooltip and action. */ - addDatasequenceAnnotations.setEnabled(true); + menuItem.setEnabled(true); for (String calcId : tipEntries.keySet()) { tooltip.append("
" + calcId + "/" + tipEntries.get(calcId)); } String tooltipText = JvSwingUtils.wrapTooltip(true, tooltip.toString()); - addDatasequenceAnnotations.setToolTipText(tooltipText); + menuItem.setToolTipText(tooltipText); - addDatasequenceAnnotations.addActionListener(new ActionListener() + menuItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) @@ -1974,6 +1876,10 @@ public class PopupMenu extends JPopupMenu protected void addReferenceAnnotations_actionPerformed( Map> candidates) { + /* + * Add annotations at the top of the annotation, in the same order as their + * related sequences. + */ for (SequenceI seq : candidates.keySet()) { for (AlignmentAnnotation ann : candidates.get(seq)) @@ -1989,8 +1895,14 @@ public class PopupMenu extends JPopupMenu } copyAnn.restrict(startRes, endRes); - // add to the sequence (sets correct copyAnn.datasetSequence) - seq.addAlignmentAnnotation(copyAnn); + /* + * Add to the sequence (sets copyAnn.datasetSequence), unless the + * original annotation is already on the sequence. + */ + if (!seq.hasAnnotation(ann)) + { + seq.addAlignmentAnnotation(copyAnn); + } // adjust for gaps copyAnn.adjustForAlignment(); // add to the alignment and set visible @@ -2665,7 +2577,8 @@ public class PopupMenu extends JPopupMenu String choice = chooser.getSelectedFile().getPath(); jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice); new AssociatePdbFileWithSeq().associatePdbWithSeq(choice, - jalview.io.AppletFormatAdapter.FILE, sequence, true); + jalview.io.AppletFormatAdapter.FILE, sequence, true, + Desktop.instance); } } @@ -2790,7 +2703,9 @@ public class PopupMenu extends JPopupMenu if (sg != null) { if (sequence == null) + { sequence = sg.getSequenceAt(0); + } EditNameDialog dialog = new EditNameDialog( sequence.getSequenceAsString(sg.getStartRes(), @@ -2803,7 +2718,7 @@ public class PopupMenu extends JPopupMenu { EditCommand editCommand = new EditCommand( MessageManager.getString("label.edit_sequences"), - EditCommand.REPLACE, dialog.getName().replace(' ', + Action.REPLACE, dialog.getName().replace(' ', ap.av.getGapCharacter()), sg.getSequencesAsArray(ap.av.getHiddenRepSequences()), sg.getStartRes(), sg.getEndRes() + 1, ap.av.getAlignment());