From: gmungoc Date: Wed, 25 Mar 2015 13:43:13 +0000 (+0000) Subject: JAL-1264 adding show/hide annotation options to applet X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=f18077aa57dea5481ae537162871045f8557e2f0;p=jalview.git JAL-1264 adding show/hide annotation options to applet --- diff --git a/resources/lang/Messages.properties b/resources/lang/Messages.properties index a797929..e6b69d5 100644 --- a/resources/lang/Messages.properties +++ b/resources/lang/Messages.properties @@ -229,7 +229,6 @@ label.documentation = Documentation label.about = About... label.show_sequence_limits = Show Sequence Limits label.feature_settings = Feature Settings... -label.sequence_features = Sequence Features label.all_columns = All Columns label.all_sequences = All Sequences label.selected_columns = Selected Columns @@ -1209,3 +1208,4 @@ label.display_name = Display Label label.description = Description label.include_description= Include Description label.start_jalview = Start Jalview +label.biojs_html_export = BioJS diff --git a/src/jalview/analysis/AlignmentUtils.java b/src/jalview/analysis/AlignmentUtils.java index 9202c0d..6f0125d 100644 --- a/src/jalview/analysis/AlignmentUtils.java +++ b/src/jalview/analysis/AlignmentUtils.java @@ -20,19 +20,9 @@ */ package jalview.analysis; -import jalview.datamodel.AlignedCodon; -import jalview.datamodel.AlignedCodonFrame; -import jalview.datamodel.AlignmentAnnotation; -import jalview.datamodel.AlignmentI; -import jalview.datamodel.Mapping; -import jalview.datamodel.SearchResults; -import jalview.datamodel.Sequence; -import jalview.datamodel.SequenceI; -import jalview.schemes.ResidueProperties; -import jalview.util.MapList; - import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -43,6 +33,18 @@ import java.util.Map.Entry; import java.util.Set; import java.util.TreeMap; +import jalview.datamodel.AlignedCodon; +import jalview.datamodel.AlignedCodonFrame; +import jalview.datamodel.AlignmentAnnotation; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.Mapping; +import jalview.datamodel.SearchResults; +import jalview.datamodel.Sequence; +import jalview.datamodel.SequenceGroup; +import jalview.datamodel.SequenceI; +import jalview.schemes.ResidueProperties; +import jalview.util.MapList; + /** * grab bag of useful alignment manipulation operations Expect these to be * refactored elsewhere at some point. @@ -1056,4 +1058,158 @@ public class AlignmentUtils */ return mapProteinToCdna(proteinDs, dnaDs) != null; } + + /** + * Finds any reference annotations associated with the sequences in + * sequenceScope, that are not already added to the alignment, and adds them + * to the 'candidates' map. Also populates a lookup table of annotation + * labels, keyed by calcId, for use in constructing tooltips or the like. + * + * @param sequenceScope + * the sequences to scan for reference annotations + * @param labelForCalcId + * (optional) map to populate with label for calcId + * @param candidates + * map to populate with annotations for sequence + * @param al + * the alignment to check for presence of annotations + */ + public static void findAddableReferenceAnnotations( + List sequenceScope, Map labelForCalcId, + final Map> candidates, + AlignmentI al) + { + if (sequenceScope == null) + { + return; + } + + /* + * For each sequence in scope, make a list of any annotations on the + * underlying dataset sequence which are not already on the alignment. + * + * Add to a map of { alignmentSequence, } + */ + for (SequenceI seq : sequenceScope) + { + SequenceI dataset = seq.getDatasetSequence(); + if (dataset == null) + { + continue; + } + AlignmentAnnotation[] datasetAnnotations = dataset.getAnnotation(); + if (datasetAnnotations == null) + { + continue; + } + final List result = new ArrayList(); + for (AlignmentAnnotation dsann : datasetAnnotations) + { + /* + * Find matching annotations on the alignment. If none is found, then + * add this annotation to the list of 'addable' annotations for this + * sequence. + */ + final Iterable matchedAlignmentAnnotations = al + .findAnnotations(seq, dsann.getCalcId(), + dsann.label); + if (!matchedAlignmentAnnotations.iterator().hasNext()) + { + result.add(dsann); + if (labelForCalcId != null) + { + labelForCalcId.put(dsann.getCalcId(), dsann.label); + } + } + } + /* + * Save any addable annotations for this sequence + */ + if (!result.isEmpty()) + { + candidates.put(seq, result); + } + } + } + + /** + * Adds annotations to the top of the alignment annotations, in the same order + * as their related sequences. + * + * @param annotations + * the annotations to add + * @param alignment + * the alignment to add them to + * @param selectionGroup + * current selection group (or null if none) + */ + public static void addReferenceAnnotations( + Map> annotations, + final AlignmentI alignment, final SequenceGroup selectionGroup) + { + for (SequenceI seq : annotations.keySet()) + { + for (AlignmentAnnotation ann : annotations.get(seq)) + { + AlignmentAnnotation copyAnn = new AlignmentAnnotation(ann); + int startRes = 0; + int endRes = ann.annotations.length; + if (selectionGroup != null) + { + startRes = selectionGroup.getStartRes(); + endRes = selectionGroup.getEndRes(); + } + copyAnn.restrict(startRes, endRes); + + /* + * 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 + alignment.addAnnotation(copyAnn); + copyAnn.visible = true; + } + } + } + + /** + * Set visibility of alignment annotations of specified types (labels), for + * specified sequences. This supports controls like + * "Show all secondary structure", "Hide all Temp factor", etc. + * + * @al the alignment to scan for annotations + * @param types + * the types (labels) of annotations to be updated + * @param forSequences + * if not null, only annotations linked to one of these sequences are + * in scope for update; if null, acts on all sequence annotations + * @param anyType + * if this flag is true, 'types' is ignored (label not checked) + * @param doShow + * if true, set visibility on, else set off + */ + public static void showOrHideSequenceAnnotations(AlignmentI al, + Collection types, List forSequences, + boolean anyType, boolean doShow) + { + for (AlignmentAnnotation aa : al + .getAlignmentAnnotation()) + { + if (anyType || types.contains(aa.label)) + { + if ((aa.sequenceRef != null) + && (forSequences == null || forSequences + .contains(aa.sequenceRef))) + { + aa.visible = doShow; + } + } + } + } } diff --git a/src/jalview/appletgui/APopupMenu.java b/src/jalview/appletgui/APopupMenu.java index 1b2d19a..d71fdd4 100644 --- a/src/jalview/appletgui/APopupMenu.java +++ b/src/jalview/appletgui/APopupMenu.java @@ -20,14 +20,33 @@ */ package jalview.appletgui; +import java.awt.CheckboxMenuItem; +import java.awt.Frame; +import java.awt.Menu; +import java.awt.MenuItem; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.Vector; + import jalview.analysis.AAFrequency; +import jalview.analysis.AlignmentAnnotationUtils; +import jalview.analysis.AlignmentUtils; 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.DBRefEntry; import jalview.datamodel.PDBEntry; -import jalview.datamodel.Sequence; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; @@ -48,20 +67,11 @@ import jalview.schemes.ZappoColourScheme; import jalview.util.MessageManager; import jalview.util.UrlLink; -import java.awt.CheckboxMenuItem; -import java.awt.Frame; -import java.awt.Menu; -import java.awt.MenuItem; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import java.util.List; -import java.util.Vector; - public class APopupMenu extends java.awt.PopupMenu implements ActionListener, ItemListener { + private static final String ALL_ANNOTATIONS = "All"; + Menu groupMenu = new Menu(); MenuItem editGroupName = new MenuItem(); @@ -112,6 +122,24 @@ public class APopupMenu extends java.awt.PopupMenu implements CheckboxMenuItem displayNonconserved = new CheckboxMenuItem(); + Menu seqShowAnnotationsMenu = new Menu( + MessageManager.getString("label.show_annotations")); + + Menu seqHideAnnotationsMenu = new Menu( + MessageManager.getString("label.hide_annotations")); + + MenuItem seqAddReferenceAnnotations = new MenuItem( + MessageManager.getString("label.add_reference_annotations")); + + Menu groupShowAnnotationsMenu = new Menu( + MessageManager.getString("label.show_annotations")); + + Menu groupHideAnnotationsMenu = new Menu( + MessageManager.getString("label.hide_annotations")); + + MenuItem groupAddReferenceAnnotations = new MenuItem( + MessageManager.getString("label.add_reference_annotations")); + Menu editMenu = new Menu(MessageManager.getString("action.edit")); MenuItem copy = new MenuItem(MessageManager.getString("action.copy")); @@ -154,7 +182,7 @@ public class APopupMenu extends java.awt.PopupMenu implements MenuItem makeReferenceSeq = new MenuItem(); - Sequence seq; + SequenceI seq; MenuItem revealAll = new MenuItem(); @@ -167,7 +195,8 @@ public class APopupMenu extends java.awt.PopupMenu implements Menu menu1 = new Menu(); - public APopupMenu(AlignmentPanel apanel, final Sequence seq, Vector links) + public APopupMenu(AlignmentPanel apanel, final SequenceI seq, + Vector links) { // ///////////////////////////////////////////////////////// // If this is activated from the sequence panel, the user may want to @@ -196,12 +225,13 @@ public class APopupMenu extends java.awt.PopupMenu implements outputmenu.add(item); } - SequenceGroup sg = ap.av.getSelectionGroup(); + buildAnnotationSubmenus(); + SequenceGroup sg = ap.av.getSelectionGroup(); if (sg != null && sg.getSize() > 0) { editGroupName.setLabel(MessageManager.formatMessage( - "label.name_param", new String[] + "label.name_param", new Object[] { sg.getName() })); showText.setState(sg.getDisplayText()); showColourText.setState(sg.getColourText()); @@ -228,10 +258,9 @@ public class APopupMenu extends java.awt.PopupMenu implements if (links != null && links.size() > 0) { Menu linkMenu = new Menu(MessageManager.getString("action.link")); - String link; for (int i = 0; i < links.size(); i++) { - link = links.elementAt(i).toString(); + String link = links.elementAt(i); UrlLink urlLink = new UrlLink(link); if (!urlLink.isValid()) { @@ -361,7 +390,7 @@ public class APopupMenu extends java.awt.PopupMenu implements .getString("action.set_as_reference")); // ); } repGroup.setLabel(MessageManager.formatMessage( - "label.represent_group_with", new String[] + "label.represent_group_with", new Object[] { seq.getName() })); } else @@ -391,6 +420,95 @@ public class APopupMenu extends java.awt.PopupMenu implements } /** + * Build menus for annotation types that may be shown or hidden, and for + * 'reference annotations' that may be added to the alignment. + */ + private void buildAnnotationSubmenus() + { + /* + * First for the currently selected sequence (if there is one): + */ + 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); + } + + /** + * Determine whether or not to enable 'add reference annotations' menu item. + * It is enable if there are any annotations, on any of the selected + * sequences, which are not yet on the alignment (visible or not). + * + * @param menu + * @param forSequences + */ + private void configureReferenceAnnotationsMenu(MenuItem menuItem, + List forSequences) + { + menuItem.setEnabled(false); + + /* + * Temporary store to hold distinct calcId / type pairs for the tooltip. + * Using TreeMap means calcIds are shown in alphabetical order. + */ + Map tipEntries = new TreeMap(); + final Map> candidates = new LinkedHashMap>(); + AlignmentI al = this.ap.av.getAlignment(); + AlignmentUtils.findAddableReferenceAnnotations(forSequences, + tipEntries, candidates, al); + if (!candidates.isEmpty()) + { + StringBuilder tooltip = new StringBuilder(64); + tooltip.append(MessageManager.getString("label.add_annotations_for")); + + /* + * Found annotations that could be added. Enable the menu item, and + * configure its action. + */ + menuItem.setEnabled(true); + + menuItem.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + addReferenceAnnotations_actionPerformed(candidates); + } + }); + } + } + + /** + * Add annotations to the sequences and to the alignment. + * + * @param candidates + * a map whose keys are sequences on the alignment, and values a list + * of annotations to add to each sequence + */ + protected void addReferenceAnnotations_actionPerformed( + Map> candidates) + { + final SequenceGroup selectionGroup = this.ap.av.getSelectionGroup(); + final AlignmentI alignment = this.ap.getAlignment(); + AlignmentUtils.addReferenceAnnotations(candidates, alignment, + selectionGroup); + refresh(); + } + + /** * add a show URL menu item to the given linkMenu * * @param linkMenu @@ -591,7 +709,7 @@ public class APopupMenu extends java.awt.PopupMenu implements { if (seq == null) { - seq = (Sequence) sg.getSequenceAt(0); + seq = sg.getSequenceAt(0); } EditNameDialog dialog = new EditNameDialog(seq.getSequenceAsString( @@ -707,7 +825,7 @@ public class APopupMenu extends java.awt.PopupMenu implements Frame frame = new Frame(); frame.add(cap); jalview.bin.JalviewLite.addFrame(frame, MessageManager.formatMessage( - "label.selection_output_command", new String[] + "label.selection_output_command", new Object[] { e.getActionCommand() }), 600, 500); // JBPNote: getSelectionAsNewSequence behaviour has changed - this method // now returns a full copy of sequence data @@ -738,7 +856,7 @@ public class APopupMenu extends java.awt.PopupMenu implements for (SequenceI seq : sequences) { contents.append(MessageManager.formatMessage( - "label.annotation_for_displayid", new String[] + "label.annotation_for_displayid", new Object[] { seq.getDisplayId(true) })); new SequenceAnnotationReport(null) .createSequenceAnnotationReport( @@ -757,7 +875,7 @@ public class APopupMenu extends java.awt.PopupMenu implements + (sequences.length == 1 ? sequences[0].getDisplayId(true) : "Selection"), 600, 500); cap.setText(MessageManager.formatMessage("label.html_content", - new String[] + new Object[] { contents.toString() })); } @@ -784,12 +902,12 @@ public class APopupMenu extends java.awt.PopupMenu implements if (ap.av.applet.jmolAvailable) { - new jalview.appletgui.AppletJmol(entry, new Sequence[] + new jalview.appletgui.AppletJmol(entry, new SequenceI[] { seq }, null, ap, AppletFormatAdapter.URL); } else { - new MCview.AppletPDBViewer(entry, new Sequence[] + new MCview.AppletPDBViewer(entry, new SequenceI[] { seq }, null, ap, AppletFormatAdapter.URL); } @@ -802,7 +920,7 @@ public class APopupMenu extends java.awt.PopupMenu implements Frame frame = new Frame(); frame.add(cap); jalview.bin.JalviewLite.addFrame(frame, MessageManager.formatMessage( - "label.paste_pdb_file_for_sequence", new String[] + "label.paste_pdb_file_for_sequence", new Object[] { seq.getName() }), 400, 300); } } @@ -846,7 +964,7 @@ public class APopupMenu extends java.awt.PopupMenu implements pdb.setLabel(MessageManager.getString("label.view_pdb_structure")); hideSeqs.setLabel(MessageManager.getString("action.hide_sequences")); repGroup.setLabel(MessageManager.formatMessage( - "label.represent_group_with", new String[] + "label.represent_group_with", new Object[] { "" })); revealAll.setLabel(MessageManager.getString("action.reveal_all")); revealSeq.setLabel(MessageManager.getString("action.reveal_sequences")); @@ -857,6 +975,9 @@ public class APopupMenu extends java.awt.PopupMenu implements this.add(revealSeq); this.add(revealAll); // groupMenu.add(selSeqDetails); + groupMenu.add(groupShowAnnotationsMenu); + groupMenu.add(groupHideAnnotationsMenu); + groupMenu.add(groupAddReferenceAnnotations); groupMenu.add(editMenu); groupMenu.add(outputmenu); groupMenu.add(sequenceFeature); @@ -923,6 +1044,9 @@ public class APopupMenu extends java.awt.PopupMenu implements editMenu.add(toLower); toLower.addActionListener(this); editMenu.add(toggleCase); + seqMenu.add(seqShowAnnotationsMenu); + seqMenu.add(seqHideAnnotationsMenu); + seqMenu.add(seqAddReferenceAnnotations); seqMenu.add(sequenceName); seqMenu.add(makeReferenceSeq); // seqMenu.add(sequenceDetails); @@ -1203,4 +1327,109 @@ public class APopupMenu extends java.awt.PopupMenu implements ap.av.sendSelection(); } + /** + * 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. 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 + * as visible (to avoid duplication of the display). For such groups we add a + * composite type name, e.g. + *

+ * IUPredWS (Long), IUPredWS (Short) + * + * @param seq + */ + protected void buildAnnotationTypesMenus(Menu showMenu, Menu hideMenu, + List forSequences) + { + showMenu.removeAll(); + hideMenu.removeAll(); + + final List all = Arrays.asList(ALL_ANNOTATIONS); + addAnnotationTypeToShowHide(showMenu, forSequences, "", all, true, true); + addAnnotationTypeToShowHide(hideMenu, forSequences, "", all, true, + false); + showMenu.addSeparator(); + hideMenu.addSeparator(); + + final AlignmentAnnotation[] annotations = ap.getAlignment() + .getAlignmentAnnotation(); + + /* + * Find shown/hidden annotations types, distinguished by source (calcId), + * 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 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(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(hideMenu, forSequences, + calcId, type, false, false); + } + } + // grey out 'hide annotations' if none are shown + hideMenu.setEnabled(!shownTypes.isEmpty()); + } + + /** + * Add one annotation type to the 'Show Annotations' or 'Hide Annotations' + * menus. + * + * @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 + * @param allTypes + * if true this is a special label meaning 'All' + * @param actionIsShow + * if true, the select menu item action is to show the annotation + * type, else hide + */ + protected void addAnnotationTypeToShowHide(Menu showOrHideMenu, + final List forSequences, String calcId, + final List types, final boolean allTypes, + final boolean actionIsShow) + { + String label = types.toString(); // [a, b, c] + label = label.substring(1, label.length() - 1); + final MenuItem item = new MenuItem(label); + item.addActionListener(new java.awt.event.ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + AlignmentUtils.showOrHideSequenceAnnotations(ap.getAlignment(), types, + forSequences, allTypes, actionIsShow); + refresh(); + } + }); + showOrHideMenu.add(item); + } + } diff --git a/src/jalview/appletgui/AlignFrame.java b/src/jalview/appletgui/AlignFrame.java index ba90075..3e919f6 100644 --- a/src/jalview/appletgui/AlignFrame.java +++ b/src/jalview/appletgui/AlignFrame.java @@ -20,7 +20,42 @@ */ package jalview.appletgui; +import java.awt.BorderLayout; +import java.awt.Canvas; +import java.awt.CheckboxMenuItem; +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Label; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.IOException; +import java.net.URL; +import java.net.URLEncoder; +import java.util.Arrays; +import java.util.Deque; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.Vector; + import jalview.analysis.AlignmentSorter; +import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder; import jalview.api.AlignViewControllerGuiI; import jalview.api.AlignViewControllerI; import jalview.api.AlignViewportI; @@ -36,6 +71,7 @@ import jalview.commands.RemoveGapsCommand; import jalview.commands.SlideSequencesCommand; import jalview.commands.TrimRegionCommand; import jalview.datamodel.Alignment; +import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AlignmentI; import jalview.datamodel.AlignmentOrder; import jalview.datamodel.ColumnSelection; @@ -68,39 +104,6 @@ import jalview.structures.models.AAStructureBindingModel; import jalview.util.MappingUtils; import jalview.util.MessageManager; -import java.awt.BorderLayout; -import java.awt.Canvas; -import java.awt.CheckboxMenuItem; -import java.awt.Color; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Frame; -import java.awt.Graphics; -import java.awt.Label; -import java.awt.Menu; -import java.awt.MenuBar; -import java.awt.MenuItem; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.IOException; -import java.net.URL; -import java.net.URLEncoder; -import java.util.Arrays; -import java.util.Deque; -import java.util.Hashtable; -import java.util.List; -import java.util.Map; -import java.util.StringTokenizer; -import java.util.Vector; - public class AlignFrame extends EmbmenuFrame implements ActionListener, ItemListener, KeyListener, AlignViewControllerGuiI { @@ -116,6 +119,14 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, String jalviewServletURL; + /* + * Flag for showing autocalculated consensus above or below other consensus + * rows + */ + private boolean showAutoCalculatedAbove; + + private SequenceAnnotationOrder annotationSortOrder; + /** * Constructor that creates the frame and adds it to the display. * @@ -184,7 +195,6 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, viewport.updateConservation(alignPanel); viewport.updateConsensus(alignPanel); - annotationPanelMenuItem.setState(viewport.isShowAnnotation()); displayNonconservedMenuItem.setState(viewport.getShowUnconserved()); followMouseOverFlag.setState(viewport.getFollowHighlight()); showGroupConsensus.setState(viewport.isShowGroupConsensus()); @@ -193,6 +203,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, showSequenceLogo.setState(viewport.isShowSequenceLogo()); normSequenceLogo.setState(viewport.isNormaliseSequenceLogo()); applyToAllGroups.setState(viewport.getColourAppliesToAllGroups()); + showAlignmentAnnotations.setState(viewport.isShowAnnotation()); + showSequenceAnnotations.setState(viewport.isShowAnnotation()); seqLimits.setState(viewport.getShowJVSuffix()); @@ -728,111 +740,188 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, @Override public void itemStateChanged(ItemEvent evt) { - if (evt.getSource() == displayNonconservedMenuItem) + final Object source = evt.getSource(); + if (source == displayNonconservedMenuItem) { displayNonconservedMenuItem_actionPerformed(); } - else if (evt.getSource() == colourTextMenuItem) + else if (source == colourTextMenuItem) { colourTextMenuItem_actionPerformed(); } - else if (evt.getSource() == wrapMenuItem) + else if (source == wrapMenuItem) { wrapMenuItem_actionPerformed(); } - else if (evt.getSource() == scaleAbove) + else if (source == scaleAbove) { viewport.setScaleAboveWrapped(scaleAbove.getState()); } - else if (evt.getSource() == scaleLeft) + else if (source == scaleLeft) { viewport.setScaleLeftWrapped(scaleLeft.getState()); } - else if (evt.getSource() == scaleRight) + else if (source == scaleRight) { viewport.setScaleRightWrapped(scaleRight.getState()); } - else if (evt.getSource() == seqLimits) + else if (source == seqLimits) { seqLimits_itemStateChanged(); } - else if (evt.getSource() == viewBoxesMenuItem) + else if (source == viewBoxesMenuItem) { viewport.setShowBoxes(viewBoxesMenuItem.getState()); } - else if (evt.getSource() == viewTextMenuItem) + else if (source == viewTextMenuItem) { viewport.setShowText(viewTextMenuItem.getState()); } - else if (evt.getSource() == renderGapsMenuItem) + else if (source == renderGapsMenuItem) { viewport.setRenderGaps(renderGapsMenuItem.getState()); } - else if (evt.getSource() == annotationPanelMenuItem) + else if (source == annotationPanelMenuItem) { viewport.setShowAnnotation(annotationPanelMenuItem.getState()); alignPanel.setAnnotationVisible(annotationPanelMenuItem.getState()); } - else if (evt.getSource() == sequenceFeatures) + else if (source == sequenceFeatures) { viewport.setShowSequenceFeatures(sequenceFeatures.getState()); alignPanel.seqPanel.seqCanvas.repaint(); } - else if (evt.getSource() == conservationMenuItem) + else if (source == showAlignmentAnnotations) + { + setAnnotationsVisibility(); + } + else if (source == showSequenceAnnotations) + { + setAnnotationsVisibility(); + } + else if (source == sortAnnBySequence) + { + boolean newState = sortAnnBySequence.getState(); + sortAnnByLabel.setState(false); + setAnnotationSortOrder(newState ? SequenceAnnotationOrder.SEQUENCE_AND_LABEL + : SequenceAnnotationOrder.NONE); + setViewportAnnotationOrder(); + } + else if (source == sortAnnByLabel) + { + boolean newState = sortAnnByLabel.getState(); + sortAnnBySequence.setState(false); + setAnnotationSortOrder(newState ? SequenceAnnotationOrder.LABEL_AND_SEQUENCE + : SequenceAnnotationOrder.NONE); + setViewportAnnotationOrder(); + } + else if (source == showAutoFirst) + { + showAutoLast.setState(!showAutoFirst.getState()); + setShowAutoCalculatedAbove(showAutoFirst.getState()); + setViewportAnnotationOrder(); + } + else if (source == showAutoLast) + { + showAutoFirst.setState(!showAutoLast.getState()); + setShowAutoCalculatedAbove(showAutoFirst.getState()); + setViewportAnnotationOrder(); + } + else if (source == conservationMenuItem) { conservationMenuItem_actionPerformed(); } - else if (evt.getSource() == abovePIDThreshold) + else if (source == abovePIDThreshold) { abovePIDThreshold_actionPerformed(); } - else if (evt.getSource() == applyToAllGroups) + else if (source == applyToAllGroups) { viewport.setColourAppliesToAllGroups(applyToAllGroups.getState()); } - else if (evt.getSource() == autoCalculate) + else if (source == autoCalculate) { viewport.autoCalculateConsensus = autoCalculate.getState(); } - else if (evt.getSource() == sortByTree) + else if (source == sortByTree) { viewport.sortByTree = sortByTree.getState(); } - else if (evt.getSource() == this.centreColumnLabelFlag) + else if (source == this.centreColumnLabelFlag) { centreColumnLabelFlag_stateChanged(); } - else if (evt.getSource() == this.followMouseOverFlag) + else if (source == this.followMouseOverFlag) { mouseOverFlag_stateChanged(); } - else if (evt.getSource() == showGroupConsensus) + else if (source == showGroupConsensus) { showGroupConsensus_actionPerformed(); } - else if (evt.getSource() == showGroupConservation) + else if (source == showGroupConservation) { showGroupConservation_actionPerformed(); } - else if (evt.getSource() == showSequenceLogo) + else if (source == showSequenceLogo) { showSequenceLogo_actionPerformed(); } - else if (evt.getSource() == normSequenceLogo) + else if (source == normSequenceLogo) { normSequenceLogo_actionPerformed(); } - else if (evt.getSource() == showConsensusHistogram) + else if (source == showConsensusHistogram) { showConsensusHistogram_actionPerformed(); } - else if (evt.getSource() == applyAutoAnnotationSettings) + else if (source == applyAutoAnnotationSettings) { applyAutoAnnotationSettings_actionPerformed(); } alignPanel.paintAlignment(true); } + /** + * Set the visibility state of sequence-related and/or alignment-related + * annotations depending on checkbox selections. Repaint after calling. + * + * @param visible + */ + private void setAnnotationsVisibility() + { + boolean showForAlignment = showAlignmentAnnotations.getState(); + boolean showForSequences = showSequenceAnnotations.getState(); + for (AlignmentAnnotation aa : alignPanel.getAlignment() + .getAlignmentAnnotation()) + { + boolean visible = (aa.sequenceRef == null ? showForAlignment + : showForSequences); + aa.visible = visible; + } + alignPanel.validateAnnotationDimensions(false); + } + + private void setAnnotationSortOrder(SequenceAnnotationOrder order) + { + this.annotationSortOrder = order; + } + + /** + * Set flags on the viewport that control annotation ordering + */ + private void setViewportAnnotationOrder() + { + this.alignPanel.av.setSortAnnotationsBy(this.annotationSortOrder); + this.alignPanel.av + .setShowAutocalculatedAbove(this.showAutoCalculatedAbove); + } + + private void setShowAutoCalculatedAbove(boolean showAbove) + { + this.showAutoCalculatedAbove = showAbove; + } + private void mouseOverFlag_stateChanged() { viewport.followHighlight = followMouseOverFlag.getState(); @@ -1740,12 +1829,12 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, SequenceGroup sg = viewport.getSelectionGroup(); copiedSequences = new StringBuffer(); - Hashtable orderedSeqs = new Hashtable(); + Map orderedSeqs = new HashMap(); for (int i = 0; i < sg.getSize(); i++) { SequenceI seq = sg.getSequenceAt(i); int index = viewport.getAlignment().findIndex(seq); - orderedSeqs.put(index + "", seq); + orderedSeqs.put(index, seq); } int index = 0, startRes, endRes; @@ -1772,11 +1861,10 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, while (seq == null) { - if (orderedSeqs.containsKey(index + "")) + if (orderedSeqs.containsKey(index)) { - seq = (SequenceI) orderedSeqs.get(index + ""); + seq = orderedSeqs.get(index); index++; - break; } else @@ -2335,13 +2423,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, if (alignPanel != null && (fr = alignPanel.getFeatureRenderer()) != null) { - List gps = fr.getFeatureGroups(); - int p=0; - String[] _gps = new String[gps.size()]; - for (Object gp:gps) - { - _gps[p++] = gp.toString(); - } + List gps = fr.getFeatureGroups(); + String[] _gps = gps.toArray(new String[gps.size()]); return _gps; } return null; @@ -2360,13 +2443,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, if (alignPanel != null && (fr = alignPanel.getFeatureRenderer()) != null) { - List gps = fr.getGroups(visible); - int p=0; - String[] _gps = new String[gps.size()]; - for (Object gp:gps) - { - _gps[p++] = gp.toString(); - } + List gps = fr.getGroups(visible); + String[] _gps = gps.toArray(new String[gps.size()]); return _gps; } return null; @@ -2898,15 +2976,6 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, MenuItem closeMenuItem = new MenuItem( MessageManager.getString("action.close")); - Menu editMenu = new Menu(MessageManager.getString("action.edit")); - - Menu viewMenu = new Menu(MessageManager.getString("action.view")); - - Menu colourMenu = new Menu(MessageManager.getString("action.colour")); - - Menu calculateMenu = new Menu( - MessageManager.getString("action.calculate")); - MenuItem selectAllSequenceMenuItem = new MenuItem( MessageManager.getString("action.select_all")); @@ -2950,8 +3019,6 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, public Label statusBar = new Label(); - Menu outputTextboxMenu = new Menu(); - MenuItem clustalColour = new MenuItem(); MenuItem zappoColour = new MenuItem(); @@ -3049,22 +3116,15 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, MenuItem modifyConservation = new MenuItem(); - CheckboxMenuItem autoCalculate = new CheckboxMenuItem( - "Autocalculate Consensus", true); + CheckboxMenuItem autoCalculate = null; CheckboxMenuItem sortByTree = new CheckboxMenuItem( "Sort Alignment With New Tree", true); Menu sortByTreeMenu = new Menu(); - Menu sort = new Menu(); - - Menu calculate = new Menu(); - MenuItem inputText = new MenuItem(); - Menu helpMenu = new Menu(); - MenuItem documentation = new MenuItem(); MenuItem about = new MenuItem(); @@ -3075,8 +3135,6 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, CheckboxMenuItem followMouseOverFlag = new CheckboxMenuItem(); - Menu autoAnnMenu = new Menu(); - CheckboxMenuItem showSequenceLogo = new CheckboxMenuItem(); CheckboxMenuItem applyAutoAnnotationSettings = new CheckboxMenuItem(); @@ -3089,18 +3147,27 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, CheckboxMenuItem normSequenceLogo = new CheckboxMenuItem(); + /** + * Initialise menus and other items + * + * @throws Exception + */ private void jbInit() throws Exception { - setMenuBar(alignFrameMenuBar); - MenuItem item; - - // dynamically fill save as menu with available formats + /* + * Configure File menu items and actions + */ + inputText + .setLabel(MessageManager.getString("label.input_from_textbox")); + inputText.addActionListener(this); + Menu outputTextboxMenu = new Menu( + MessageManager.getString("label.out_to_textbox")); for (int i = 0; i < jalview.io.AppletFormatAdapter.WRITEABLE_FORMATS.length; i++) { - item = new MenuItem( + MenuItem item = new MenuItem( jalview.io.AppletFormatAdapter.WRITEABLE_FORMATS[i]); item.addActionListener(new java.awt.event.ActionListener() @@ -3116,14 +3183,31 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, } closeMenuItem.addActionListener(this); loadApplication.addActionListener(this); - loadTree.addActionListener(this); loadAnnotations.addActionListener(this); outputFeatures.addActionListener(this); outputAnnotations.addActionListener(this); - selectAllSequenceMenuItem.addActionListener(this); - deselectAllSequenceMenuItem.addActionListener(this); - invertSequenceMenuItem.addActionListener(this); + + /* + * Configure Edit menu items and actions + */ + undoMenuItem.setEnabled(false); + undoMenuItem.setLabel(MessageManager.getString("action.undo")); + undoMenuItem.addActionListener(this); + redoMenuItem.setEnabled(false); + redoMenuItem.setLabel(MessageManager.getString("action.redo")); + redoMenuItem.addActionListener(this); + copy.setLabel(MessageManager.getString("action.copy")); + copy.addActionListener(this); + cut.setLabel(MessageManager.getString("action.cut")); + cut.addActionListener(this); + delete.setLabel(MessageManager.getString("action.delete")); + delete.addActionListener(this); + pasteMenu.setLabel(MessageManager.getString("action.paste")); + pasteNew.setLabel(MessageManager.getString("label.to_new_alignment")); + pasteNew.addActionListener(this); + pasteThis.setLabel(MessageManager.getString("label.to_this_alignment")); + pasteThis.addActionListener(this); remove2LeftMenuItem.setLabel(MessageManager .getString("action.remove_left")); remove2LeftMenuItem.addActionListener(this); @@ -3136,128 +3220,23 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, removeAllGapsMenuItem.setLabel(MessageManager .getString("action.remove_all_gaps")); removeAllGapsMenuItem.addActionListener(this); - viewBoxesMenuItem.setLabel(MessageManager.getString("action.boxes")); - viewBoxesMenuItem.setState(true); - viewBoxesMenuItem.addItemListener(this); - viewTextMenuItem.setLabel(MessageManager.getString("action.text")); - viewTextMenuItem.setState(true); - viewTextMenuItem.addItemListener(this); - sortPairwiseMenuItem.setLabel(MessageManager - .getString("action.by_pairwise_id")); - sortPairwiseMenuItem.addActionListener(this); - sortIDMenuItem.setLabel(MessageManager.getString("action.by_id")); - sortIDMenuItem.addActionListener(this); - sortLengthMenuItem.setLabel(MessageManager - .getString("action.by_length")); - sortLengthMenuItem.addActionListener(this); - sortGroupMenuItem.setLabel(MessageManager.getString("action.by_group")); - sortGroupMenuItem.addActionListener(this); - removeRedundancyMenuItem.setLabel(MessageManager - .getString("action.remove_redundancy").concat("...")); + removeRedundancyMenuItem.setLabel(MessageManager.getString( + "action.remove_redundancy").concat("...")); removeRedundancyMenuItem.addActionListener(this); - pairwiseAlignmentMenuItem.setLabel(MessageManager - .getString("action.pairwise_alignment")); - pairwiseAlignmentMenuItem.addActionListener(this); - PCAMenuItem.setLabel(MessageManager - .getString("label.principal_component_analysis")); - PCAMenuItem.addActionListener(this); - averageDistanceTreeMenuItem.setLabel(MessageManager - .getString("label.average_distance_identity")); - averageDistanceTreeMenuItem.addActionListener(this); - neighbourTreeMenuItem.setLabel(MessageManager - .getString("label.neighbour_joining_identity")); - neighbourTreeMenuItem.addActionListener(this); - statusBar.setBackground(Color.white); - statusBar.setFont(new java.awt.Font("Verdana", 0, 11)); - statusBar.setText(MessageManager.getString("label.status_bar")); - outputTextboxMenu.setLabel(MessageManager - .getString("label.out_to_textbox")); - clustalColour.setLabel(MessageManager.getString("label.clustalx")); - clustalColour.addActionListener(this); - zappoColour.setLabel(MessageManager.getString("label.zappo")); - zappoColour.addActionListener(this); - taylorColour.setLabel(MessageManager.getString("label.taylor")); - taylorColour.addActionListener(this); - hydrophobicityColour.setLabel(MessageManager - .getString("label.hydrophobicity")); - hydrophobicityColour.addActionListener(this); - helixColour - .setLabel(MessageManager.getString("label.helix_propensity")); - helixColour.addActionListener(this); - strandColour.setLabel(MessageManager - .getString("label.strand_propensity")); - strandColour.addActionListener(this); - turnColour.setLabel(MessageManager.getString("label.turn_propensity")); - turnColour.addActionListener(this); - buriedColour.setLabel(MessageManager.getString("label.buried_index")); - buriedColour.addActionListener(this); - purinePyrimidineColour.setLabel(MessageManager - .getString("label.purine_pyrimidine")); - purinePyrimidineColour.addActionListener(this); - RNAInteractionColour.setLabel(MessageManager - .getString("label.rna_interaction")); - RNAInteractionColour.addActionListener(this); - RNAHelixColour.setLabel(MessageManager - .getString("action.by_rna_helixes")); - RNAHelixColour.addActionListener(this); - userDefinedColour.setLabel(MessageManager - .getString("action.user_defined")); - userDefinedColour.addActionListener(this); - PIDColour.setLabel(MessageManager - .getString("label.percentage_identity")); - PIDColour.addActionListener(this); - BLOSUM62Colour.setLabel(MessageManager - .getString("label.blosum62_score")); - BLOSUM62Colour.addActionListener(this); - tcoffeeColour - .setLabel(MessageManager.getString("label.tcoffee_scores")); - tcoffeeColour.setEnabled(false); // it will enabled only if a score file is - // provided - tcoffeeColour.addActionListener(this); - avDistanceTreeBlosumMenuItem.setLabel(MessageManager - .getString("label.average_distance_bloslum62")); - avDistanceTreeBlosumMenuItem.addActionListener(this); - njTreeBlosumMenuItem.setLabel(MessageManager - .getString("label.neighbour_blosum62")); - njTreeBlosumMenuItem.addActionListener(this); - annotationPanelMenuItem.setLabel(MessageManager - .getString("label.show_annotations")); - annotationPanelMenuItem.addItemListener(this); - colourTextMenuItem.setLabel(MessageManager - .getString("label.colour_text")); - colourTextMenuItem.addItemListener(this); - displayNonconservedMenuItem.setLabel(MessageManager - .getString("label.show_non_conversed")); - displayNonconservedMenuItem.addItemListener(this); - alProperties.addActionListener(this); - overviewMenuItem.setLabel(MessageManager - .getString("label.overview_window")); - overviewMenuItem.addActionListener(this); - undoMenuItem.setEnabled(false); - undoMenuItem.setLabel(MessageManager.getString("action.undo")); - undoMenuItem.addActionListener(this); - redoMenuItem.setEnabled(false); - redoMenuItem.setLabel(MessageManager.getString("action.redo")); - redoMenuItem.addActionListener(this); - conservationMenuItem.setLabel(MessageManager - .getString("action.by_conservation")); - conservationMenuItem.addItemListener(this); - noColourmenuItem.setLabel(MessageManager.getString("label.none")); - noColourmenuItem.addActionListener(this); - wrapMenuItem.setLabel(MessageManager.getString("action.wrap")); - wrapMenuItem.addItemListener(this); - renderGapsMenuItem.setLabel(MessageManager - .getString("action.show_gaps")); - renderGapsMenuItem.setState(true); - renderGapsMenuItem.addItemListener(this); + /* + * Configure Select menu items and actions + */ findMenuItem.setLabel(MessageManager.getString("action.find")); findMenuItem.addActionListener(this); - abovePIDThreshold.setLabel(MessageManager - .getString("label.above_identity_threshold")); - abovePIDThreshold.addItemListener(this); - nucleotideColour.setLabel(MessageManager.getString("label.nucleotide")); - nucleotideColour.addActionListener(this); + selectAllSequenceMenuItem.addActionListener(this); + deselectAllSequenceMenuItem.addActionListener(this); + invertSequenceMenuItem.setLabel(MessageManager + .getString("action.invert_sequence_selection")); + invertSequenceMenuItem.addActionListener(this); + invertColSel.setLabel(MessageManager + .getString("action.invert_column_selection")); + invertColSel.addActionListener(this); deleteGroups.setLabel(MessageManager .getString("action.undefine_groups")); deleteGroups.addActionListener(this); @@ -3266,88 +3245,18 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, grpsFromSelection.addActionListener(this); createGroup.setLabel(MessageManager.getString("action.create_group")); unGroup.setLabel(MessageManager.getString("action.remove_group")); - copy.setLabel(MessageManager.getString("action.copy")); - copy.addActionListener(this); - cut.setLabel(MessageManager.getString("action.cut")); - cut.addActionListener(this); - delete.setLabel(MessageManager.getString("action.delete")); - delete.addActionListener(this); - pasteMenu.setLabel(MessageManager.getString("action.paste")); - pasteNew.setLabel(MessageManager.getString("label.to_new_alignment")); - pasteNew.addActionListener(this); - pasteThis.setLabel(MessageManager.getString("label.to_this_alignment")); - pasteThis.addActionListener(this); - applyToAllGroups.setLabel(MessageManager - .getString("label.apply_colour_to_all_groups")); - applyToAllGroups.setState(true); - applyToAllGroups.addItemListener(this); - font.setLabel(MessageManager.getString("action.font")); - font.addActionListener(this); - scaleAbove.setLabel(MessageManager.getString("action.scale_above")); - scaleAbove.setState(true); - scaleAbove.setEnabled(false); - scaleAbove.addItemListener(this); - scaleLeft.setEnabled(false); - scaleLeft.setState(true); - scaleLeft.setLabel(MessageManager.getString("action.scale_left")); - scaleLeft.addItemListener(this); - scaleRight.setEnabled(false); - scaleRight.setState(true); - scaleRight.setLabel(MessageManager.getString("action.scale_right")); - scaleRight.addItemListener(this); - modifyPID.setLabel(MessageManager - .getString("label.modify_identity_thereshold")); - modifyPID.addActionListener(this); - modifyConservation.setLabel(MessageManager - .getString("label.modify_conservation_thereshold")); - modifyConservation.addActionListener(this); - sortByTreeMenu.setLabel(MessageManager - .getString("action.by_tree_order")); - sort.setLabel(MessageManager.getString("action.sort")); - calculate.setLabel(MessageManager.getString("action.calculate_tree")); - autoCalculate.addItemListener(this); - sortByTree.addItemListener(this); - inputText - .setLabel(MessageManager.getString("label.input_from_textbox")); - inputText.addActionListener(this); - centreColumnLabelFlag.setLabel(MessageManager - .getString("label.centre_column_labels")); - centreColumnLabelFlag.addItemListener(this); - followMouseOverFlag.setLabel(MessageManager - .getString("label.automatic_scrolling")); - followMouseOverFlag.addItemListener(this); - helpMenu.setLabel(MessageManager.getString("action.help")); - documentation.setLabel(MessageManager.getString("label.documentation")); - documentation.addActionListener(this); - - about.setLabel(MessageManager.getString("label.about")); - about.addActionListener(this); - seqLimits.setState(true); - seqLimits.setLabel(MessageManager - .getString("label.show_sequence_limits")); - seqLimits.addItemListener(this); - featureSettings.setLabel(MessageManager - .getString("label.feature_settings")); - featureSettings.addActionListener(this); - sequenceFeatures.setLabel(MessageManager - .getString("label.sequence_features")); - sequenceFeatures.addItemListener(this); - sequenceFeatures.setState(false); - annotationColour.setLabel(MessageManager - .getString("action.by_annotation")); - annotationColour.addActionListener(this); - annotationColumnSelection.setLabel("Select by Annotation"); annotationColumnSelection.addActionListener(this); - invertSequenceMenuItem.setLabel(MessageManager - .getString("action.invert_sequence_selection")); - invertColSel.setLabel(MessageManager - .getString("action.invert_column_selection")); - menu1.setLabel(MessageManager.getString("action.show")); + /* + * Configure View menu items and actions + */ + newView.setLabel(MessageManager.getString("action.new_view")); + newView.addActionListener(this); + Menu showMenu = new Menu(MessageManager.getString("action.show")); showColumns.setLabel(MessageManager.getString("label.all_columns")); showSeqs.setLabel(MessageManager.getString("label.all_sequences")); - menu2.setLabel(MessageManager.getString("action.hide")); + Menu hideMenu = new Menu(MessageManager.getString("action.hide")); hideColumns .setLabel(MessageManager.getString("label.selected_columns")); hideSequences.setLabel(MessageManager @@ -3358,6 +3267,34 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, .getString("label.selected_region")); showAllHidden.setLabel(MessageManager .getString("label.all_sequences_columns")); + showColumns.addActionListener(this); + showSeqs.addActionListener(this); + hideColumns.addActionListener(this); + hideSequences.addActionListener(this); + hideAllButSelection.addActionListener(this); + hideAllSelection.addActionListener(this); + showAllHidden.addActionListener(this); + featureSettings.setLabel(MessageManager + .getString("label.feature_settings")); + featureSettings.addActionListener(this); + sequenceFeatures.setLabel(MessageManager + .getString("label.show_sequence_features")); + sequenceFeatures.addItemListener(this); + sequenceFeatures.setState(false); + followMouseOverFlag.setLabel(MessageManager + .getString("label.automatic_scrolling")); + followMouseOverFlag.addItemListener(this); + alProperties.addActionListener(this); + overviewMenuItem.setLabel(MessageManager + .getString("label.overview_window")); + overviewMenuItem.addActionListener(this); + + /* + * Configure Annotations menu items and actions + */ + annotationPanelMenuItem.setLabel(MessageManager + .getString("label.show_annotations")); + annotationPanelMenuItem.addItemListener(this); showGroupConsensus.setLabel(MessageManager .getString("label.group_consensus")); showGroupConservation.setLabel(MessageManager @@ -3371,58 +3308,243 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, applyAutoAnnotationSettings.setLabel(MessageManager .getString("label.apply_all_groups")); applyAutoAnnotationSettings.setState(true); - autoAnnMenu.setLabel(MessageManager - .getString("label.autocalculated_annotation")); - - invertColSel.addActionListener(this); - showColumns.addActionListener(this); - showSeqs.addActionListener(this); - hideColumns.addActionListener(this); - hideSequences.addActionListener(this); - hideAllButSelection.addActionListener(this); - hideAllSelection.addActionListener(this); - showAllHidden.addActionListener(this); + Menu autoAnnMenu = new Menu( + MessageManager.getString("label.autocalculated_annotation")); showGroupConsensus.addItemListener(this); showGroupConservation.addItemListener(this); showConsensusHistogram.addItemListener(this); showSequenceLogo.addItemListener(this); normSequenceLogo.addItemListener(this); - applyAutoAnnotationSettings.addItemListener(this); - formatMenu.setLabel(MessageManager.getString("action.format")); - selectMenu.setLabel(MessageManager.getString("action.select")); - newView.setLabel(MessageManager.getString("action.new_view")); - newView.addActionListener(this); + showAlignmentAnnotations = new CheckboxMenuItem( + MessageManager.getString("label.show_all_al_annotations")); + showSequenceAnnotations = new CheckboxMenuItem( + MessageManager.getString("label.show_all_seq_annotations")); + sortAnnBySequence = new CheckboxMenuItem( + MessageManager.getString("label.sort_annotations_by_sequence")); + sortAnnByLabel = new CheckboxMenuItem( + MessageManager.getString("label.sort_annotations_by_label")); + showAutoFirst = new CheckboxMenuItem( + MessageManager.getString("label.show_first")); + showAutoLast = new CheckboxMenuItem( + MessageManager.getString("label.show_last")); + showAlignmentAnnotations.addItemListener(this); + showSequenceAnnotations.addItemListener(this); + sortAnnBySequence.addItemListener(this); + sortAnnByLabel.addItemListener(this); + showAutoFirst.addItemListener(this); + showAutoLast.addItemListener(this); + + /* + * Configure Format menu items and actions + */ + font.setLabel(MessageManager.getString("action.font")); + font.addActionListener(this); + scaleAbove.setLabel(MessageManager.getString("action.scale_above")); + scaleAbove.setState(true); + scaleAbove.setEnabled(false); + scaleAbove.addItemListener(this); + scaleLeft.setEnabled(false); + scaleLeft.setState(true); + scaleLeft.setLabel(MessageManager.getString("action.scale_left")); + scaleLeft.addItemListener(this); + scaleRight.setEnabled(false); + scaleRight.setState(true); + scaleRight.setLabel(MessageManager.getString("action.scale_right")); + scaleRight.addItemListener(this); + viewBoxesMenuItem.setLabel(MessageManager.getString("action.boxes")); + viewBoxesMenuItem.setState(true); + viewBoxesMenuItem.addItemListener(this); + viewTextMenuItem.setLabel(MessageManager.getString("action.text")); + viewTextMenuItem.setState(true); + viewTextMenuItem.addItemListener(this); + colourTextMenuItem.setLabel(MessageManager + .getString("label.colour_text")); + colourTextMenuItem.addItemListener(this); + displayNonconservedMenuItem.setLabel(MessageManager + .getString("label.show_non_conversed")); + displayNonconservedMenuItem.addItemListener(this); + wrapMenuItem.setLabel(MessageManager.getString("action.wrap")); + wrapMenuItem.addItemListener(this); + renderGapsMenuItem.setLabel(MessageManager + .getString("action.show_gaps")); + renderGapsMenuItem.setState(true); + renderGapsMenuItem.addItemListener(this); + centreColumnLabelFlag.setLabel(MessageManager + .getString("label.centre_column_labels")); + centreColumnLabelFlag.addItemListener(this); + seqLimits.setState(true); + seqLimits.setLabel(MessageManager + .getString("label.show_sequence_limits")); + seqLimits.addItemListener(this); + + /* + * Configure Colour menu items and actions + */ + applyToAllGroups.setLabel(MessageManager + .getString("label.apply_colour_to_all_groups")); + applyToAllGroups.setState(true); + applyToAllGroups.addItemListener(this); + clustalColour.setLabel(MessageManager.getString("label.clustalx")); + clustalColour.addActionListener(this); + zappoColour.setLabel(MessageManager.getString("label.zappo")); + zappoColour.addActionListener(this); + taylorColour.setLabel(MessageManager.getString("label.taylor")); + taylorColour.addActionListener(this); + hydrophobicityColour.setLabel(MessageManager + .getString("label.hydrophobicity")); + hydrophobicityColour.addActionListener(this); + helixColour + .setLabel(MessageManager.getString("label.helix_propensity")); + helixColour.addActionListener(this); + strandColour.setLabel(MessageManager + .getString("label.strand_propensity")); + strandColour.addActionListener(this); + turnColour.setLabel(MessageManager.getString("label.turn_propensity")); + turnColour.addActionListener(this); + buriedColour.setLabel(MessageManager.getString("label.buried_index")); + buriedColour.addActionListener(this); + purinePyrimidineColour.setLabel(MessageManager + .getString("label.purine_pyrimidine")); + purinePyrimidineColour.addActionListener(this); + RNAInteractionColour.setLabel(MessageManager + .getString("label.rna_interaction")); + RNAInteractionColour.addActionListener(this); + RNAHelixColour.setLabel(MessageManager + .getString("action.by_rna_helixes")); + RNAHelixColour.addActionListener(this); + userDefinedColour.setLabel(MessageManager + .getString("action.user_defined")); + userDefinedColour.addActionListener(this); + PIDColour.setLabel(MessageManager + .getString("label.percentage_identity")); + PIDColour.addActionListener(this); + BLOSUM62Colour.setLabel(MessageManager + .getString("label.blosum62_score")); + BLOSUM62Colour.addActionListener(this); + tcoffeeColour + .setLabel(MessageManager.getString("label.tcoffee_scores")); + // it will be enabled only if a score file is provided + tcoffeeColour.setEnabled(false); + tcoffeeColour.addActionListener(this); + conservationMenuItem.setLabel(MessageManager + .getString("action.by_conservation")); + conservationMenuItem.addItemListener(this); + noColourmenuItem.setLabel(MessageManager.getString("label.none")); + noColourmenuItem.addActionListener(this); + abovePIDThreshold.setLabel(MessageManager + .getString("label.above_identity_threshold")); + abovePIDThreshold.addItemListener(this); + nucleotideColour.setLabel(MessageManager.getString("label.nucleotide")); + nucleotideColour.addActionListener(this); + modifyPID.setLabel(MessageManager + .getString("label.modify_identity_thereshold")); + modifyPID.addActionListener(this); + modifyConservation.setLabel(MessageManager + .getString("label.modify_conservation_thereshold")); + modifyConservation.addActionListener(this); + annotationColour.setLabel(MessageManager + .getString("action.by_annotation")); + annotationColour.addActionListener(this); + + /* + * Configure Calculate menu items and actions + */ + sortPairwiseMenuItem.setLabel(MessageManager + .getString("action.by_pairwise_id")); + sortPairwiseMenuItem.addActionListener(this); + sortIDMenuItem.setLabel(MessageManager.getString("action.by_id")); + sortIDMenuItem.addActionListener(this); + sortLengthMenuItem.setLabel(MessageManager + .getString("action.by_length")); + sortLengthMenuItem.addActionListener(this); + sortGroupMenuItem.setLabel(MessageManager.getString("action.by_group")); + sortGroupMenuItem.addActionListener(this); + pairwiseAlignmentMenuItem.setLabel(MessageManager + .getString("action.pairwise_alignment")); + pairwiseAlignmentMenuItem.addActionListener(this); + PCAMenuItem.setLabel(MessageManager + .getString("label.principal_component_analysis")); + PCAMenuItem.addActionListener(this); + autoCalculate = new CheckboxMenuItem( + MessageManager.getString("label.autocalculate_consensus"), true); + averageDistanceTreeMenuItem.setLabel(MessageManager + .getString("label.average_distance_identity")); + averageDistanceTreeMenuItem.addActionListener(this); + neighbourTreeMenuItem.setLabel(MessageManager + .getString("label.neighbour_joining_identity")); + neighbourTreeMenuItem.addActionListener(this); + avDistanceTreeBlosumMenuItem.setLabel(MessageManager + .getString("label.average_distance_bloslum62")); + avDistanceTreeBlosumMenuItem.addActionListener(this); + njTreeBlosumMenuItem.setLabel(MessageManager + .getString("label.neighbour_blosum62")); + njTreeBlosumMenuItem.addActionListener(this); + sortByTreeMenu.setLabel(MessageManager + .getString("action.by_tree_order")); + Menu sortMenu = new Menu(MessageManager.getString("action.sort")); + Menu calculateTreeMenu = new Menu( + MessageManager.getString("action.calculate_tree")); + autoCalculate.addItemListener(this); + sortByTree.addItemListener(this); + + /* + * Configure Help menu items and actions + */ + Menu helpMenu = new Menu(MessageManager.getString("action.help")); + documentation.setLabel(MessageManager.getString("label.documentation")); + documentation.addActionListener(this); + about.setLabel(MessageManager.getString("label.about")); + about.addActionListener(this); + + /* + * Add top level menus to frame + */ alignFrameMenuBar.add(fileMenu); + Menu editMenu = new Menu(MessageManager.getString("action.edit")); alignFrameMenuBar.add(editMenu); + Menu selectMenu = new Menu(MessageManager.getString("action.select")); alignFrameMenuBar.add(selectMenu); + Menu viewMenu = new Menu(MessageManager.getString("action.view")); alignFrameMenuBar.add(viewMenu); + Menu annotationsMenu = new Menu( + MessageManager.getString("action.annotations")); + alignFrameMenuBar.add(annotationsMenu); + Menu formatMenu = new Menu(MessageManager.getString("action.format")); alignFrameMenuBar.add(formatMenu); + Menu colourMenu = new Menu(MessageManager.getString("action.colour")); alignFrameMenuBar.add(colourMenu); + Menu calculateMenu = new Menu( + MessageManager.getString("action.calculate")); alignFrameMenuBar.add(calculateMenu); alignFrameMenuBar.add(helpMenu); + /* + * File menu + */ fileMenu.add(inputText); fileMenu.add(loadTree); fileMenu.add(loadAnnotations); - fileMenu.addSeparator(); fileMenu.add(outputTextboxMenu); fileMenu.add(outputFeatures); fileMenu.add(outputAnnotations); - if (jalviewServletURL != null) { fileMenu.add(loadApplication); } - fileMenu.addSeparator(); fileMenu.add(closeMenuItem); + /* + * Edit menu + */ editMenu.add(undoMenuItem); editMenu.add(redoMenuItem); editMenu.add(cut); editMenu.add(copy); + pasteMenu.add(pasteNew); + pasteMenu.add(pasteThis); editMenu.add(pasteMenu); editMenu.add(delete); editMenu.addSeparator(); @@ -3431,21 +3553,38 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, editMenu.add(removeGappedColumnMenuItem); editMenu.add(removeAllGapsMenuItem); editMenu.add(removeRedundancyMenuItem); + + /* + * Select menu + */ + selectMenu.add(findMenuItem); + selectMenu.addSeparator(); + selectMenu.add(selectAllSequenceMenuItem); + selectMenu.add(deselectAllSequenceMenuItem); + selectMenu.add(invertSequenceMenuItem); + selectMenu.add(invertColSel); + selectMenu.add(createGroup); + selectMenu.add(unGroup); + selectMenu.add(grpsFromSelection); + selectMenu.add(deleteGroups); + selectMenu.add(annotationColumnSelection); + + /* + * View menu + */ viewMenu.add(newView); viewMenu.addSeparator(); - viewMenu.add(menu1); - viewMenu.add(menu2); + showMenu.add(showColumns); + showMenu.add(showSeqs); + showMenu.add(showAllHidden); + viewMenu.add(showMenu); + hideMenu.add(hideColumns); + hideMenu.add(hideSequences); + hideMenu.add(hideAllSelection); + hideMenu.add(hideAllButSelection); + viewMenu.add(hideMenu); viewMenu.addSeparator(); viewMenu.add(followMouseOverFlag); - viewMenu.add(annotationPanelMenuItem); - autoAnnMenu.add(applyAutoAnnotationSettings); - autoAnnMenu.add(showConsensusHistogram); - autoAnnMenu.add(showSequenceLogo); - autoAnnMenu.add(normSequenceLogo); - autoAnnMenu.addSeparator(); - autoAnnMenu.add(showGroupConservation); - autoAnnMenu.add(showGroupConsensus); - viewMenu.add(autoAnnMenu); viewMenu.addSeparator(); viewMenu.add(sequenceFeatures); viewMenu.add(featureSettings); @@ -3453,6 +3592,48 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, viewMenu.add(alProperties); viewMenu.addSeparator(); viewMenu.add(overviewMenuItem); + + /* + * Annotations menu + */ + // annotationsMenu.add(annotationPanelMenuItem); + // annotationsMenu.addSeparator(); + annotationsMenu.add(showAlignmentAnnotations); + annotationsMenu.add(showSequenceAnnotations); + annotationsMenu.add(sortAnnBySequence); + annotationsMenu.add(sortAnnByLabel); + annotationsMenu.addSeparator(); + autoAnnMenu.add(showAutoFirst); + autoAnnMenu.add(showAutoLast); + autoAnnMenu.addSeparator(); + autoAnnMenu.add(applyAutoAnnotationSettings); + autoAnnMenu.add(showConsensusHistogram); + autoAnnMenu.add(showSequenceLogo); + autoAnnMenu.add(normSequenceLogo); + autoAnnMenu.addSeparator(); + autoAnnMenu.add(showGroupConservation); + autoAnnMenu.add(showGroupConsensus); + annotationsMenu.add(autoAnnMenu); + + /* + * Format menu + */ + formatMenu.add(font); + formatMenu.add(seqLimits); + formatMenu.add(wrapMenuItem); + formatMenu.add(scaleAbove); + formatMenu.add(scaleLeft); + formatMenu.add(scaleRight); + formatMenu.add(viewBoxesMenuItem); + formatMenu.add(viewTextMenuItem); + formatMenu.add(colourTextMenuItem); + formatMenu.add(displayNonconservedMenuItem); + formatMenu.add(renderGapsMenuItem); + formatMenu.add(centreColumnLabelFlag); + + /* + * Colour menu + */ colourMenu.add(applyToAllGroups); colourMenu.addSeparator(); colourMenu.add(noColourmenuItem); @@ -3478,58 +3659,40 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, colourMenu.add(modifyPID); colourMenu.add(annotationColour); colourMenu.add(RNAHelixColour); - calculateMenu.add(sort); - calculateMenu.add(calculate); + + /* + * Calculate menu + */ + sortMenu.add(sortIDMenuItem); + sortMenu.add(sortLengthMenuItem); + sortMenu.add(sortByTreeMenu); + sortMenu.add(sortGroupMenuItem); + sortMenu.add(sortPairwiseMenuItem); + calculateMenu.add(sortMenu); + calculateTreeMenu.add(averageDistanceTreeMenuItem); + calculateTreeMenu.add(neighbourTreeMenuItem); + calculateTreeMenu.add(avDistanceTreeBlosumMenuItem); + calculateTreeMenu.add(njTreeBlosumMenuItem); + calculateMenu.add(calculateTreeMenu); calculateMenu.addSeparator(); calculateMenu.add(pairwiseAlignmentMenuItem); calculateMenu.add(PCAMenuItem); calculateMenu.add(autoCalculate); calculateMenu.add(sortByTree); - this.add(statusBar, BorderLayout.SOUTH); - pasteMenu.add(pasteNew); - pasteMenu.add(pasteThis); - sort.add(sortIDMenuItem); - sort.add(sortLengthMenuItem); - sort.add(sortByTreeMenu); - sort.add(sortGroupMenuItem); - sort.add(sortPairwiseMenuItem); - calculate.add(averageDistanceTreeMenuItem); - calculate.add(neighbourTreeMenuItem); - calculate.add(avDistanceTreeBlosumMenuItem); - calculate.add(njTreeBlosumMenuItem); + + /* + * Help menu + */ helpMenu.add(documentation); helpMenu.add(about); - menu1.add(showColumns); - menu1.add(showSeqs); - menu1.add(showAllHidden); - menu2.add(hideColumns); - menu2.add(hideSequences); - menu2.add(hideAllSelection); - menu2.add(hideAllButSelection); - formatMenu.add(font); - formatMenu.add(seqLimits); - formatMenu.add(wrapMenuItem); - formatMenu.add(scaleAbove); - formatMenu.add(scaleLeft); - formatMenu.add(scaleRight); - formatMenu.add(viewBoxesMenuItem); - formatMenu.add(viewTextMenuItem); - formatMenu.add(colourTextMenuItem); - formatMenu.add(displayNonconservedMenuItem); - formatMenu.add(renderGapsMenuItem); - formatMenu.add(centreColumnLabelFlag); - selectMenu.add(findMenuItem); - selectMenu.addSeparator(); - selectMenu.add(selectAllSequenceMenuItem); - selectMenu.add(deselectAllSequenceMenuItem); - selectMenu.add(invertSequenceMenuItem); - selectMenu.add(invertColSel); - selectMenu.add(createGroup); - selectMenu.add(unGroup); - selectMenu.add(grpsFromSelection); - selectMenu.add(deleteGroups); - selectMenu.add(annotationColumnSelection); + /* + * Status bar + */ + statusBar.setBackground(Color.white); + statusBar.setFont(new java.awt.Font("Verdana", 0, 11)); + statusBar.setText(MessageManager.getString("label.status_bar")); + this.add(statusBar, BorderLayout.SOUTH); } public void setStatus(String string) @@ -3547,14 +3710,10 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, MenuItem invertColSel = new MenuItem(); - Menu menu1 = new Menu(); - MenuItem showColumns = new MenuItem(); MenuItem showSeqs = new MenuItem(); - Menu menu2 = new Menu(); - MenuItem hideColumns = new MenuItem(); MenuItem hideSequences = new MenuItem(); @@ -3565,11 +3724,19 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, MenuItem showAllHidden = new MenuItem(); - Menu formatMenu = new Menu(); + MenuItem newView = new MenuItem(); - Menu selectMenu = new Menu(); + private CheckboxMenuItem showAlignmentAnnotations; - MenuItem newView = new MenuItem(); + private CheckboxMenuItem showSequenceAnnotations; + + private CheckboxMenuItem sortAnnBySequence; + + private CheckboxMenuItem sortAnnByLabel; + + private CheckboxMenuItem showAutoFirst; + + private CheckboxMenuItem showAutoLast; /** * Attach the alignFrame panels after embedding menus, if necessary. This used diff --git a/src/jalview/appletgui/AlignmentPanel.java b/src/jalview/appletgui/AlignmentPanel.java index 9896ee7..c74914f 100644 --- a/src/jalview/appletgui/AlignmentPanel.java +++ b/src/jalview/appletgui/AlignmentPanel.java @@ -20,13 +20,6 @@ */ package jalview.appletgui; -import jalview.api.AlignViewportI; -import jalview.api.AlignmentViewPanel; -import jalview.datamodel.AlignmentI; -import jalview.datamodel.SearchResults; -import jalview.datamodel.SequenceI; -import jalview.structure.StructureSelectionManager; - import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; @@ -40,6 +33,14 @@ import java.awt.event.AdjustmentListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; +import jalview.analysis.AnnotationSorter; +import jalview.api.AlignViewportI; +import jalview.api.AlignmentViewPanel; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.SearchResults; +import jalview.datamodel.SequenceI; +import jalview.structure.StructureSelectionManager; + public class AlignmentPanel extends Panel implements AdjustmentListener, AlignmentViewPanel { @@ -801,8 +802,15 @@ public class AlignmentPanel extends Panel implements AdjustmentListener, av.endSeq); } + /** + * Repaint the alignment and annotations, and, optionally, any overview window + */ public void paintAlignment(boolean updateOverview) { + final AnnotationSorter sorter = new AnnotationSorter(getAlignment(), + av.isShowAutocalculatedAbove()); + sorter.sort(getAlignment().getAlignmentAnnotation(), + av.getSortAnnotationsBy()); repaint(); if (updateOverview) diff --git a/src/jalview/appletgui/AnnotationLabels.java b/src/jalview/appletgui/AnnotationLabels.java index ce50cee..67faf11 100755 --- a/src/jalview/appletgui/AnnotationLabels.java +++ b/src/jalview/appletgui/AnnotationLabels.java @@ -20,13 +20,6 @@ */ package jalview.appletgui; -import jalview.datamodel.AlignmentAnnotation; -import jalview.datamodel.Annotation; -import jalview.datamodel.SequenceGroup; -import jalview.datamodel.SequenceI; -import jalview.util.MessageManager; -import jalview.util.ParseHtmlBodyAndLinks; - import java.awt.Checkbox; import java.awt.CheckboxMenuItem; import java.awt.Color; @@ -48,8 +41,17 @@ import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.util.Arrays; +import java.util.Collections; import java.util.Vector; +import jalview.analysis.AlignmentUtils; +import jalview.datamodel.AlignmentAnnotation; +import jalview.datamodel.Annotation; +import jalview.datamodel.SequenceGroup; +import jalview.datamodel.SequenceI; +import jalview.util.MessageManager; +import jalview.util.ParseHtmlBodyAndLinks; + public class AnnotationLabels extends Panel implements ActionListener, MouseListener, MouseMotionListener { @@ -211,6 +213,14 @@ public class AnnotationLabels extends Panel implements ActionListener, } } + refresh(); + } + + /** + * Adjust size and repaint + */ + protected void refresh() + { ap.annotationPanel.adjustPanelHeight(); setSize(getSize().width, ap.annotationPanel.getSize().height); ap.validate(); @@ -461,6 +471,32 @@ public class AnnotationLabels extends Panel implements ActionListener, item = new MenuItem(HIDE); item.addActionListener(this); popup.add(item); + + /* + * Hide all