Merge remote-tracking branch 'origin/task/JAL-2662' into develop
authorkiramt <k.mourao@dundee.ac.uk>
Thu, 11 Jan 2018 17:28:29 +0000 (17:28 +0000)
committerkiramt <k.mourao@dundee.ac.uk>
Thu, 11 Jan 2018 17:28:29 +0000 (17:28 +0000)
Conflicts:
benchmarking/README

634 files changed:
.ant-targets-build.xml [new file with mode: 0644]
.checkstyle
.classpath
README
RELEASE
benchmarking/.gitignore
benchmarking/README
benchmarking/src/main/java/org/jalview/HiddenColumnsBenchmark.java
build.xml
examples/example.json
examples/groovy/PIDmatrix.groovy [new file with mode: 0644]
help/help.jhm
help/helpTOC.xml
help/html/calculations/pairwise.html
help/html/calculations/sorting.html
help/html/features/overview.gif [deleted file]
help/html/features/overview.html
help/html/features/overview.png [new file with mode: 0644]
help/html/features/pdbseqfetcher.png
help/html/features/pdbsequencefetcher.html
help/html/features/preferences.html
help/html/features/splitView.html
help/html/features/uniprotseqfetcher.png
help/html/features/uniprotsequencefetcher.html
help/html/features/viewingpdbs.html
help/html/releases.html
help/html/whatsNew.html
lib/groovy-all-2.4.12-indy.jar [moved from lib/groovy-all-2.4.6-indy.jar with 62% similarity]
lib/jabaws-min-client-2.2.0.jar
resources/lang/Messages.properties
resources/lang/Messages_es.properties
resources/uniprot_mapping.xml
src/MCview/AppletPDBCanvas.java
src/MCview/AppletPDBViewer.java
src/MCview/PDBCanvas.java
src/MCview/PDBChain.java
src/MCview/PDBfile.java
src/ext/edu/ucsf/rbvi/strucviz2/ChimeraResidue.java
src/jalview/analysis/AAFrequency.java
src/jalview/analysis/AlignSeq.java
src/jalview/analysis/AlignmentAnnotationUtils.java
src/jalview/analysis/AlignmentSorter.java
src/jalview/analysis/AlignmentUtils.java
src/jalview/analysis/AnnotationSorter.java
src/jalview/analysis/AverageDistanceTree.java
src/jalview/analysis/Conservation.java
src/jalview/analysis/CrossRef.java
src/jalview/analysis/Dna.java
src/jalview/analysis/Finder.java
src/jalview/analysis/Grouping.java
src/jalview/analysis/NJTree.java
src/jalview/analysis/PCA.java
src/jalview/analysis/ParseProperties.java
src/jalview/analysis/Rna.java
src/jalview/analysis/SecStrConsensus.java
src/jalview/analysis/SeqsetUtils.java
src/jalview/analysis/SequenceIdMatcher.java
src/jalview/analysis/StructureFrequency.java
src/jalview/analysis/TreeBuilder.java
src/jalview/analysis/TreeModel.java
src/jalview/analysis/scoremodels/DistanceScoreModel.java
src/jalview/analysis/scoremodels/FeatureDistanceModel.java
src/jalview/analysis/scoremodels/PIDModel.java
src/jalview/analysis/scoremodels/ScoreMatrix.java
src/jalview/analysis/scoremodels/ScoreModels.java
src/jalview/analysis/scoremodels/SimilarityParams.java
src/jalview/analysis/scoremodels/SimilarityScoreModel.java
src/jalview/analysis/scoremodels/SmithWatermanModel.java
src/jalview/api/AlignViewportI.java
src/jalview/api/AlignmentColsCollectionI.java
src/jalview/api/AlignmentRowsCollectionI.java
src/jalview/api/AlignmentViewPanel.java
src/jalview/api/DBRefEntryI.java
src/jalview/api/FeatureColourI.java
src/jalview/api/FeatureRenderer.java
src/jalview/api/FeaturesDisplayedI.java
src/jalview/api/RendererListenerI.java [moved from src/jalview/io/ClansFile.java with 87% similarity]
src/jalview/api/analysis/PairwiseScoreModelI.java
src/jalview/api/analysis/ScoreModelI.java
src/jalview/api/analysis/SimilarityParamsI.java
src/jalview/appletgui/APopupMenu.java
src/jalview/appletgui/AlignFrame.java
src/jalview/appletgui/AlignViewport.java
src/jalview/appletgui/AlignmentPanel.java
src/jalview/appletgui/AnnotationColourChooser.java
src/jalview/appletgui/AnnotationColumnChooser.java
src/jalview/appletgui/AnnotationLabels.java
src/jalview/appletgui/AnnotationPanel.java
src/jalview/appletgui/AnnotationRowFilter.java
src/jalview/appletgui/AppletJmol.java
src/jalview/appletgui/AppletJmolBinding.java
src/jalview/appletgui/CutAndPasteTransfer.java
src/jalview/appletgui/EmbmenuFrame.java
src/jalview/appletgui/ExtJmol.java
src/jalview/appletgui/FeatureColourChooser.java
src/jalview/appletgui/FeatureRenderer.java
src/jalview/appletgui/FeatureSettings.java
src/jalview/appletgui/Finder.java
src/jalview/appletgui/FontChooser.java
src/jalview/appletgui/IdCanvas.java
src/jalview/appletgui/IdPanel.java
src/jalview/appletgui/IdwidthAdjuster.java
src/jalview/appletgui/JVDialog.java
src/jalview/appletgui/OverviewCanvas.java
src/jalview/appletgui/OverviewPanel.java
src/jalview/appletgui/PCAPanel.java
src/jalview/appletgui/PaintRefresher.java
src/jalview/appletgui/PairwiseAlignPanel.java
src/jalview/appletgui/RedundancyPanel.java
src/jalview/appletgui/RotatableCanvas.java
src/jalview/appletgui/ScalePanel.java
src/jalview/appletgui/SeqCanvas.java
src/jalview/appletgui/SeqPanel.java
src/jalview/appletgui/SequenceRenderer.java
src/jalview/appletgui/SliderPanel.java
src/jalview/appletgui/SplitFrame.java
src/jalview/appletgui/Tooltip.java
src/jalview/appletgui/TreeCanvas.java
src/jalview/appletgui/TreePanel.java
src/jalview/appletgui/UserDefinedColours.java
src/jalview/bin/Cache.java
src/jalview/bin/Jalview.java
src/jalview/bin/JalviewLite.java
src/jalview/bin/JalviewLiteURLRetrieve.java
src/jalview/binding/Alignment.java
src/jalview/binding/Annotation.java
src/jalview/binding/AnnotationElement.java
src/jalview/binding/Colour.java
src/jalview/binding/Feature.java
src/jalview/binding/FeatureSettings.java
src/jalview/binding/Features.java
src/jalview/binding/JGroup.java
src/jalview/binding/JSeq.java
src/jalview/binding/JalviewModel.java
src/jalview/binding/JalviewModelSequence.java
src/jalview/binding/JalviewUserColours.java
src/jalview/binding/Pdbentry.java
src/jalview/binding/PdbentryItem.java
src/jalview/binding/Pdbids.java
src/jalview/binding/Property.java
src/jalview/binding/Sequence.java
src/jalview/binding/SequenceSet.java
src/jalview/binding/SequenceType.java
src/jalview/binding/Setting.java
src/jalview/binding/Tree.java
src/jalview/binding/UserColourScheme.java
src/jalview/binding/UserColours.java
src/jalview/binding/VAMSAS.java
src/jalview/binding/VamsasModel.java
src/jalview/binding/Viewport.java
src/jalview/commands/EditCommand.java
src/jalview/commands/RemoveGapColCommand.java
src/jalview/commands/RemoveGapsCommand.java
src/jalview/controller/AlignViewController.java
src/jalview/datamodel/AlignedCodonFrame.java
src/jalview/datamodel/Alignment.java
src/jalview/datamodel/AlignmentAnnotation.java
src/jalview/datamodel/AlignmentI.java
src/jalview/datamodel/AlignmentOrder.java
src/jalview/datamodel/AlignmentView.java
src/jalview/datamodel/AllColsCollection.java
src/jalview/datamodel/AllColsIterator.java
src/jalview/datamodel/AllRowsCollection.java
src/jalview/datamodel/AllRowsIterator.java
src/jalview/datamodel/Annotation.java
src/jalview/datamodel/BinaryNode.java
src/jalview/datamodel/BinarySequence.java
src/jalview/datamodel/CigarArray.java
src/jalview/datamodel/CigarBase.java
src/jalview/datamodel/CigarCigar.java
src/jalview/datamodel/ColumnSelection.java
src/jalview/datamodel/ContiguousI.java [new file with mode: 0644]
src/jalview/datamodel/DBRefEntry.java
src/jalview/datamodel/FeatureProperties.java
src/jalview/datamodel/GraphLine.java
src/jalview/datamodel/HiddenColumns.java
src/jalview/datamodel/HiddenSequences.java
src/jalview/datamodel/Mapping.java
src/jalview/datamodel/PDBEntry.java
src/jalview/datamodel/Profile.java
src/jalview/datamodel/Profiles.java
src/jalview/datamodel/Range.java [new file with mode: 0644]
src/jalview/datamodel/ResidueCount.java
src/jalview/datamodel/SearchResults.java
src/jalview/datamodel/SearchResultsI.java
src/jalview/datamodel/SeqCigar.java
src/jalview/datamodel/Sequence.java
src/jalview/datamodel/SequenceCursor.java [new file with mode: 0644]
src/jalview/datamodel/SequenceFeature.java
src/jalview/datamodel/SequenceGroup.java
src/jalview/datamodel/SequenceI.java
src/jalview/datamodel/VisibleColsCollection.java
src/jalview/datamodel/VisibleColsIterator.java
src/jalview/datamodel/VisibleRowsCollection.java
src/jalview/datamodel/VisibleRowsIterator.java
src/jalview/datamodel/features/FeatureLocationI.java [moved from src/jalview/io/MatrixFile.java with 66% similarity]
src/jalview/datamodel/features/FeatureStore.java [new file with mode: 0644]
src/jalview/datamodel/features/NCList.java [new file with mode: 0644]
src/jalview/datamodel/features/NCNode.java [new file with mode: 0644]
src/jalview/datamodel/features/RangeComparator.java [new file with mode: 0644]
src/jalview/datamodel/features/SequenceFeatures.java [new file with mode: 0644]
src/jalview/datamodel/features/SequenceFeaturesI.java [new file with mode: 0644]
src/jalview/datamodel/xdb/embl/EmblEntry.java
src/jalview/datamodel/xdb/embl/EmblFile.java
src/jalview/datamodel/xdb/uniprot/UniprotEntry.java [moved from src/jalview/datamodel/UniprotEntry.java with 90% similarity]
src/jalview/datamodel/xdb/uniprot/UniprotFeature.java [new file with mode: 0644]
src/jalview/datamodel/xdb/uniprot/UniprotFile.java [moved from src/jalview/datamodel/UniprotFile.java with 96% similarity]
src/jalview/datamodel/xdb/uniprot/UniprotProteinName.java [moved from src/jalview/datamodel/UniprotProteinName.java with 97% similarity]
src/jalview/datamodel/xdb/uniprot/UniprotSequence.java [moved from src/jalview/datamodel/UniprotSequence.java with 97% similarity]
src/jalview/ext/ensembl/EnsemblCdna.java
src/jalview/ext/ensembl/EnsemblGene.java
src/jalview/ext/ensembl/EnsemblGenomes.java
src/jalview/ext/ensembl/EnsemblInfo.java
src/jalview/ext/ensembl/EnsemblLookup.java
src/jalview/ext/ensembl/EnsemblProtein.java
src/jalview/ext/ensembl/EnsemblRestClient.java
src/jalview/ext/ensembl/EnsemblSeqProxy.java
src/jalview/ext/ensembl/EnsemblSequenceFetcher.java
src/jalview/ext/ensembl/EnsemblSymbol.java
src/jalview/ext/ensembl/EnsemblXref.java
src/jalview/ext/ensembl/Species.java
src/jalview/ext/htsjdk/HtsContigDb.java
src/jalview/ext/jmol/JalviewJmolBinding.java
src/jalview/ext/jmol/JmolCommands.java
src/jalview/ext/jmol/JmolParser.java
src/jalview/ext/paradise/Annotate3D.java
src/jalview/ext/rbvi/chimera/AtomSpecModel.java
src/jalview/ext/rbvi/chimera/ChimeraCommands.java
src/jalview/ext/rbvi/chimera/ChimeraListener.java
src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java
src/jalview/ext/so/SequenceOntology.java
src/jalview/ext/varna/JalviewVarnaBinding.java
src/jalview/ext/varna/VarnaCommands.java
src/jalview/fts/api/GFTSPanelI.java
src/jalview/fts/core/DecimalFormatTableCellRenderer.java
src/jalview/fts/core/FTSDataColumnPreferences.java
src/jalview/fts/core/FTSRestClient.java
src/jalview/fts/core/FTSRestRequest.java
src/jalview/fts/core/FTSRestResponse.java
src/jalview/fts/core/GFTSPanel.java
src/jalview/fts/service/pdb/PDBFTSPanel.java
src/jalview/fts/service/pdb/PDBFTSRestClient.java
src/jalview/fts/service/uniprot/UniProtFTSRestClient.java
src/jalview/fts/service/uniprot/UniprotFTSPanel.java
src/jalview/gui/AlignExportSettings.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AlignViewport.java
src/jalview/gui/AlignmentPanel.java
src/jalview/gui/AnnotationChooser.java
src/jalview/gui/AnnotationColourChooser.java
src/jalview/gui/AnnotationColumnChooser.java
src/jalview/gui/AnnotationExporter.java
src/jalview/gui/AnnotationLabels.java
src/jalview/gui/AnnotationPanel.java
src/jalview/gui/AnnotationRowFilter.java
src/jalview/gui/AppJmol.java
src/jalview/gui/AppJmolBinding.java
src/jalview/gui/AppVarna.java
src/jalview/gui/AppVarnaBinding.java
src/jalview/gui/AquaInternalFrameManager.java [new file with mode: 0644]
src/jalview/gui/AssociatePdbFileWithSeq.java
src/jalview/gui/BlogReader.java
src/jalview/gui/CalculationChooser.java
src/jalview/gui/ChimeraViewFrame.java
src/jalview/gui/ColourMenuHelper.java
src/jalview/gui/ComboBoxTooltipRenderer.java
src/jalview/gui/Console.java
src/jalview/gui/CrossRefAction.java
src/jalview/gui/CutAndPasteHtmlTransfer.java
src/jalview/gui/CutAndPasteTransfer.java
src/jalview/gui/DasSourceBrowser.java
src/jalview/gui/Desktop.java
src/jalview/gui/EPSOptions.java
src/jalview/gui/FeatureColourChooser.java
src/jalview/gui/FeatureRenderer.java
src/jalview/gui/FeatureSettings.java
src/jalview/gui/Finder.java
src/jalview/gui/FontChooser.java
src/jalview/gui/HTMLOptions.java
src/jalview/gui/IProgressIndicator.java
src/jalview/gui/IdCanvas.java
src/jalview/gui/IdPanel.java
src/jalview/gui/IdwidthAdjuster.java
src/jalview/gui/JDatabaseTree.java
src/jalview/gui/Jalview2XML.java
src/jalview/gui/Jalview2XML_V1.java
src/jalview/gui/JalviewChimeraBindingModel.java
src/jalview/gui/JvOptionPane.java
src/jalview/gui/JvSwingUtils.java
src/jalview/gui/OOMWarning.java
src/jalview/gui/OptsAndParamsPage.java
src/jalview/gui/OverviewCanvas.java
src/jalview/gui/OverviewPanel.java
src/jalview/gui/PCAPanel.java
src/jalview/gui/PaintRefresher.java
src/jalview/gui/PairwiseAlignPanel.java
src/jalview/gui/PopupMenu.java
src/jalview/gui/Preferences.java
src/jalview/gui/ProgressBar.java
src/jalview/gui/ProgressPanel.java [new file with mode: 0644]
src/jalview/gui/PromptUserConfig.java
src/jalview/gui/RedundancyPanel.java
src/jalview/gui/RestInputParamEditDialog.java
src/jalview/gui/RestServiceEditorPane.java
src/jalview/gui/RotatableCanvas.java
src/jalview/gui/SVGOptions.java
src/jalview/gui/ScalePanel.java
src/jalview/gui/SeqCanvas.java
src/jalview/gui/SeqPanel.java
src/jalview/gui/SequenceFetcher.java
src/jalview/gui/SequenceRenderer.java
src/jalview/gui/SliderPanel.java
src/jalview/gui/SplashScreen.java
src/jalview/gui/SplitFrame.java
src/jalview/gui/StructureChooser.java
src/jalview/gui/StructureViewer.java
src/jalview/gui/StructureViewerBase.java
src/jalview/gui/TextColourChooser.java
src/jalview/gui/TreeCanvas.java
src/jalview/gui/TreePanel.java
src/jalview/gui/UserDefinedColours.java
src/jalview/gui/UserQuestionnaireCheck.java
src/jalview/gui/VamsasApplication.java
src/jalview/gui/ViewSelectionMenu.java
src/jalview/gui/WebserviceInfo.java
src/jalview/gui/WsJobParameters.java
src/jalview/gui/WsParamSetManager.java
src/jalview/gui/WsPreferences.java
src/jalview/httpserver/AbstractRequestHandler.java
src/jalview/httpserver/HttpServer.java
src/jalview/io/AlignFile.java
src/jalview/io/AlignmentFileReaderI.java
src/jalview/io/AlignmentFileWriterI.java
src/jalview/io/AnnotationFile.java
src/jalview/io/AppletFormatAdapter.java
src/jalview/io/BLCFile.java
src/jalview/io/BioJsHTMLOutput.java
src/jalview/io/ClustalFile.java
src/jalview/io/DataSourceType.java
src/jalview/io/FastaFile.java
src/jalview/io/FeaturesFile.java
src/jalview/io/FileFormat.java
src/jalview/io/FileFormatException.java
src/jalview/io/FileFormatI.java
src/jalview/io/FileFormats.java
src/jalview/io/FileLoader.java
src/jalview/io/FileParse.java
src/jalview/io/FormatAdapter.java
src/jalview/io/HTMLOutput.java [changed mode: 0755->0644]
src/jalview/io/HtmlSvgOutput.java
src/jalview/io/IdentifyFile.java
src/jalview/io/InputStreamParser.java
src/jalview/io/JPredFile.java
src/jalview/io/JSONFile.java
src/jalview/io/JalviewFileChooser.java
src/jalview/io/JalviewFileView.java
src/jalview/io/JnetAnnotationMaker.java
src/jalview/io/MSFfile.java
src/jalview/io/ModellerDescription.java
src/jalview/io/NewickFile.java
src/jalview/io/PfamFile.java
src/jalview/io/PhylipFile.java
src/jalview/io/PileUpfile.java
src/jalview/io/RnamlFile.java
src/jalview/io/ScoreMatrixFile.java
src/jalview/io/SequenceAnnotationReport.java
src/jalview/io/SimpleBlastFile.java
src/jalview/io/StockholmFile.java
src/jalview/io/StructureFile.java
src/jalview/io/TCoffeeScoreFile.java
src/jalview/io/VamsasAppDatastore.java
src/jalview/io/WSWUBlastClient.java
src/jalview/io/cache/AppCache.java
src/jalview/io/cache/JvCacheableInputBox.java
src/jalview/io/gff/ExonerateHelper.java
src/jalview/io/gff/Gff3Helper.java
src/jalview/io/gff/GffHelperBase.java
src/jalview/io/gff/InterProScanHelper.java
src/jalview/io/packed/ParsePackedSet.java
src/jalview/io/vamsas/Datasetsequence.java
src/jalview/io/vamsas/DatastoreItem.java
src/jalview/io/vamsas/Dbref.java
src/jalview/io/vamsas/Rangetype.java
src/jalview/io/vamsas/Sequencefeature.java
src/jalview/io/vamsas/Sequencemapping.java
src/jalview/io/vamsas/Tree.java
src/jalview/javascript/JSFunctionExec.java
src/jalview/javascript/JalviewLiteJsApi.java
src/jalview/javascript/JsSelectionSender.java
src/jalview/javascript/MouseOverListener.java
src/jalview/javascript/MouseOverStructureListener.java
src/jalview/jbgui/GAlignExportSettings.java
src/jalview/jbgui/GAlignFrame.java
src/jalview/jbgui/GCutAndPasteHtmlTransfer.java
src/jalview/jbgui/GCutAndPasteTransfer.java
src/jalview/jbgui/GDasSourceBrowser.java
src/jalview/jbgui/GDesktop.java
src/jalview/jbgui/GFinder.java
src/jalview/jbgui/GPCAPanel.java
src/jalview/jbgui/GPairwiseAlignPanel.java
src/jalview/jbgui/GPreferences.java
src/jalview/jbgui/GRestInputParamEditDialog.java
src/jalview/jbgui/GRestServiceEditorPane.java
src/jalview/jbgui/GSequenceLink.java
src/jalview/jbgui/GSliderPanel.java
src/jalview/jbgui/GSplitFrame.java
src/jalview/jbgui/GStructureChooser.java
src/jalview/jbgui/GStructureViewer.java
src/jalview/jbgui/GTreePanel.java
src/jalview/jbgui/GUserDefinedColours.java
src/jalview/jbgui/GWebserviceInfo.java
src/jalview/jbgui/GWsPreferences.java
src/jalview/json/binding/biojs/BioJSRepositoryPojo.java
src/jalview/json/binding/biojson/v1/AlignmentAnnotationPojo.java
src/jalview/json/binding/biojson/v1/AlignmentPojo.java
src/jalview/json/binding/biojson/v1/AnnotationPojo.java
src/jalview/json/binding/biojson/v1/SequencePojo.java
src/jalview/math/Matrix.java
src/jalview/math/MatrixI.java
src/jalview/math/RotatableMatrix.java
src/jalview/math/SparseMatrix.java
src/jalview/renderer/AnnotationRenderer.java
src/jalview/renderer/OverviewRenderer.java
src/jalview/renderer/OverviewResColourFinder.java [new file with mode: 0644]
src/jalview/renderer/ResidueColourFinder.java [new file with mode: 0644]
src/jalview/renderer/ResidueShader.java
src/jalview/renderer/ResidueShaderI.java
src/jalview/renderer/ScaleRenderer.java
src/jalview/renderer/seqfeatures/FeatureColourFinder.java
src/jalview/renderer/seqfeatures/FeatureRenderer.java
src/jalview/schemes/AnnotationColourGradient.java
src/jalview/schemes/Blosum62ColourScheme.java
src/jalview/schemes/ClustalxColourScheme.java
src/jalview/schemes/ColourSchemeI.java
src/jalview/schemes/ColourSchemeLoader.java
src/jalview/schemes/ColourSchemeProperty.java
src/jalview/schemes/ColourSchemes.java
src/jalview/schemes/CovariationColourScheme.java
src/jalview/schemes/FeatureColour.java
src/jalview/schemes/JalviewColourScheme.java
src/jalview/schemes/PIDColourScheme.java
src/jalview/schemes/RNAHelicesColour.java
src/jalview/schemes/RNAHelicesColourChooser.java
src/jalview/schemes/ResidueColourScheme.java
src/jalview/schemes/ResidueProperties.java
src/jalview/schemes/TCoffeeColourScheme.java
src/jalview/schemes/UserColourScheme.java
src/jalview/structure/SecondaryStructureListener.java
src/jalview/structure/SelectionListener.java
src/jalview/structure/StructureSelectionManager.java
src/jalview/structures/models/AAStructureBindingModel.java
src/jalview/structures/models/SequenceStructureBindingModel.java
src/jalview/urls/CustomUrlProvider.java
src/jalview/urls/IdentifiersUrlProvider.java
src/jalview/urls/UrlLinkDisplay.java
src/jalview/urls/UrlLinkTableModel.java
src/jalview/urls/UrlProvider.java
src/jalview/urls/UrlProviderImpl.java
src/jalview/urls/api/UrlProviderFactoryI.java
src/jalview/util/AWTConsole.java
src/jalview/util/BrowserLauncher.java
src/jalview/util/CaseInsensitiveString.java
src/jalview/util/ColorUtils.java
src/jalview/util/Comparison.java
src/jalview/util/DBRefUtils.java
src/jalview/util/Format.java
src/jalview/util/GroupUrlLink.java
src/jalview/util/ImageMaker.java
src/jalview/util/IntRangeComparator.java [new file with mode: 0644]
src/jalview/util/MapList.java
src/jalview/util/MappingUtils.java
src/jalview/util/MessageManager.java
src/jalview/util/ParseHtmlBodyAndLinks.java
src/jalview/util/Platform.java
src/jalview/util/QuickSort.java
src/jalview/util/RangeComparator.java [deleted file]
src/jalview/util/SetUtils.java
src/jalview/util/SparseCount.java
src/jalview/util/StringUtils.java
src/jalview/util/TableSorter.java
src/jalview/util/UrlConstants.java
src/jalview/util/UrlLink.java
src/jalview/viewmodel/AlignmentViewport.java
src/jalview/viewmodel/OverviewDimensions.java
src/jalview/viewmodel/OverviewDimensionsHideHidden.java
src/jalview/viewmodel/OverviewDimensionsShowHidden.java
src/jalview/viewmodel/PCAModel.java
src/jalview/viewmodel/ViewportListenerI.java
src/jalview/viewmodel/ViewportRanges.java
src/jalview/viewmodel/annotationfilter/AnnotationFilterParameter.java
src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java
src/jalview/viewmodel/seqfeatures/FeaturesDisplayed.java
src/jalview/viewmodel/styles/ViewStyle.java
src/jalview/workers/AlignCalcManager.java
src/jalview/workers/AlignmentAnnotationFactory.java
src/jalview/workers/AnnotationWorker.java
src/jalview/workers/ColumnCounterSetWorker.java
src/jalview/workers/ConsensusThread.java
src/jalview/workers/ConservationThread.java
src/jalview/workers/StrucConsensusThread.java
src/jalview/ws/AWSThread.java
src/jalview/ws/DBRefFetcher.java
src/jalview/ws/DasSequenceFeatureFetcher.java
src/jalview/ws/HttpClientUtils.java
src/jalview/ws/JobStateSummary.java
src/jalview/ws/SequenceFetcher.java
src/jalview/ws/dbsources/EmblXmlSource.java
src/jalview/ws/dbsources/Pdb.java
src/jalview/ws/dbsources/PfamFull.java
src/jalview/ws/dbsources/PfamSeed.java
src/jalview/ws/dbsources/RfamFull.java
src/jalview/ws/dbsources/Uniprot.java
src/jalview/ws/dbsources/Xfam.java
src/jalview/ws/dbsources/das/datamodel/DasSequenceSource.java
src/jalview/ws/dbsources/das/datamodel/DasSourceRegistry.java
src/jalview/ws/dbsources/das/datamodel/JalviewSource.java
src/jalview/ws/ebi/EBIFetchClient.java
src/jalview/ws/jws1/Annotate3D.java
src/jalview/ws/jws1/Discoverer.java
src/jalview/ws/jws1/JPredClient.java
src/jalview/ws/jws1/JPredThread.java
src/jalview/ws/jws1/MsaWSClient.java
src/jalview/ws/jws1/MsaWSThread.java
src/jalview/ws/jws1/SeqSearchWSClient.java
src/jalview/ws/jws1/SeqSearchWSThread.java
src/jalview/ws/jws1/WS1Client.java
src/jalview/ws/jws2/AADisorderClient.java
src/jalview/ws/jws2/AbstractJabaCalcWorker.java
src/jalview/ws/jws2/JWs2Job.java
src/jalview/ws/jws2/JabaParamStore.java
src/jalview/ws/jws2/JabaPreset.java
src/jalview/ws/jws2/JabaWsServerQuery.java
src/jalview/ws/jws2/JabawsCalcWorker.java
src/jalview/ws/jws2/JabawsMsaInterfaceAlignCalcWorker.java
src/jalview/ws/jws2/Jws2Client.java
src/jalview/ws/jws2/Jws2Discoverer.java
src/jalview/ws/jws2/MsaWSClient.java
src/jalview/ws/jws2/MsaWSThread.java
src/jalview/ws/jws2/ParameterUtils.java
src/jalview/ws/jws2/RNAalifoldClient.java
src/jalview/ws/jws2/SequenceAnnotationWSClient.java
src/jalview/ws/jws2/dm/AAConSettings.java
src/jalview/ws/jws2/dm/JabaOption.java
src/jalview/ws/jws2/dm/JabaValueConstrain.java
src/jalview/ws/jws2/dm/JabaWsParamSet.java
src/jalview/ws/jws2/jabaws2/Jws2Instance.java
src/jalview/ws/jws2/jabaws2/Jws2InstanceFactory.java
src/jalview/ws/params/ParamManager.java
src/jalview/ws/params/simple/BooleanOption.java
src/jalview/ws/params/simple/IntegerParameter.java
src/jalview/ws/params/simple/Parameter.java
src/jalview/ws/rest/HttpResultSet.java
src/jalview/ws/rest/InputType.java
src/jalview/ws/rest/RestClient.java
src/jalview/ws/rest/RestJob.java
src/jalview/ws/rest/RestJobThread.java
src/jalview/ws/rest/RestServiceDescription.java
src/jalview/ws/rest/params/Alignment.java
src/jalview/ws/rest/params/AnnotationFile.java
src/jalview/ws/rest/params/JobConstant.java
src/jalview/ws/rest/params/SeqGroupIndexVector.java
src/jalview/ws/rest/params/SeqIdVector.java
src/jalview/ws/rest/params/SeqVector.java
src/jalview/ws/rest/params/Tree.java
src/jalview/ws/seqfetcher/ASequenceFetcher.java
src/jalview/ws/seqfetcher/DbSourceProxyImpl.java
src/jalview/ws/sifts/MappingOutputPojo.java
src/jalview/ws/sifts/SiftsClient.java
src/jalview/ws/utils/UrlDownloadClient.java
test/MCview/PDBChainTest.java
test/jalview/analysis/AlignmentGenerator.java
test/jalview/analysis/AlignmentSorterTest.java
test/jalview/analysis/AlignmentUtilsTests.java
test/jalview/analysis/RnaTest.java
test/jalview/analysis/SeqsetUtilsTest.java
test/jalview/analysis/TestAlignSeq.java
test/jalview/analysis/scoremodels/FeatureDistanceModelTest.java
test/jalview/commands/EditCommandTest.java
test/jalview/datamodel/AlignmentTest.java
test/jalview/datamodel/CigarArrayTest.java [new file with mode: 0644]
test/jalview/datamodel/SeqCigarTest.java
test/jalview/datamodel/SequenceFeatureTest.java
test/jalview/datamodel/SequenceTest.java
test/jalview/datamodel/features/FeatureStoreTest.java [new file with mode: 0644]
test/jalview/datamodel/features/NCListTest.java [new file with mode: 0644]
test/jalview/datamodel/features/NCNodeTest.java [new file with mode: 0644]
test/jalview/datamodel/features/RangeComparatorTest.java [new file with mode: 0644]
test/jalview/datamodel/features/SequenceFeaturesTest.java [new file with mode: 0644]
test/jalview/ext/ensembl/EnsemblCdnaTest.java
test/jalview/ext/ensembl/EnsemblCdsTest.java
test/jalview/ext/ensembl/EnsemblGeneTest.java
test/jalview/ext/ensembl/EnsemblGenomeTest.java
test/jalview/ext/ensembl/EnsemblRestClientTest.java
test/jalview/ext/ensembl/EnsemblSeqProxyTest.java
test/jalview/ext/ensembl/SpeciesTest.java [new file with mode: 0644]
test/jalview/ext/jmol/JmolParserTest.java
test/jalview/ext/paradise/TestAnnotate3D.java
test/jalview/ext/rbvi/chimera/AtomSpecModelTest.java
test/jalview/ext/rbvi/chimera/JalviewChimeraView.java
test/jalview/gui/AlignViewportTest.java
test/jalview/gui/AlignmentPanelTest.java
test/jalview/gui/AnnotationColumnChooserTest.java [new file with mode: 0644]
test/jalview/gui/FreeUpMemoryTest.java [new file with mode: 0644]
test/jalview/gui/PairwiseAlignmentPanelTest.java [new file with mode: 0644]
test/jalview/gui/ProgressBarTest.java
test/jalview/gui/SeqCanvasTest.java [new file with mode: 0644]
test/jalview/gui/SequenceRendererTest.java
test/jalview/gui/StructureViewerTest.java
test/jalview/io/AnnotatedPDBFileInputTest.java
test/jalview/io/CrossRef2xmlTests.java
test/jalview/io/FeaturesFileTest.java
test/jalview/io/JSONFileTest.java
test/jalview/io/SequenceAnnotationReportTest.java
test/jalview/io/StockholmFileTest.java
test/jalview/io/gff/Gff3HelperTest.java
test/jalview/io/gff/InterProScanHelperTest.java
test/jalview/renderer/OverviewResColourFinderTest.java [new file with mode: 0644]
test/jalview/renderer/ResidueColourFinderTest.java [new file with mode: 0644]
test/jalview/renderer/ResidueShaderTest.java
test/jalview/renderer/ScaleRendererTest.java
test/jalview/renderer/seqfeatures/FeatureColourFinderTest.java
test/jalview/renderer/seqfeatures/FeatureRendererTest.java [new file with mode: 0644]
test/jalview/schemes/AnnotationColourGradientTest.java
test/jalview/schemes/FeatureColourTest.java
test/jalview/structure/StructureSelectionManagerTest.java
test/jalview/structures/models/AAStructureBindingModelTest.java
test/jalview/util/MappingUtilsTest.java
test/jalview/viewmodel/ViewportRangesTest.java
test/jalview/ws/dbsources/UniprotTest.java
test/jalview/ws/ebi/EBIFetchClientTest.java
test/jalview/ws/seqfetcher/DbRefFetcherTest.java
utils/InstallAnywhere/Jalview.iap_xml
utils/checkstyle/checkstyle-suppress.xml
utils/checkstyle/import-control.xml

diff --git a/.ant-targets-build.xml b/.ant-targets-build.xml
new file mode 100644 (file)
index 0000000..15432a1
--- /dev/null
@@ -0,0 +1,31 @@
+build
+buildPropertiesFile
+buildTests
+buildextclients
+buildindices
+castorbinding
+clean
+compileApplet
+distclean
+help
+init
+linkcheck
+makeApplet
+makedist
+makefulldist
+obfuscate
+packageApplet
+prepare
+prepareTests
+preparejnlp
+prepubapplet_1
+pubapplet
+runenv
+signApplet
+sourcedist
+sourcedoc
+sourcescrub
+testclean
+testng
+usage
+writejnlpf
index 0329bb7..a87fa04 100644 (file)
@@ -8,5 +8,4 @@
     <file-match-pattern match-pattern="src/.*.java" include-pattern="true"/>
     <file-match-pattern match-pattern="resources/.*.properties" include-pattern="true"/>
   </fileset>
-  <filter name="NonSrcDirs" enabled="false"/>
 </fileset-config>
index c4a2832..d704f10 100644 (file)
@@ -68,6 +68,6 @@
        <classpathentry kind="con" path="org.testng.TESTNG_CONTAINER"/>
        <classpathentry kind="lib" path="lib/biojava-core-4.1.0.jar"/>
        <classpathentry kind="lib" path="lib/biojava-ontology-4.1.0.jar"/>
-       <classpathentry kind="lib" path="lib/groovy-all-2.4.6-indy.jar"/>
+       <classpathentry kind="lib" path="lib/groovy-all-2.4.12-indy.jar"/>
        <classpathentry kind="output" path="classes"/>
 </classpath>
diff --git a/README b/README
index cbc93b1..eaf226b 100755 (executable)
--- a/README
+++ b/README
@@ -25,7 +25,10 @@ To run application:
 
 java -Djava.ext.dirs=JALVIEW_HOME/lib -cp JALVIEW_HOME/jalview.jar jalview.bin.Jalview
 
-Replace JALVIEW_HOME with the full path to Jalview Installation Directory.
+Replace JALVIEW_HOME with the full path to Jalview Installation Directory. If building from source:
+
+java -Djava.ext.dirs=JALVIEW_BUILD/dist -cp JALVIEW_BUILD/dist/jalview.jar jalview.bin.Jalview
+
 
 ##################
 
diff --git a/RELEASE b/RELEASE
index 6dffc29..f1faf34 100644 (file)
--- a/RELEASE
+++ b/RELEASE
@@ -1,2 +1,2 @@
-jalview.release=releases/Release_2_10_2_Branch
-jalview.version=2.10.2
+jalview.release=releases/Release_2_10_3_Branch
+jalview.version=2.10.3
index b83d222..f4da43d 100644 (file)
@@ -1 +1,6 @@
 /target/
+/bin
+/results
+*.log
+*.json
+*~
index 4011e5a..ccf53c1 100644 (file)
@@ -1,29 +1,33 @@
 To set up benchmarking:
 
+You will need to install Maven: https://maven.apache.org/install.html
 
-1. In the jalview directory run 
+1. Run the makedist target of build.xml in Eclipse, or in the jalview directory run 
   ant makedist
 
 This builds a jalview.jar file and puts it into dist/
 
 
-2. Make a lib directory in benchmarking/ if not already present.
+2. Make a lib directory in benchmarking/ if not already present and cd into this directory.
 
 
-3. In the benchmarking directory run:
-       mvn install:install-file -Dfile=../dist/jalview.jar -DgroupId=jalview.org -DartifactId=jalview -Dversion=1.0 -Dpackaging=jar -DlocalRepositoryPath=lib
+3. Purge any previous maven dependencies:
+   mvn dependency:purge-local-repository -DactTransitively=false -DreResolve=false
 
+
+4. Run
+  mvn install:install-file -Dfile=../dist/jalview.jar -DgroupId=jalview.org -DartifactId=jalview -Dversion=1.0 -Dpackaging=jar -DlocalRepositoryPath=lib
 to install the jalview.jar file in the local maven repository. The pom.xml in the benchmarking references this installation, so if you change the names the pom.xml file will also need to be updated.
 
 
-4. Build and run jmh benchmarking. In the benchmarking directory:
-       mvn clean install
-       java -jar target/benchmarks.jar
+5. Build and run jmh benchmarking. In the benchmarking directory:
+  mvn clean install
+  java -jar target/benchmarks.jar
   
-  To get output as a json file use instead:
-       java -jar target/benchmarks.jar -rf json
+  To get JSON output instead use:
+  java -jar target/benchmarks.jar -rf json
   
-  JSON files can be visualised using the viewer at http://jmh.morethan.io/
+  JSON output can be viewed quickly by drag-dropping on http://jmh.morethan.io/
   
   To get help use the standard -h option:
        java -jar target/benchmarks.jar -h
@@ -33,8 +37,4 @@ to install the jalview.jar file in the local maven repository. The pom.xml in th
        http://java-performance.info/jmh/
   
   
- 5. If you make changes to the jalview code everything will need to be refreshed, by calling:
-       mvn dependency:purge-local-repository -DactTransitively=false -DreResolve=false
-  
-  followed by steps 3 and 4 again.
-  
\ No newline at end of file
+ 6. If you make changes to the Jalview code everything will need to be refreshed, by performing steps 3-5 again.
index 2518494..d3c67d7 100644 (file)
 package org.jalview;
 
 import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
 import org.openjdk.jmh.annotations.Setup;
 import org.openjdk.jmh.annotations.State;
-import org.openjdk.jmh.annotations.TearDown;
+import org.openjdk.jmh.annotations.Warmup;
 import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Param;
+
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Random;
+import java.util.concurrent.TimeUnit;
 
+import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.HiddenColumns;
 
 /*
  * A class to benchmark hidden columns performance
  */
+@Warmup(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@Fork(1)
 public class HiddenColumnsBenchmark 
 {
-       @State(Scope.Thread)
-       public static class ThreadState
-       {
-               HiddenColumns h = new HiddenColumns();
-               int MAXCOLS = 100000;
-               Random rand = new Random();
-       
-               @Setup
-               public void setup()
-               {
-                       rand.setSeed(1234);
-               for (int i=0; i<MAXCOLS; ++i)
-               {
-                       int col = rand.nextInt(MAXCOLS); 
-                       h.hideColumns(col, col+1);
-               }
-               }
-       
-               @TearDown
-               public void tearDown()
-               {
-                       
-               }
-    }
-       
-       /*
-        * isVisible benchmarking
-        */
-    @Benchmark
-    public boolean benchIsVisibleLastCol(ThreadState tstate) 
-    {
-       return tstate.h.isVisible(tstate.MAXCOLS - 3); 
-    }
-    
-    @Benchmark
-    public boolean benchIsVisibleFirstCol(ThreadState tstate)
+  /*
+   * State with multiple hidden columns and a start position set
+   */
+  @State(Scope.Thread)
+  public static class HiddenColsAndStartState
+  {
+    @Param({ "300", "10000", "100000" })
+    public int maxcols;
+
+    @Param({ "1", "50", "90" })
+    public int startpcnt; // position as percentage of maxcols
+
+    @Param({ "1", "15", "100" })
+    public int hide;
+
+    HiddenColumns h = new HiddenColumns();
+
+    Random rand = new Random();
+
+    public int hiddenColumn;
+
+    public int visibleColumn;
+
+    @Setup
+    public void setup()
     {
-       return tstate.h.isVisible(1);
+      rand.setSeed(1234);
+      int lastcol = 0;
+      while (lastcol < maxcols)
+      {
+        int count = rand.nextInt(100);
+        lastcol += count;
+        h.hideColumns(lastcol, lastcol + hide);
+        lastcol += hide;
+      }
+
+      // make sure column at start is hidden
+      hiddenColumn = (int) (maxcols * startpcnt / 100.0);
+      h.hideColumns(hiddenColumn, hiddenColumn);
+
+      // and column <hide> after start is visible
+      ColumnSelection sel = new ColumnSelection();
+      h.revealHiddenColumns(hiddenColumn + hide, sel);
+      visibleColumn = hiddenColumn + hide;
+
+      System.out.println("Maxcols: " + maxcols + " HiddenCol: "
+              + hiddenColumn + " Hide: " + hide);
+      System.out.println("Number of hidden columns: " + h.getSize());
     }
+  }
+
+  /* Convention: functions in alphabetical order */
+
+  @Benchmark
+  @BenchmarkMode({ Mode.Throughput })
+  public int benchAdjustForHiddenColumns(HiddenColsAndStartState tstate)
+  {
+    return tstate.h.adjustForHiddenColumns(tstate.visibleColumn);
+  }
+
+  @Benchmark
+  @BenchmarkMode({ Mode.Throughput })
+  public int benchFindColumnPosition(HiddenColsAndStartState tstate)
+  {
+    return tstate.h.findColumnPosition(tstate.visibleColumn);
+  }
+
+  @Benchmark
+  @BenchmarkMode({ Mode.Throughput })
+  public List<Integer> benchFindHiddenRegionPositions(
+          HiddenColsAndStartState tstate)
+  {
+    return tstate.h.findHiddenRegionPositions();
+  }
+
+  @Benchmark
+  @BenchmarkMode({ Mode.Throughput })
+  public ArrayList<int[]> benchGetHiddenColumnsCopy(
+          HiddenColsAndStartState tstate)
+  {
+    return tstate.h.getHiddenColumnsCopy();
+  }
+
+  @Benchmark
+  @BenchmarkMode({ Mode.Throughput })
+  public int benchGetSize(HiddenColsAndStartState tstate)
+  {
+    return tstate.h.getSize();
+  }
+
+  @Benchmark
+  @BenchmarkMode({ Mode.Throughput })
+  public HiddenColumns benchHideCols(HiddenColsAndStartState tstate)
+  {
+    tstate.h.hideColumns(tstate.visibleColumn, tstate.visibleColumn + 2000);
+    return tstate.h;
+  }
+
+  @Benchmark
+  @BenchmarkMode({ Mode.Throughput })
+  public boolean benchIsVisible(HiddenColsAndStartState tstate)
+  {
+    return tstate.h.isVisible(tstate.hiddenColumn);
+  }
+
+  @Benchmark
+  @BenchmarkMode({ Mode.Throughput })
+  public HiddenColumns benchReveal(HiddenColsAndStartState tstate)
+  {
+    ColumnSelection sel = new ColumnSelection();
+    tstate.h.revealHiddenColumns(tstate.hiddenColumn, sel);
+    return tstate.h;
+  }
+
+  @Benchmark
+  @BenchmarkMode({ Mode.Throughput })
+  public HiddenColumns benchRevealAll(HiddenColsAndStartState tstate)
+  {
+    ColumnSelection sel = new ColumnSelection();
+    tstate.h.revealAllHiddenColumns(sel);
+    return tstate.h;
+  }
 
-}
+}
\ No newline at end of file
index 94f32fd..4931cfb 100755 (executable)
--- a/build.xml
+++ b/build.xml
           <offline_allowed />
         </information>
         <resources>
-          <j2se version="9+" />
-          <j2se version="7,8" initial_heap_size="${inih}" max_heap_size="${maxh}" />
+          <j2se version="1.7+" />
           <jar main="true" href="jalview.jar"/>
           <fileset dir="${packageDir}">
             <exclude name="jalview.jar" />
     </presetdef>
 
     <jnlpf toFile="${jnlpFile}" />
-    <!-- add a j2se entry for java 9 -->
-    <replace file="${jnlpFile}" value="j2se version=&quot;9+&quot; initial-heap-size=&quot;${inih}&quot; max-heap-size=&quot;${maxh}&quot; java-vm-args=&quot;--add-modules=java.se.ee&quot;">
-          <replacetoken>j2se version="9+"</replacetoken>
+    <!-- add the add-modules j2se attribute for java 9 -->
+    <replace file="${jnlpFile}" value="j2se version=&quot;1.7+&quot; initial-heap-size=&quot;${inih}&quot; max-heap-size=&quot;${maxh}&quot; java-vm-args=&quot;--add-modules=java.se.ee --illegal-access=warn&quot;">
+          <replacetoken>j2se version="1.7+"</replacetoken>
            
         </replace>
   </target>
index 5f6e784..93c19db 100644 (file)
@@ -1 +1 @@
-{"seqs":[{"name":"FER_CAPAN/3-34","start":3,"svid":"1.0","end":34,"id":"1665704504","seq":"SVSATMISTSFMPRKPAVTSL-KPIPNVGE--ALF","order":1},{"name":"FER1_SOLLC/3-34","start":3,"svid":"1.0","end":34,"id":"1003594867","seq":"SISGTMISTSFLPRKPAVTSL-KAISNVGE--ALF","order":2},{"name":"Q93XJ9_SOLTU/3-34","start":3,"svid":"1.0","end":34,"id":"1332961135","seq":"SISGTMISTSFLPRKPVVTSL-KAISNVGE--ALF","order":3},{"name":"FER1_PEA/6-37","start":6,"svid":"1.0","end":37,"id":"1335040546","seq":"ALYGTAVSTSFLRTQPMPMSV-TTTKAFSN--GFL","order":4},{"name":"Q7XA98_TRIPR/6-39","start":6,"svid":"1.0","end":39,"id":"1777084554","seq":"ALYGTAVSTSFMRRQPVPMSV-ATTTTTKAFPSGF","order":5},{"name":"FER_TOCH/3-34","start":3,"svid":"1.0","end":34,"id":"823528539","seq":"FILGTMISKSFLFRKPAVTSL-KAISNVGE--ALF","order":6}],"appSettings":{"globalColorScheme":"zappo","webStartUrl":"www.jalview.org/services/launchApp","application":"Jalview","hiddenSeqs":"823528539","showSeqFeatures":"true","version":"2.9","hiddenCols":"32-33;34-34"},"seqGroups":[{"displayText":true,"startRes":21,"groupName":"JGroup:1883305585","endRes":29,"colourText":false,"sequenceRefs":["1003594867","1332961135","1335040546","1777084554"],"svid":"1.0","showNonconserved":false,"colourScheme":"Zappo","displayBoxes":true}],"alignAnnotation":[{"svid":"1.0","annotations":[{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"α","value":0,"secondaryStructure":"H"},{"displayCharacter":"α","value":0,"secondaryStructure":"H"},{"displayCharacter":"α","value":0,"secondaryStructure":"H"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"β","value":0,"secondaryStructure":"E"},{"displayCharacter":"β","value":0,"secondaryStructure":"E"},{"displayCharacter":"β","value":0,"secondaryStructure":"E"},{"displayCharacter":"β","value":0,"secondaryStructure":"E"},{"displayCharacter":"β","value":0,"secondaryStructure":"E"},{"displayCharacter":"β","value":0,"secondaryStructure":"E"},{"displayCharacter":"β","value":0,"secondaryStructure":"E"},{"displayCharacter":"β","value":0,"secondaryStructure":"E"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"α","value":0,"secondaryStructure":"H"},{"displayCharacter":"α","value":0,"secondaryStructure":"H"},{"displayCharacter":"α","value":0,"secondaryStructure":"H"},{"displayCharacter":"α","value":0,"secondaryStructure":"H"},{"displayCharacter":"α","value":0,"secondaryStructure":"H"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"}],"description":"New description","label":"Secondary Structure"}],"svid":"1.0","seqFeatures":[{"fillColor":"#7d1633","score":0,"sequenceRef":"1332961135","featureGroup":"Jalview","svid":"1.0","description":"desciption","xStart":3,"xEnd":13,"type":"feature_x"},{"fillColor":"#7d1633","score":0,"sequenceRef":"1335040546","featureGroup":"Jalview","svid":"1.0","description":"desciption","xStart":3,"xEnd":13,"type":"feature_x"},{"fillColor":"#7d1633","score":0,"sequenceRef":"1777084554","featureGroup":"Jalview","svid":"1.0","description":"desciption","xStart":3,"xEnd":13,"type":"feature_x"}]}
\ No newline at end of file
+{"seqs":[{"name":"FER_CAPAN/3-34","start":3,"svid":"1.0","end":34,"id":"1665704504","seq":"SVSATMISTSFMPRKPAVTSL-KPIPNVGE--ALF","order":1},{"name":"FER1_SOLLC/3-34","start":3,"svid":"1.0","end":34,"id":"1003594867","seq":"SISGTMISTSFLPRKPAVTSL-KAISNVGE--ALF","order":2},{"name":"Q93XJ9_SOLTU/3-34","start":3,"svid":"1.0","end":34,"id":"1332961135","seq":"SISGTMISTSFLPRKPVVTSL-KAISNVGE--ALF","order":3},{"name":"FER1_PEA/6-37","start":6,"svid":"1.0","end":37,"id":"1335040546","seq":"ALYGTAVSTSFLRTQPMPMSV-TTTKAFSN--GFL","order":4},{"name":"Q7XA98_TRIPR/6-39","start":6,"svid":"1.0","end":39,"id":"1777084554","seq":"ALYGTAVSTSFMRRQPVPMSV-ATTTTTKAFPSGF","order":5},{"name":"FER_TOCH/3-34","start":3,"svid":"1.0","end":34,"id":"823528539","seq":"FILGTMISKSFLFRKPAVTSL-KAISNVGE--ALF","order":6}],"appSettings":{"globalColorScheme":"zappo","webStartUrl":"www.jalview.org/services/launchApp","application":"Jalview","hiddenSeqs":"823528539","showSeqFeatures":"true","version":"2.9","hiddenCols":"32-33;34-34"},"seqGroups":[{"displayText":true,"startRes":21,"groupName":"JGroup:1883305585","endRes":29,"colourText":false,"sequenceRefs":["1003594867","1332961135","1335040546","1777084554"],"svid":"1.0","showNonconserved":false,"colourScheme":"Zappo","displayBoxes":true}],"alignAnnotation":[{"svid":"1.0","annotations":[{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"α","value":0,"secondaryStructure":"H"},{"displayCharacter":"α","value":0,"secondaryStructure":"H"},{"displayCharacter":"α","value":0,"secondaryStructure":"H"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"β","value":0,"secondaryStructure":"E"},{"displayCharacter":"β","value":0,"secondaryStructure":"E"},{"displayCharacter":"β","value":0,"secondaryStructure":"E"},{"displayCharacter":"β","value":0,"secondaryStructure":"E"},{"displayCharacter":"β","value":0,"secondaryStructure":"E"},{"displayCharacter":"β","value":0,"secondaryStructure":"E"},{"displayCharacter":"β","value":0,"secondaryStructure":"E"},{"displayCharacter":"β","value":0,"secondaryStructure":"E"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"α","value":0,"secondaryStructure":"H"},{"displayCharacter":"α","value":0,"secondaryStructure":"H"},{"displayCharacter":"α","value":0,"secondaryStructure":"H"},{"displayCharacter":"α","value":0,"secondaryStructure":"H"},{"displayCharacter":"α","value":0,"secondaryStructure":"H"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"},{"displayCharacter":"","value":0,"secondaryStructure":"\u0000"}],"description":"New description","label":"Secondary Structure"}],"svid":"1.0","seqFeatures":[{"fillColor":"#7d1633","score":0,"otherDetails":{"status":"+"},"sequenceRef":"1332961135","featureGroup":"Pfam","svid":"1.0","description":"My description","xStart":0,"xEnd":0,"type":"Domain"},{"fillColor":"#7d1633","score":0,"sequenceRef":"1332961135","featureGroup":"Jalview","svid":"1.0","description":"theDesc","xStart":3,"xEnd":13,"type":"feature_x"},{"fillColor":"#7d1633","score":0,"sequenceRef":"1335040546","featureGroup":"Jalview","svid":"1.0","description":"theDesc","xStart":3,"xEnd":13,"type":"feature_x"},{"fillColor":"#7d1633","score":0,"sequenceRef":"1777084554","featureGroup":"Jalview","svid":"1.0","description":"theDesc","xStart":3,"xEnd":13,"type":"feature_x"}]}
\ No newline at end of file
diff --git a/examples/groovy/PIDmatrix.groovy b/examples/groovy/PIDmatrix.groovy
new file mode 100644 (file)
index 0000000..b97abcc
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+
+import jalview.analysis.scoremodels.ScoreModels
+import jalview.analysis.scoremodels.SimilarityParams
+
+// generate matrix for current selection using standard Jalview PID
+
+printSimilarityMatrix(true,true,SimilarityParams.Jalview)
+
+/** 
+ * this function prints a sequence similarity matrix in PHYLIP format. 
+ * printSimilarityMatrix(selected-only, include-ids, pidMethod)
+ * 
+ * Allowed values for pidMethod:
+ * 
+ * Jalview's Comparison.PID method includes matching gaps 
+ * and counts over the length of the shorter gapped sequence
+ * SimilarityParams.Jalview;
+ *
+ * 'SeqSpace' mode PCA calculation does not count matching 
+ * gaps but uses longest gapped sequence length
+ *  SimilarityParams.SeqSpace;
+ *
+ * PID calcs from the Raghava-Barton paper
+ * SimilarityParams.PID1: ignores gap-gap, does not score gap-residue,
+ * includes gap-residue in lengths, matches on longer of two sequences.
+ * 
+ * SimilarityParams.PID2: ignores gap-gap,ignores gap-residue, 
+ * matches on longer of two sequences
+ * 
+ * SimilarityParams.PID3: ignores gap-gap,ignores gap-residue, 
+ * matches on shorter of sequences only
+ * 
+ * SimilarityParams.PID4: ignores gap-gap,does not score gap-residue,
+ * includes gap-residue in lengths,matches on shorter of sequences only.
+ */
+
+void printSimilarityMatrix(boolean selview=false, boolean includeids=true, SimilarityParams pidMethod) {
+
+  def currentAlignFrame = jalview.bin.Jalview.getCurrentAlignFrame()
+
+  jalview.gui.AlignViewport av = currentAlignFrame.getCurrentView()
+
+  jalview.datamodel.AlignmentView seqStrings = av.getAlignmentView(selview)
+
+  if (!selview || av.getSelectionGroup()==null) {
+    start = 0
+    end = av.getAlignment().getWidth()
+    seqs = av.getAlignment().getSequencesArray()
+  } else {
+    start = av.getSelectionGroup().getStartRes()
+    end = av.getSelectionGroup().getEndRes() + 1
+    seqs = av.getSelectionGroup().getSequencesInOrder(av.getAlignment())
+  }
+
+  distanceCalc = ScoreModels.getInstance().getScoreModel("PID",
+      (jalview.api.AlignmentViewPanel) currentAlignFrame.alignPanel)
+
+  def distance=distanceCalc.findSimilarities(
+      seqStrings.getSequenceStrings(jalview.util.Comparison.GAP_DASH),pidMethod)
+
+  // output the PHYLIP Matrix
+
+  print distance.width()+" "+distance.height()+"\n"
+
+  p = 0
+
+  for (v in 1..distance.height()) {
+
+    if (includeids) {
+      print seqs[p++].getDisplayId(false)+" "
+    }
+
+    for (r in 1..distance.width()) {
+      print distance.getValue(v-1,r-1)+" "
+    }
+
+    print "\n"
+  }
+}
\ No newline at end of file
index cb0c4c4..010bca8 100755 (executable)
@@ -22,7 +22,7 @@
    <mapID target="home" url="html/index.html" />
    
    <mapID target="new" url="html/whatsNew.html"/>
-   <mapID target="release" url="html/releases.html#Jalview.2.10.2"/>
+   <mapID target="release" url="html/releases.html#Jalview.2.10.3"/>
    <mapID target="alannotation" url="html/features/annotation.html"/>
    <mapID target="keys" url="html/keys.html"/>
    <mapID target="newkeys" url="html/features/newkeystrokes.html"/>
    <mapID target="printSetupIcon" url="icons/setup.png" />
    
    <mapID target="overview" url="html/features/overview.html" />
+   <mapID target="overviewprefs" url="html/features/preferences.html#overview" />
 </map>
index f3311a7..20dd8db 100755 (executable)
        <tocitem text="Jalview Documentation" target="home" expand="true">
                        <tocitem text="What's new" target="new" expand="true">
                                <tocitem text="Latest Release Notes" target="release"/>
-        <tocitem text="Calculations Dialog" target="calcs.dialog"/>
-                               <tocitem text="Groovy Features Counter example" target="groovy.featurescounter"/>
-                               <tocitem text="Custom Colourschemes in Groovy" target="groovy.colours"/>
-                               <tocitem text="Omit hidden regions in Overview" target="overview"/>
-                               <tocitem text="identifers.org for URL Links" target="linksprefs" />
-                               <tocitem text="New features in Split Frame View" target="splitframe.mirrorfonts" />
                </tocitem>
                
                <tocitem text="Editing Alignments" target="edit" />
index bb80b84..1090253 100755 (executable)
   <p>
     Gap open : 12 <br> Gap extend : 2
   </p>
-  <p>When you select the pairwise alignment option a new window will
-    come up which will display the alignments in a text format as they
-    are calculated. Also displayed is information about the alignment
-    such as alignment score, length and percentage identity between the
+  <p>When you select the pairwise alignment option, a new window
+    will come up which displays the alignments in a text format, for
+    example:</p>
+  <p>
+  <pre>
+    FER1_SPIOL/5-13 TTMMGMAT<br />
+                    |. .. ||<br />
+    FER1_MESCR/5-15 TAALSGAT
+    </pre>
+  shows the aligned sequences, where '|' links identical residues, and
+  (for peptide) '.' links residues that have a positive PAM250 score.
+  <p>The window also shows information about the alignment such as
+    alignment score, length and percentage identity between the
     sequences.</p>
-  <p>&nbsp;</p>
+  <p>A button is also provided to allow you to view the sequences as
+    an alignment.</p>
 </body>
 </html>
index aeb461a..a0412d0 100755 (executable)
@@ -46,8 +46,7 @@
     <li><p>
         <strong>Sort by Pairwise Identity</strong>
       </p>
-      <p>Places pairs of sequences together that align with the
-        greatest fraction of conserved residues.</p>
+      <p>Sorts sequences in the selection or alignment according to percent identity with respect to the first sequence in the view.</p>
       <p></li>
     <li><p>
         <strong>Sort by Tree Order</strong>
diff --git a/help/html/features/overview.gif b/help/html/features/overview.gif
deleted file mode 100755 (executable)
index b5b1bc5..0000000
Binary files a/help/html/features/overview.gif and /dev/null differ
index ac5aecb..6401fdd 100755 (executable)
     <strong>View&#8594;Overview window</strong>
   </p>
   <p>Select the overview window menu item to get a navigable image
-    of the whole alignment.</p>
+    of the whole alignment. By default, gaps are shown as dark grey, in
+    the overview (since 2.10.2b1).</p>
   <p>The red box indicates the currently viewed region of the
     alignment, this may be moved by clicking and dragging with the
     mouse.</p>
   <p>Click anywhere else in the overview to centre the view on that
     position</p>
-    <p></p>
+  <p></p>
   <p>
     <strong>Hiding hidden regions in the overview</strong>
   </p>
     Hidden sequences and columns are by default shown as dark-grey rows
     and columns in the overview. Hidden regions can also be omitted
     entirely (to make the Overview 'WYSIWIG') by <strong>Right-clicking</strong>
-    (or CMD-Clicking) to open the overview's popup menu.<br />
-    <br /> <em>The option to include/exclude hidden regions in the
+    (or CMD-Clicking) to open the overview's popup menu.<br /> <br />
+    <em>The option to include/exclude hidden regions in the
       overview was introduced in Jalview 2.10.2</em>.
   
   <p>
-    <img src="overview.gif" width="407" height="137">
+    <img src="overview.png" width="800" height="196" alt="1hdc.pfam example alignment">
   </p>
   <p>&nbsp;</p>
+  <em>Previous to 2.10.2b1, gaps were white, and sequences shown as
+    dark grey unless coloured.</em>
 </body>
 </html>
diff --git a/help/html/features/overview.png b/help/html/features/overview.png
new file mode 100644 (file)
index 0000000..d7aaa19
Binary files /dev/null and b/help/html/features/overview.png differ
index 97a779a..2081a3d 100644 (file)
Binary files a/help/html/features/pdbseqfetcher.png and b/help/html/features/pdbseqfetcher.png differ
index 2962ba6..bb63bed 100644 (file)
@@ -37,7 +37,7 @@
   <p>
     To open the PDB Sequence Fetcher, select PDB as the database from
     any <a href="seqfetch.html">Sequence Fetcher</a> dialog (opened <em>via</em>
-    <strong>&quot;File &#8594;Fetch Sequences&quot;</strong>).
+    <strong>&quot;File &#8594;Fetch Sequences&quot;</strong>). 
   </p>
   <img src="pdbseqfetcher.png" align="left"
     alt="PDB sequence fetcher (introduced in Jalview 2.9)" />
   <p>
     <strong>Searching the PDB Database</strong>
   </p>
+  <p>To search the PDB, begin typing in the text box. If the
+    'autosearch' checkbox is enabled, then the results of your query
+    will be automatically updated and shown in the search results tab;
+    otherwise, press return to update the results. To access previous
+    searches, press the down-arrow or click the drop down menu icon at
+    the side of the search box. If you just want to paste in a list of
+    IDs, the 'Retrieve IDs' tab provides a batch-retrieval interface.</p>
   <p>
-    To search the PDB, begin typing in the text box. The results of your
-    query are shown in the search results tab, which updates every time
-    you type in the search text box. You can sort results according to
-    the displayed columns, and select entries with the mouse and
-    keyboard. Once you have selected one or more entries, hit the <strong>OK</strong>
-    button to retrieve and view them in Jalview.
+    You can sort results according to the displayed columns, and select
+    entries with the mouse and keyboard. Once you have selected one or
+    more entries, hit the <strong>OK</strong> button to retrieve and
+    view them in Jalview.
   </p>
   <p>
   <ul>
@@ -64,9 +69,8 @@
       1xyz:A</li>
 
     <li><strong>Bulk PDB retrieval</strong><br>Multiple PDB
-      IDs can be specified by separating them with a semi-colon.<br />
-      e.g. 1xyz;2xyz;3xyz<br />Hitting Return or OK will automatically
-      fetch those IDs, like the default Sequence Fetcher interface.</li>
+      IDs can be specified for retrieval via the 
+      <strong>Retrieve IDs</strong> tab.</li>
 
     <li><strong>Wild card searching</strong><br>The following
       wild cards are supported by the EMBL-EBI PDBe query service:
index acd7ba6..b29b66b 100755 (executable)
@@ -41,6 +41,9 @@
         Preferences</a> tab allows you to configure default colourschemes
       for a new alignment window.
     </li>
+    <li>The <a href="#overview"><strong>&quot;Overview&quot;</strong>
+        Preferences</a> tab configures defaults for the overview window.
+    </li>
     <li>The <a href="#structure"><strong>&quot;Structure&quot;</strong>
         Preferences</a> tab allows you to configure options for obtaining
       and displaying structure information.
       by Annotation...</a> is selected from the alignment window's colours
     menu.
   </p>
+   <p>
+    <a name="overview"><strong>&quot;Overview&quot;
+        Preferences tab</strong>
+  </p>
+  <p>
+    <em>Use legacy gap colouring (gaps are white)</em> - when enabled,
+    Jalview's overview shows gaps as white, and sequences with no
+    colourscheme applied as grey.
+  </p>
+  <p>
+    <em>Show Hidden regions when opening overview</em> - default setting
+    for inclusion of hidden regions.
+  </p>
+  <p>
+    <em>Gap Colour</em> - When legacy gap colouring is not enabled, this
+    configures the default colour for gaps in the overview.
+  </p>
+  <p>
+    <em>Hidden Colour</em> - colour used to highlight regions in the
+    overview that are hidden in the alignment.
+  </p>
+  <p>
+    <em>Gap Colour</em> - The default colour scheme for a new alignment
+    window. If the chosen option is &quot;User Defined&quot; then the
+    last User Defined Colour loaded or saved via the User Defined
+    Colours panel will be loaded.
+  </p>
   <p>
     <a name="structure"><strong>&quot;Structure&quot;
         Preferences tab</strong></a><em> added in Jalview 2.8.2</em>
index 3862c39..be1bd66 100644 (file)
       alignments, the <strong><a href="../menus/alwformat.html">"Format&#8594;Font"</a></strong>
       menu option has an option 'Scale protein residues to codons'. This
       option will make each protein residue the same width as a DNA
-      codon (so the alignments 'line up' vertically).<br/><br/>
-      <a name="mirror"/>The 'Use same 
-      font for cDNA and peptide' checkbox, when enabled, ensures that font or
-       font-size changes in either the cDNA or Protein alignment will also 
-       be mirrored. (<em>Added in 2.10.2</em>)
-    </li>
+      codon (so the alignments 'line up' vertically).</li>
+    <li><a name="mirror" />The 'Use same font for cDNA and peptide'
+      checkbox, when enabled, ensures that font or font-size changes in
+      either the cDNA or Protein alignment will also be mirrored. (<em>Added
+        in 2.10.2</em>)</li>
     <li><strong>"View&#8594;Protein"</strong> (in the cDNA panel)
       or <strong>"View&#8594;Nucleotide"</strong> (in the protein panel)
       allows you to show or hide one or other of the linked alignment
index a592e8e..23b55fa 100644 (file)
Binary files a/help/html/features/uniprotseqfetcher.png and b/help/html/features/uniprotseqfetcher.png differ
index edd8995..4a64f52 100644 (file)
   <p>
     <strong>Searching the UniProt Database</strong>
   </p>
-  <p>
-    To search UniProt, simply begin typing in the text box. After a
-    short delay (about 1.5 seconds), results will be shown in the table
-    below. You can sort results by clicking on the displayed columns,
+  <p>To search UniProt, simply begin typing in the text box. If the
+    'autosearch' check box is enabled, then after a short delay (about
+    1.5 seconds), results will be shown in the table below. Results are
+    also updated whenever you press Enter, and you can access previous
+    searches by pressing the 'Down' arrow or clicking the drop-down menu
+    icon at the side of the search box.</p>
+  <p>You can sort results by clicking on the displayed columns,
     and select entries with the mouse or keyboard. Once you have
     selected one or more entries, hit the <strong>OK</strong> button to
     retrieve the sequences.
 
 
     <li><strong>Bulk UniProt record retrieval</strong><br> To
-      retrieve several uniprot accessions at once, first select <strong>UniProt
-        ID</strong> from the dropdown menu, then paste in the accession IDs as a
-      semi-colon separated list. (e.g. fila_human; mnt_human;
-      mnt_mouse).<br />Hitting Return or OK will automatically fetch
-      those IDs, like the default Sequence Fetcher interface.</li>
+      retrieve sequences for a list of Uniprot accessions, please enter
+      them via the 'Retrieve IDs' tab.</li>
 
     <li><strong><a name="text-search">Complex queries
           with the UniProt query Syntax</a></strong> The text box also allows complex
index 0fcbbf9..45d979f 100755 (executable)
@@ -56,7 +56,7 @@
         <li><strong>Viewing Cached Structures</strong><br />If
           previously downloaded structures are available for your
           sequences, the structure chooser will automatically offer them
-          via the <strong>Cached PDB Entries</strong> view. If you wish
+          via the <strong>Cached Structures</strong> view. If you wish
           to download new structures, select one of the PDBe selection
           criteria from the drop-down menu.</li>
       </ul></li>
index 89a39a3..a36e31a 100755 (executable)
@@ -68,6 +68,369 @@ li:before {
       </td>
     </tr>
     <tr>
+      <td width=="60" nowrap>
+        <div align="center">
+          <strong><a name="Jalview.2.10.3b1">2.10.3b1</a><br /> <em>5/12/2017</em></strong>
+        </div>
+      </td>
+      <td><div align="left">
+          <em></em>
+      </td>
+      <td><div align="left">
+          <ul>
+            <li><!-- JAL-2851-->Alignment doesn't appear to scroll vertically via trackpad and scrollwheel</li>
+            <li><!-- JAL-2842-->Jalview hangs if up/down arrows pressed in cursor mode when cursor lies in hidden region at start of alignment</li>
+            <li><!-- JAL-2827-->Helix annotation has 'notches' when scrolled into view if columns are hidden</li>
+            <li><!-- JAL-2740-->Annotation column filter can be slow to reset (ie after hitting cancel) for large numbers of hidden columns</li>
+            <li><!-- JAL-2849-->User preference for disabling inclusion of sequence limits when exporting as flat file has no effect</li>
+          <ul>
+      </td>
+    </tr>
+    <tr>
+      <td width="60" nowrap>
+        <div align="center">
+          <strong><a name="Jalview.2.10.3">2.10.3</a><br /> <em>17/11/2017</em></strong>
+        </div>
+      </td>
+      <td><div align="left">
+          <em></em>
+          <ul>
+            <li>
+              <!-- JAL-2446 -->Faster and more efficient management and
+              rendering of sequence features
+            </li>
+            <li>
+              <!-- JAL 2523-->More reliable Ensembl fetching with HTTP
+              429 rate limit request hander
+            </li>
+            <li>
+              <!-- JAL-2773 -->Structure views don't get updated unless
+              their colours have changed
+            </li>
+            <li>
+              <!-- JAL-2495 -->All linked sequences are highlighted for
+              a structure mousover (Jmol) or selection (Chimera)
+            </li>
+            <li>
+              <!-- JAL-2790 -->'Cancel' button in progress bar for
+              JABAWS AACon, RNAAliFold and Disorder prediction jobs
+            </li>
+            <li>
+              <!-- JAL-2617 -->Stop codons are excluded in CDS/Protein
+              view from Ensembl locus cross-references
+            </li>
+            <li>
+              <!-- JAL-2685 -->Start/End limits are shown in Pairwise
+              Alignment report
+            </li>
+            <li>
+              <!-- JAL-2810 -->Sequence fetcher's Free text 'autosearch'
+              feature can be disabled
+            </li>
+            <li>
+              <!-- JAL-2810 -->Retrieve IDs tab added for UniProt and
+              PDB easier retrieval of sequences for lists of IDs
+            </li>
+            <li>
+              <!-- JAL-2758 -->Short names for sequences retrieved from
+              Uniprot
+            </li>
+          </ul>
+          <em>Scripting</em>
+          <ul>
+            <li>Groovy interpreter updated to 2.4.12</li>
+            <li>Example groovy script for generating a matrix of
+              percent identity scores for current alignment.</li>
+          </ul>
+          <em>Testing and Deployment</em>
+          <ul>
+            <li>
+              <!-- JAL-2727 -->Test to catch memory leaks in Jalview UI
+            </li>
+          </ul>
+        </div></td>
+      <td><div align="left">
+          <em>General</em>
+          <ul>
+            <li>
+              <!-- JAL-2643 -->Pressing tab after updating the colour
+              threshold text field doesn't trigger an update to the
+              alignment view
+            </li>
+            <li>
+              <!-- JAL-2682 -->Race condition when parsing sequence ID
+              strings in parallel
+            </li>
+            <li>
+              <!-- JAL-2608 -->Overview windows are also closed when
+              alignment window is closed
+            </li>
+            <li>
+              <!-- JAL-2548 -->Export of features doesn't always respect
+              group visibility
+            </li>
+            <li>
+              <!-- JAL-2831 -->Jumping from column 1 to column 100,000
+              takes a long time in Cursor mode
+            </li>
+          </ul>
+          <em>Desktop</em>
+          <ul>
+            <li>
+              <!-- JAL-2777 -->Structures with whitespace chainCode
+              cannot be viewed in Chimera
+            </li>
+            <li>
+              <!-- JAL-2728 -->Protein annotation panel too high in
+              CDS/Protein view
+            </li>
+            <li>
+              <!-- JAL-2757 -->Can't edit the query after the server
+              error warning icon is shown in Uniprot and PDB Free Text
+              Search Dialogs
+            </li>
+            <li>
+              <!-- JAL-2253 -->Slow EnsemblGenome ID lookup
+            </li>
+            <li>
+              <!-- JAL-2529 -->Revised Ensembl REST API CDNA query
+            </li>
+            <li>
+              <!-- JAL-2739 -->Hidden column marker in last column not
+              rendered when switching back from Wrapped to normal view
+            </li>
+            <li>
+              <!-- JAL-2768 -->Annotation display corrupted when
+              scrolling right in unwapped alignment view
+            </li>
+            <li>
+              <!-- JAL-2542 -->Existing features on subsequence
+              incorrectly relocated when full sequence retrieved from
+              database
+            </li>
+            <li>
+              <!-- JAL-2733 -->Last reported memory still shown when
+              Desktop->Show Memory is unticked (OSX only)
+            </li>
+            <li>
+              <!-- JAL-2658 -->Amend Features dialog doesn't allow
+              features of same type and group to be selected for
+              amending
+            </li>
+            <li>
+              <!-- JAL-2524 -->Jalview becomes sluggish in wide
+              alignments when hidden columns are present
+            </li>
+            <li>
+              <!-- JAL-2392 -->Jalview freezes when loading and
+              displaying several structures
+            </li>
+            <li>
+              <!-- JAL-2732 -->Black outlines left after resizing or
+              moving a window
+            </li>
+            <li>
+              <!-- JAL-1900,JAL-1625 -->Unable to minimise windows
+              within the Jalview desktop on OSX
+            </li>
+            <li>
+              <!-- JAL-2667 -->Mouse wheel doesn't scroll vertically
+              when in wrapped alignment mode
+            </li>
+            <li>
+              <!-- JAL-2636 -->Scale mark not shown when close to right
+              hand end of alignment
+            </li>
+            <li>
+              <!-- JAL-2684 -->Pairwise alignment of selected regions of
+              each selected sequence do not have correct start/end
+              positions
+            </li>
+            <li>
+              <!-- JAL-2793 -->Alignment ruler height set incorrectly
+              after canceling the Alignment Window's Font dialog
+            </li>
+            <li>
+              <!-- JAL-2036 -->Show cross-references not enabled after
+              restoring project until a new view is created
+            </li>
+            <li>
+              <!-- JAL-2756 -->Warning popup about use of SEQUENCE_ID in
+              URL links appears when only default EMBL-EBI link is
+              configured (since 2.10.2b2)
+            </li>
+            <li>
+              <!-- JAL-2775 -->Overview redraws whole window when box
+              position is adjusted
+            </li>
+            <li>
+              <!-- JAL-2225 -->Structure viewer doesn't map all chains
+              in a multi-chain structure when viewing alignment
+              involving more than one chain (since 2.10)
+            </li>
+            <li>
+              <!-- JAL-2811 -->Double residue highlights in cursor mode
+              if new selection moves alignment window
+            </li>
+            <li>
+              <!-- JAL-2837,JAL-2840 -->Alignment vanishes when using
+              arrow key in cursor mode to pass hidden column marker
+            </li>
+            <li>
+              <!-- JAL-2679 -->Ensembl Genomes example ID changed to one
+              that produces correctly annotated transcripts and products
+            </li>
+            <li>
+              <!-- JAL-2776 -->Toggling a feature group after first time
+              doesn't update associated structure view
+            </li>
+          </ul>
+          <em>Applet</em><br />
+          <ul>
+            <li>
+              <!-- JAL-2687 -->Concurrent modification exception when
+              closing alignment panel
+            </li>
+          </ul>
+          <em>BioJSON</em><br />
+          <ul>
+            <li>
+              <!-- JAL-2546 -->BioJSON export does not preserve
+              non-positional features
+            </li>
+          </ul>
+          <em>New Known Issues</em>
+          <ul>
+            <li>
+              <!-- JAL-2541 -->Delete/Cut selection doesn't relocate
+              sequence features correctly (for many previous versions of
+              Jalview)
+            </li>
+            <li>
+              <!-- JAL-2841 -->Cursor mode unexpectedly scrolls when
+              using cursor in wrapped panel other than top
+            </li>
+            <li>
+              <!-- JAL-2791 -->Select columns containing feature ignores
+              graduated colour threshold
+            </li>
+            <li>
+              <!-- JAL-2822,JAL-2823 -->Edit sequence operation doesn't
+              always preserve numbering and sequence features
+            </li>
+          </ul>
+          <em>Known Java 9 Issues</em>
+          <ul>
+            <li>
+              <!-- JAL-2902 -->Groovy Console very slow to open and is
+              not responsive when entering characters (Webstart, Java
+              9.01, OSX 10.10)
+            </li>
+          </ul>
+        </div></td>
+    </tr>
+    <tr>
+      <td width="60" nowrap>
+        <div align="center">
+          <strong><a name="Jalview.2.10.2b2">2.10.2b2</a><br />
+            <em>2/10/2017</em></strong>
+        </div>
+      </td>
+      <td><div align="left">
+          <em>New features in Jalview Desktop</em>
+          <ul>
+            <li>
+              <!-- JAL-2748 -->Uniprot Sequence Fetcher now uses web API at uniprot.org 
+            </li>
+            <li>  <!-- JAL-2745 -->HTTPS used for all connections to ebi.ac.uk 
+            </li>
+          </ul>
+        </div></td>
+      <td><div align="left">
+        </div></td>
+    </tr>
+    <tr>
+      <td width="60" nowrap>
+        <div align="center">
+          <strong><a name="Jalview.2.10.2b1">2.10.2b1</a><br />
+            <em>7/9/2017</em></strong>
+        </div>
+      </td>
+      <td><div align="left">
+          <em></em>
+          <ul>
+            <li>
+              <!-- JAL-2588 -->Show gaps in overview window by colouring
+              in grey (sequences used to be coloured grey, and gaps were
+              white)
+            </li>
+            <li>
+              <!-- JAL-2588,JAL-2527 -->Overview tab in Jalview Desktop
+              Preferences
+            </li>
+            <li>
+              <!-- JAL-2587 -->Overview updates immediately on increase
+              in size and progress bar shown as higher resolution
+              overview is recalculated
+            </li>
+
+          </ul>
+        </div></td>
+      <td><div align="left">
+          <em></em>
+          <ul>
+            <li>
+              <!-- JAL-2664 -->Overview window redraws every hidden
+              column region row by row
+            </li>
+            <li>
+              <!-- JAL-2681 -->duplicate protein sequences shown after
+              retrieving Ensembl crossrefs for sequences from Uniprot
+            </li>
+            <li>
+              <!-- JAL-2603 -->Overview window throws NPE if show boxes
+              format setting is unticked
+            </li>
+            <li>
+              <!-- JAL-2610 -->Groups are coloured wrongly in overview
+              if group has show boxes format setting unticked
+            </li>
+            <li>
+              <!-- JAL-2672,JAL-2665 -->Redraw problems when
+              autoscrolling whilst dragging current selection group to
+              include sequences and columns not currently displayed
+            </li>
+            <li>
+              <!-- JAL-2691 -->Not all chains are mapped when multimeric
+              assemblies are imported via CIF file
+            </li>
+            <li>
+              <!-- JAL-2704 -->Gap colour in custom colourscheme is not
+              displayed when threshold or conservation colouring is also
+              enabled.
+            </li>
+            <li>
+              <!-- JAL-2549 -->JABAWS 2.2 services report wrong JABAWS
+              server version
+            </li>
+            <li>
+              <!-- JAL-2673 -->Jalview continues to scroll after
+              dragging a selected region off the visible region of the
+              alignment
+            </li>
+            <li>
+              <!-- JAL-2724 -->Cannot apply annotation based
+              colourscheme to all groups in a view
+            </li>
+            <li>
+              <!-- JAL-2511 -->IDs don't line up with sequences
+              initially after font size change using the Font chooser or
+              middle-mouse zoom
+            </li>
+          </ul>
+        </div></td>
+    </tr>
+    <tr>
       <td width="60" nowrap>
         <div align="center">
           <strong><a name="Jalview.2.10.2">2.10.2</a><br /> <em>17/8/2017</em></strong>
@@ -122,10 +485,6 @@ li:before {
               with alignment and overview windows
             </li>
             <li>
-              <!--  JAL-2491 -->Linked scrolling of CDS/Protein views
-              via Overview or sequence motif search operations
-            </li>
-            <li>
               <!-- JAL-2514 -->Scrolling of wrapped alignment views via
               overview
             </li>
@@ -167,6 +526,10 @@ li:before {
               the application.
             </li>
             <li>
+              <!--  JAL-2491 -->Linked scrolling of CDS/Protein views
+              via Overview or sequence motif search operations
+            </li>
+            <li>
               <!-- JAL-2547 -->Amend sequence features dialog box can be
               opened by double clicking gaps within sequence feature
               extent
@@ -180,6 +543,10 @@ li:before {
           <em>3D Structure</em>
           <ul>
             <li>
+              <!-- JAL-2430 -->Hidden regions in alignment views are not
+              coloured in linked structure views
+            </li>
+            <li>
               <!-- JAL-1596 -->Faster Chimera/Jalview communication by
               file-based command exchange
             </li>
@@ -197,7 +564,7 @@ li:before {
               <!-- JAL-2295, JAL-2296 -->New entries in the Chimera menu
               to transfer Chimera's structure attributes as Jalview
               features, and vice-versa (<strong>Experimental
-                Feauture</strong>)
+                Feature</strong>)
             </li>
           </ul>
           <em>Web Services</em>
@@ -206,7 +573,9 @@ li:before {
               <!-- JAL-2549 -->Updated JABAWS client to v2.2
             </li>
             <li>
-              <!-- JAL-2335 -->Filter non-standard amino acids and nucleotides when submitting to AACon and other MSA Analysis services
+              <!-- JAL-2335 -->Filter non-standard amino acids and
+              nucleotides when submitting to AACon and other MSA
+              Analysis services
             </li>
             <li>
               <!-- JAL-2316, -->URLs for viewing database
@@ -237,7 +606,7 @@ li:before {
           <em>Documentation</em>
           <ul>
             <li>
-              <!-- JAL-2339 -->Release notes reformatted for readibility
+              <!-- JAL-2339 -->Release notes reformatted for readability
               with the built-in Java help viewer
             </li>
             <li>
@@ -268,22 +637,23 @@ li:before {
               matrix - C->R should be '-3'<br />Old matrix restored
               with this one-line groovy script:<br />jalview.analysis.scoremodels.ScoreModels.instance.BLOSUM62.@matrix[4][1]=3
             </li>
-            <li>
-              <!-- JAL-2397 -->Fixed Jalview's treatment of gaps in PCA
-              and substitution matrix based Tree calculations.<br />In
-              earlier versions of Jalview, gaps matching gaps were
-              penalised, and gaps matching non-gaps penalised even more.
-              In the PCA calculation, gaps were actually treated as
-              non-gaps - so different costs were applied, which meant
-              Jalview's PCAs were different to those produced by
-              SeqSpace.<br />Jalview now treats gaps in the same way as
-              SeqSpace (ie it scores them as 0). To restore pre-2.10.2
-              behaviour<br />
-              jalview.viewmodel.PCAModel.scoreGapAsAny=true // for
-              2.10.1 mode<br />
-              jalview.viewmodel.PCAModel.scoreGapAsAny=false // to
-              restore 2.10.2 mode
-            </li>
+            <li><a name="2102scoremodelbugs" /> <!-- JAL-2397 -->Fixed
+              Jalview's treatment of gaps in PCA and substitution matrix
+              based Tree calculations.<br /> <br />In earlier versions
+              of Jalview, gaps matching gaps were penalised, and gaps
+              matching non-gaps penalised even more. In the PCA
+              calculation, gaps were actually treated as non-gaps - so
+              different costs were applied, which meant Jalview's PCAs
+              were different to those produced by SeqSpace.<br />Jalview
+              now treats gaps in the same way as SeqSpace (ie it scores
+              them as 0). <br /> <br />Enter the following in the
+              Groovy console to restore pre-2.10.2 behaviour:<br />
+              jalview.analysis.scoremodels.ScoreMatrix.scoreGapAsAny=true
+              // for 2.10.1 mode <br />
+              jalview.analysis.scoremodels.ScoreMatrix.scoreGapAsAny=false
+              // to restore 2.10.2 mode <br /> <br /> <em>Note:
+                these settings will affect all subsequent tree and PCA
+                calculations (not recommended)</em></li>
             <li>
               <!-- JAL-2424 -->Fixed off-by-one bug that affected
               scaling of branch lengths for trees computed using
@@ -415,10 +785,6 @@ li:before {
           <em>Rendering</em>
           <ul>
             <li>
-              <!-- JAL-2430 -->Hidden regions in alignment views are not
-              coloured in linked structure views
-            </li>
-            <li>
               <!-- JAL-2421 -->Overview window visible region moves
               erratically when hidden rows or columns are present
             </li>
@@ -624,11 +990,11 @@ li:before {
             <li>
               <!-- JAL-2550 -->Importing annotation file with rows
               containing just upper and lower case letters are
-              interpreted as WUSS rna secondary structure symbols
+              interpreted as WUSS RNA secondary structure symbols
             </li>
             <li>
-              <!-- JAL-2590 -->Cannot load Newick trees from eggnog
-              ortholog database
+              <!-- JAL-2590 -->Cannot load and display Newick trees
+              reliably from eggnog Ortholog database
             </li>
             <li>
               <!-- JAL-2468 -->Status bar shows 'Marked x columns
@@ -640,7 +1006,8 @@ li:before {
               doesn't always add secondary structure annotation.
             </li>
           </ul>
-        </div><tr>
+        </div>
+    <tr>
       <td width="60" nowrap>
         <div align="center">
           <strong><a name="Jalview.2.10.1">2.10.1</a><br /> <em>29/11/2016</em></strong>
@@ -1317,6 +1684,10 @@ li:before {
               after clicking on it to create new annotation for a
               column.
             </li>
+            <li>
+              <!-- JAL-1980 -->Null Pointer Exception raised when 
+              pressing Add on an orphaned cut'n'paste window.
+            </li>
             <!--  may exclude, this is an external service stability issue  JAL-1941 
             -- > RNA 3D structure not added via DSSR service</li> -->
           </ul>
index 60769a4..4bf1cec 100755 (executable)
 </head>
 <body>
   <p>
-    <strong>What's new in Jalview 2.10.2 ?</strong>
+    <strong>What's new in Jalview 2.10.3 ?</strong>
   </p>
   <p>
-    Full details about Jalview 2.10.2 are in the <a
-      href="releases.html#Jalview.2.10.2"> Release Notes</a>, but the
-    highlights are below.
+    Version 2.10.3 was released in November 2017. The major focus was to
+    improve Jalview's sequence features datamodel and the scalability of
+    the alignment rendering system. The full list of bug fixes and new
+    features can be found in the <a href="releases.html#Jalview.2.10.3">2.10.3
+      Release Notes</a>. Key improvements include:
   </p>
   <ul>
-    <li><strong>New UI, and faster and more configurable
-        implementation for PCA, Neighbour-Joining and UPGMA Trees</strong><br>
-      Menu entries for calculating PCA and different types of tree have
-      been replaced by a single <em>Calculations</em> dialog box. The
-      underlying implementation for the PCA and tree calculations have
-      been made faster and more memory efficient. A new framework has
-      also been created for the score models used to calculate distances
-      between sequences. This framework allows import of substitution
-      matrices in NCBI and AAIndex format, and custom score models to be
-      created via a groovy script.</li>
-    <li><strong>Update to JABAWS 2.2</strong><br />Jalview's
-      alignment, protein conservation analysis, and protein disorder and
-      RNA secondary structure prediction services are now provided by <a
-      href="http://www.compbio.dundee.ac.uk/jabaws">JABAWS 2.2</a>.
-      Several of the programs provided as services have been updated, so
-      their options and parameters have changed.</li>
-    <li>New preferences for <a href="webServices/urllinks.html">opening
-        web pages for database cross-references</a> via the UK Elixir's
-      EMBL-EBI's MIRIAM database and identifiers.org services.
+    <li>Faster and more responsive UI when importing and working
+      with wide alignments and handling hundreds and thousands of
+      sequence features</li>
+    <li>Improved usability with <a
+      href="features/pdbsequencefetcher.html">PDB</a> and <a
+      href="features/uniprotsequencefetcher.html">UniProt</a> Free Text
+      Search dialog, and new tab for retrieval of sequences for lists of
+      IDs.
     </li>
-    <li><em>Showing and hiding regions</em>
-      <ul>
-        <li><a href="menus/popupMenu.html#hideinserts">Hide
-            insertions</a> in the PopUp menu has changed its behaviour.
-          Prior to 2.10.2, columns were only shown or hidden according
-          to gaps in the sequence under the popup menu. Now, only
-          columns that are gapped in all selected sequences as well as
-          the sequence under the popup menu are hidden, and column
-          visibility outside the selected region is left as is. This
-          makes it easy to filter insertions from the alignment view
-          (just select the region containing insertions to remove)
-          without affecting the rest of the hidden columns.</li>
-      </ul></li>
-    <li>Recent search histories for <a
-      href="features/search.html#queryhistory">Find</a> and the free
-      text search system (for querying Uniprot and the PDBe).</li>
+    <li>Short names assigned to sequences retrieved from UniProt</li>
+    <li>Groovy console upgraded to 2.4.12 (improved support for Java 9)</li>
   </ul>
   <p>
     <strong><a name="experimental">Experimental Features</a></strong>
   </p>
   <p>
-    This release of Jalview includes a new option in the Jalview Desktop
-    that allows you to try out features that are still in development.
-    To access the features described below, please first enable the <strong>Tools&#8594;Enable
-      Experimental Features</strong> option, and then restart Jalview.
+    Remember, please enable the <em>Experimental Features</em> option in
+    the Jalview Desktop's <em>Tools</em> menu, and then restart Jalview
+    if you want to try out features below:
   </p>
   <ul>
     <li><em>Annotation transfer between Chimera and Jalview</em><br />Two
         the Chimera viewer's Chimera menu</a> allow positional annotation to
       be exchanged between Chimera and Jalview.</li>
   </ul>
-  <p>
-    <strong>Scripting</strong><br />New <a
-      href="http://www.jalview.org/examples/groovy">groovy examples</a>
-    demonstrate Jalview 2.10.2 APIs for creation of data-driven
-    colourschemes, and custom alignment file handlers. The <a
-      href="groovy/featuresCounter.html">FeatureAnnotationWorker</a>
-    introduced in Jalview 2.10 has also been refactored to allow
-    efficient counting across multiple feature types. Please be aware
-    that feature counter scripts created for earlier versions will not
-    execute in Jalview 2.10.2.
-  </p>
+  
 </body>
 </html>
similarity index 62%
rename from lib/groovy-all-2.4.6-indy.jar
rename to lib/groovy-all-2.4.12-indy.jar
index 5f3d51c..bb246a3 100644 (file)
Binary files a/lib/groovy-all-2.4.6-indy.jar and b/lib/groovy-all-2.4.12-indy.jar differ
index bf1e8b1..37426c3 100644 (file)
Binary files a/lib/jabaws-min-client-2.2.0.jar and b/lib/jabaws-min-client-2.2.0.jar differ
index 162f10f..94f7eff 100644 (file)
@@ -913,7 +913,6 @@ label.as_percentage = As Percentage
 error.not_implemented = Not implemented
 error.no_such_method_as_clone1_for = No such method as clone1 for {0}
 error.null_from_clone1 = Null from clone1!
-error.implementation_error_sortbyfeature = Implementation Error - sortByFeature method must be one of FEATURE_SCORE, FEATURE_LABEL or FEATURE_DENSITY.
 error.not_yet_implemented = Not yet implemented
 error.unknown_type_dna_or_pep = Unknown Type {0} - dna or pep are the only allowed values.
 error.implementation_error_dont_know_threshold_annotationcolourgradient = Implementation error: don't know about threshold setting for current AnnotationColourGradient.
@@ -1296,7 +1295,6 @@ label.database = Database
 label.urltooltip = Only one url, which must use a sequence id, can be selected for the 'On Click' option
 label.edit_sequence_url_link = Edit sequence URL link
 warn.name_cannot_be_duplicate = User-defined URL names must be unique and cannot be MIRIAM ids
-label.invalid_name = Invalid Name !
 label.output_seq_details = Output Sequence Details to list all database references
 label.urllinks = Links
 label.default_cache_size = Default Cache Size
@@ -1311,3 +1309,16 @@ label.occupancy_descr = Number of aligned positions
 label.show_experimental = Enable experimental features
 label.show_experimental_tip = Enable any new and currently 'experimental' features (see Latest Release Notes for details)
 label.warning_hidden = Warning: {0} {1} is currently hidden
+label.overview_settings = Overview settings
+label.ov_legacy_gap = Use legacy gap colouring (gaps are white)
+label.gap_colour = Gap colour:
+label.ov_show_hide_default = Show hidden regions when opening overview
+label.hidden_colour = Hidden colour:
+label.select_gap_colour = Select gap colour
+label.select_hidden_colour = Select hidden colour
+label.overview = Overview
+label.reset_to_defaults = Reset to defaults
+label.oview_calc = Recalculating overview...
+option.enable_disable_autosearch = When ticked, search is performed automatically.
+option.autosearch = Autosearch
+label.retrieve_ids = Retrieve IDs
\ No newline at end of file
index 8385142..e8fd411 100644 (file)
@@ -838,7 +838,6 @@ label.as_percentage = Como Porcentaje
 error.not_implemented = No implementado
 error.no_such_method_as_clone1_for = No existe ese método como un clone1 de {0}
 error.null_from_clone1 = Nulo de clone1!
-error.implementation_error_sortbyfeature = Error de implementación - sortByFeature debe ser uno de FEATURE_SCORE, FEATURE_LABEL o FEATURE_DENSITY.
 error.not_yet_implemented = No se ha implementado todavía
 error.unknown_type_dna_or_pep = Tipo desconocido {0} - dna o pep son los Ãºnicos valores permitidos
 error.implementation_error_dont_know_threshold_annotationcolourgradient = Error de implementación: no se conoce el valor umbral para el AnnotationColourGradient actual.
@@ -1296,7 +1295,6 @@ label.database = Base de datos
 label.urltooltip = Sólo una url, que debe usar una id de secuencia, puede ser seleccionada en la opción 'On Click'
 label.edit_sequence_url_link = Editar link de secuencia URL
 warn.name_cannot_be_duplicate = Los nombres URL definidos por el usuario deben ser Ãºnicos y no pueden ser ids de MIRIAM
-label.invalid_name = Nombre inválido !
 label.output_seq_details = Seleccionar Detalles de la secuencia para ver todas
 label.urllinks = Enlaces
 label.default_cache_size = Tamaño del caché por defecto
@@ -1311,3 +1309,13 @@ label.togglehidden = Mostrar regiones ocultas
 label.show_experimental = Habilitar funciones experimentales
 label.show_experimental_tip = Habilitar funciones nuevas y experimentales (ver Latest Release Notes para más detalles)
 label.warning_hidden = Advertencia: {0} {1} está actualmente oculto
+label.overview_settings = Ajustes para la ventana resumen
+label.ov_legacy_gap = <html>Utilizar el color heredado de huecos<br>(los huecos son blancos)
+label.gap_colour = Color de huecos:
+label.ov_show_hide_default = Mostrar regiones ocultas al abrir el resumen
+label.hidden_colour = Color de las regiones ocultas:
+label.select_gap_colour = Seleccionar color de huecos
+label.select_hidden_colour = Seleccionar color de las regiones ocultas 
+label.overview = Resumen
+label.reset_to_defaults = Restablecen a los predeterminados
+label.oview_calc = Recalculando resumen
index 4a981ad..6344d1e 100755 (executable)
  * The Jalview Authors are detailed in the 'AUTHORS' file.
 -->
 <mapping>
-       <class name="jalview.datamodel.UniprotFile">
+       <class name="jalview.datamodel.xdb.uniprot.UniprotFile">
                  <map-to xml="uniprot"/>               
-                 <field name="UniprotEntries" type="jalview.datamodel.UniprotEntry" collection="vector">
+                 <field name="UniprotEntries" type="jalview.datamodel.xdb.uniprot.UniprotEntry" collection="vector">
                      <bind-xml name="entry"/>
                 </field>               
         </class>
                 
-        <class name="jalview.datamodel.UniprotEntry">
+        <class name="jalview.datamodel.xdb.uniprot.UniprotEntry">
                <field name="name" type="string" collection="vector"/>
                <field name="accession" type="string" collection="vector"/>
-               <field name="protein" type="jalview.datamodel.UniprotProteinName"/>
-           <field name="UniprotSequence" type="jalview.datamodel.UniprotSequence">
+               <field name="protein" type="jalview.datamodel.xdb.uniprot.UniprotProteinName"/>
+           <field name="UniprotSequence" type="jalview.datamodel.xdb.uniprot.UniprotSequence">
                <bind-xml name="sequence"/> 
            </field>
-           <field name="feature" type="jalview.datamodel.SequenceFeature" collection="vector"/>
+           <field name="feature" type="jalview.datamodel.xdb.uniprot.UniprotFeature" collection="vector"/>
            <field name="dbReference" type="jalview.datamodel.PDBEntry" collection="vector"/>
                       
         </class>
-       <class name="jalview.datamodel.UniprotProteinName">
+       <class name="jalview.datamodel.xdb.uniprot.UniprotProteinName">
                <field name="name" collection="vector" type="string">
                        <bind-xml name="fullName" location="recommendedName" node="element"/>
                </field>
        </class>
         <!-- uniprot protein name is now a collection of collections - the INCLUDES and CONTAINS entries of the uniprot
                record. This means this doesn't exist anymore...
-        <class name="jalview.datamodel.UniprotProteinName">
+        <class name="jalview.datamodel.xdb.uniprot.UniprotProteinName">
                <field name="name" type="string" collection="vector">
                        <bind-xml name="name"/>
                </field>                
         </class>
         -->
         
-        <class name="jalview.datamodel.SequenceFeature">
+        <class name="jalview.datamodel.xdb.uniprot.UniprotFeature">
                <field name="type">
                        <bind-xml node="attribute"/>
                </field>
@@ -71,7 +71,7 @@
                 </field>
         </class>
        
-          <class name="jalview.datamodel.UniprotSequence">
+          <class name="jalview.datamodel.xdb.uniprot.UniprotSequence">
                     <field name="content" type="string">
                        <bind-xml name="sequence" node="text"/>
                     </field>
index 39111c3..b15c3cc 100644 (file)
@@ -52,8 +52,8 @@ import java.io.PrintStream;
 import java.util.List;
 import java.util.Vector;
 
-public class AppletPDBCanvas extends Panel implements MouseListener,
-        MouseMotionListener, StructureListener
+public class AppletPDBCanvas extends Panel
+        implements MouseListener, MouseMotionListener, StructureListener
 {
 
   MCMatrix idmat = new MCMatrix(3, 3);
@@ -159,7 +159,7 @@ public class AppletPDBCanvas extends Panel implements MouseListener,
 
     try
     {
-      pdb = ssm.setMapping(seq, chains, pdbentry.getFile(), protocol);
+      pdb = ssm.setMapping(seq, chains, pdbentry.getFile(), protocol, null);
 
       if (protocol == DataSourceType.PASTE)
       {
@@ -191,10 +191,9 @@ public class AppletPDBCanvas extends Panel implements MouseListener,
     for (int i = 0; i < pdb.getChains().size(); i++)
     {
 
-      mappingDetails
-              .append("\n\nPDB Sequence is :\nSequence = "
-                      + pdb.getChains().elementAt(i).sequence
-                              .getSequenceAsString());
+      mappingDetails.append("\n\nPDB Sequence is :\nSequence = "
+              + pdb.getChains().elementAt(i).sequence
+                      .getSequenceAsString());
       mappingDetails.append("\nNo of residues = "
               + pdb.getChains().elementAt(i).residues.size() + "\n\n");
 
@@ -203,8 +202,9 @@ public class AppletPDBCanvas extends Panel implements MouseListener,
       // Align the sequence to the pdb
       // TODO: DNa/Pep switch
       AlignSeq as = new AlignSeq(sequence,
-              pdb.getChains().elementAt(i).sequence, pdb.getChains()
-                      .elementAt(i).isNa ? AlignSeq.DNA : AlignSeq.PEP);
+              pdb.getChains().elementAt(i).sequence,
+              pdb.getChains().elementAt(i).isNa ? AlignSeq.DNA
+                      : AlignSeq.PEP);
       as.calcScoreMatrix();
       as.traceAlignment();
       PrintStream ps = new PrintStream(System.out)
@@ -488,9 +488,8 @@ public class AppletPDBCanvas extends Panel implements MouseListener,
       g.fillRect(0, 0, getSize().width, getSize().height);
       g.setColor(Color.black);
       g.setFont(new Font("Verdana", Font.BOLD, 14));
-      g.drawString(
-              MessageManager.getString("label.error_loading_pdb_data"), 50,
-              getSize().height / 2);
+      g.drawString(MessageManager.getString("label.error_loading_pdb_data"),
+              50, getSize().height / 2);
       return;
     }
 
@@ -614,8 +613,8 @@ public class AppletPDBCanvas extends Panel implements MouseListener,
                 if (pos > 0)
                 {
                   pos = sequence[s].findIndex(pos);
-                  tmp.endCol = sr
-                          .getResidueColour(sequence[s], pos, finder);
+                  tmp.endCol = sr.getResidueColour(sequence[s], pos,
+                          finder);
                 }
               }
             }
@@ -644,11 +643,15 @@ public class AppletPDBCanvas extends Panel implements MouseListener,
     {
       tmpBond = visiblebonds.elementAt(i);
 
-      xstart = (int) (((tmpBond.start[0] - centre[0]) * scale) + (getSize().width / 2));
-      ystart = (int) (((centre[1] - tmpBond.start[1]) * scale) + (getSize().height / 2));
+      xstart = (int) (((tmpBond.start[0] - centre[0]) * scale)
+              + (getSize().width / 2));
+      ystart = (int) (((centre[1] - tmpBond.start[1]) * scale)
+              + (getSize().height / 2));
 
-      xend = (int) (((tmpBond.end[0] - centre[0]) * scale) + (getSize().width / 2));
-      yend = (int) (((centre[1] - tmpBond.end[1]) * scale) + (getSize().height / 2));
+      xend = (int) (((tmpBond.end[0] - centre[0]) * scale)
+              + (getSize().width / 2));
+      yend = (int) (((centre[1] - tmpBond.end[1]) * scale)
+              + (getSize().height / 2));
 
       xmid = (xend + xstart) / 2;
       ymid = (yend + ystart) / 2;
@@ -965,8 +968,10 @@ public class AppletPDBCanvas extends Panel implements MouseListener,
 
     if (n == 1)
     {
-      int xstart = (int) (((b.start[0] - centre[0]) * scale) + (getSize().width / 2));
-      int ystart = (int) (((centre[1] - b.start[1]) * scale) + (getSize().height / 2));
+      int xstart = (int) (((b.start[0] - centre[0]) * scale)
+              + (getSize().width / 2));
+      int ystart = (int) (((centre[1] - b.start[1]) * scale)
+              + (getSize().height / 2));
 
       g.setColor(Color.red);
       g.drawString(b.at1.resName + "-" + b.at1.resNumber, xstart, ystart);
@@ -974,8 +979,10 @@ public class AppletPDBCanvas extends Panel implements MouseListener,
 
     if (n == 2)
     {
-      int xstart = (int) (((b.end[0] - centre[0]) * scale) + (getSize().width / 2));
-      int ystart = (int) (((centre[1] - b.end[1]) * scale) + (getSize().height / 2));
+      int xstart = (int) (((b.end[0] - centre[0]) * scale)
+              + (getSize().width / 2));
+      int ystart = (int) (((centre[1] - b.end[1]) * scale)
+              + (getSize().height / 2));
 
       g.setColor(Color.red);
       g.drawString(b.at2.resName + "-" + b.at2.resNumber, xstart, ystart);
@@ -1004,11 +1011,13 @@ public class AppletPDBCanvas extends Panel implements MouseListener,
         {
           tmpBond = bonds.elementAt(i);
 
-          truex = (int) (((tmpBond.start[0] - centre[0]) * scale) + (getSize().width / 2));
+          truex = (int) (((tmpBond.start[0] - centre[0]) * scale)
+                  + (getSize().width / 2));
 
           if (Math.abs(truex - x) <= 2)
           {
-            int truey = (int) (((centre[1] - tmpBond.start[1]) * scale) + (getSize().height / 2));
+            int truey = (int) (((centre[1] - tmpBond.start[1]) * scale)
+                    + (getSize().height / 2));
 
             if (Math.abs(truey - y) <= 2)
             {
@@ -1021,11 +1030,13 @@ public class AppletPDBCanvas extends Panel implements MouseListener,
 
         // Still here? Maybe its the last bond
 
-        truex = (int) (((tmpBond.end[0] - centre[0]) * scale) + (getSize().width / 2));
+        truex = (int) (((tmpBond.end[0] - centre[0]) * scale)
+                + (getSize().width / 2));
 
         if (Math.abs(truex - x) <= 2)
         {
-          int truey = (int) (((tmpBond.end[1] - centre[1]) * scale) + (getSize().height / 2));
+          int truey = (int) (((tmpBond.end[1] - centre[1]) * scale)
+                  + (getSize().height / 2));
 
           if (Math.abs(truey - y) <= 2)
           {
index 133565c..adf833f 100644 (file)
@@ -46,8 +46,8 @@ import java.awt.event.ActionListener;
 import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
 
-public class AppletPDBViewer extends EmbmenuFrame implements
-        ActionListener, ItemListener
+public class AppletPDBViewer extends EmbmenuFrame
+        implements ActionListener, ItemListener
 {
   AppletPDBCanvas pdbcanvas;
 
@@ -67,8 +67,8 @@ public class AppletPDBViewer extends EmbmenuFrame implements
     embedMenuIfNeeded(pdbcanvas);
     add(pdbcanvas, BorderLayout.CENTER);
 
-    StringBuffer title = new StringBuffer(seq[0].getName() + ":"
-            + pdbcanvas.pdbentry.getFile());
+    StringBuffer title = new StringBuffer(
+            seq[0].getName() + ":" + pdbcanvas.pdbentry.getFile());
 
     jalview.bin.JalviewLite.addFrame(this, title.toString(), 400, 400);
 
@@ -185,8 +185,8 @@ public class AppletPDBViewer extends EmbmenuFrame implements
     zbuffer.addItemListener(this);
     charge.setLabel(MessageManager.getString("label.charge_cysteine"));
     charge.addActionListener(this);
-    hydro.setLabel(MessageManager
-            .getString("label.colourScheme_hydrophobic"));
+    hydro.setLabel(
+            MessageManager.getString("label.colourScheme_hydrophobic"));
     hydro.addActionListener(this);
     chain.setLabel(MessageManager.getString("action.by_chain"));
     chain.addActionListener(this);
@@ -206,11 +206,11 @@ public class AppletPDBViewer extends EmbmenuFrame implements
     strand.setLabel(MessageManager
             .getString("label.colourScheme_strand_propensity"));
     strand.addActionListener(this);
-    turn.setLabel(MessageManager
-            .getString("label.colourScheme_turn_propensity"));
+    turn.setLabel(
+            MessageManager.getString("label.colourScheme_turn_propensity"));
     turn.addActionListener(this);
-    buried.setLabel(MessageManager
-            .getString("label.colourScheme_buried_index"));
+    buried.setLabel(
+            MessageManager.getString("label.colourScheme_buried_index"));
     buried.addActionListener(this);
     user.setLabel(MessageManager.getString("action.user_defined"));
     user.addActionListener(this);
index 83642cc..ab172f2 100644 (file)
@@ -55,8 +55,8 @@ import java.util.Vector;
 import javax.swing.JPanel;
 import javax.swing.ToolTipManager;
 
-public class PDBCanvas extends JPanel implements MouseListener,
-        MouseMotionListener, StructureListener
+public class PDBCanvas extends JPanel
+        implements MouseListener, MouseMotionListener, StructureListener
 {
   boolean redrawneeded = true;
 
@@ -153,7 +153,8 @@ public class PDBCanvas extends JPanel implements MouseListener,
 
     try
     {
-      pdb = ssm.setMapping(seq, chains, pdbentry.getFile(), protocol);
+      pdb = ssm.setMapping(seq, chains, pdbentry.getFile(), protocol,
+              ap.alignFrame);
 
       if (protocol.equals(jalview.io.DataSourceType.PASTE))
       {
@@ -190,10 +191,9 @@ public class PDBCanvas extends JPanel implements MouseListener,
     for (int i = 0; i < pdb.getChains().size(); i++)
     {
 
-      mappingDetails
-              .append("\n\nPDB Sequence is :\nSequence = "
-                      + pdb.getChains().elementAt(i).sequence
-                              .getSequenceAsString());
+      mappingDetails.append("\n\nPDB Sequence is :\nSequence = "
+              + pdb.getChains().elementAt(i).sequence
+                      .getSequenceAsString());
       mappingDetails.append("\nNo of residues = "
               + pdb.getChains().elementAt(i).residues.size() + "\n\n");
 
@@ -582,8 +582,8 @@ public class PDBCanvas extends JPanel implements MouseListener,
                 if (pos > 0)
                 {
                   pos = sequence[s].findIndex(pos);
-                  tmp.endCol = sr
-                          .getResidueColour(sequence[s], pos, finder);
+                  tmp.endCol = sr.getResidueColour(sequence[s], pos,
+                          finder);
                 }
 
               }
@@ -613,11 +613,15 @@ public class PDBCanvas extends JPanel implements MouseListener,
     {
       tmpBond = visiblebonds.elementAt(i);
 
-      xstart = (int) (((tmpBond.start[0] - centre[0]) * scale) + (getWidth() / 2));
-      ystart = (int) (((centre[1] - tmpBond.start[1]) * scale) + (getHeight() / 2));
+      xstart = (int) (((tmpBond.start[0] - centre[0]) * scale)
+              + (getWidth() / 2));
+      ystart = (int) (((centre[1] - tmpBond.start[1]) * scale)
+              + (getHeight() / 2));
 
-      xend = (int) (((tmpBond.end[0] - centre[0]) * scale) + (getWidth() / 2));
-      yend = (int) (((centre[1] - tmpBond.end[1]) * scale) + (getHeight() / 2));
+      xend = (int) (((tmpBond.end[0] - centre[0]) * scale)
+              + (getWidth() / 2));
+      yend = (int) (((centre[1] - tmpBond.end[1]) * scale)
+              + (getHeight() / 2));
 
       xmid = (xend + xstart) / 2;
       ymid = (yend + ystart) / 2;
@@ -681,8 +685,8 @@ public class PDBCanvas extends JPanel implements MouseListener,
 
       if (highlightBond1 != null && highlightBond1 == tmpBond)
       {
-        g.setColor(tmpBond.endCol.brighter().brighter().brighter()
-                .brighter());
+        g.setColor(
+                tmpBond.endCol.brighter().brighter().brighter().brighter());
         drawLine(g, xmid, ymid, xend, yend);
       }
 
@@ -818,8 +822,8 @@ public class PDBCanvas extends JPanel implements MouseListener,
 
     if (fatom != null)
     {
-      this.setToolTipText(chain.id + ":" + fatom.resNumber + " "
-              + fatom.resName);
+      this.setToolTipText(
+              chain.id + ":" + fatom.resNumber + " " + fatom.resName);
     }
     else
     {
@@ -929,16 +933,20 @@ public class PDBCanvas extends JPanel implements MouseListener,
     g.setColor(Color.red);
     if (n == 1)
     {
-      int xstart = (int) (((b.start[0] - centre[0]) * scale) + (getWidth() / 2));
-      int ystart = (int) (((centre[1] - b.start[1]) * scale) + (getHeight() / 2));
+      int xstart = (int) (((b.start[0] - centre[0]) * scale)
+              + (getWidth() / 2));
+      int ystart = (int) (((centre[1] - b.start[1]) * scale)
+              + (getHeight() / 2));
 
       g.drawString(b.at1.resName + "-" + b.at1.resNumber, xstart, ystart);
     }
 
     if (n == 2)
     {
-      int xstart = (int) (((b.end[0] - centre[0]) * scale) + (getWidth() / 2));
-      int ystart = (int) (((centre[1] - b.end[1]) * scale) + (getHeight() / 2));
+      int xstart = (int) (((b.end[0] - centre[0]) * scale)
+              + (getWidth() / 2));
+      int ystart = (int) (((centre[1] - b.end[1]) * scale)
+              + (getHeight() / 2));
 
       g.drawString(b.at2.resName + "-" + b.at2.resNumber, xstart, ystart);
     }
@@ -964,11 +972,13 @@ public class PDBCanvas extends JPanel implements MouseListener,
         {
           tmpBond = bond;
 
-          truex = (int) (((tmpBond.start[0] - centre[0]) * scale) + (getWidth() / 2));
+          truex = (int) (((tmpBond.start[0] - centre[0]) * scale)
+                  + (getWidth() / 2));
 
           if (Math.abs(truex - x) <= 2)
           {
-            int truey = (int) (((centre[1] - tmpBond.start[1]) * scale) + (getHeight() / 2));
+            int truey = (int) (((centre[1] - tmpBond.start[1]) * scale)
+                    + (getHeight() / 2));
 
             if (Math.abs(truey - y) <= 2)
             {
@@ -981,11 +991,13 @@ public class PDBCanvas extends JPanel implements MouseListener,
 
         // Still here? Maybe its the last bond
 
-        truex = (int) (((tmpBond.end[0] - centre[0]) * scale) + (getWidth() / 2));
+        truex = (int) (((tmpBond.end[0] - centre[0]) * scale)
+                + (getWidth() / 2));
 
         if (Math.abs(truex - x) <= 2)
         {
-          int truey = (int) (((tmpBond.end[1] - centre[1]) * scale) + (getHeight() / 2));
+          int truey = (int) (((tmpBond.end[1] - centre[1]) * scale)
+                  + (getHeight() / 2));
 
           if (Math.abs(truey - y) <= 2)
           {
index ba93046..f4bd31c 100755 (executable)
@@ -41,11 +41,6 @@ public class PDBChain
 {
   public static final String RESNUM_FEATURE = "RESNUM";
 
-  /**
-   * SequenceFeature group for PDB File features added to sequences
-   */
-  private static final String PDBFILEFEATURE = "PDBFile";
-
   private static final String IEASTATUS = "IEA:jalview";
 
   public String id;
@@ -83,10 +78,10 @@ public class PDBChain
 
   public String pdbid = "";
 
-  public PDBChain(String pdbid, String id)
+  public PDBChain(String thePdbid, String theId)
   {
-    this.pdbid = pdbid == null ? pdbid : pdbid.toLowerCase();
-    this.id = id;
+    this.pdbid = thePdbid == null ? thePdbid : thePdbid.toLowerCase();
+    this.id = theId;
   }
 
   /**
@@ -167,15 +162,14 @@ public class PDBChain
   }
 
   /**
-   * copy over the RESNUM seqfeatures from the internal chain sequence to the
+   * Copies over the RESNUM seqfeatures from the internal chain sequence to the
    * mapped sequence
    * 
    * @param seq
    * @param status
    *          The Status of the transferred annotation
-   * @return the features added to sq (or its dataset)
    */
-  public SequenceFeature[] transferRESNUMFeatures(SequenceI seq,
+  public void transferRESNUMFeatures(SequenceI seq,
           String status)
   {
     SequenceI sq = seq;
@@ -184,10 +178,11 @@ public class PDBChain
       sq = sq.getDatasetSequence();
       if (sq == sequence)
       {
-        return null;
+        return;
       }
     }
-    /**
+
+    /*
      * Remove any existing features for this chain if they exist ?
      * SequenceFeature[] seqsfeatures=seq.getSequenceFeatures(); int
      * totfeat=seqsfeatures.length; // Remove any features for this exact chain
@@ -197,23 +192,22 @@ public class PDBChain
     {
       status = PDBChain.IEASTATUS;
     }
-    SequenceFeature[] features = sequence.getSequenceFeatures();
-    if (features == null)
-    {
-      return null;
-    }
-    for (int i = 0; i < features.length; i++)
+
+    List<SequenceFeature> features = sequence.getSequenceFeatures();
+    for (SequenceFeature feature : features)
     {
-      if (features[i].getFeatureGroup() != null
-              && features[i].getFeatureGroup().equals(pdbid))
+      if (feature.getFeatureGroup() != null
+              && feature.getFeatureGroup().equals(pdbid))
       {
-        SequenceFeature tx = new SequenceFeature(features[i]);
-        tx.setBegin(1 + residues.elementAt(tx.getBegin() - offset).atoms
-                .elementAt(0).alignmentMapping);
-        tx.setEnd(1 + residues.elementAt(tx.getEnd() - offset).atoms
-                .elementAt(0).alignmentMapping);
+        int newBegin = 1 + residues.elementAt(feature.getBegin() - offset).atoms
+                .elementAt(0).alignmentMapping;
+        int newEnd = 1 + residues.elementAt(feature.getEnd() - offset).atoms
+                .elementAt(0).alignmentMapping;
+        SequenceFeature tx = new SequenceFeature(feature, newBegin, newEnd,
+                feature.getFeatureGroup(), feature.getScore());
         tx.setStatus(status
-                + ((tx.getStatus() == null || tx.getStatus().length() == 0) ? ""
+                + ((tx.getStatus() == null || tx.getStatus().length() == 0)
+                        ? ""
                         : ":" + tx.getStatus()));
         if (tx.begin != 0 && tx.end != 0)
         {
@@ -221,7 +215,6 @@ public class PDBChain
         }
       }
     }
-    return features;
   }
 
   /**
@@ -349,47 +342,48 @@ public class PDBChain
 
       // Add inserted residues as features to the base residue
       Atom currAtom = resAtoms.get(0);
-      if (currAtom.insCode != ' '
-              && !residues.isEmpty()
-              && residues.lastElement().atoms.get(0).resNumber == currAtom.resNumber)
+      if (currAtom.insCode != ' ' && !residues.isEmpty()
+              && residues.lastElement().atoms
+                      .get(0).resNumber == currAtom.resNumber)
       {
-        SequenceFeature sf = new SequenceFeature("INSERTION",
-                currAtom.resName + ":" + currAtom.resNumIns + " " + pdbid
-                        + id, "", offset + count - 1, offset + count - 1,
-                "PDB_INS");
+        String desc = currAtom.resName + ":" + currAtom.resNumIns + " "
+                + pdbid + id;
+        SequenceFeature sf = new SequenceFeature("INSERTION", desc, offset
+                + count - 1, offset + count - 1, "PDB_INS");
         resFeatures.addElement(sf);
         residues.lastElement().atoms.addAll(resAtoms);
       }
       else
       {
-
         // Make a new Residue object with the new atoms vector
         residues.addElement(new Residue(resAtoms, resNumber - 1, count));
 
         Residue tmpres = residues.lastElement();
         Atom tmpat = tmpres.atoms.get(0);
         // Make A new SequenceFeature for the current residue numbering
-        SequenceFeature sf = new SequenceFeature(RESNUM_FEATURE, tmpat.resName
-                + ":" + tmpat.resNumIns + " " + pdbid + id, "", offset
-                + count, offset + count, pdbid);
+        String desc = tmpat.resName
+                + ":" + tmpat.resNumIns + " " + pdbid + id;
+        SequenceFeature sf = new SequenceFeature(RESNUM_FEATURE, desc,
+                offset + count, offset + count, pdbid);
         resFeatures.addElement(sf);
         resAnnotation.addElement(new Annotation(tmpat.tfactor));
         // Keep totting up the sequence
 
-        if ((symbol = ResidueProperties.getAA3Hash().get(tmpat.resName)) == null)
+        if ((symbol = ResidueProperties.getAA3Hash()
+                .get(tmpat.resName)) == null)
         {
           String nucname = tmpat.resName.trim();
           // use the aaIndex rather than call 'toLower' - which would take a bit
           // more time.
           deoxyn = nucname.length() == 2
-                  && ResidueProperties.aaIndex[nucname.charAt(0)] == ResidueProperties.aaIndex['D'];
+                  && ResidueProperties.aaIndex[nucname
+                          .charAt(0)] == ResidueProperties.aaIndex['D'];
           if (tmpat.name.equalsIgnoreCase("CA")
                   || ResidueProperties.nucleotideIndex[nucname
                           .charAt((deoxyn ? 1 : 0))] == -1)
           {
-            char r = ResidueProperties
-                    .getSingleCharacterCode(ResidueProperties
-                            .getCanonicalAminoAcid(tmpat.resName));
+            char r = ResidueProperties.getSingleCharacterCode(
+                    ResidueProperties.getCanonicalAminoAcid(tmpat.resName));
             seq.append(r == '0' ? 'X' : r);
             // System.err.println("PDBReader:Null aa3Hash for " +
             // tmpat.resName);
@@ -405,8 +399,8 @@ public class PDBChain
         {
           if (nucleotide)
           {
-            System.err
-                    .println("Warning: mixed nucleotide and amino acid chain.. its gonna do bad things to you!");
+            System.err.println(
+                    "Warning: mixed nucleotide and amino acid chain.. its gonna do bad things to you!");
           }
           seq.append(ResidueProperties.aa[((Integer) symbol).intValue()]);
         }
@@ -518,8 +512,8 @@ public class PDBChain
       try
       {
         index = ResidueProperties.aa3Hash.get(b.at1.resName).intValue();
-        b.startCol = cs.findColour(ResidueProperties.aa[index].charAt(0),
-                0, null, null, 0f);
+        b.startCol = cs.findColour(ResidueProperties.aa[index].charAt(0), 0,
+                null, null, 0f);
 
         index = ResidueProperties.aa3Hash.get(b.at2.resName).intValue();
         b.endCol = cs.findColour(ResidueProperties.aa[index].charAt(0), 0,
@@ -569,8 +563,8 @@ public class PDBChain
 
         for (AlignmentAnnotation ana : shadow.getAnnotation())
         {
-          List<AlignmentAnnotation> transfer = sq.getAlignmentAnnotations(
-                  ana.getCalcId(), ana.label);
+          List<AlignmentAnnotation> transfer = sq
+                  .getAlignmentAnnotations(ana.getCalcId(), ana.label);
           if (transfer == null || transfer.size() == 0)
           {
             ana = new AlignmentAnnotation(ana);
@@ -611,7 +605,8 @@ public class PDBChain
         // Useful for debugging mappings - adds annotation for mapped position
         float min = -1, max = 0;
         Annotation[] an = new Annotation[sq.getEnd() - sq.getStart() + 1];
-        for (int i = sq.getStart(), j = sq.getEnd(), k = 0; i <= j; i++, k++)
+        for (int i = sq.getStart(), j = sq
+                .getEnd(), k = 0; i <= j; i++, k++)
         {
           int prn = mapping.getPDBResNum(k + 1);
 
index 6d3d342..ebc52aa 100755 (executable)
@@ -48,8 +48,7 @@ public class PDBfile extends StructureFile
 
   public PDBfile(boolean addAlignmentAnnotations, boolean predictSecStr,
           boolean externalSecStr, String dataObject,
-          DataSourceType sourceType)
-          throws IOException
+          DataSourceType sourceType) throws IOException
   {
     super(false, dataObject, sourceType);
     addSettings(addAlignmentAnnotations, predictSecStr, externalSecStr);
@@ -190,9 +189,8 @@ public class PDBfile extends StructureFile
     } catch (OutOfMemoryError er)
     {
       System.out.println("OUT OF MEMORY LOADING PDB FILE");
-      throw new IOException(
-              MessageManager
-                      .getString("exception.outofmemory_loading_pdb_file"));
+      throw new IOException(MessageManager
+              .getString("exception.outofmemory_loading_pdb_file"));
     } catch (NumberFormatException ex)
     {
       if (line != null)
@@ -228,8 +226,8 @@ public class PDBfile extends StructureFile
   public static String relocateCalcId(String calcId,
           Hashtable<String, String> alreadyLoadedPDB) throws Exception
   {
-    int s = CALC_ID_PREFIX.length(), end = calcId
-            .indexOf(CALC_ID_PREFIX, s);
+    int s = CALC_ID_PREFIX.length(),
+            end = calcId.indexOf(CALC_ID_PREFIX, s);
     String between = calcId.substring(s, end - 1);
     return CALC_ID_PREFIX + alreadyLoadedPDB.get(between) + ":"
             + calcId.substring(end);
index 0045e97..3abbe75 100644 (file)
@@ -383,6 +383,8 @@ public class ChimeraResidue implements ChimeraStructuralObject,
   public void splitInsertionCode(String residue)
   {
     // OK, split the index into number and insertion code
+    // JBPNote - m.matches() can be true even if there is no resnum - this can
+    // cause NumberFormatExceptions below
     Pattern p = Pattern.compile("(\\d*)([A-Z]?)");
     Matcher m = p.matcher(residue);
     if (m.matches())
index b806355..e4f2dfa 100755 (executable)
@@ -147,14 +147,13 @@ public class AAFrequency
       {
         if (sequences[row] == null)
         {
-          System.err
-                  .println("WARNING: Consensus skipping null sequence - possible race condition.");
+          System.err.println(
+                  "WARNING: Consensus skipping null sequence - possible race condition.");
           continue;
         }
-        char[] seq = sequences[row].getSequence();
-        if (seq.length > column)
+        if (sequences[row].getLength() > column)
         {
-          char c = seq[column];
+          char c = sequences[row].getCharAt(column);
           residueCounts.add(c);
           if (Comparison.isNucleotide(c))
           {
@@ -316,7 +315,7 @@ public class AAFrequency
     // always set ranges again
     gaprow.graphMax = nseq;
     gaprow.graphMin = 0;
-    double scale = 0.8/nseq;
+    double scale = 0.8 / nseq;
     for (int i = startCol; i < endCol; i++)
     {
       ProfileI profile = profiles.get(i);
@@ -334,9 +333,9 @@ public class AAFrequency
 
       String description = "" + gapped;
 
-      gaprow.annotations[i] = new Annotation("", description,
-              '\0', gapped, jalview.util.ColorUtils.bleachColour(
-                      Color.DARK_GRAY, (float) scale * gapped));
+      gaprow.annotations[i] = new Annotation("", description, '\0', gapped,
+              jalview.util.ColorUtils.bleachColour(Color.DARK_GRAY,
+                      (float) scale * gapped));
     }
   }
 
@@ -345,7 +344,8 @@ public class AAFrequency
    * <ul>
    * <li>the full profile (percentages of all residues present), if
    * showSequenceLogo is true, or</li>
-   * <li>just the modal (most common) residue(s), if showSequenceLogo is false</li>
+   * <li>just the modal (most common) residue(s), if showSequenceLogo is
+   * false</li>
    * </ul>
    * Percentages are as a fraction of all sequence, or only ungapped sequences
    * if ignoreGaps is true.
@@ -366,8 +366,8 @@ public class AAFrequency
     String description = null;
     if (counts != null && showSequenceLogo)
     {
-      int normaliseBy = ignoreGaps ? profile.getNonGapped() : profile
-              .getHeight();
+      int normaliseBy = ignoreGaps ? profile.getNonGapped()
+              : profile.getHeight();
       description = counts.getTooltip(normaliseBy, dp);
     }
     else
@@ -424,8 +424,8 @@ public class AAFrequency
     QuickSort.sort(values, symbols);
     int nextArrayPos = 2;
     int totalPercentage = 0;
-    final int divisor = ignoreGaps ? profile.getNonGapped() : profile
-            .getHeight();
+    final int divisor = ignoreGaps ? profile.getNonGapped()
+            : profile.getHeight();
 
     /*
      * traverse the arrays in reverse order (highest counts first)
@@ -542,8 +542,8 @@ public class AAFrequency
         {
           continue;
         }
-        List<char[]> codons = MappingUtils
-                .findCodonsFor(seq, col, mappings);
+        List<char[]> codons = MappingUtils.findCodonsFor(seq, col,
+                mappings);
         for (char[] codon : codons)
         {
           int codonEncoded = CodingUtils.encodeCodon(codon);
@@ -623,10 +623,10 @@ public class AAFrequency
 
       int modalCodonEncoded = codons[codons.length - 1];
       int modalCodonCount = sortedCodonCounts[codons.length - 1];
-      String modalCodon = String.valueOf(CodingUtils
-              .decodeCodon(modalCodonEncoded));
-      if (sortedCodonCounts.length > 1
-              && sortedCodonCounts[codons.length - 2] == sortedCodonCounts[codons.length - 1])
+      String modalCodon = String
+              .valueOf(CodingUtils.decodeCodon(modalCodonEncoded));
+      if (sortedCodonCounts.length > 1 && sortedCodonCounts[codons.length
+              - 2] == sortedCodonCounts[codons.length - 1])
       {
         /*
          * two or more codons share the modal count
@@ -685,8 +685,8 @@ public class AAFrequency
           {
             if (samePercent.length() > 0)
             {
-              mouseOver.append(samePercent).append(": ")
-                      .append(lastPercent).append("% ");
+              mouseOver.append(samePercent).append(": ").append(lastPercent)
+                      .append("% ");
             }
             samePercent.setLength(0);
             samePercent.append(codon);
index 07f43da..1b2578e 100755 (executable)
@@ -36,6 +36,7 @@ import jalview.util.MessageManager;
 
 import java.awt.Color;
 import java.awt.Graphics;
+import java.io.PrintStream;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -49,6 +50,14 @@ import java.util.StringTokenizer;
  */
 public class AlignSeq
 {
+  private static final int MAX_NAME_LENGTH = 30;
+
+  private static final int GAP_OPEN_COST = 120;
+
+  private static final int GAP_EXTEND_COST = 20;
+
+  private static final int GAP_INDEX = -1;
+
   public static final String PEP = "pep";
 
   public static final String DNA = "dna";
@@ -61,7 +70,7 @@ public class AlignSeq
 
   float[][] F;
 
-  int[][] traceback;
+  int[][] traceback; // todo is this actually used?
 
   int[] seq1;
 
@@ -96,36 +105,29 @@ public class AlignSeq
   /** DOCUMENT ME!! */
   public int seq2start;
 
-  /** DOCUMENT ME!! */
   public int seq2end;
 
   int count;
 
-  /** DOCUMENT ME!! */
   public float maxscore;
 
-  float pid;
-
   int prev = 0;
 
-  int gapOpen = 120;
-
-  int gapExtend = 20;
-
   StringBuffer output = new StringBuffer();
 
   String type; // AlignSeq.PEP or AlignSeq.DNA
 
   private ScoreMatrix scoreMatrix;
 
-  private static final int GAP_INDEX = -1;
-
   /**
    * Creates a new AlignSeq object.
    * 
-   * @param s1 first sequence for alignment
-   * @param s2 second sequence for alignment
-   * @param type molecule type, either AlignSeq.PEP or AlignSeq.DNA
+   * @param s1
+   *          first sequence for alignment
+   * @param s2
+   *          second sequence for alignment
+   * @param type
+   *          molecule type, either AlignSeq.PEP or AlignSeq.DNA
    */
   public AlignSeq(SequenceI s1, SequenceI s2, String type)
   {
@@ -258,8 +260,8 @@ public class AlignSeq
     SequenceI alSeq1 = new Sequence(s1.getName(), getAStr1());
     alSeq1.setStart(s1.getStart() + getSeq1Start() - 1);
     alSeq1.setEnd(s1.getStart() + getSeq1End() - 1);
-    alSeq1.setDatasetSequence(s1.getDatasetSequence() == null ? s1 : s1
-            .getDatasetSequence());
+    alSeq1.setDatasetSequence(
+            s1.getDatasetSequence() == null ? s1 : s1.getDatasetSequence());
     return alSeq1;
   }
 
@@ -272,8 +274,8 @@ public class AlignSeq
     SequenceI alSeq2 = new Sequence(s2.getName(), getAStr2());
     alSeq2.setStart(s2.getStart() + getSeq2Start() - 1);
     alSeq2.setEnd(s2.getStart() + getSeq2End() - 1);
-    alSeq2.setDatasetSequence(s2.getDatasetSequence() == null ? s2 : s2
-            .getDatasetSequence());
+    alSeq2.setDatasetSequence(
+            s2.getDatasetSequence() == null ? s2 : s2.getDatasetSequence());
     return alSeq2;
   }
 
@@ -314,9 +316,9 @@ public class AlignSeq
 
     if (s1str.length() == 0 || s2str.length() == 0)
     {
-      output.append("ALL GAPS: "
-              + (s1str.length() == 0 ? s1.getName() : " ")
-              + (s2str.length() == 0 ? s2.getName() : ""));
+      output.append(
+              "ALL GAPS: " + (s1str.length() == 0 ? s1.getName() : " ")
+                      + (s2str.length() == 0 ? s2.getName() : ""));
       return;
     }
 
@@ -337,14 +339,14 @@ public class AlignSeq
     if (!PEP.equals(moleculeType) && !DNA.equals(moleculeType))
     {
       output.append("Wrong type = dna or pep only");
-      throw new Error(MessageManager.formatMessage(
-              "error.unknown_type_dna_or_pep",
-              new String[] { moleculeType }));
+      throw new Error(MessageManager
+              .formatMessage("error.unknown_type_dna_or_pep", new String[]
+              { moleculeType }));
     }
 
     type = moleculeType;
-    scoreMatrix = ScoreModels.getInstance().getDefaultModel(
-            PEP.equals(type));
+    scoreMatrix = ScoreModels.getInstance()
+            .getDefaultModel(PEP.equals(type));
   }
 
   /**
@@ -375,11 +377,10 @@ public class AlignSeq
       }
     }
 
-    // System.out.println(maxi + " " + maxj + " " + score[maxi][maxj]);
     int i = maxi;
     int j = maxj;
     int trace;
-    maxscore = score[i][j] / 10;
+    maxscore = score[i][j] / 10f;
 
     seq1end = maxi + 1;
     seq2end = maxj + 1;
@@ -448,49 +449,48 @@ public class AlignSeq
   /**
    * DOCUMENT ME!
    */
-  public void printAlignment(java.io.PrintStream os)
+  public void printAlignment(PrintStream os)
   {
     // TODO: Use original sequence characters rather than re-translated
     // characters in output
     // Find the biggest id length for formatting purposes
-    String s1id = s1.getName(), s2id = s2.getName();
-    int maxid = s1.getName().length();
-    if (s2.getName().length() > maxid)
-    {
-      maxid = s2.getName().length();
-    }
-    if (maxid > 30)
+    String s1id = getAlignedSeq1().getDisplayId(true);
+    String s2id = getAlignedSeq2().getDisplayId(true);
+    int nameLength = Math.max(s1id.length(), s2id.length());
+    if (nameLength > MAX_NAME_LENGTH)
     {
-      maxid = 30;
+      int truncateBy = nameLength - MAX_NAME_LENGTH;
+      nameLength = MAX_NAME_LENGTH;
       // JAL-527 - truncate the sequence ids
-      if (s1.getName().length() > maxid)
+      if (s1id.length() > nameLength)
       {
-        s1id = s1.getName().substring(0, 30);
+        int slashPos = s1id.lastIndexOf('/');
+        s1id = s1id.substring(0, slashPos - truncateBy)
+                + s1id.substring(slashPos);
       }
-      if (s2.getName().length() > maxid)
+      if (s2id.length() > nameLength)
       {
-        s2id = s2.getName().substring(0, 30);
+        int slashPos = s2id.lastIndexOf('/');
+        s2id = s2id.substring(0, slashPos - truncateBy)
+                + s2id.substring(slashPos);
       }
     }
-    int len = 72 - maxid - 1;
+    int len = 72 - nameLength - 1;
     int nochunks = ((aseq1.length - count) / len)
             + ((aseq1.length - count) % len > 0 ? 1 : 0);
-    pid = 0;
+    float pid = 0f;
 
     output.append("Score = ").append(score[maxi][maxj]).append(NEWLINE);
     output.append("Length of alignment = ")
             .append(String.valueOf(aseq1.length - count)).append(NEWLINE);
     output.append("Sequence ");
-    output.append(new Format("%" + maxid + "s").form(s1.getName()));
-    output.append(" :  ").append(String.valueOf(s1.getStart()))
-            .append(" - ").append(String.valueOf(s1.getEnd()));
+    Format nameFormat = new Format("%" + nameLength + "s");
+    output.append(nameFormat.form(s1id));
     output.append(" (Sequence length = ")
             .append(String.valueOf(s1str.length())).append(")")
             .append(NEWLINE);
     output.append("Sequence ");
-    output.append(new Format("%" + maxid + "s").form(s2.getName()));
-    output.append(" :  ").append(String.valueOf(s2.getStart()))
-            .append(" - ").append(String.valueOf(s2.getEnd()));
+    output.append(nameFormat.form(s2id));
     output.append(" (Sequence length = ")
             .append(String.valueOf(s2str.length())).append(")")
             .append(NEWLINE).append(NEWLINE);
@@ -500,7 +500,7 @@ public class AlignSeq
     for (int j = 0; j < nochunks; j++)
     {
       // Print the first aligned sequence
-      output.append(new Format("%" + (maxid) + "s").form(s1id)).append(" ");
+      output.append(nameFormat.form(s1id)).append(" ");
 
       for (int i = 0; i < len; i++)
       {
@@ -511,7 +511,7 @@ public class AlignSeq
       }
 
       output.append(NEWLINE);
-      output.append(new Format("%" + (maxid) + "s").form(" ")).append(" ");
+      output.append(nameFormat.form(" ")).append(" ");
 
       /*
        * Print out the match symbols:
@@ -531,7 +531,7 @@ public class AlignSeq
             pid++;
             output.append("|");
           }
-          else if (type.equals("pep"))
+          else if (PEP.equals(type))
           {
             if (pam250.getPairwiseScore(c1, c2) > 0)
             {
@@ -551,8 +551,7 @@ public class AlignSeq
 
       // Now print the second aligned sequence
       output = output.append(NEWLINE);
-      output = output.append(new Format("%" + (maxid) + "s").form(s2id))
-              .append(" ");
+      output = output.append(nameFormat.form(s2id)).append(" ");
 
       for (int i = 0; i < len; i++)
       {
@@ -566,7 +565,8 @@ public class AlignSeq
     }
 
     pid = pid / (aseq1.length - count) * 100;
-    output = output.append(new Format("Percentage ID = %2.2f\n").form(pid));
+    output.append(new Format("Percentage ID = %3.2f\n").form(pid));
+    output.append(NEWLINE);
     try
     {
       os.print(output.toString());
@@ -588,7 +588,6 @@ public class AlignSeq
   public int findTrace(int i, int j)
   {
     int t = 0;
-    // float pairwiseScore = lookup[seq1[i]][seq2[j]];
     float pairwiseScore = scoreMatrix.getPairwiseScore(s1str.charAt(i),
             s2str.charAt(j));
     float max = score[i - 1][j - 1] + (pairwiseScore * 10);
@@ -637,19 +636,19 @@ public class AlignSeq
     // top left hand element
     score[0][0] = scoreMatrix.getPairwiseScore(s1str.charAt(0),
             s2str.charAt(0)) * 10;
-    E[0][0] = -gapExtend;
+    E[0][0] = -GAP_EXTEND_COST;
     F[0][0] = 0;
 
     // Calculate the top row first
     for (int j = 1; j < m; j++)
     {
       // What should these values be? 0 maybe
-      E[0][j] = max(score[0][j - 1] - gapOpen, E[0][j - 1] - gapExtend);
-      F[0][j] = -gapExtend;
+      E[0][j] = max(score[0][j - 1] - GAP_OPEN_COST, E[0][j - 1] - GAP_EXTEND_COST);
+      F[0][j] = -GAP_EXTEND_COST;
 
       float pairwiseScore = scoreMatrix.getPairwiseScore(s1str.charAt(0),
               s2str.charAt(j));
-      score[0][j] = max(pairwiseScore * 10, -gapOpen, -gapExtend);
+      score[0][j] = max(pairwiseScore * 10, -GAP_OPEN_COST, -GAP_EXTEND_COST);
 
       traceback[0][j] = 1;
     }
@@ -657,8 +656,8 @@ public class AlignSeq
     // Now do the left hand column
     for (int i = 1; i < n; i++)
     {
-      E[i][0] = -gapOpen;
-      F[i][0] = max(score[i - 1][0] - gapOpen, F[i - 1][0] - gapExtend);
+      E[i][0] = -GAP_OPEN_COST;
+      F[i][0] = max(score[i - 1][0] - GAP_OPEN_COST, F[i - 1][0] - GAP_EXTEND_COST);
 
       float pairwiseScore = scoreMatrix.getPairwiseScore(s1str.charAt(i),
               s2str.charAt(0));
@@ -671,13 +670,13 @@ public class AlignSeq
     {
       for (int j = 1; j < m; j++)
       {
-        E[i][j] = max(score[i][j - 1] - gapOpen, E[i][j - 1] - gapExtend);
-        F[i][j] = max(score[i - 1][j] - gapOpen, F[i - 1][j] - gapExtend);
+        E[i][j] = max(score[i][j - 1] - GAP_OPEN_COST, E[i][j - 1] - GAP_EXTEND_COST);
+        F[i][j] = max(score[i - 1][j] - GAP_OPEN_COST, F[i - 1][j] - GAP_EXTEND_COST);
 
         float pairwiseScore = scoreMatrix.getPairwiseScore(s1str.charAt(i),
                 s2str.charAt(j));
-        score[i][j] = max(score[i - 1][j - 1]
-                + (pairwiseScore * 10), E[i][j], F[i][j]);
+        score[i][j] = max(score[i - 1][j - 1] + (pairwiseScore * 10),
+                E[i][j], F[i][j]);
         traceback[i][j] = findTrace(i, j);
       }
     }
@@ -863,7 +862,8 @@ public class AlignSeq
    */
   public jalview.datamodel.Mapping getMappingFromS1(boolean allowmismatch)
   {
-    ArrayList<Integer> as1 = new ArrayList<Integer>(), as2 = new ArrayList<Integer>();
+    ArrayList<Integer> as1 = new ArrayList<Integer>(),
+            as2 = new ArrayList<Integer>();
     int pdbpos = s2.getStart() + getSeq2Start() - 2;
     int alignpos = s1.getStart() + getSeq1Start() - 2;
     int lp2 = pdbpos - 3, lp1 = alignpos - 3;
@@ -907,8 +907,8 @@ public class AlignSeq
     }
     // construct range pairs
 
-    int[] mapseq1 = new int[as1.size() + (lastmatch ? 1 : 0)], mapseq2 = new int[as2
-            .size() + (lastmatch ? 1 : 0)];
+    int[] mapseq1 = new int[as1.size() + (lastmatch ? 1 : 0)],
+            mapseq2 = new int[as2.size() + (lastmatch ? 1 : 0)];
     int i = 0;
     for (Integer ip : as1)
     {
@@ -951,7 +951,8 @@ public class AlignSeq
           List<SequenceI> ochains, AlignmentI al, String dnaOrProtein,
           boolean removeOldAnnots)
   {
-    List<SequenceI> orig = new ArrayList<SequenceI>(), repl = new ArrayList<SequenceI>();
+    List<SequenceI> orig = new ArrayList<SequenceI>(),
+            repl = new ArrayList<SequenceI>();
     List<AlignSeq> aligs = new ArrayList<AlignSeq>();
     if (al != null && al.getHeight() > 0)
     {
index 5cf7f08..f5626ce 100644 (file)
@@ -91,9 +91,8 @@ public class AlignmentAnnotationUtils
       {
         continue;
       }
-      if (forSequences != null
-              && (aa.sequenceRef != null && forSequences
-                      .contains(aa.sequenceRef)))
+      if (forSequences != null && (aa.sequenceRef != null
+              && forSequences.contains(aa.sequenceRef)))
       {
         String calcId = aa.getCalcId();
 
@@ -114,8 +113,8 @@ public class AlignmentAnnotationUtils
                   .get(calcId);
           if (groupLabelsForCalcId.containsKey(aa.graphGroup))
           {
-            if (!groupLabelsForCalcId.get(aa.graphGroup).contains(
-                    displayLabel))
+            if (!groupLabelsForCalcId.get(aa.graphGroup)
+                    .contains(displayLabel))
             {
               groupLabelsForCalcId.get(aa.graphGroup).add(displayLabel);
             }
index 693e794..b5cefe0 100755 (executable)
@@ -29,11 +29,11 @@ import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.datamodel.SequenceNode;
-import jalview.util.MessageManager;
 import jalview.util.QuickSort;
 
 import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 
 /**
@@ -53,7 +53,7 @@ import java.util.List;
  */
 public class AlignmentSorter
 {
-  /**
+  /*
    * todo: refactor searches to follow a basic pattern: (search property, last
    * search state, current sort direction)
    */
@@ -71,19 +71,18 @@ public class AlignmentSorter
 
   static boolean sortTreeAscending = true;
 
-  /**
-   * last Annotation Label used by sortByScore
+  /*
+   * last Annotation Label used for sort by Annotation score
    */
-  private static String lastSortByScore;
-
-  private static boolean sortByScoreAscending = true;
+  private static String lastSortByAnnotation;
 
-  /**
-   * compact representation of last arguments to SortByFeatureScore
+  /*
+   * string hash of last arguments to sortByFeature
+   * (sort order toggles if this is unchanged between sorts)
    */
-  private static String lastSortByFeatureScore;
+  private static String sortByFeatureCriteria;
 
-  private static boolean sortByFeatureScoreAscending = true;
+  private static boolean sortByFeatureAscending = true;
 
   private static boolean sortLengthAscending;
 
@@ -109,8 +108,9 @@ public class AlignmentSorter
             true);
     for (int i = 0; i < nSeq; i++)
     {
-      scores[i] = (float) PIDModel.computePID(align.getSequenceAt(i)
-              .getSequenceAsString(), refSeq, pidParams);
+      scores[i] = (float) PIDModel.computePID(
+              align.getSequenceAt(i).getSequenceAsString(), refSeq,
+              pidParams);
       seqs[i] = align.getSequenceAt(i);
     }
 
@@ -416,7 +416,8 @@ public class AlignmentSorter
     }
     else
     {
-      setReverseOrder(align, vectorSubsetToArray(tmp, align.getSequences()));
+      setReverseOrder(align,
+              vectorSubsetToArray(tmp, align.getSequences()));
     }
   }
 
@@ -451,12 +452,9 @@ public class AlignmentSorter
 
       if (tmp.size() != nSeq)
       {
-        System.err
-                .println("WARNING: tmp.size()="
-                        + tmp.size()
-                        + " != nseq="
-                        + nSeq
-                        + " in getOrderByTree - tree contains sequences not in alignment");
+        System.err.println("WARNING: tmp.size()=" + tmp.size() + " != nseq="
+                + nSeq
+                + " in getOrderByTree - tree contains sequences not in alignment");
       }
     }
 
@@ -492,7 +490,8 @@ public class AlignmentSorter
     }
     else
     {
-      setReverseOrder(align, vectorSubsetToArray(tmp, align.getSequences()));
+      setReverseOrder(align,
+              vectorSubsetToArray(tmp, align.getSequences()));
     }
   }
 
@@ -659,9 +658,9 @@ public class AlignmentSorter
     }
 
     jalview.util.QuickSort.sort(scores, seqs);
-    if (lastSortByScore != scoreLabel)
+    if (lastSortByAnnotation != scoreLabel)
     {
-      lastSortByScore = scoreLabel;
+      lastSortByAnnotation = scoreLabel;
       setOrder(alignment, seqs);
     }
     else
@@ -683,100 +682,40 @@ public class AlignmentSorter
   public static String FEATURE_DENSITY = "density";
 
   /**
-   * sort the alignment using the features on each sequence found between start
-   * and stop with the given featureLabel (and optional group qualifier)
+   * Sort sequences by feature score or density, optionally restricted by
+   * feature types, feature groups, or alignment start/end positions.
+   * <p>
+   * If the sort is repeated for the same combination of types and groups, sort
+   * order is reversed.
    * 
-   * @param featureLabel
-   *          (may not be null)
-   * @param groupLabel
-   *          (may be null)
-   * @param start
-   *          (-1 to include non-positional features)
-   * @param stop
-   *          (-1 to only sort on non-positional features)
+   * @param featureTypes
+   *          a list of feature types to include (or null for all)
+   * @param groups
+   *          a list of feature groups to include (or null for all)
+   * @param startCol
+   *          start column position to include (base zero)
+   * @param endCol
+   *          end column position to include (base zero)
    * @param alignment
-   *          - aligned sequences containing features
+   *          the alignment to be sorted
    * @param method
-   *          - one of the string constants FEATURE_SCORE, FEATURE_LABEL,
-   *          FEATURE_DENSITY
+   *          either "average_score" or "density" ("text" not yet implemented)
    */
-  public static void sortByFeature(String featureLabel, String groupLabel,
-          int start, int stop, AlignmentI alignment, String method)
-  {
-    sortByFeature(
-            featureLabel == null ? null
-                    : Arrays.asList(new String[] { featureLabel }),
-            groupLabel == null ? null : Arrays
-                    .asList(new String[] { groupLabel }), start, stop,
-            alignment, method);
-  }
-
-  private static boolean containsIgnoreCase(final String lab,
-          final List<String> labs)
-  {
-    if (labs == null)
-    {
-      return true;
-    }
-    if (lab == null)
-    {
-      return false;
-    }
-    for (String label : labs)
-    {
-      if (lab.equalsIgnoreCase(label))
-      {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  public static void sortByFeature(List<String> featureLabels,
-          List<String> groupLabels, int start, int stop,
+  public static void sortByFeature(List<String> featureTypes,
+          List<String> groups, final int startCol, final int endCol,
           AlignmentI alignment, String method)
   {
     if (method != FEATURE_SCORE && method != FEATURE_LABEL
             && method != FEATURE_DENSITY)
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_error_sortbyfeature"));
-    }
-
-    boolean ignoreScore = method != FEATURE_SCORE;
-    StringBuffer scoreLabel = new StringBuffer();
-    scoreLabel.append(start + stop + method);
-    // This doesn't quite work yet - we'd like to have a canonical ordering that
-    // can be preserved from call to call
-    if (featureLabels != null)
-    {
-      for (String label : featureLabels)
-      {
-        scoreLabel.append(label);
-      }
-    }
-    if (groupLabels != null)
-    {
-      for (String label : groupLabels)
-      {
-        scoreLabel.append(label);
-      }
+      String msg = String
+              .format("Implementation Error - sortByFeature method must be either '%s' or '%s'",
+                      FEATURE_SCORE, FEATURE_DENSITY);
+      System.err.println(msg);
+      return;
     }
 
-    /*
-     * if resorting the same feature, toggle sort order
-     */
-    if (lastSortByFeatureScore == null
-            || !scoreLabel.toString().equals(lastSortByFeatureScore))
-    {
-      sortByFeatureScoreAscending = true;
-    }
-    else
-    {
-      sortByFeatureScoreAscending = !sortByFeatureScoreAscending;
-    }
-    lastSortByFeatureScore = scoreLabel.toString();
+    flipFeatureSortIfUnchanged(method, featureTypes, groups, startCol, endCol);
 
     SequenceI[] seqs = alignment.getSequencesArray();
 
@@ -785,58 +724,44 @@ public class AlignmentSorter
     int hasScores = 0; // number of scores present on set
     double[] scores = new double[seqs.length];
     int[] seqScores = new int[seqs.length];
-    Object[] feats = new Object[seqs.length];
-    double min = 0, max = 0;
+    Object[][] feats = new Object[seqs.length][];
+    double min = 0d;
+    double max = 0d;
+
     for (int i = 0; i < seqs.length; i++)
     {
-      SequenceFeature[] sf = seqs[i].getSequenceFeatures();
-      if (sf == null)
-      {
-        sf = new SequenceFeature[0];
-      }
-      else
-      {
-        SequenceFeature[] tmp = new SequenceFeature[sf.length];
-        for (int s = 0; s < tmp.length; s++)
-        {
-          tmp[s] = sf[s];
-        }
-        sf = tmp;
-      }
-      int sstart = (start == -1) ? start : seqs[i].findPosition(start);
-      int sstop = (stop == -1) ? stop : seqs[i].findPosition(stop);
+      /*
+       * get sequence residues overlapping column region
+       * and features for residue positions and specified types
+       */
+      String[] types = featureTypes == null ? null : featureTypes
+              .toArray(new String[featureTypes.size()]);
+      List<SequenceFeature> sfs = seqs[i].findFeatures(startCol + 1,
+              endCol + 1, types);
+
       seqScores[i] = 0;
       scores[i] = 0.0;
-      int n = sf.length;
-      for (int f = 0; f < sf.length; f++)
+
+      Iterator<SequenceFeature> it = sfs.listIterator();
+      while (it.hasNext())
       {
-        // filter for selection criteria
-        SequenceFeature feature = sf[f];
+        SequenceFeature sf = it.next();
 
         /*
-         * double-check feature overlaps columns (JAL-2544)
-         * (could avoid this with a findPositions(fromCol, toCol) method)
-         * findIndex returns base 1 column values, startCol/endCol are base 0
+         * accept all features with null or empty group, otherwise
+         * check group is one of the currently visible groups
          */
-        boolean noOverlap = seqs[i].findIndex(feature.getBegin()) > stop + 1
-                || seqs[i].findIndex(feature.getEnd()) < start + 1;
-        boolean skipFeatureType = featureLabels != null
-                && !AlignmentSorter.containsIgnoreCase(feature.type,
-                        featureLabels);
-        boolean skipFeatureGroup = groupLabels != null
-                && (feature.getFeatureGroup() != null && !AlignmentSorter
-                        .containsIgnoreCase(feature.getFeatureGroup(),
-                                groupLabels));
-        if (noOverlap || skipFeatureType || skipFeatureGroup)
+        String featureGroup = sf.getFeatureGroup();
+        if (groups != null && featureGroup != null
+                && !"".equals(featureGroup)
+                && !groups.contains(featureGroup))
         {
-          // forget about this feature
-          sf[f] = null;
-          n--;
+          it.remove();
         }
         else
         {
-          // or, also take a look at the scores if necessary.
-          if (!ignoreScore && !Float.isNaN(feature.getScore()))
+          float score = sf.getScore();
+          if (FEATURE_SCORE.equals(method) && !Float.isNaN(score))
           {
             if (seqScores[i] == 0)
             {
@@ -844,33 +769,26 @@ public class AlignmentSorter
             }
             seqScores[i]++;
             hasScore[i] = true;
-            scores[i] += feature.getScore(); // take the first instance of this
-            // score.
+            scores[i] += score;
+            // take the first instance of this score // ??
           }
         }
       }
-      SequenceFeature[] fs;
-      feats[i] = fs = new SequenceFeature[n];
-      if (n > 0)
+
+      feats[i] = sfs.toArray(new SequenceFeature[sfs.size()]);
+      if (!sfs.isEmpty())
       {
-        n = 0;
-        for (int f = 0; f < sf.length; f++)
-        {
-          if (sf[f] != null)
-          {
-            ((SequenceFeature[]) feats[i])[n++] = sf[f];
-          }
-        }
         if (method == FEATURE_LABEL)
         {
-          // order the labels by alphabet
-          String[] labs = new String[fs.length];
-          for (int l = 0; l < labs.length; l++)
+          // order the labels by alphabet (not yet implemented)
+          String[] labs = new String[sfs.size()];
+          for (int l = 0; l < sfs.size(); l++)
           {
-            labs[l] = (fs[l].getDescription() != null ? fs[l]
-                    .getDescription() : fs[l].getType());
+            SequenceFeature sf = sfs.get(l);
+            String description = sf.getDescription();
+            labs[l] = (description != null ? description : sf.getType());
           }
-          QuickSort.sort(labs, ((Object[]) feats[i]));
+          QuickSort.sort(labs, feats[i]);
         }
       }
       if (hasScore[i])
@@ -880,23 +798,18 @@ public class AlignmentSorter
         // update the score bounds.
         if (hasScores == 1)
         {
-          max = min = scores[i];
+          min = scores[i];
+          max = min;
         }
         else
         {
-          if (max < scores[i])
-          {
-            max = scores[i];
-          }
-          if (min > scores[i])
-          {
-            min = scores[i];
-          }
+          max = Math.max(max, scores[i]);
+          min = Math.min(min, scores[i]);
         }
       }
     }
 
-    if (method == FEATURE_SCORE)
+    if (FEATURE_SCORE.equals(method))
     {
       if (hasScores == 0)
       {
@@ -921,9 +834,9 @@ public class AlignmentSorter
           }
         }
       }
-      QuickSort.sortByDouble(scores, seqs, sortByFeatureScoreAscending);
+      QuickSort.sortByDouble(scores, seqs, sortByFeatureAscending);
     }
-    else if (method == FEATURE_DENSITY)
+    else if (FEATURE_DENSITY.equals(method))
     {
       for (int i = 0; i < seqs.length; i++)
       {
@@ -933,18 +846,53 @@ public class AlignmentSorter
         // System.err.println("Sorting on Density: seq "+seqs[i].getName()+
         // " Feats: "+featureCount+" Score : "+scores[i]);
       }
-      QuickSort.sortByDouble(scores, seqs, sortByFeatureScoreAscending);
+      QuickSort.sortByDouble(scores, seqs, sortByFeatureAscending);
     }
-    else
+
+    setOrder(alignment, seqs);
+  }
+
+  /**
+   * Builds a string hash of criteria for sorting, and if unchanged from last
+   * time, reverse the sort order
+   * 
+   * @param method
+   * @param featureTypes
+   * @param groups
+   * @param startCol
+   * @param endCol
+   */
+  protected static void flipFeatureSortIfUnchanged(String method,
+          List<String> featureTypes, List<String> groups,
+          final int startCol, final int endCol)
+  {
+    StringBuilder sb = new StringBuilder(64);
+    sb.append(startCol).append(method).append(endCol);
+    if (featureTypes != null)
     {
-      if (method == FEATURE_LABEL)
-      {
-        throw new Error(
-                MessageManager.getString("error.not_yet_implemented"));
-      }
+      Collections.sort(featureTypes);
+      sb.append(featureTypes.toString());
     }
+    if (groups != null)
+    {
+      Collections.sort(groups);
+      sb.append(groups.toString());
+    }
+    String scoreCriteria = sb.toString();
 
-    setOrder(alignment, seqs);
+    /*
+     * if resorting on the same criteria, toggle sort order
+     */
+    if (sortByFeatureCriteria == null
+            || !scoreCriteria.equals(sortByFeatureCriteria))
+    {
+      sortByFeatureAscending = true;
+    }
+    else
+    {
+      sortByFeatureAscending = !sortByFeatureAscending;
+    }
+    sortByFeatureCriteria = scoreCriteria;
   }
 
 }
index 232cb5d..90d9197 100644 (file)
@@ -35,14 +35,14 @@ import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
-import jalview.io.gff.SequenceOntologyFactory;
+import jalview.datamodel.features.SequenceFeatures;
 import jalview.io.gff.SequenceOntologyI;
 import jalview.schemes.ResidueProperties;
 import jalview.util.Comparison;
 import jalview.util.DBRefUtils;
+import jalview.util.IntRangeComparator;
 import jalview.util.MapList;
 import jalview.util.MappingUtils;
-import jalview.util.RangeComparator;
 import jalview.util.StringUtils;
 
 import java.io.UnsupportedEncodingException;
@@ -51,7 +51,6 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -171,10 +170,12 @@ public class AlignmentUtils
         }
       }
       // TODO use Character.toLowerCase to avoid creating String objects?
-      char[] upstream = new String(ds.getSequence(s.getStart() - 1
-              - ustream_ds, s.getStart() - 1)).toLowerCase().toCharArray();
-      char[] downstream = new String(ds.getSequence(s_end - 1, s_end
-              + dstream_ds)).toLowerCase().toCharArray();
+      char[] upstream = new String(ds
+              .getSequence(s.getStart() - 1 - ustream_ds, s.getStart() - 1))
+                      .toLowerCase().toCharArray();
+      char[] downstream = new String(
+              ds.getSequence(s_end - 1, s_end + dstream_ds)).toLowerCase()
+                      .toCharArray();
       char[] coreseq = s.getSequence();
       char[] nseq = new char[offset + upstream.length + downstream.length
               + coreseq.length];
@@ -189,8 +190,8 @@ public class AlignmentUtils
       System.arraycopy(upstream, 0, nseq, p, upstream.length);
       System.arraycopy(coreseq, 0, nseq, p + upstream.length,
               coreseq.length);
-      System.arraycopy(downstream, 0, nseq, p + coreseq.length
-              + upstream.length, downstream.length);
+      System.arraycopy(downstream, 0, nseq,
+              p + coreseq.length + upstream.length, downstream.length);
       s.setSequence(new String(nseq));
       s.setStart(s.getStart() - ustream_ds);
       s.setEnd(s_end + downstream.length);
@@ -317,9 +318,9 @@ public class AlignmentUtils
    * @return
    */
   protected static boolean mapProteinToCdna(
-          final AlignmentI proteinAlignment,
-          final AlignmentI cdnaAlignment, Set<SequenceI> mappedDna,
-          Set<SequenceI> mappedProtein, boolean xrefsOnly)
+          final AlignmentI proteinAlignment, final AlignmentI cdnaAlignment,
+          Set<SequenceI> mappedDna, Set<SequenceI> mappedProtein,
+          boolean xrefsOnly)
   {
     boolean mappingExistsOrAdded = false;
     List<SequenceI> thisSeqs = proteinAlignment.getSequences();
@@ -348,9 +349,8 @@ public class AlignmentUtils
          * Don't map non-xrefd sequences more than once each. This heuristic
          * allows us to pair up similar sequences in ordered alignments.
          */
-        if (!xrefsOnly
-                && (mappedProtein.contains(aaSeq) || mappedDna
-                        .contains(cdnaSeq)))
+        if (!xrefsOnly && (mappedProtein.contains(aaSeq)
+                || mappedDna.contains(cdnaSeq)))
         {
           continue;
         }
@@ -403,7 +403,8 @@ public class AlignmentUtils
   /**
    * Builds a mapping (if possible) of a cDNA to a protein sequence.
    * <ul>
-   * <li>first checks if the cdna translates exactly to the protein sequence</li>
+   * <li>first checks if the cdna translates exactly to the protein
+   * sequence</li>
    * <li>else checks for translation after removing a STOP codon</li>
    * <li>else checks for translation after removing a START codon</li>
    * <li>if that fails, inspect CDS features on the cDNA sequence</li>
@@ -425,8 +426,9 @@ public class AlignmentUtils
      * String objects.
      */
     final SequenceI proteinDataset = proteinSeq.getDatasetSequence();
-    char[] aaSeqChars = proteinDataset != null ? proteinDataset
-            .getSequence() : proteinSeq.getSequence();
+    char[] aaSeqChars = proteinDataset != null
+            ? proteinDataset.getSequence()
+            : proteinSeq.getSequence();
     final SequenceI cdnaDataset = cdnaSeq.getDatasetSequence();
     char[] cdnaSeqChars = cdnaDataset != null ? cdnaDataset.getSequence()
             : cdnaSeq.getSequence();
@@ -467,8 +469,7 @@ public class AlignmentUtils
      * If lengths still don't match, try ignoring start codon.
      */
     int startOffset = 0;
-    if (cdnaLength != mappedLength
-            && cdnaLength > 2
+    if (cdnaLength != mappedLength && cdnaLength > 2
             && String.valueOf(cdnaSeqChars, 0, CODON_LENGTH).toUpperCase()
                     .equals(ResidueProperties.START))
     {
@@ -482,8 +483,9 @@ public class AlignmentUtils
       /*
        * protein is translation of dna (+/- start/stop codons)
        */
-      MapList map = new MapList(new int[] { cdnaStart, cdnaEnd }, new int[]
-      { proteinStart, proteinEnd }, CODON_LENGTH, 1);
+      MapList map = new MapList(new int[] { cdnaStart, cdnaEnd },
+              new int[]
+              { proteinStart, proteinEnd }, CODON_LENGTH, 1);
       return map;
     }
 
@@ -513,7 +515,8 @@ public class AlignmentUtils
 
     int aaPos = 0;
     int dnaPos = cdnaStart;
-    for (; dnaPos < cdnaSeqChars.length - 2 && aaPos < aaSeqChars.length; dnaPos += CODON_LENGTH, aaPos++)
+    for (; dnaPos < cdnaSeqChars.length - 2
+            && aaPos < aaSeqChars.length; dnaPos += CODON_LENGTH, aaPos++)
     {
       String codon = String.valueOf(cdnaSeqChars, dnaPos, CODON_LENGTH);
       final String translated = ResidueProperties.codonTranslate(codon);
@@ -632,10 +635,9 @@ public class AlignmentUtils
    * @param preserveUnmappedGaps
    * @param preserveMappedGaps
    */
-  public static void alignSequenceAs(SequenceI alignTo,
-          SequenceI alignFrom, AlignedCodonFrame mapping, String myGap,
-          char sourceGap, boolean preserveMappedGaps,
-          boolean preserveUnmappedGaps)
+  public static void alignSequenceAs(SequenceI alignTo, SequenceI alignFrom,
+          AlignedCodonFrame mapping, String myGap, char sourceGap,
+          boolean preserveMappedGaps, boolean preserveUnmappedGaps)
   {
     // TODO generalise to work for Protein-Protein, dna-dna, dna-protein
 
@@ -651,15 +653,16 @@ public class AlignmentUtils
     int toOffset = alignTo.getStart() - 1;
     int sourceGapMappedLength = 0;
     boolean inExon = false;
-    final char[] thisSeq = alignTo.getSequence();
-    final char[] thatAligned = alignFrom.getSequence();
-    StringBuilder thisAligned = new StringBuilder(2 * thisSeq.length);
+    final int toLength = alignTo.getLength();
+    final int fromLength = alignFrom.getLength();
+    StringBuilder thisAligned = new StringBuilder(2 * toLength);
 
     /*
      * Traverse the 'model' aligned sequence
      */
-    for (char sourceChar : thatAligned)
+    for (int i = 0; i < fromLength; i++)
     {
+      char sourceChar = alignFrom.getCharAt(i);
       if (sourceChar == sourceGap)
       {
         sourceGapMappedLength += ratio;
@@ -699,9 +702,9 @@ public class AlignmentUtils
        */
       int intronLength = 0;
       while (basesWritten + toOffset < mappedCodonEnd
-              && thisSeqPos < thisSeq.length)
+              && thisSeqPos < toLength)
       {
-        final char c = thisSeq[thisSeqPos++];
+        final char c = alignTo.getCharAt(thisSeqPos++);
         if (c != myGapChar)
         {
           basesWritten++;
@@ -727,7 +730,7 @@ public class AlignmentUtils
             int gapsToAdd = calculateGapsToInsert(preserveMappedGaps,
                     preserveUnmappedGaps, sourceGapMappedLength, inExon,
                     trailingCopiedGap.length(), intronLength, startOfCodon);
-            for (int i = 0; i < gapsToAdd; i++)
+            for (int k = 0; k < gapsToAdd; k++)
             {
               thisAligned.append(myGapChar);
             }
@@ -755,9 +758,9 @@ public class AlignmentUtils
      * At end of model aligned sequence. Copy any remaining target sequence, optionally
      * including (intron) gaps.
      */
-    while (thisSeqPos < thisSeq.length)
+    while (thisSeqPos < toLength)
     {
-      final char c = thisSeq[thisSeqPos++];
+      final char c = alignTo.getCharAt(thisSeqPos++);
       if (c != myGapChar || preserveUnmappedGaps)
       {
         thisAligned.append(c);
@@ -830,8 +833,9 @@ public class AlignmentUtils
         }
         else
         {
-          gapsToAdd = Math.min(intronLength + trailingGapLength
-                  - sourceGapMappedLength, trailingGapLength);
+          gapsToAdd = Math.min(
+                  intronLength + trailingGapLength - sourceGapMappedLength,
+                  trailingGapLength);
         }
       }
     }
@@ -930,7 +934,8 @@ public class AlignmentUtils
    * @return
    */
   static boolean alignCdsSequenceAsProtein(SequenceI cdsSeq,
-          AlignmentI protein, List<AlignedCodonFrame> mappings, char gapChar)
+          AlignmentI protein, List<AlignedCodonFrame> mappings,
+          char gapChar)
   {
     SequenceI cdsDss = cdsSeq.getDatasetSequence();
     if (cdsDss == null)
@@ -947,7 +952,7 @@ public class AlignmentUtils
       SequenceI peptide = mapping.findAlignedSequence(cdsSeq, protein);
       if (peptide != null)
       {
-        int peptideLength = peptide.getLength();
+        final int peptideLength = peptide.getLength();
         Mapping map = mapping.getMappingBetween(cdsSeq, peptide);
         if (map != null)
         {
@@ -956,21 +961,20 @@ public class AlignmentUtils
           {
             mapList = mapList.getInverse();
           }
-          int cdsLength = cdsDss.getLength();
+          final int cdsLength = cdsDss.getLength();
           int mappedFromLength = MappingUtils.getLength(mapList
                   .getFromRanges());
           int mappedToLength = MappingUtils
                   .getLength(mapList.getToRanges());
           boolean addStopCodon = (cdsLength == mappedFromLength
                   * CODON_LENGTH + CODON_LENGTH)
-                  || (peptide.getDatasetSequence().getLength() == mappedFromLength - 1);
+                  || (peptide.getDatasetSequence()
+                          .getLength() == mappedFromLength - 1);
           if (cdsLength != mappedToLength && !addStopCodon)
           {
-            System.err
-                    .println(String
-                            .format("Can't align cds as protein (length mismatch %d/%d): %s",
-                                    cdsLength, mappedToLength,
-                                    cdsSeq.getName()));
+            System.err.println(String.format(
+                    "Can't align cds as protein (length mismatch %d/%d): %s",
+                    cdsLength, mappedToLength, cdsSeq.getName()));
           }
 
           /*
@@ -984,14 +988,15 @@ public class AlignmentUtils
            * walk over the aligned peptide sequence and insert mapped 
            * codons for residues in the aligned cds sequence 
            */
-          char[] alignedPeptide = peptide.getSequence();
-          char[] nucleotides = cdsDss.getSequence();
           int copiedBases = 0;
           int cdsStart = cdsDss.getStart();
           int proteinPos = peptide.getStart() - 1;
           int cdsCol = 0;
-          for (char residue : alignedPeptide)
+
+          for (int col = 0; col < peptideLength; col++)
           {
+            char residue = peptide.getCharAt(col);
+
             if (Comparison.isGap(residue))
             {
               cdsCol += CODON_LENGTH;
@@ -1009,7 +1014,7 @@ public class AlignmentUtils
               {
                 for (int j = codon[0]; j <= codon[1]; j++)
                 {
-                  char mappedBase = nucleotides[j - cdsStart];
+                  char mappedBase = cdsDss.getCharAt(j - cdsStart);
                   alignedCds[cdsCol++] = mappedBase;
                   copiedBases++;
                 }
@@ -1021,7 +1026,7 @@ public class AlignmentUtils
            * append stop codon if not mapped from protein,
            * closing it up to the end of the mapped sequence
            */
-          if (copiedBases == nucleotides.length - CODON_LENGTH)
+          if (copiedBases == cdsLength - CODON_LENGTH)
           {
             for (int i = alignedCds.length - 1; i >= 0; i--)
             {
@@ -1031,9 +1036,9 @@ public class AlignmentUtils
                 break;
               }
             }
-            for (int i = nucleotides.length - CODON_LENGTH; i < nucleotides.length; i++)
+            for (int i = cdsLength - CODON_LENGTH; i < cdsLength; i++)
             {
-              alignedCds[cdsCol++] = nucleotides[i];
+              alignedCds[cdsCol++] = cdsDss.getCharAt(i);
             }
           }
           cdsSeq.setSequence(new String(alignedCds));
@@ -1087,8 +1092,8 @@ public class AlignmentUtils
         if (prot != null)
         {
           Mapping seqMap = mapping.getMappingForSequence(dnaSeq);
-          addCodonPositions(dnaSeq, prot, protein.getGapCharacter(),
-                  seqMap, alignedCodons);
+          addCodonPositions(dnaSeq, prot, protein.getGapCharacter(), seqMap,
+                  alignedCodons);
           unmappedProtein.remove(prot);
         }
       }
@@ -1141,8 +1146,8 @@ public class AlignmentUtils
         AlignedCodon codon = sequenceCodon.getValue();
         if (codon.peptideCol > 1)
         {
-          System.err
-                  .println("Problem mapping protein with >1 unmapped start positions: "
+          System.err.println(
+                  "Problem mapping protein with >1 unmapped start positions: "
                           + seq.getName());
         }
         else if (codon.peptideCol == 1)
@@ -1153,8 +1158,8 @@ public class AlignmentUtils
           if (lastCodon != null)
           {
             AlignedCodon firstPeptide = new AlignedCodon(lastCodon.pos1,
-                    lastCodon.pos2, lastCodon.pos3, String.valueOf(seq
-                            .getCharAt(0)), 0);
+                    lastCodon.pos2, lastCodon.pos3,
+                    String.valueOf(seq.getCharAt(0)), 0);
             toAdd.put(seq, firstPeptide);
           }
           else
@@ -1203,21 +1208,26 @@ public class AlignmentUtils
           List<SequenceI> unmappedProtein)
   {
     /*
-     * Prefill aligned sequences with gaps before inserting aligned protein
-     * residues.
+     * prefill peptide sequences with gaps 
      */
     int alignedWidth = alignedCodons.size();
     char[] gaps = new char[alignedWidth];
     Arrays.fill(gaps, protein.getGapCharacter());
-    String allGaps = String.valueOf(gaps);
+    Map<SequenceI, char[]> peptides = new HashMap<>();
     for (SequenceI seq : protein.getSequences())
     {
       if (!unmappedProtein.contains(seq))
       {
-        seq.setSequence(allGaps);
+        peptides.put(seq, Arrays.copyOf(gaps, gaps.length));
       }
     }
 
+    /*
+     * Traverse the codons left to right (as defined by CodonComparator)
+     * and insert peptides in each column where the sequence is mapped.
+     * This gives a peptide 'alignment' where residues are aligned if their
+     * corresponding codons occupy the same columns in the cdna alignment.
+     */
     int column = 0;
     for (AlignedCodon codon : alignedCodons.keySet())
     {
@@ -1225,12 +1235,20 @@ public class AlignmentUtils
               .get(codon);
       for (Entry<SequenceI, AlignedCodon> entry : columnResidues.entrySet())
       {
-        // place translated codon at its column position in sequence
-        entry.getKey().getSequence()[column] = entry.getValue().product
-                .charAt(0);
+        char residue = entry.getValue().product.charAt(0);
+        peptides.get(entry.getKey())[column] = residue;
       }
       column++;
     }
+
+    /*
+     * and finally set the constructed sequences
+     */
+    for (Entry<SequenceI, char[]> entry : peptides.entrySet())
+    {
+      entry.getKey().setSequence(new String(entry.getValue()));
+    }
+
     return 0;
   }
 
@@ -1303,7 +1321,8 @@ public class AlignmentUtils
    * <ul>
    * <li>One alignment must be nucleotide, and the other protein</li>
    * <li>At least one pair of sequences must be already mapped, or mappable</li>
-   * <li>Mappable means the nucleotide translation matches the protein sequence</li>
+   * <li>Mappable means the nucleotide translation matches the protein
+   * sequence</li>
    * <li>The translation may ignore start and stop codons if present in the
    * nucleotide</li>
    * </ul>
@@ -1359,9 +1378,10 @@ public class AlignmentUtils
       return false;
     }
 
-    SequenceI dnaDs = dnaSeq.getDatasetSequence() == null ? dnaSeq : dnaSeq
-            .getDatasetSequence();
-    SequenceI proteinDs = proteinSeq.getDatasetSequence() == null ? proteinSeq
+    SequenceI dnaDs = dnaSeq.getDatasetSequence() == null ? dnaSeq
+            : dnaSeq.getDatasetSequence();
+    SequenceI proteinDs = proteinSeq.getDatasetSequence() == null
+            ? proteinSeq
             : proteinSeq.getDatasetSequence();
 
     for (AlignedCodonFrame mapping : mappings)
@@ -1398,8 +1418,7 @@ public class AlignmentUtils
    *          the alignment to check for presence of annotations
    */
   public static void findAddableReferenceAnnotations(
-          List<SequenceI> sequenceScope,
-          Map<String, String> labelForCalcId,
+          List<SequenceI> sequenceScope, Map<String, String> labelForCalcId,
           final Map<SequenceI, List<AlignmentAnnotation>> candidates,
           AlignmentI al)
   {
@@ -1503,8 +1522,8 @@ public class AlignmentUtils
 
   /**
    * 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.
+   * specified sequences. This supports controls like "Show all secondary
+   * structure", "Hide all Temp factor", etc.
    * 
    * @al the alignment to scan for annotations
    * @param types
@@ -1528,9 +1547,8 @@ public class AlignmentUtils
       {
         if (anyType || types.contains(aa.label))
         {
-          if ((aa.sequenceRef != null)
-                  && (forSequences == null || forSequences
-                          .contains(aa.sequenceRef)))
+          if ((aa.sequenceRef != null) && (forSequences == null
+                  || forSequences.contains(aa.sequenceRef)))
           {
             aa.visible = doShow;
           }
@@ -1618,8 +1636,8 @@ public class AlignmentUtils
       productSeqs = new HashSet<SequenceI>();
       for (SequenceI seq : products)
       {
-        productSeqs.add(seq.getDatasetSequence() == null ? seq : seq
-                .getDatasetSequence());
+        productSeqs.add(seq.getDatasetSequence() == null ? seq
+                : seq.getDatasetSequence());
       }
     }
 
@@ -1712,8 +1730,9 @@ public class AlignmentUtils
           /*
            * add a mapping from CDS to the (unchanged) mapped to range
            */
-          List<int[]> cdsRange = Collections.singletonList(new int[] { 1,
-              cdsSeq.getLength() });
+          List<int[]> cdsRange = Collections
+                  .singletonList(new int[]
+                  { 1, cdsSeq.getLength() });
           MapList cdsToProteinMap = new MapList(cdsRange,
                   mapList.getToRanges(), mapList.getFromRatio(),
                   mapList.getToRatio());
@@ -1778,12 +1797,11 @@ public class AlignmentUtils
             // 'CDS|emblcdsacc'
             // assuming cds version same as dna ?!?
 
-            DBRefEntry proteinToCdsRef = new DBRefEntry(
-                    primRef.getSource(), primRef.getVersion(),
-                    cdsSeq.getName());
+            DBRefEntry proteinToCdsRef = new DBRefEntry(primRef.getSource(),
+                    primRef.getVersion(), cdsSeq.getName());
             //
-            proteinToCdsRef.setMap(new Mapping(cdsSeqDss, cdsToProteinMap
-                    .getInverse()));
+            proteinToCdsRef.setMap(
+                    new Mapping(cdsSeqDss, cdsToProteinMap.getInverse()));
             proteinProduct.addDBRef(proteinToCdsRef);
           }
 
@@ -1796,8 +1814,8 @@ public class AlignmentUtils
       }
     }
 
-    AlignmentI cds = new Alignment(cdsSeqs.toArray(new SequenceI[cdsSeqs
-            .size()]));
+    AlignmentI cds = new Alignment(
+            cdsSeqs.toArray(new SequenceI[cdsSeqs.size()]));
     cds.setDataset(dataset);
 
     return cds;
@@ -1834,8 +1852,8 @@ public class AlignmentUtils
      * is this mapping from the whole dna sequence (i.e. CDS)?
      * allowing for possible stop codon on dna but not peptide
      */
-    int mappedFromLength = MappingUtils.getLength(aMapping.getMap()
-            .getFromRanges());
+    int mappedFromLength = MappingUtils
+            .getLength(aMapping.getMap().getFromRanges());
     int dnaLength = seqDss.getLength();
     if (mappedFromLength == dnaLength
             || mappedFromLength == dnaLength - CODON_LENGTH)
@@ -1859,8 +1877,8 @@ public class AlignmentUtils
                 && proteinProduct == mapping.getTo()
                 && seqDss != map.getFromSeq())
         {
-          mappedFromLength = MappingUtils.getLength(mapping.getMap()
-                  .getFromRanges());
+          mappedFromLength = MappingUtils
+                  .getLength(mapping.getMap().getFromRanges());
           if (mappedFromLength == map.getFromSeq().getLength())
           {
             /*
@@ -1958,8 +1976,8 @@ public class AlignmentUtils
           }
           else
           {
-            System.err
-                    .println("JAL-2154 regression: warning - found (and ignnored a duplicate CDS sequence):"
+            System.err.println(
+                    "JAL-2154 regression: warning - found (and ignnored a duplicate CDS sequence):"
                             + mtch.toString());
           }
         }
@@ -2011,16 +2029,17 @@ public class AlignmentUtils
     for (DBRefEntry cdsref : direct)
     {
       // clone maplist and mapping
-      MapList cdsposmap = new MapList(Arrays.asList(new int[][] { new int[]
-      { cdsSeq.getStart(), cdsSeq.getEnd() } }), cdsref.getMap().getMap()
-              .getToRanges(), 3, 1);
-      Mapping cdsmap = new Mapping(cdsref.getMap().getTo(), cdsref.getMap()
-              .getMap());
+      MapList cdsposmap = new MapList(
+              Arrays.asList(new int[][]
+              { new int[] { cdsSeq.getStart(), cdsSeq.getEnd() } }),
+              cdsref.getMap().getMap().getToRanges(), 3, 1);
+      Mapping cdsmap = new Mapping(cdsref.getMap().getTo(),
+              cdsref.getMap().getMap());
 
       // create dbref
       DBRefEntry newref = new DBRefEntry(cdsref.getSource(),
-              cdsref.getVersion(), cdsref.getAccessionId(), new Mapping(
-                      cdsmap.getTo(), cdsposmap));
+              cdsref.getVersion(), cdsref.getAccessionId(),
+              new Mapping(cdsmap.getTo(), cdsposmap));
 
       // and see if we can map to the protein product for this mapping.
       // onSource is the filtered set of accessions on protein that we are
@@ -2055,11 +2074,11 @@ public class AlignmentUtils
    * 
    * @param fromSeq
    * @param toSeq
+   * @param mapping
+   *          the mapping from 'fromSeq' to 'toSeq'
    * @param select
    *          if not null, only features of this type are copied (including
    *          subtypes in the Sequence Ontology)
-   * @param mapping
-   *          the mapping from 'fromSeq' to 'toSeq'
    * @param omitting
    */
   public static int transferFeatures(SequenceI fromSeq, SequenceI toSeq,
@@ -2071,82 +2090,84 @@ public class AlignmentUtils
       copyTo = copyTo.getDatasetSequence();
     }
 
-    SequenceOntologyI so = SequenceOntologyFactory.getInstance();
+    /*
+     * get features, optionally restricted by an ontology term
+     */
+    List<SequenceFeature> sfs = select == null ? fromSeq.getFeatures()
+            .getPositionalFeatures() : fromSeq.getFeatures()
+            .getFeaturesByOntology(select);
+
     int count = 0;
-    SequenceFeature[] sfs = fromSeq.getSequenceFeatures();
-    if (sfs != null)
+    for (SequenceFeature sf : sfs)
     {
-      for (SequenceFeature sf : sfs)
+      String type = sf.getType();
+      boolean omit = false;
+      for (String toOmit : omitting)
       {
-        String type = sf.getType();
-        if (select != null && !so.isA(type, select))
-        {
-          continue;
-        }
-        boolean omit = false;
-        for (String toOmit : omitting)
-        {
-          if (type.equals(toOmit))
-          {
-            omit = true;
-          }
-        }
-        if (omit)
+        if (type.equals(toOmit))
         {
-          continue;
+          omit = true;
         }
+      }
+      if (omit)
+      {
+        continue;
+      }
 
-        /*
-         * locate the mapped range - null if either start or end is
-         * not mapped (no partial overlaps are calculated)
-         */
-        int start = sf.getBegin();
-        int end = sf.getEnd();
-        int[] mappedTo = mapping.locateInTo(start, end);
-        /*
-         * if whole exon range doesn't map, try interpreting it
-         * as 5' or 3' exon overlapping the CDS range
-         */
-        if (mappedTo == null)
-        {
-          mappedTo = mapping.locateInTo(end, end);
-          if (mappedTo != null)
-          {
-            /*
-             * end of exon is in CDS range - 5' overlap
-             * to a range from the start of the peptide
-             */
-            mappedTo[0] = 1;
-          }
-        }
-        if (mappedTo == null)
+      /*
+       * locate the mapped range - null if either start or end is
+       * not mapped (no partial overlaps are calculated)
+       */
+      int start = sf.getBegin();
+      int end = sf.getEnd();
+      int[] mappedTo = mapping.locateInTo(start, end);
+      /*
+       * if whole exon range doesn't map, try interpreting it
+       * as 5' or 3' exon overlapping the CDS range
+       */
+      if (mappedTo == null)
+      {
+        mappedTo = mapping.locateInTo(end, end);
+        if (mappedTo != null)
         {
-          mappedTo = mapping.locateInTo(start, start);
-          if (mappedTo != null)
-          {
-            /*
-             * start of exon is in CDS range - 3' overlap
-             * to a range up to the end of the peptide
-             */
-            mappedTo[1] = toSeq.getLength();
-          }
+          /*
+           * end of exon is in CDS range - 5' overlap
+           * to a range from the start of the peptide
+           */
+          mappedTo[0] = 1;
         }
+      }
+      if (mappedTo == null)
+      {
+        mappedTo = mapping.locateInTo(start, start);
         if (mappedTo != null)
         {
-          SequenceFeature copy = new SequenceFeature(sf);
-          copy.setBegin(Math.min(mappedTo[0], mappedTo[1]));
-          copy.setEnd(Math.max(mappedTo[0], mappedTo[1]));
-          copyTo.addSequenceFeature(copy);
-          count++;
+          /*
+           * start of exon is in CDS range - 3' overlap
+           * to a range up to the end of the peptide
+           */
+          mappedTo[1] = toSeq.getLength();
         }
       }
+      if (mappedTo != null)
+      {
+        int newBegin = Math.min(mappedTo[0], mappedTo[1]);
+        int newEnd = Math.max(mappedTo[0], mappedTo[1]);
+        SequenceFeature copy = new SequenceFeature(sf, newBegin, newEnd,
+                sf.getFeatureGroup(), sf.getScore());
+        copyTo.addSequenceFeature(copy);
+        count++;
+      }
     }
     return count;
   }
 
   /**
    * Returns a mapping from dna to protein by inspecting sequence features of
-   * type "CDS" on the dna.
+   * type "CDS" on the dna. A mapping is constructed if the total CDS feature
+   * length is 3 times the peptide length (optionally after dropping a trailing
+   * stop codon). This method does not check whether the CDS nucleotide sequence
+   * translates to the peptide sequence.
    * 
    * @param dnaSeq
    * @param proteinSeq
@@ -2158,6 +2179,15 @@ public class AlignmentUtils
     List<int[]> ranges = findCdsPositions(dnaSeq);
     int mappedDnaLength = MappingUtils.getLength(ranges);
 
+    /*
+     * if not a whole number of codons, something is wrong,
+     * abort mapping
+     */
+    if (mappedDnaLength % CODON_LENGTH > 0)
+    {
+      return null;
+    }
+
     int proteinLength = proteinSeq.getLength();
     int proteinStart = proteinSeq.getStart();
     int proteinEnd = proteinSeq.getEnd();
@@ -2181,8 +2211,12 @@ public class AlignmentUtils
     if (codesForResidues == (proteinLength + 1))
     {
       // assuming extra codon is for STOP and not in peptide
+      // todo: check trailing codon is indeed a STOP codon
       codesForResidues--;
+      mappedDnaLength -= CODON_LENGTH;
+      MappingUtils.removeEndPositions(CODON_LENGTH, ranges);
     }
+
     if (codesForResidues == proteinLength)
     {
       proteinRange.add(new int[] { proteinStart, proteinEnd });
@@ -2193,7 +2227,7 @@ public class AlignmentUtils
 
   /**
    * Returns a list of CDS ranges found (as sequence positions base 1), i.e. of
-   * start/end positions of sequence features of type "CDS" (or a sub-type of
+   * [start, end] positions of sequence features of type "CDS" (or a sub-type of
    * CDS in the Sequence Ontology). The ranges are sorted into ascending start
    * position order, so this method is only valid for linear CDS in the same
    * sense as the protein product.
@@ -2204,59 +2238,43 @@ public class AlignmentUtils
   public static List<int[]> findCdsPositions(SequenceI dnaSeq)
   {
     List<int[]> result = new ArrayList<int[]>();
-    SequenceFeature[] sfs = dnaSeq.getSequenceFeatures();
-    if (sfs == null)
+
+    List<SequenceFeature> sfs = dnaSeq.getFeatures().getFeaturesByOntology(
+            SequenceOntologyI.CDS);
+    if (sfs.isEmpty())
     {
       return result;
     }
-
-    SequenceOntologyI so = SequenceOntologyFactory.getInstance();
-    int startPhase = 0;
+    SequenceFeatures.sortFeatures(sfs, true);
 
     for (SequenceFeature sf : sfs)
     {
+      int phase = 0;
+      try
+      {
+        phase = Integer.parseInt(sf.getPhase());
+      } catch (NumberFormatException e)
+      {
+        // ignore
+      }
       /*
-       * process a CDS feature (or a sub-type of CDS)
+       * phase > 0 on first codon means 5' incomplete - skip to the start
+       * of the next codon; example ENST00000496384
        */
-      if (so.isA(sf.getType(), SequenceOntologyI.CDS))
+      int begin = sf.getBegin();
+      int end = sf.getEnd();
+      if (result.isEmpty() && phase > 0)
       {
-        int phase = 0;
-        try
-        {
-          phase = Integer.parseInt(sf.getPhase());
-        } catch (NumberFormatException e)
-        {
-          // ignore
-        }
-        /*
-         * phase > 0 on first codon means 5' incomplete - skip to the start
-         * of the next codon; example ENST00000496384
-         */
-        int begin = sf.getBegin();
-        int end = sf.getEnd();
-        if (result.isEmpty())
+        begin += phase;
+        if (begin > end)
         {
-          begin += phase;
-          if (begin > end)
-          {
-            // shouldn't happen!
-            System.err
-                    .println("Error: start phase extends beyond start CDS in "
-                            + dnaSeq.getName());
-          }
+          // shouldn't happen!
+          System.err
+                  .println("Error: start phase extends beyond start CDS in "
+                          + dnaSeq.getName());
         }
-        result.add(new int[] { begin, end });
       }
-    }
-
-    /*
-     * remove 'startPhase' positions (usually 0) from the first range 
-     * so we begin at the start of a complete codon
-     */
-    if (!result.isEmpty())
-    {
-      // TODO JAL-2022 correctly model start phase > 0
-      result.get(0)[0] += startPhase;
+      result.add(new int[] { begin, end });
     }
 
     /*
@@ -2266,7 +2284,7 @@ public class AlignmentUtils
      * ranges are assembled in order. Other cases should not use this method,
      * but instead construct an explicit mapping for CDS (e.g. EMBL parsing).
      */
-    Collections.sort(result, new RangeComparator(true));
+    Collections.sort(result, IntRangeComparator.ASCENDING);
     return result;
   }
 
@@ -2319,24 +2337,6 @@ public class AlignmentUtils
       count += computePeptideVariants(peptide, peptidePos, codonVariants);
     }
 
-    /*
-     * sort to get sequence features in start position order
-     * - would be better to store in Sequence as a TreeSet or NCList?
-     */
-    if (peptide.getSequenceFeatures() != null)
-    {
-      Arrays.sort(peptide.getSequenceFeatures(),
-              new Comparator<SequenceFeature>()
-              {
-                @Override
-                public int compare(SequenceFeature o1, SequenceFeature o2)
-                {
-                  int c = Integer.compare(o1.getBegin(), o2.getBegin());
-                  return c == 0 ? Integer.compare(o1.getEnd(), o2.getEnd())
-                          : c;
-                }
-              });
-    }
     return count;
   }
 
@@ -2455,8 +2455,8 @@ public class AlignmentUtils
      * are currently ignored here
      */
     String trans = codon.contains("-") ? "-"
-            : (codon.length() > CODON_LENGTH ? null : ResidueProperties
-                    .codonTranslate(codon));
+            : (codon.length() > CODON_LENGTH ? null
+                    : ResidueProperties.codonTranslate(codon));
     if (trans != null && !trans.equals(residue))
     {
       String residue3Char = StringUtils
@@ -2464,10 +2464,9 @@ public class AlignmentUtils
       String trans3Char = StringUtils
               .toSentenceCase(ResidueProperties.aa2Triplet.get(trans));
       String desc = "p." + residue3Char + peptidePos + trans3Char;
-      // set score to 0f so 'graduated colour' option is offered! JAL-2060
       SequenceFeature sf = new SequenceFeature(
               SequenceOntologyI.SEQUENCE_VARIANT, desc, peptidePos,
-              peptidePos, 0f, var.getSource());
+              peptidePos, var.getSource());
       StringBuilder attributes = new StringBuilder(32);
       String id = (String) var.variant.getValue(ID);
       if (id != null)
@@ -2482,10 +2481,8 @@ public class AlignmentUtils
         StringBuilder link = new StringBuilder(32);
         try
         {
-          link.append(desc)
-                  .append(" ")
-                  .append(id)
-                  .append("|http://www.ensembl.org/Homo_sapiens/Variation/Summary?v=")
+          link.append(desc).append(" ").append(id).append(
+                  "|http://www.ensembl.org/Homo_sapiens/Variation/Summary?v=")
                   .append(URLEncoder.encode(id, "UTF-8"));
           sf.addLink(link.toString());
         } catch (UnsupportedEncodingException e)
@@ -2527,10 +2524,10 @@ public class AlignmentUtils
      * LinkedHashMap ensures we keep the peptide features in sequence order
      */
     LinkedHashMap<Integer, List<DnaVariant>[]> variants = new LinkedHashMap<Integer, List<DnaVariant>[]>();
-    SequenceOntologyI so = SequenceOntologyFactory.getInstance();
 
-    SequenceFeature[] dnaFeatures = dnaSeq.getSequenceFeatures();
-    if (dnaFeatures == null)
+    List<SequenceFeature> dnaFeatures = dnaSeq.getFeatures()
+            .getFeaturesByOntology(SequenceOntologyI.SEQUENCE_VARIANT);
+    if (dnaFeatures.isEmpty())
     {
       return variants;
     }
@@ -2550,84 +2547,80 @@ public class AlignmentUtils
         // not handling multi-locus variant features
         continue;
       }
-      if (so.isA(sf.getType(), SequenceOntologyI.SEQUENCE_VARIANT))
+      int[] mapsTo = dnaToProtein.locateInTo(dnaCol, dnaCol);
+      if (mapsTo == null)
       {
-        int[] mapsTo = dnaToProtein.locateInTo(dnaCol, dnaCol);
-        if (mapsTo == null)
-        {
-          // feature doesn't lie within coding region
-          continue;
-        }
-        int peptidePosition = mapsTo[0];
-        List<DnaVariant>[] codonVariants = variants.get(peptidePosition);
-        if (codonVariants == null)
-        {
-          codonVariants = new ArrayList[CODON_LENGTH];
-          codonVariants[0] = new ArrayList<DnaVariant>();
-          codonVariants[1] = new ArrayList<DnaVariant>();
-          codonVariants[2] = new ArrayList<DnaVariant>();
-          variants.put(peptidePosition, codonVariants);
-        }
+        // feature doesn't lie within coding region
+        continue;
+      }
+      int peptidePosition = mapsTo[0];
+      List<DnaVariant>[] codonVariants = variants.get(peptidePosition);
+      if (codonVariants == null)
+      {
+        codonVariants = new ArrayList[CODON_LENGTH];
+        codonVariants[0] = new ArrayList<DnaVariant>();
+        codonVariants[1] = new ArrayList<DnaVariant>();
+        codonVariants[2] = new ArrayList<DnaVariant>();
+        variants.put(peptidePosition, codonVariants);
+      }
 
-        /*
-         * extract dna variants to a string array
-         */
-        String alls = (String) sf.getValue("alleles");
-        if (alls == null)
-        {
-          continue;
-        }
-        String[] alleles = alls.toUpperCase().split(",");
-        int i = 0;
-        for (String allele : alleles)
-        {
-          alleles[i++] = allele.trim(); // lose any space characters "A, G"
-        }
+      /*
+       * extract dna variants to a string array
+       */
+      String alls = (String) sf.getValue("alleles");
+      if (alls == null)
+      {
+        continue;
+      }
+      String[] alleles = alls.toUpperCase().split(",");
+      int i = 0;
+      for (String allele : alleles)
+      {
+        alleles[i++] = allele.trim(); // lose any space characters "A, G"
+      }
 
-        /*
-         * get this peptide's codon positions e.g. [3, 4, 5] or [4, 7, 10]
-         */
-        int[] codon = peptidePosition == lastPeptidePostion ? lastCodon
-                : MappingUtils.flattenRanges(dnaToProtein.locateInFrom(
-                        peptidePosition, peptidePosition));
-        lastPeptidePostion = peptidePosition;
-        lastCodon = codon;
+      /*
+       * get this peptide's codon positions e.g. [3, 4, 5] or [4, 7, 10]
+       */
+      int[] codon = peptidePosition == lastPeptidePostion ? lastCodon
+              : MappingUtils.flattenRanges(dnaToProtein.locateInFrom(
+                      peptidePosition, peptidePosition));
+      lastPeptidePostion = peptidePosition;
+      lastCodon = codon;
 
-        /*
-         * save nucleotide (and any variant) for each codon position
-         */
-        for (int codonPos = 0; codonPos < CODON_LENGTH; codonPos++)
+      /*
+       * save nucleotide (and any variant) for each codon position
+       */
+      for (int codonPos = 0; codonPos < CODON_LENGTH; codonPos++)
+      {
+        String nucleotide = String.valueOf(
+                dnaSeq.getCharAt(codon[codonPos] - dnaStart)).toUpperCase();
+        List<DnaVariant> codonVariant = codonVariants[codonPos];
+        if (codon[codonPos] == dnaCol)
         {
-          String nucleotide = String.valueOf(
-                  dnaSeq.getCharAt(codon[codonPos] - dnaStart))
-                  .toUpperCase();
-          List<DnaVariant> codonVariant = codonVariants[codonPos];
-          if (codon[codonPos] == dnaCol)
+          if (!codonVariant.isEmpty()
+                  && codonVariant.get(0).variant == null)
           {
-            if (!codonVariant.isEmpty()
-                    && codonVariant.get(0).variant == null)
-            {
-              /*
-               * already recorded base value, add this variant
-               */
-              codonVariant.get(0).variant = sf;
-            }
-            else
-            {
-              /*
-               * add variant with base value
-               */
-              codonVariant.add(new DnaVariant(nucleotide, sf));
-            }
+            /*
+             * already recorded base value, add this variant
+             */
+            codonVariant.get(0).variant = sf;
           }
-          else if (codonVariant.isEmpty())
+          else
           {
             /*
-             * record (possibly non-varying) base value
+             * add variant with base value
              */
-            codonVariant.add(new DnaVariant(nucleotide));
+            codonVariant.add(new DnaVariant(nucleotide, sf));
           }
         }
+        else if (codonVariant.isEmpty())
+        {
+          /*
+           * record (possibly non-varying) base value
+           */
+          codonVariant.add(new DnaVariant(nucleotide));
+        }
       }
     }
     return variants;
@@ -2811,8 +2804,8 @@ public class AlignmentUtils
      */
     for (SequenceI seq : unaligned.getSequences())
     {
-      List<SequenceI> alignedSequences = alignedDatasets.get(seq
-              .getDatasetSequence());
+      List<SequenceI> alignedSequences = alignedDatasets
+              .get(seq.getDatasetSequence());
       // TODO: getSequenceAsString() will be deprecated in the future
       // TODO: need to leave to SequenceI implementor to update gaps
       seq.setSequence(alignedSequences.get(0).getSequenceAsString());
@@ -2836,7 +2829,8 @@ public class AlignmentUtils
    * @return
    */
   static SortedMap<Integer, Map<SequenceI, Character>> buildMappedColumnsMap(
-          AlignmentI unaligned, AlignmentI aligned, List<SequenceI> unmapped)
+          AlignmentI unaligned, AlignmentI aligned,
+          List<SequenceI> unmapped)
   {
     /*
      * Map will hold, for each aligned column position, a map of
@@ -2871,7 +2865,8 @@ public class AlignmentUtils
   }
 
   /**
-   * Helper method that adds to a map the mapped column positions of a sequence. <br>
+   * Helper method that adds to a map the mapped column positions of a sequence.
+   * <br>
    * For example if aaTT-Tg-gAAA is mapped to TTTAAA then the map should record
    * that columns 3,4,6,10,11,12 map to characters T,T,T,A,A,A of the mapped to
    * sequence.
@@ -2900,13 +2895,11 @@ public class AlignmentUtils
      */
     if (seqMap.getTo() == fromSeq.getDatasetSequence())
     {
-      seqMap = new Mapping(seq.getDatasetSequence(), seqMap.getMap()
-              .getInverse());
+      seqMap = new Mapping(seq.getDatasetSequence(),
+              seqMap.getMap().getInverse());
     }
 
-    char[] fromChars = fromSeq.getSequence();
     int toStart = seq.getStart();
-    char[] toChars = seq.getSequence();
 
     /*
      * traverse [start, end, start, end...] ranges in fromSeq
@@ -2937,10 +2930,10 @@ public class AlignmentUtils
          * of the next character of the mapped-to sequence; stop when all
          * the characters of the range have been counted
          */
-        while (mappedCharPos <= range[1] && fromCol <= fromChars.length
+        while (mappedCharPos <= range[1] && fromCol <= fromSeq.getLength()
                 && fromCol >= 0)
         {
-          if (!Comparison.isGap(fromChars[fromCol - 1]))
+          if (!Comparison.isGap(fromSeq.getCharAt(fromCol - 1)))
           {
             /*
              * mapped from sequence has a character in this column
@@ -2952,7 +2945,7 @@ public class AlignmentUtils
               seqsMap = new HashMap<SequenceI, Character>();
               map.put(fromCol, seqsMap);
             }
-            seqsMap.put(seq, toChars[mappedCharPos - toStart]);
+            seqsMap.put(seq, seq.getCharAt(mappedCharPos - toStart));
             mappedCharPos++;
           }
           fromCol += (forward ? 1 : -1);
index 711e8c9..2f556f1 100644 (file)
@@ -50,8 +50,8 @@ public class AnnotationSorter
   public enum SequenceAnnotationOrder
   {
     // Text descriptions surface in the Preferences Sort by... options
-    SEQUENCE_AND_LABEL("Sequence"), LABEL_AND_SEQUENCE("Label"), NONE(
-            "No sort");
+    SEQUENCE_AND_LABEL("Sequence"), LABEL_AND_SEQUENCE("Label"),
+    NONE("No sort");
 
     private String description;
 
@@ -108,7 +108,8 @@ public class AnnotationSorter
    * <ul>
    * <li>annotations with a reference to a sequence in the alignment are sorted
    * on sequence ordering</li>
-   * <li>other annotations go 'at the end', with their mutual order unchanged</li>
+   * <li>other annotations go 'at the end', with their mutual order
+   * unchanged</li>
    * <li>within the same sequence ref, sort by label (non-case-sensitive)</li>
    * </ul>
    */
@@ -169,7 +170,8 @@ public class AnnotationSorter
    * <ul>
    * <li>annotations with a reference to a sequence in the alignment are sorted
    * on label (non-case-sensitive)</li>
-   * <li>other annotations go 'at the end', with their mutual order unchanged</li>
+   * <li>other annotations go 'at the end', with their mutual order
+   * unchanged</li>
    * <li>within the same label, sort by order of the related sequences</li>
    * </ul>
    */
@@ -278,7 +280,8 @@ public class AnnotationSorter
     // cache 'alignment sequence position' for the annotations
     saveSequenceIndices(alignmentAnnotations);
 
-    Comparator<? super AlignmentAnnotation> comparator = getComparator(order);
+    Comparator<? super AlignmentAnnotation> comparator = getComparator(
+            order);
 
     if (alignmentAnnotations != null)
     {
index 907109e..c726627 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.analysis;
 
 import jalview.api.analysis.ScoreModelI;
@@ -46,8 +66,8 @@ public class AverageDistanceTree extends TreeBuilder
     {
       if ((l != i) && (l != j))
       {
-        newdist[l] = ((distances.getValue(i, l) * noi) + (distances
-                .getValue(j, l) * noj)) / (noi + noj);
+        newdist[l] = ((distances.getValue(i, l) * noi)
+                + (distances.getValue(j, l) * noj)) / (noi + noj);
       }
       else
       {
index 2b5a8f6..131b39c 100755 (executable)
@@ -143,8 +143,8 @@ public class Conservation
    * @param end
    *          end column position
    */
-  public Conservation(String name, int threshold,
-          List<SequenceI> sequences, int start, int end)
+  public Conservation(String name, int threshold, List<SequenceI> sequences,
+          int start, int end)
   {
     this.name = name;
     this.threshold = threshold;
@@ -244,8 +244,8 @@ public class Conservation
     else
     {
       // JBPNote INFO level debug
-      System.err
-              .println("ERROR: calcSeqNum called with out of range sequence index for Alignment\n");
+      System.err.println(
+              "ERROR: calcSeqNum called with out of range sequence index for Alignment\n");
     }
   }
 
@@ -414,7 +414,8 @@ public class Conservation
         continue;
       }
 
-      char c = sequences[i].getCharAt(column); // gaps do not have upper/lower case
+      char c = sequences[i].getCharAt(column); // gaps do not have upper/lower
+                                               // case
 
       if (Comparison.isGap((c)))
       {
@@ -618,7 +619,8 @@ public class Conservation
    * @param endCol
    * @param scoreMatrix
    */
-  protected void findQuality(int startCol, int endCol, ScoreMatrix scoreMatrix)
+  protected void findQuality(int startCol, int endCol,
+          ScoreMatrix scoreMatrix)
   {
     quality = new Vector<Double>();
 
@@ -734,28 +736,23 @@ public class Conservation
   public void completeAnnotations(AlignmentAnnotation conservation,
           AlignmentAnnotation quality2, int istart, int alWidth)
   {
-    char[] sequence = getConsSequence().getSequence();
-    float minR;
-    float minG;
-    float minB;
-    float maxR;
-    float maxG;
-    float maxB;
-    minR = 0.3f;
-    minG = 0.0f;
-    minB = 0f;
-    maxR = 1.0f - minR;
-    maxG = 0.9f - minG;
-    maxB = 0f - minB; // scalable range for colouring both Conservation and
-    // Quality
+    SequenceI cons = getConsSequence();
+
+    /*
+     * colour scale for Conservation and Quality;
+     */
+    float minR = 0.3f;
+    float minG = 0.0f;
+    float minB = 0f;
+    float maxR = 1.0f - minR;
+    float maxG = 0.9f - minG;
+    float maxB = 0f - minB;
 
     float min = 0f;
     float max = 11f;
     float qmin = 0f;
     float qmax = 0f;
 
-    char c;
-
     if (conservation != null && conservation.annotations != null
             && conservation.annotations.length < alWidth)
     {
@@ -778,7 +775,7 @@ public class Conservation
     {
       float value = 0;
 
-      c = sequence[i];
+      char c = cons.getCharAt(i);
 
       if (Character.isDigit(c))
       {
@@ -798,11 +795,11 @@ public class Conservation
         float vprop = value - min;
         vprop /= max;
         int consp = i - start;
-        String conssym = (value > 0 && consp > -1 && consp < consSymbs.length) ? consSymbs[consp]
-                : "";
+        String conssym = (value > 0 && consp > -1
+                && consp < consSymbs.length) ? consSymbs[consp] : "";
         conservation.annotations[i] = new Annotation(String.valueOf(c),
-                conssym, ' ', value, new Color(minR + (maxR * vprop), minG
-                        + (maxG * vprop), minB + (maxB * vprop)));
+                conssym, ' ', value, new Color(minR + (maxR * vprop),
+                        minG + (maxG * vprop), minB + (maxB * vprop)));
       }
 
       // Quality calc
@@ -811,10 +808,9 @@ public class Conservation
         value = quality.elementAt(i).floatValue();
         float vprop = value - qmin;
         vprop /= qmax;
-        quality2.annotations[i] = new Annotation(" ",
-                String.valueOf(value), ' ', value, new Color(minR
-                        + (maxR * vprop), minG + (maxG * vprop), minB
-                        + (maxB * vprop)));
+        quality2.annotations[i] = new Annotation(" ", String.valueOf(value),
+                ' ', value, new Color(minR + (maxR * vprop),
+                        minG + (maxG * vprop), minB + (maxB * vprop)));
       }
     }
   }
@@ -865,11 +861,12 @@ public class Conservation
    */
   String getTooltip(int column)
   {
-    char[] sequence = getConsSequence().getSequence();
-    char val = column < sequence.length ? sequence[column] : '-';
+    SequenceI cons = getConsSequence();
+    char val = column < cons.getLength() ? cons.getCharAt(column) : '-';
     boolean hasConservation = val != '-' && val != '0';
     int consp = column - start;
-    String tip = (hasConservation && consp > -1 && consp < consSymbs.length) ? consSymbs[consp]
+    String tip = (hasConservation && consp > -1 && consp < consSymbs.length)
+            ? consSymbs[consp]
             : "";
     return tip;
   }
index 4ba7e41..e6bae9b 100644 (file)
@@ -164,8 +164,8 @@ public class CrossRef
        */
       for (SequenceI rs : foundSeqs)
       {
-        DBRefEntry[] xrs = DBRefUtils
-                .selectDbRefs(!fromDna, rs.getDBRefs());
+        DBRefEntry[] xrs = DBRefUtils.selectDbRefs(!fromDna,
+                rs.getDBRefs());
         addXrefsToSources(xrs, sources);
       }
     }
@@ -230,8 +230,8 @@ public class CrossRef
         dss = dss.getDatasetSequence();
       }
       boolean found = false;
-      DBRefEntry[] xrfs = DBRefUtils
-              .selectDbRefs(!fromDna, dss.getDBRefs());
+      DBRefEntry[] xrfs = DBRefUtils.selectDbRefs(!fromDna,
+              dss.getDBRefs());
       // ENST & ENSP comes in to both Protein and nucleotide, so we need to
       // filter them
       // out later.
@@ -291,13 +291,10 @@ public class CrossRef
             if (matchInDataset != null && xref.getMap().getTo() != null
                     && matchInDataset != xref.getMap().getTo())
             {
-              System.err
-                      .println("Implementation problem (reopen JAL-2154): CrossRef.findInDataset seems to have recovered a different sequence than the one explicitly mapped for xref."
-                              + "Found:"
-                              + matchInDataset
-                              + "\nExpected:"
-                              + xref.getMap().getTo()
-                              + "\nFor xref:"
+              System.err.println(
+                      "Implementation problem (reopen JAL-2154): CrossRef.findInDataset seems to have recovered a different sequence than the one explicitly mapped for xref."
+                              + "Found:" + matchInDataset + "\nExpected:"
+                              + xref.getMap().getTo() + "\nFor xref:"
                               + xref);
             }
             /*matcher.findIdMatch(mappedTo);*/
@@ -323,8 +320,9 @@ public class CrossRef
                 }
                 else
                 {
-                  cf.addMap(matchInDataset, dss, xref.getMap().getMap()
-                          .getInverse(), xref.getMap().getMappedFromId());
+                  cf.addMap(matchInDataset, dss,
+                          xref.getMap().getMap().getInverse(),
+                          xref.getMap().getMappedFromId());
                 }
               }
 
@@ -340,8 +338,8 @@ public class CrossRef
               if (fromDna)
               {
                 // map is from dna seq to a protein product
-                cf.addMap(dss, rsq, xref.getMap().getMap(), xref.getMap()
-                        .getMappedFromId());
+                cf.addMap(dss, rsq, xref.getMap().getMap(),
+                        xref.getMap().getMappedFromId());
               }
               else
               {
@@ -355,8 +353,8 @@ public class CrossRef
 
         if (!found)
         {
-          SequenceI matchedSeq = matcher.findIdMatch(xref.getSource() + "|"
-                  + xref.getAccessionId());
+          SequenceI matchedSeq = matcher.findIdMatch(
+                  xref.getSource() + "|" + xref.getAccessionId());
           // if there was a match, check it's at least the right type of
           // molecule!
           if (matchedSeq != null && matchedSeq.isProtein() == fromDna)
@@ -406,8 +404,8 @@ public class CrossRef
   {
     ASequenceFetcher sftch = SequenceFetcherFactory.getSequenceFetcher();
     SequenceI[] retrieved = null;
-    SequenceI dss = seq.getDatasetSequence() == null ? seq : seq
-            .getDatasetSequence();
+    SequenceI dss = seq.getDatasetSequence() == null ? seq
+            : seq.getDatasetSequence();
     // first filter in case we are retrieving crossrefs that have already been
     // retrieved. this happens for cases where a database record doesn't yield
     // protein products for CDS
@@ -423,8 +421,8 @@ public class CrossRef
       retrieved = sftch.getSequences(sourceRefs, !fromDna);
     } catch (Exception e)
     {
-      System.err
-              .println("Problem whilst retrieving cross references for Sequence : "
+      System.err.println(
+              "Problem whilst retrieving cross references for Sequence : "
                       + seq.getName());
       e.printStackTrace();
     }
@@ -432,14 +430,16 @@ public class CrossRef
     if (retrieved != null)
     {
       boolean addedXref = false;
-      List<SequenceI> newDsSeqs = new ArrayList<SequenceI>(), doNotAdd = new ArrayList<SequenceI>();
+      List<SequenceI> newDsSeqs = new ArrayList<SequenceI>(),
+              doNotAdd = new ArrayList<SequenceI>();
 
       for (SequenceI retrievedSequence : retrieved)
       {
         // dataset gets contaminated ccwith non-ds sequences. why ??!
         // try: Ensembl -> Nuc->Ensembl, Nuc->Uniprot-->Protein->EMBL->
-        SequenceI retrievedDss = retrievedSequence.getDatasetSequence() == null ? retrievedSequence
-                : retrievedSequence.getDatasetSequence();
+        SequenceI retrievedDss = retrievedSequence
+                .getDatasetSequence() == null ? retrievedSequence
+                        : retrievedSequence.getDatasetSequence();
         addedXref |= importCrossRefSeq(cf, newDsSeqs, doNotAdd, dss,
                 retrievedDss);
       }
@@ -452,8 +452,9 @@ public class CrossRef
         {
           // dataset gets contaminated ccwith non-ds sequences. why ??!
           // try: Ensembl -> Nuc->Ensembl, Nuc->Uniprot-->Protein->EMBL->
-          SequenceI retrievedDss = retrievedSequence.getDatasetSequence() == null ? retrievedSequence
-                  : retrievedSequence.getDatasetSequence();
+          SequenceI retrievedDss = retrievedSequence
+                  .getDatasetSequence() == null ? retrievedSequence
+                          : retrievedSequence.getDatasetSequence();
           addedXref |= importCrossRefSeq(cf, newDsSeqs, doNotAdd, dss,
                   retrievedDss);
         }
@@ -577,9 +578,8 @@ public class CrossRef
               int sf = map.getMap().getToLowest();
               int st = map.getMap().getToHighest();
               SequenceI mappedrg = ms.getSubSequence(sf, st);
-              if (mappedrg.getLength() > 0
-                      && ms.getSequenceAsString().equals(
-                              matched.getSequenceAsString()))
+              if (mappedrg.getLength() > 0 && ms.getSequenceAsString()
+                      .equals(matched.getSequenceAsString()))
               {
                 /*
                  * sequences were a match, 
@@ -597,8 +597,8 @@ public class CrossRef
                    */
                   for (DBRefEntry ref : toRefs)
                   {
-                    if (dbref.getSrcAccString().equals(
-                            ref.getSrcAccString()))
+                    if (dbref.getSrcAccString()
+                            .equals(ref.getSrcAccString()))
                     {
                       continue; // avoid overwriting the ref on source sequence
                     }
@@ -619,34 +619,31 @@ public class CrossRef
                  * duplication (e.g. same variation from two 
                  * transcripts)
                  */
-                SequenceFeature[] sfs = ms.getSequenceFeatures();
-                if (sfs != null)
+                List<SequenceFeature> sfs = ms.getFeatures()
+                        .getAllFeatures();
+                for (SequenceFeature feat : sfs)
                 {
-                  for (SequenceFeature feat : sfs)
+                  /*
+                   * make a flyweight feature object which ignores Parent
+                   * attribute in equality test; this avoids creating many
+                   * otherwise duplicate exon features on genomic sequence
+                   */
+                  SequenceFeature newFeature = new SequenceFeature(feat)
                   {
-                    /*
-                     * make a flyweight feature object which ignores Parent
-                     * attribute in equality test; this avoids creating many
-                     * otherwise duplicate exon features on genomic sequence
-                     */
-                    SequenceFeature newFeature = new SequenceFeature(feat)
+                    @Override
+                    public boolean equals(Object o)
                     {
-                      @Override
-                      public boolean equals(Object o)
-                      {
-                        return super.equals(o, true);
-                      }
-                    };
-                    matched.addSequenceFeature(newFeature);
-                  }
+                      return super.equals(o, true);
+                    }
+                  };
+                  matched.addSequenceFeature(newFeature);
                 }
-
               }
               cf.addMap(retrievedSequence, map.getTo(), map.getMap());
             } catch (Exception e)
             {
-              System.err
-                      .println("Exception when consolidating Mapped sequence set...");
+              System.err.println(
+                      "Exception when consolidating Mapped sequence set...");
               e.printStackTrace(System.err);
             }
           }
@@ -725,8 +722,8 @@ public class CrossRef
     SequenceI mapsTo = xref.getMap().getTo();
     String name = xref.getAccessionId();
     String name2 = xref.getSource() + "|" + name;
-    SequenceI dss = mapsTo.getDatasetSequence() == null ? mapsTo : mapsTo
-            .getDatasetSequence();
+    SequenceI dss = mapsTo.getDatasetSequence() == null ? mapsTo
+            : mapsTo.getDatasetSequence();
     // first check ds if ds is directly referenced
     if (dataset.findIndex(dss) > -1)
     {
@@ -741,8 +738,8 @@ public class CrossRef
     for (SequenceI seq : dataset.getSequences())
     {
       // first check primary refs.
-      List<DBRefEntry> match = DBRefUtils.searchRefs(seq.getPrimaryDBRefs()
-              .toArray(new DBRefEntry[0]), template);
+      List<DBRefEntry> match = DBRefUtils.searchRefs(
+              seq.getPrimaryDBRefs().toArray(new DBRefEntry[0]), template);
       if (match != null && match.size() == 1 && sameSequence(seq, dss))
       {
         return seq;
@@ -752,9 +749,8 @@ public class CrossRef
        * returns sequences with a dbref to the matched accession id 
        * which we don't want
        */
-      if (firstIdMatch == null
-              && (name.equals(seq.getName()) || seq.getName().startsWith(
-                      name2)))
+      if (firstIdMatch == null && (name.equals(seq.getName())
+              || seq.getName().startsWith(name2)))
       {
         if (sameSequence(seq, dss))
         {
@@ -786,15 +782,15 @@ public class CrossRef
     {
       return false;
     }
-    char[] c1 = seq1.getSequence();
-    char[] c2 = seq2.getSequence();
-    if (c1.length != c2.length)
+
+    if (seq1.getLength() != seq2.getLength())
     {
       return false;
     }
-    for (int i = 0; i < c1.length; i++)
+    int length = seq1.getLength();
+    for (int i = 0; i < length; i++)
     {
-      int diff = c1[i] - c2[i];
+      int diff = seq1.getCharAt(i) - seq2.getCharAt(i);
       /*
        * same char or differ in case only ('a'-'A' == 32)
        */
@@ -865,8 +861,8 @@ public class CrossRef
     MapList mapping = null;
     SequenceI dsmapFrom = mapFrom.getDatasetSequence() == null ? mapFrom
             : mapFrom.getDatasetSequence();
-    SequenceI dsmapTo = mapTo.getDatasetSequence() == null ? mapTo : mapTo
-            .getDatasetSequence();
+    SequenceI dsmapTo = mapTo.getDatasetSequence() == null ? mapTo
+            : mapTo.getDatasetSequence();
     /*
      * look for a reverse mapping, if found make its inverse. 
      * Note - we do this on dataset sequences only.
@@ -950,7 +946,8 @@ public class CrossRef
    * @return true if matches were found.
    */
   private boolean searchDatasetXrefs(boolean fromDna, SequenceI sequenceI,
-          DBRefEntry[] lrfs, List<SequenceI> foundSeqs, AlignedCodonFrame cf)
+          DBRefEntry[] lrfs, List<SequenceI> foundSeqs,
+          AlignedCodonFrame cf)
   {
     boolean found = false;
     if (lrfs == null)
@@ -963,7 +960,8 @@ public class CrossRef
       // add in wildcards
       xref.setVersion(null);
       xref.setMap(null);
-      found |= searchDataset(fromDna, sequenceI, xref, foundSeqs, cf, false);
+      found |= searchDataset(fromDna, sequenceI, xref, foundSeqs, cf,
+              false);
     }
     return found;
   }
@@ -1019,10 +1017,9 @@ public class CrossRef
         {
           if (nxt.getDatasetSequence() != null)
           {
-            System.err
-                    .println("Implementation warning: CrossRef initialised with a dataset alignment with non-dataset sequences in it! ("
-                            + nxt.getDisplayId(true)
-                            + " has ds reference "
+            System.err.println(
+                    "Implementation warning: CrossRef initialised with a dataset alignment with non-dataset sequences in it! ("
+                            + nxt.getDisplayId(true) + " has ds reference "
                             + nxt.getDatasetSequence().getDisplayId(true)
                             + ")");
           }
index 799a8ed..a10b037 100644 (file)
@@ -45,7 +45,6 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.List;
-import java.util.Map;
 
 public class Dna
 {
@@ -134,7 +133,8 @@ public class Dna
    * @param ac2
    * @return
    */
-  private static int jalview_2_8_2compare(AlignedCodon ac1, AlignedCodon ac2)
+  private static int jalview_2_8_2compare(AlignedCodon ac1,
+          AlignedCodon ac2)
   {
     if (ac1 == null || ac2 == null || (ac1.equals(ac2)))
     {
@@ -435,7 +435,8 @@ public class Dna
         /*
          * Filled up a reading frame...
          */
-        AlignedCodon alignedCodon = new AlignedCodon(cdp[0], cdp[1], cdp[2]);
+        AlignedCodon alignedCodon = new AlignedCodon(cdp[0], cdp[1],
+                cdp[2]);
         String aa = ResidueProperties.codonTranslate(new String(codon));
         rf = 0;
         final String gapString = String.valueOf(gapChar);
@@ -444,10 +445,11 @@ public class Dna
           aa = gapString;
           if (skipint == null)
           {
-            skipint = new int[] { alignedCodon.pos1, alignedCodon.pos3 /*
-                                                                        * cdp[0],
-                                                                        * cdp[2]
-                                                                        */};
+            skipint = new int[] { alignedCodon.pos1,
+                alignedCodon.pos3 /*
+                                   * cdp[0],
+                                   * cdp[2]
+                                   */ };
           }
           skipint[1] = alignedCodon.pos3; // cdp[2];
         }
@@ -502,8 +504,8 @@ public class Dna
                       }
                       if (vc + 2 < t.length)
                       {
-                        System.arraycopy(scontigs, vc + 2, t, vc, t.length
-                                - vc + 2);
+                        System.arraycopy(scontigs, vc + 2, t, vc,
+                                t.length - vc + 2);
                       }
                       scontigs = t;
                     }
@@ -596,9 +598,9 @@ public class Dna
         }
         else if (!alignedCodons[aspos].equals(alignedCodon))
         {
-          throw new IllegalStateException("Tried to coalign "
-                  + alignedCodons[aspos].toString() + " with "
-                  + alignedCodon.toString());
+          throw new IllegalStateException(
+                  "Tried to coalign " + alignedCodons[aspos].toString()
+                          + " with " + alignedCodon.toString());
         }
         if (aspos >= aaWidth)
         {
@@ -685,7 +687,7 @@ public class Dna
          */
         MapList map = new MapList(scontigs, new int[] { 1, resSize }, 3, 1);
 
-        transferCodedFeatures(selection, newseq, map, null, null);
+        transferCodedFeatures(selection, newseq, map);
 
         /*
          * Construct a dataset sequence for our new peptide.
@@ -754,25 +756,15 @@ public class Dna
 
   /**
    * Given a peptide newly translated from a dna sequence, copy over and set any
-   * features on the peptide from the DNA. If featureTypes is null, all features
-   * on the dna sequence are searched (rather than just the displayed ones), and
-   * similarly for featureGroups.
+   * features on the peptide from the DNA.
    * 
    * @param dna
    * @param pep
    * @param map
-   * @param featureTypes
-   *          hash whose keys are the displayed feature type strings
-   * @param featureGroups
-   *          hash where keys are feature groups and values are Boolean objects
-   *          indicating if they are displayed.
    */
   private static void transferCodedFeatures(SequenceI dna, SequenceI pep,
-          MapList map, Map<String, Object> featureTypes,
-          Map<String, Boolean> featureGroups)
+          MapList map)
   {
-    SequenceFeature[] sfs = dna.getSequenceFeatures();
-    Boolean fgstate;
     DBRefEntry[] dnarefs = DBRefUtils.selectRefs(dna.getDBRefs(),
             DBRefSource.DNACODINGDBS);
     if (dnarefs != null)
@@ -786,24 +778,15 @@ public class Dna
         }
       }
     }
-    if (sfs != null)
+    for (SequenceFeature sf : dna.getFeatures().getAllFeatures())
     {
-      for (SequenceFeature sf : sfs)
-      {
-        fgstate = (featureGroups == null) ? null : featureGroups
-                .get(sf.featureGroup);
-        if ((featureTypes == null || featureTypes.containsKey(sf.getType()))
-                && (fgstate == null || fgstate.booleanValue()))
+        if (FeatureProperties.isCodingFeature(null, sf.getType()))
         {
-          if (FeatureProperties.isCodingFeature(null, sf.getType()))
+          // if (map.intersectsFrom(sf[f].begin, sf[f].end))
           {
-            // if (map.intersectsFrom(sf[f].begin, sf[f].end))
-            {
 
-            }
           }
         }
-      }
     }
   }
 
index 25ee7d2..191f6e8 100644 (file)
@@ -207,9 +207,8 @@ public class Finder
         {
           resIndex = regex.matchedFrom();
 
-          if ((selection != null && selection.getSize() > 0)
-                  && (resIndex + spaces.get(resIndex) < selection
-                          .getStartRes()))
+          if ((selection != null && selection.getSize() > 0) && (resIndex
+                  + spaces.get(resIndex) < selection.getStartRes()))
           {
             continue;
           }
@@ -218,9 +217,9 @@ public class Finder
           int eres = seq.findPosition(regex.matchedTo() - 1
                   + (spaces.get(regex.matchedTo() - 1)));
           // only add result if not contained in previous result
-          if (lastm == null
-                  || (lastm.getSequence() != seq || (!(lastm.getStart() <= sres && lastm
-                          .getEnd() >= eres))))
+          if (lastm == null || (lastm.getSequence() != seq
+                  || (!(lastm.getStart() <= sres
+                          && lastm.getEnd() >= eres))))
           {
             lastm = searchResults.addResult(seq, sres, eres);
           }
index 2ddd015..066814e 100644 (file)
@@ -91,8 +91,8 @@ public class Grouping
     i = 0;
     for (String key : gps.keySet())
     {
-      SequenceGroup group = new SequenceGroup(gps.get(key), "Subseq: "
-              + key, null, true, true, false, 0, width - 1);
+      SequenceGroup group = new SequenceGroup(gps.get(key),
+              "Subseq: " + key, null, true, true, false, 0, width - 1);
 
       groups[i++] = group;
     }
@@ -178,8 +178,8 @@ public class Grouping
     i = 0;
     for (String key : gps.keySet())
     {
-      SequenceGroup group = new SequenceGroup(gps.get(key), "Subseq: "
-              + key, null, true, true, false, 0, width - 1);
+      SequenceGroup group = new SequenceGroup(gps.get(key),
+              "Subseq: " + key, null, true, true, false, 0, width - 1);
 
       groups[i++] = group;
     }
index 487e85e..522c2b1 100644 (file)
@@ -108,25 +108,25 @@ public class NJTree extends TreeBuilder
    * @param j
    */
   @Override
-  protected
-  void findClusterDistance(int i, int j)
+  protected void findClusterDistance(int i, int j)
   {
     // New distances from cluster i to others
     double[] newdist = new double[noseqs];
-  
+
     double ijDistance = distances.getValue(i, j);
     for (int l = 0; l < noseqs; l++)
     {
       if ((l != i) && (l != j))
       {
-        newdist[l] = (distances.getValue(i, l) + distances.getValue(j, l) - ijDistance) / 2;
+        newdist[l] = (distances.getValue(i, l) + distances.getValue(j, l)
+                - ijDistance) / 2;
       }
       else
       {
         newdist[l] = 0;
       }
     }
-  
+
     for (int ii = 0; ii < noseqs; ii++)
     {
       distances.setValue(i, ii, newdist[ii]);
index 3ec7995..42a168d 100755 (executable)
@@ -43,7 +43,7 @@ public class PCA implements Runnable
   final private AlignmentView seqs;
 
   private ScoreModelI scoreModel;
-  
+
   private SimilarityParamsI similarityParams;
 
   public PCA(AlignmentView s, ScoreModelI sm, SimilarityParamsI options)
@@ -51,7 +51,7 @@ public class PCA implements Runnable
     this.seqs = s;
     this.similarityParams = options;
     this.scoreModel = sm;
-    
+
     details.append("PCA calculation using " + sm.getName()
             + " sequence similarity matrix\n========\n\n");
   }
@@ -193,7 +193,8 @@ public class PCA implements Runnable
       q.printStackTrace();
       details.append("\n*** Unexpected exception when performing PCA ***\n"
               + q.getLocalizedMessage());
-      details.append("*** Matrices below may not be fully diagonalised. ***\n");
+      details.append(
+              "*** Matrices below may not be fully diagonalised. ***\n");
     }
 
     details.append(" --- New diagonalization matrix ---\n");
index eb639b6..629a8a3 100644 (file)
@@ -58,7 +58,8 @@ public class ParseProperties
           String ScoreDescriptions, String regex, boolean repeat)
   {
     return getScoresFromDescription(new String[] { ScoreName },
-            new String[] { ScoreDescriptions }, regex, repeat);
+            new String[]
+            { ScoreDescriptions }, regex, repeat);
   }
 
   public int getScoresFromDescription(String[] ScoreNames,
@@ -85,9 +86,8 @@ public class ParseProperties
    *          description string of each sequence
    * @return total number of sequences that matched the regex
    */
-  public int getScoresFromDescription(SequenceI[] seqs,
-          String[] ScoreNames, String[] ScoreDescriptions, String regex,
-          boolean repeat)
+  public int getScoresFromDescription(SequenceI[] seqs, String[] ScoreNames,
+          String[] ScoreDescriptions, String regex, boolean repeat)
   {
     int count = 0;
     Regex pattern = new Regex(regex);
@@ -141,8 +141,8 @@ public class ParseProperties
             continue;
           }
           // add score to sequence annotation.
-          AlignmentAnnotation an = new AlignmentAnnotation(ScoreNames[cols]
-                  + ((reps > 0) ? "_" + reps : ""),
+          AlignmentAnnotation an = new AlignmentAnnotation(
+                  ScoreNames[cols] + ((reps > 0) ? "_" + reps : ""),
                   ScoreDescriptions[cols], null);
           an.setScore(score);
           System.out.println(seqs[i].getName() + " score: '"
index 89c5c30..0d39abf 100644 (file)
@@ -31,10 +31,11 @@ import jalview.datamodel.SequenceFeature;
 import jalview.util.MessageManager;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.List;
+import java.util.Map;
 import java.util.Stack;
-import java.util.Vector;
 
 public class Rna
 {
@@ -48,7 +49,8 @@ public class Rna
    */
   public static boolean isOpeningParenthesis(char c)
   {
-    return ('A' <= c && c <= 'Z' || c == '(' || c == '[' || c == '{' || c == '<');
+    return ('A' <= c && c <= 'Z' || c == '(' || c == '[' || c == '{'
+            || c == '<');
   }
 
   /**
@@ -73,7 +75,8 @@ public class Rna
    */
   public static boolean isClosingParenthesis(char c)
   {
-    return ('a' <= c && c <= 'z' || c == ')' || c == ']' || c == '}' || c == '>');
+    return ('a' <= c && c <= 'z' || c == ')' || c == ']' || c == '}'
+            || c == '>');
   }
 
   /**
@@ -132,11 +135,11 @@ public class Rna
    * @return
    * @throw {@link WUSSParseException}
    */
-  public static Vector<SimpleBP> getSimpleBPs(CharSequence line)
+  protected static List<SimpleBP> getSimpleBPs(CharSequence line)
           throws WUSSParseException
   {
     Hashtable<Character, Stack<Integer>> stacks = new Hashtable<Character, Stack<Integer>>();
-    Vector<SimpleBP> pairs = new Vector<SimpleBP>();
+    List<SimpleBP> pairs = new ArrayList<SimpleBP>();
     int i = 0;
     while (i < line.length())
     {
@@ -159,8 +162,8 @@ public class Rna
         if (!stacks.containsKey(opening))
         {
           throw new WUSSParseException(MessageManager.formatMessage(
-                  "exception.mismatched_unseen_closing_char",
-                  new String[] { String.valueOf(base) }), i);
+                  "exception.mismatched_unseen_closing_char", new String[]
+                  { String.valueOf(base) }), i);
         }
 
         Stack<Integer> stack = stacks.get(opening);
@@ -168,8 +171,8 @@ public class Rna
         {
           // error whilst parsing i'th position. pass back
           throw new WUSSParseException(MessageManager.formatMessage(
-                  "exception.mismatched_closing_char",
-                  new String[] { String.valueOf(base) }), i);
+                  "exception.mismatched_closing_char", new String[]
+                  { String.valueOf(base) }), i);
         }
         int temp = stack.pop();
 
@@ -187,33 +190,17 @@ public class Rna
          * i (length of input string)
          */
         throw new WUSSParseException(MessageManager.formatMessage(
-                "exception.mismatched_opening_char",
-                new String[] { String.valueOf(opening),
-                    String.valueOf(stack.pop()) }), i);
+                "exception.mismatched_opening_char", new String[]
+                { String.valueOf(opening), String.valueOf(stack.pop()) }),
+                i);
       }
     }
     return pairs;
   }
 
-  public static SequenceFeature[] getBasePairs(List<SimpleBP> bps)
-          throws WUSSParseException
-  {
-    SequenceFeature[] outPairs = new SequenceFeature[bps.size()];
-    for (int p = 0; p < bps.size(); p++)
-    {
-      SimpleBP bp = bps.get(p);
-      outPairs[p] = new SequenceFeature("RNA helix", "", "", bp.getBP5(),
-              bp.getBP3(), "");
-    }
-    return outPairs;
-  }
+  
 
-  public static List<SimpleBP> getModeleBP(CharSequence line)
-          throws WUSSParseException
-  {
-    Vector<SimpleBP> bps = getSimpleBPs(line);
-    return new ArrayList<SimpleBP>(bps);
-  }
+  
 
   /**
    * Function to get the end position corresponding to a given start position
@@ -230,88 +217,6 @@ public class Rna
    */
 
   /**
-   * Figures out which helix each position belongs to and stores the helix
-   * number in the 'featureGroup' member of a SequenceFeature Based off of RALEE
-   * code ralee-helix-map.
-   * 
-   * @param pairs
-   *          Array of SequenceFeature (output from Rna.GetBasePairs)
-   */
-  public static void HelixMap(SequenceFeature[] pairs)
-  {
-
-    int helix = 0; // Number of helices/current helix
-    int lastopen = 0; // Position of last open bracket reviewed
-    int lastclose = 9999999; // Position of last close bracket reviewed
-    int i = pairs.length; // Number of pairs
-
-    int open; // Position of an open bracket under review
-    int close; // Position of a close bracket under review
-    int j; // Counter
-
-    Hashtable<Integer, Integer> helices = new Hashtable<Integer, Integer>();
-    // Keep track of helix number for each position
-
-    // Go through each base pair and assign positions a helix
-    for (i = 0; i < pairs.length; i++)
-    {
-
-      open = pairs[i].getBegin();
-      close = pairs[i].getEnd();
-
-      // System.out.println("open " + open + " close " + close);
-      // System.out.println("lastclose " + lastclose + " lastopen " + lastopen);
-
-      // we're moving from right to left based on closing pair
-      /*
-       * catch things like <<..>>..<<..>> |
-       */
-      if (open > lastclose)
-      {
-        helix++;
-      }
-
-      /*
-       * catch things like <<..<<..>>..<<..>>>> |
-       */
-      j = pairs.length - 1;
-      while (j >= 0)
-      {
-        int popen = pairs[j].getBegin();
-
-        // System.out.println("j " + j + " popen " + popen + " lastopen "
-        // +lastopen + " open " + open);
-        if ((popen < lastopen) && (popen > open))
-        {
-          if (helices.containsValue(popen)
-                  && ((helices.get(popen)) == helix))
-          {
-            continue;
-          }
-          else
-          {
-            helix++;
-            break;
-          }
-        }
-
-        j -= 1;
-      }
-
-      // Put positions and helix information into the hashtable
-      helices.put(open, helix);
-      helices.put(close, helix);
-
-      // Record helix as featuregroup
-      pairs[i].setFeatureGroup(Integer.toString(helix));
-
-      lastopen = open;
-      lastclose = close;
-
-    }
-  }
-
-  /**
    * Answers true if the character is a recognised symbol for RNA secondary
    * structure. Currently accepts a-z, A-Z, ()[]{}<>.
    * 
@@ -500,4 +405,76 @@ public class Rna
       return c;
     }
   }
+
+  public static SequenceFeature[] getHelixMap(CharSequence rnaAnnotation)
+          throws WUSSParseException
+  {
+    List<SequenceFeature> result = new ArrayList<SequenceFeature>();
+
+    int helix = 0; // Number of helices/current helix
+    int lastopen = 0; // Position of last open bracket reviewed
+    int lastclose = 9999999; // Position of last close bracket reviewed
+
+    Map<Integer, Integer> helices = new HashMap<Integer, Integer>();
+    // Keep track of helix number for each position
+
+    // Go through each base pair and assign positions a helix
+    List<SimpleBP> bps = getSimpleBPs(rnaAnnotation);
+    for (SimpleBP basePair : bps)
+    {
+      final int open = basePair.getBP5();
+      final int close = basePair.getBP3();
+
+      // System.out.println("open " + open + " close " + close);
+      // System.out.println("lastclose " + lastclose + " lastopen " + lastopen);
+
+      // we're moving from right to left based on closing pair
+      /*
+       * catch things like <<..>>..<<..>> |
+       */
+      if (open > lastclose)
+      {
+        helix++;
+      }
+
+      /*
+       * catch things like <<..<<..>>..<<..>>>> |
+       */
+      int j = bps.size() - 1;
+      while (j >= 0)
+      {
+        int popen = bps.get(j).getBP5();
+
+        // System.out.println("j " + j + " popen " + popen + " lastopen "
+        // +lastopen + " open " + open);
+        if ((popen < lastopen) && (popen > open))
+        {
+          if (helices.containsValue(popen)
+                  && ((helices.get(popen)) == helix))
+          {
+            continue;
+          }
+          else
+          {
+            helix++;
+            break;
+          }
+        }
+        j -= 1;
+      }
+
+      // Put positions and helix information into the hashtable
+      helices.put(open, helix);
+      helices.put(close, helix);
+
+      // Record helix as featuregroup
+      result.add(new SequenceFeature("RNA helix", "", open, close,
+              String.valueOf(helix)));
+
+      lastopen = open;
+      lastclose = close;
+    }
+
+    return result.toArray(new SequenceFeature[result.size()]);
+  }
 }
index 3e007c4..05c20a0 100644 (file)
@@ -179,8 +179,8 @@ public class SecStrConsensus
               {
                 fact2 = tab[k + 1][j];
               }
-              tab[i][j] = Math.max(tab[i][j], basePairScore(seq, i, k)
-                      + fact1 + fact2);
+              tab[i][j] = Math.max(tab[i][j],
+                      basePairScore(seq, i, k) + fact1 + fact2);
             }
           }
         }
index 21ad1cc..fabd0c6 100755 (executable)
@@ -27,6 +27,7 @@ import jalview.datamodel.SequenceI;
 
 import java.util.Enumeration;
 import java.util.Hashtable;
+import java.util.List;
 import java.util.Vector;
 
 public class SeqsetUtils
@@ -50,15 +51,11 @@ public class SeqsetUtils
     {
       sqinfo.put("Description", seq.getDescription());
     }
-    Vector sfeat = new Vector();
-    jalview.datamodel.SequenceFeature[] sfarray = seq.getSequenceFeatures();
-    if (sfarray != null && sfarray.length > 0)
-    {
-      for (int i = 0; i < sfarray.length; i++)
-      {
-        sfeat.addElement(sfarray[i]);
-      }
-    }
+
+    Vector<SequenceFeature> sfeat = new Vector<SequenceFeature>();
+    List<SequenceFeature> sfs = seq.getFeatures().getAllFeatures();
+    sfeat.addAll(sfs);
+
     if (seq.getDatasetSequence() == null)
     {
       sqinfo.put("SeqFeatures", sfeat);
@@ -95,7 +92,8 @@ public class SeqsetUtils
     String oldname = (String) sqinfo.get("Name");
     Integer start = (Integer) sqinfo.get("Start");
     Integer end = (Integer) sqinfo.get("End");
-    Vector sfeatures = (Vector) sqinfo.get("SeqFeatures");
+    Vector<SequenceFeature> sfeatures = (Vector<SequenceFeature>) sqinfo
+            .get("SeqFeatures");
     Vector<PDBEntry> pdbid = (Vector<PDBEntry>) sqinfo.get("PdbId");
     String description = (String) sqinfo.get("Description");
     Sequence seqds = (Sequence) sqinfo.get("datasetSequence");
@@ -118,27 +116,21 @@ public class SeqsetUtils
       sq.setEnd(end.intValue());
     }
 
-    if ((sfeatures != null) && (sfeatures.size() > 0))
+    if (sfeatures != null && !sfeatures.isEmpty())
     {
-      SequenceFeature[] sfarray = new SequenceFeature[sfeatures.size()];
-      for (int is = 0, isize = sfeatures.size(); is < isize; is++)
-      {
-        sfarray[is] = (SequenceFeature) sfeatures.elementAt(is);
-      }
-      sq.setSequenceFeatures(sfarray);
+      sq.setSequenceFeatures(sfeatures);
     }
     if (description != null)
     {
       sq.setDescription(description);
     }
-    if ((seqds != null)
-            && !(seqds.getName().equals("THISISAPLACEHOLDER") && seqds
-                    .getLength() == 0))
+    if ((seqds != null) && !(seqds.getName().equals("THISISAPLACEHOLDER")
+            && seqds.getLength() == 0))
     {
       if (sfeatures != null)
       {
-        System.err
-                .println("Implementation error: setting dataset sequence for a sequence which has sequence features.\n\tDataset sequence features will not be visible.");
+        System.err.println(
+                "Implementation error: setting dataset sequence for a sequence which has sequence features.\n\tDataset sequence features will not be visible.");
       }
       sq.setDatasetSequence(seqds);
     }
@@ -261,8 +253,9 @@ public class SeqsetUtils
     if (unmatched.size() > 0 && !quiet)
     {
       System.err.println("Did not find matches for :");
-      for (Enumeration i = unmatched.elements(); i.hasMoreElements(); System.out
-              .println(((SequenceI) i.nextElement()).getName()))
+      for (Enumeration i = unmatched.elements(); i
+              .hasMoreElements(); System.out
+                      .println(((SequenceI) i.nextElement()).getName()))
       {
         ;
       }
index c12de4e..3d4cbe7 100755 (executable)
@@ -147,9 +147,8 @@ public class SequenceIdMatcher
       names.put(new SeqIdName(cand.getName()), cand);
       int q, w, candlen = cand.getName().length();
       // keep the one with an id 'closer' to the given seqnam string
-      if ((q = Math.abs(matchlen - namlen)) > (w = Math.abs(candlen
-              - namlen))
-              && candlen > matchlen)
+      if ((q = Math.abs(matchlen - namlen)) > (w = Math
+              .abs(candlen - namlen)) && candlen > matchlen)
       {
         best.clear();
         match = cand;
@@ -301,8 +300,8 @@ public class SequenceIdMatcher
     @Override
     public int hashCode()
     {
-      return ((id.length() >= 4) ? id.substring(0, 4).hashCode() : id
-              .hashCode());
+      return ((id.length() >= 4) ? id.substring(0, 4).hashCode()
+              : id.hashCode());
     }
 
     @Override
@@ -348,13 +347,16 @@ public class SequenceIdMatcher
     {
       if (id.length() > s.length())
       {
-        return id.startsWith(s) ? (WORD_SEP.indexOf(id.charAt(s.length())) > -1)
+        return id.startsWith(s)
+                ? (WORD_SEP.indexOf(id.charAt(s.length())) > -1)
                 : false;
       }
       else
       {
-        return s.startsWith(id) ? (s.equals(id) ? true : (WORD_SEP
-                .indexOf(s.charAt(id.length())) > -1)) : false;
+        return s.startsWith(id)
+                ? (s.equals(id) ? true
+                        : (WORD_SEP.indexOf(s.charAt(id.length())) > -1))
+                : false;
       }
     }
 
index 7b0858d..b681aa6 100644 (file)
@@ -149,8 +149,8 @@ public class StructureFrequency
           {
             if (sequences[j] == null)
             {
-              System.err
-                      .println("WARNING: Consensus skipping null sequence - possible race condition.");
+              System.err.println(
+                      "WARNING: Consensus skipping null sequence - possible race condition.");
               continue;
             }
 
@@ -195,8 +195,9 @@ public class StructureFrequency
       if (profile)
       {
         // TODO 1-dim array with jsize in [0], nongapped in [1]; or Pojo
-        residueHash.put(PROFILE, new int[][] { values,
-            new int[] { jSize, (jSize - values['-']) } });
+        residueHash.put(PROFILE,
+                new int[][]
+                { values, new int[] { jSize, (jSize - values['-']) } });
 
         residueHash.put(PAIRPROFILE, pairs);
       }
@@ -217,7 +218,8 @@ public class StructureFrequency
       {
         if (canonicalOrWobblePairCount >= otherPairCount)
         {
-          maxResidue = (canonicalOrWobblePairCount - canonical) < canonical ? "("
+          maxResidue = (canonicalOrWobblePairCount - canonical) < canonical
+                  ? "("
                   : "[";
         }
         else
@@ -252,8 +254,9 @@ public class StructureFrequency
         residueHash = new Hashtable();
         if (profile)
         {
-          residueHash.put(PROFILE, new int[][] { values,
-              new int[] { jSize, (jSize - values['-']) } });
+          residueHash.put(PROFILE,
+                  new int[][]
+                  { values, new int[] { jSize, (jSize - values['-']) } });
 
           residueHash.put(PAIRPROFILE, pairs);
         }
@@ -444,7 +447,8 @@ public class StructureFrequency
     int valuesCount = 0;
     rtnval[1] = 0;
     int offset = 2;
-    final int divisor = profile[1][ignoreGapsInConsensusCalculation ? 1 : 0];
+    final int divisor = profile[1][ignoreGapsInConsensusCalculation ? 1
+            : 0];
     for (int c = 624; c > 0; c--)
     {
       if (vl[c] > 0)
index effef9a..0601dd9 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.analysis;
 
 import jalview.api.analysis.ScoreModelI;
@@ -79,8 +99,8 @@ public abstract class TreeBuilder
     {
       start = av.getSelectionGroup().getStartRes();
       end = av.getSelectionGroup().getEndRes() + 1;
-      this.sequences = av.getSelectionGroup().getSequencesInOrder(
-              av.getAlignment());
+      this.sequences = av.getSelectionGroup()
+              .getSequencesInOrder(av.getAlignment());
     }
 
     init(seqStrings, start, end);
@@ -107,11 +127,11 @@ public abstract class TreeBuilder
     {
       return maxheight;
     }
-  
+
     if ((nd.left() == null) && (nd.right() == null))
     {
       nd.height = ((SequenceNode) nd.parent()).height + nd.dist;
-  
+
       if (nd.height > maxheight)
       {
         return nd.height;
@@ -132,11 +152,11 @@ public abstract class TreeBuilder
         maxheight = 0;
         nd.height = (float) 0.0;
       }
-  
+
       maxheight = findHeight((SequenceNode) (nd.left()));
       maxheight = findHeight((SequenceNode) (nd.right()));
     }
-  
+
     return maxheight;
   }
 
@@ -164,23 +184,24 @@ public abstract class TreeBuilder
   {
     // if (_lycount<_lylimit)
     // {
-    // System.err.println("Warning: depth of _recount greater than number of nodes.");
+    // System.err.println("Warning: depth of _recount greater than number of
+    // nodes.");
     // }
     if (nd == null)
     {
       return;
     }
     // _lycount++;
-  
+
     if ((nd.left() != null) && (nd.right() != null))
     {
-  
+
       _reCount((SequenceNode) nd.left());
       _reCount((SequenceNode) nd.right());
-  
+
       SequenceNode l = (SequenceNode) nd.left();
       SequenceNode r = (SequenceNode) nd.right();
-  
+
       nd.count = l.count + r.count;
       nd.ycount = (l.ycount + r.ycount) / 2;
     }
@@ -234,18 +255,18 @@ public abstract class TreeBuilder
     while (noClus > 2)
     {
       findMinDistance();
-  
+
       joinClusters(mini, minj);
-  
+
       noClus--;
     }
-  
+
     int rightChild = done.nextClearBit(0);
     int leftChild = done.nextClearBit(rightChild + 1);
-  
+
     joinClusters(leftChild, rightChild);
     top = (node.elementAt(leftChild));
-  
+
     reCount(top);
     findHeight(top);
     findMaxDist(top);
@@ -275,11 +296,11 @@ public abstract class TreeBuilder
   protected void computeTree(ScoreModelI sm, SimilarityParamsI scoreOptions)
   {
     distances = sm.findDistances(seqData, scoreOptions);
-  
+
     makeLeaves();
-  
+
     noClus = clusters.size();
-  
+
     cluster();
   }
 
@@ -295,11 +316,11 @@ public abstract class TreeBuilder
     {
       return;
     }
-  
+
     if ((nd.left() == null) && (nd.right() == null))
     {
       double dist = nd.dist;
-  
+
       if (dist > maxDistValue)
       {
         maxdist = nd;
@@ -324,7 +345,7 @@ public abstract class TreeBuilder
   protected double findr(int i, int j)
   {
     double tmp = 1;
-  
+
     for (int k = 0; k < noseqs; k++)
     {
       if ((k != i) && (k != j) && (!done.get(k)))
@@ -332,12 +353,12 @@ public abstract class TreeBuilder
         tmp = tmp + distances.getValue(i, k);
       }
     }
-  
+
     if (noClus > 2)
     {
       tmp = tmp / (noClus - 2);
     }
-  
+
     return tmp;
   }
 
@@ -359,14 +380,14 @@ public abstract class TreeBuilder
       sdata.addOperation(CigarArray.M, end - start + 1);
       this.seqData = new AlignmentView(sdata, start);
     }
-  
+
     /*
      * count the non-null sequences
      */
     noseqs = 0;
-  
+
     done = new BitSet();
-  
+
     for (SequenceI seq : sequences)
     {
       if (seq != null)
@@ -385,27 +406,27 @@ public abstract class TreeBuilder
   void joinClusters(final int i, final int j)
   {
     double dist = distances.getValue(i, j);
-  
+
     ri = findr(i, j);
     rj = findr(j, i);
-  
+
     findClusterDistance(i, j);
-  
+
     SequenceNode sn = new SequenceNode();
-  
+
     sn.setLeft((node.elementAt(i)));
     sn.setRight((node.elementAt(j)));
-  
+
     SequenceNode tmpi = (node.elementAt(i));
     SequenceNode tmpj = (node.elementAt(j));
-  
+
     findNewDistances(tmpi, tmpj, dist);
-  
+
     tmpi.setParent(sn);
     tmpj.setParent(sn);
-  
+
     node.setElementAt(sn, i);
-  
+
     /*
      * move the members of cluster(j) to cluster(i)
      * and mark cluster j as out of the game
@@ -438,11 +459,11 @@ public abstract class TreeBuilder
   void makeLeaves()
   {
     clusters = new Vector<BitSet>();
-  
+
     for (int i = 0; i < noseqs; i++)
     {
       SequenceNode sn = new SequenceNode();
-  
+
       sn.setElement(sequences[i]);
       sn.setName(sequences[i].getName());
       node.addElement(sn);
index 5a41802..a50634e 100644 (file)
@@ -77,10 +77,11 @@ public class TreeModel
    * @param treefile
    *          NewickFile
    */
-  public TreeModel(SequenceI[] seqs, AlignmentView odata, NewickFile treefile)
+  public TreeModel(SequenceI[] seqs, AlignmentView odata,
+          NewickFile treefile)
   {
-    this(seqs, treefile.getTree(), treefile.HasDistances(), treefile
-            .HasBootstrap(), treefile.HasRootDistance());
+    this(seqs, treefile.getTree(), treefile.HasDistances(),
+            treefile.HasBootstrap(), treefile.HasRootDistance());
     seqData = odata;
 
     associateLeavesToSequences(seqs);
@@ -93,8 +94,8 @@ public class TreeModel
    */
   public TreeModel(TreeBuilder tree)
   {
-    this(tree.getSequences(), tree.getTopNode(), tree.hasDistances(), tree
-            .hasBootstrap(), tree.hasRootDistance());
+    this(tree.getSequences(), tree.getTopNode(), tree.hasDistances(),
+            tree.hasBootstrap(), tree.hasRootDistance());
     seqData = tree.getOriginalData();
   }
 
@@ -187,8 +188,12 @@ public class TreeModel
   {
     NewickFile fout = new NewickFile(getTopNode());
 
-    return fout.print(hasBootstrap(), hasDistances(),
-            hasRootDistance()); // output all data available for tree
+    return fout.print(hasBootstrap(), hasDistances(), hasRootDistance()); // output
+                                                                          // all
+                                                                          // data
+                                                                          // available
+                                                                          // for
+                                                                          // tree
   }
 
   /**
@@ -248,8 +253,8 @@ public class TreeModel
           if (!leaf.isPlaceholder())
           {
             // Construct a new placeholder sequence object for this leaf
-            leaf.setElement(new Sequence(leaf.getName(),
-                    "THISISAPLACEHLDER"));
+            leaf.setElement(
+                    new Sequence(leaf.getName(), "THISISAPLACEHLDER"));
           }
           leaf.setPlaceholder(true);
 
@@ -478,8 +483,8 @@ public class TreeModel
       System.out.println(" name = " + ((SequenceI) nd.element()).getName());
     }
 
-    System.out.println(" dist = " + nd.dist + " " + nd.count + " "
-            + nd.height);
+    System.out.println(
+            " dist = " + nd.dist + " " + nd.count + " " + nd.height);
   }
 
   /**
@@ -508,7 +513,8 @@ public class TreeModel
   {
     // if (_lycount<_lylimit)
     // {
-    // System.err.println("Warning: depth of _recount greater than number of nodes.");
+    // System.err.println("Warning: depth of _recount greater than number of
+    // nodes.");
     // }
     if (nd == null)
     {
@@ -659,8 +665,8 @@ public class TreeModel
   public void applyToNodes(NodeTransformI nodeTransformI)
   {
     for (Enumeration<SequenceNode> nodes = node.elements(); nodes
-            .hasMoreElements(); nodeTransformI.transform(nodes
-            .nextElement()))
+            .hasMoreElements(); nodeTransformI
+                    .transform(nodes.nextElement()))
     {
       ;
     }
index 0dd7617..3521757 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.analysis.scoremodels;
 
 import jalview.api.analysis.ScoreModelI;
index 056ecdb..e506be2 100644 (file)
@@ -124,8 +124,8 @@ public class FeatureDistanceModel extends DistanceScoreModel
         /*
          * first record feature types in this column for each sequence
          */
-        Map<SeqCigar, Set<String>> sfap = findFeatureTypesAtColumn(
-                seqs, cpos);
+        Map<SeqCigar, Set<String>> sfap = findFeatureTypesAtColumn(seqs,
+                cpos);
 
         /*
          * count feature types on either i'th or j'th sequence but not both
@@ -177,10 +177,12 @@ public class FeatureDistanceModel extends DistanceScoreModel
   /**
    * Builds and returns a map containing a (possibly empty) list (one per
    * SeqCigar) of visible feature types at the given column position. The map
-   * has no entry for sequences which are gapped at the column position.
+   * does not include entries for features which straddle a gapped column
+   * positions.
    * 
    * @param seqs
    * @param columnPosition
+   *          (0..)
    * @return
    */
   protected Map<SeqCigar, Set<String>> findFeatureTypesAtColumn(
@@ -192,9 +194,12 @@ public class FeatureDistanceModel extends DistanceScoreModel
       int spos = seq.findPosition(columnPosition);
       if (spos != -1)
       {
+        /*
+         * position is not a gap
+         */
         Set<String> types = new HashSet<String>();
-        List<SequenceFeature> sfs = fr.findFeaturesAtRes(seq.getRefSeq(),
-                spos);
+        List<SequenceFeature> sfs = fr.findFeaturesAtResidue(
+                seq.getRefSeq(), spos);
         for (SequenceFeature sf : sfs)
         {
           types.add(sf.getType());
index 721ba45..c1e8b42 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.analysis.scoremodels;
 
 import jalview.api.AlignmentViewPanel;
@@ -14,8 +34,8 @@ import jalview.util.Comparison;
  * Instances of this class are immutable and thread-safe, so the same object is
  * returned from calls to getInstance().
  */
-public class PIDModel extends SimilarityScoreModel implements
-        PairwiseScoreModelI
+public class PIDModel extends SimilarityScoreModel
+        implements PairwiseScoreModelI
 {
   private static final String NAME = "PID";
 
index efaeb43..6cdfacb 100644 (file)
@@ -36,8 +36,8 @@ import java.util.Arrays;
  * symbols. Instances of this class are immutable and thread-safe, so the same
  * object is returned from calls to getInstance().
  */
-public class ScoreMatrix extends SimilarityScoreModel implements
-        PairwiseScoreModelI
+public class ScoreMatrix extends SimilarityScoreModel
+        implements PairwiseScoreModelI
 {
   private static final char GAP_CHARACTER = Comparison.GAP_DASH;
 
@@ -98,7 +98,7 @@ public class ScoreMatrix extends SimilarityScoreModel implements
   private float minValue;
 
   private float maxValue;
-  
+
   /**
    * Constructor given a name, symbol alphabet, and matrix of scores for pairs
    * of symbols. The matrix should be square and of the same size as the
@@ -130,8 +130,8 @@ public class ScoreMatrix extends SimilarityScoreModel implements
    * @param values
    *          Pairwise scores indexed according to the symbol alphabet
    */
-  public ScoreMatrix(String theName, String theDescription,
-          char[] alphabet, float[][] values)
+  public ScoreMatrix(String theName, String theDescription, char[] alphabet,
+          float[][] values)
   {
     if (alphabet.length != values.length)
     {
@@ -454,7 +454,8 @@ public class ScoreMatrix extends SimilarityScoreModel implements
    * @param params
    * @return
    */
-  protected MatrixI findSimilarities(String[] seqs, SimilarityParamsI params)
+  protected MatrixI findSimilarities(String[] seqs,
+          SimilarityParamsI params)
   {
     double[][] values = new double[seqs.length][];
     for (int row = 0; row < seqs.length; row++)
index 654136a..7262fb8 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.analysis.scoremodels;
 
 import jalview.api.AlignmentViewPanel;
@@ -68,14 +88,15 @@ public class ScoreModels
       /*
        * delegate parsing to ScoreMatrixFile
        */
-      FileParse fp = new FileParse(resourcePath, DataSourceType.CLASSLOADER);
+      FileParse fp = new FileParse(resourcePath,
+              DataSourceType.CLASSLOADER);
       ScoreMatrix sm = new ScoreMatrixFile(fp).parseMatrix();
       registerScoreModel(sm);
       return sm;
     } catch (IOException e)
     {
-      System.err.println("Error reading " + resourcePath + ": "
-              + e.getMessage());
+      System.err.println(
+              "Error reading " + resourcePath + ": " + e.getMessage());
     }
     return null;
   }
index e5751ca..58b08dd 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.analysis.scoremodels;
 
 import jalview.api.analysis.SimilarityParamsI;
@@ -20,8 +40,8 @@ public class SimilarityParams implements SimilarityParamsI
    * Based on Jalview's Comparison.PID method, which includes gaps and counts
    * them as matching; it counts over the length of the shorter sequence
    */
-  public static final SimilarityParamsI Jalview = new SimilarityParams(
-          true, true, true, true);
+  public static final SimilarityParamsI Jalview = new SimilarityParams(true,
+          true, true, true);
 
   /**
    * 'SeqSpace' mode PCA calculation includes gaps but does not count them as
index dae1f62..e702340 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.analysis.scoremodels;
 
 import jalview.api.analysis.ScoreModelI;
index f88101f..ca6d279 100644 (file)
@@ -51,8 +51,8 @@ public class SmithWatermanModel extends SimilarityScoreModel
   public MatrixI findSimilarities(AlignmentView seqData,
           SimilarityParamsI options)
   {
-    SequenceI[] sequenceString = seqData.getVisibleAlignment(
-            Comparison.GAP_SPACE).getSequencesArray();
+    SequenceI[] sequenceString = seqData
+            .getVisibleAlignment(Comparison.GAP_SPACE).getSequencesArray();
     int noseqs = sequenceString.length;
     double[][] distances = new double[noseqs][noseqs];
 
index 9e6d1c0..931eba6 100644 (file)
 package jalview.api;
 
 import jalview.analysis.Conservation;
+import jalview.analysis.TreeModel;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.AlignmentView;
-import jalview.datamodel.CigarArray;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.ProfilesI;
 import jalview.datamodel.SearchResultsI;
@@ -243,16 +243,6 @@ public interface AlignViewportI extends ViewStyleI
   void clearSequenceColours();
 
   /**
-   * This method returns the visible alignment as text, as seen on the GUI, ie
-   * if columns are hidden they will not be returned in the result. Use this for
-   * calculating trees, PCA, redundancy etc on views which contain hidden
-   * columns.
-   * 
-   * @return String[]
-   */
-  CigarArray getViewAsCigars(boolean selectedRegionOnly);
-
-  /**
    * return a compact representation of the current alignment selection to pass
    * to an analysis function
    * 
@@ -486,6 +476,7 @@ public interface AlignViewportI extends ViewStyleI
    * 
    * @return
    */
+  @Override
   boolean isProteinFontAsCdna();
 
   /**
@@ -493,5 +484,10 @@ public interface AlignViewportI extends ViewStyleI
    * 
    * @return
    */
+  @Override
   void setProteinFontAsCdna(boolean b);
+
+  public abstract TreeModel getCurrentTree();
+
+  public abstract void setCurrentTree(TreeModel tree);
 }
index 603da98..06b1675 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.api;
 
 public interface AlignmentColsCollectionI extends Iterable<Integer>
@@ -10,4 +30,11 @@ public interface AlignmentColsCollectionI extends Iterable<Integer>
    * @return true if the column at the position is hidden
    */
   public boolean isHidden(int c);
+
+  /**
+   * Answers if any column in this collection is hidden
+   * 
+   * @return true if there is at least 1 hidden column
+   */
+  public boolean hasHidden();
 }
index 09b039d..fbf6ceb 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.api;
 
 import jalview.datamodel.SequenceI;
@@ -14,6 +34,13 @@ public interface AlignmentRowsCollectionI extends Iterable<Integer>
   public boolean isHidden(int r);
 
   /**
+   * Answers if any row in this collection is hidden
+   * 
+   * @return true if there is at least 1 hidden row
+   */
+  public boolean hasHidden();
+
+  /**
    * Answers the sequence at the given position in the alignment
    * 
    * @param r
index ef59996..0b1ca21 100644 (file)
@@ -43,9 +43,10 @@ public interface AlignmentViewPanel extends OOMHandlerI
    * 
    * @param updateOverview
    *          - if true, the overview panel will also be updated and repainted
+   * @param updateStructures
+   *          - if true then any linked structure views will also be updated
    */
-
-  void paintAlignment(boolean updateOverview);
+  void paintAlignment(boolean updateOverview, boolean updateStructures);
 
   /**
    * automatically adjust annotation panel height for new annotation whilst
index 51c35c5..672d6b4 100644 (file)
@@ -92,7 +92,8 @@ public interface DBRefEntryI
   public boolean updateFrom(DBRefEntryI otherEntry);
 
   /**
-   * Answers true if the ref looks like a primary (direct) database reference. <br>
+   * Answers true if the ref looks like a primary (direct) database reference.
+   * <br>
    * The only way a dbref's mappings can be fully verified is via the local
    * sequence frame, so rather than use isPrimaryCandidate directly, please use
    * SequenceI.getPrimaryDbRefs(). <br>
index 01eb7fa..0ded079 100644 (file)
@@ -146,7 +146,9 @@ public interface FeatureColourI
   boolean hasThreshold();
 
   /**
-   * Returns the computed colour for the given sequence feature
+   * Returns the computed colour for the given sequence feature. Answers null if
+   * the score of this feature instance is outside the range to render (if any),
+   * i.e. lies below or above a configured threshold.
    * 
    * @param feature
    * @return
@@ -154,17 +156,6 @@ public interface FeatureColourI
   Color getColor(SequenceFeature feature);
 
   /**
-   * Answers true if the feature has a simple colour, or is coloured by label,
-   * or has a graduated colour and the score of this feature instance is within
-   * the range to render (if any), i.e. does not lie below or above any
-   * threshold set.
-   * 
-   * @param feature
-   * @return
-   */
-  boolean isColored(SequenceFeature feature);
-
-  /**
    * Update the min-max range for a graduated colour scheme
    * 
    * @param min
index 7123b8c..9d2d7f4 100644 (file)
@@ -60,6 +60,7 @@ public interface FeatureRenderer
    * 
    * @param sequence
    * @param column
+   *          aligned column position (1..)
    * @param g
    * @return
    */
@@ -147,14 +148,27 @@ public interface FeatureRenderer
   void setGroupVisibility(String group, boolean visible);
 
   /**
-   * Returns features at the specified position on the given sequence.
+   * Returns features at the specified aligned column on the given sequence.
+   * Non-positional features are not included. If the column has a gap, then
+   * enclosing features are included (but not contact features).
+   * 
+   * @param sequence
+   * @param column
+   *          aligned column position (1..)
+   * @return
+   */
+  List<SequenceFeature> findFeaturesAtColumn(SequenceI sequence, int column);
+
+  /**
+   * Returns features at the specified residue position on the given sequence.
    * Non-positional features are not included.
    * 
    * @param sequence
-   * @param res
+   * @param resNo
+   *          residue position (start..)
    * @return
    */
-  List<SequenceFeature> findFeaturesAtRes(SequenceI sequence, int res);
+  List<SequenceFeature> findFeaturesAtResidue(SequenceI sequence, int resNo);
 
   /**
    * get current displayed types, in ordering of rendering (on top last)
@@ -165,9 +179,9 @@ public interface FeatureRenderer
   List<String> getDisplayedFeatureTypes();
 
   /**
-   * get current displayed groups
+   * Returns a (possibly empty) list of currently visible feature groups
    * 
-   * @return a (possibly empty) list of feature groups
+   * @return
    */
   List<String> getDisplayedFeatureGroups();
 
@@ -200,4 +214,5 @@ public interface FeatureRenderer
    * @return
    */
   float getTransparency();
+
 }
index 32b0565..e69785f 100644 (file)
 package jalview.api;
 
 import java.util.Collection;
-import java.util.Iterator;
+import java.util.Set;
 
 public interface FeaturesDisplayedI
 {
 
-  Iterator<String> getVisibleFeatures();
+  /**
+   * answers an unmodifiable view of the set of visible feature types
+   */
+  Set<String> getVisibleFeatures();
 
   boolean isVisible(String featureType);
 
@@ -36,6 +39,12 @@ public interface FeaturesDisplayedI
 
   void setVisible(String featureType);
 
+  /**
+   * Sets all the specified feature types to visible. Visibility of other
+   * feature types is not changed.
+   * 
+   * @param featureTypes
+   */
   void setAllVisible(Collection<String> featureTypes);
 
   boolean isRegistered(String type);
similarity index 87%
rename from src/jalview/io/ClansFile.java
rename to src/jalview/api/RendererListenerI.java
index d0b1c72..0ce4116 100644 (file)
  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
-package jalview.io;
+package jalview.api;
 
-/**
- * Read or write a CLANS style score matrix file.
- */
+import java.beans.PropertyChangeListener;
 
-public class ClansFile extends FileParse
+public interface RendererListenerI extends PropertyChangeListener
 {
 
 }
index ecada36..5801a96 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.api.analysis;
 
 /**
index 7f138cd..275cd92 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.api.analysis;
 
 import jalview.api.AlignmentViewPanel;
@@ -65,7 +85,8 @@ public interface ScoreModelI
    * @param options
    * @return
    */
-  MatrixI findSimilarities(AlignmentView seqData, SimilarityParamsI options);
+  MatrixI findSimilarities(AlignmentView seqData,
+          SimilarityParamsI options);
 
   /**
    * Returns a score model object configured for the given alignment view.
index 581449f..8d83a17 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.api.analysis;
 
 /**
index 86610a2..46bd4fd 100644 (file)
@@ -76,8 +76,8 @@ import java.util.SortedMap;
 import java.util.TreeMap;
 import java.util.Vector;
 
-public class APopupMenu extends java.awt.PopupMenu implements
-        ActionListener, ItemListener
+public class APopupMenu extends java.awt.PopupMenu
+        implements ActionListener, ItemListener
 {
   Menu groupMenu = new Menu();
 
@@ -262,8 +262,9 @@ public class APopupMenu extends java.awt.PopupMenu implements
         purinePyrimidineColour.setEnabled(false);
         nucleotideColour.setEnabled(false);
       }
-      editGroupName.setLabel(MessageManager.formatMessage(
-              "label.name_param", new Object[] { sg.getName() }));
+      editGroupName.setLabel(
+              MessageManager.formatMessage("label.name_param", new Object[]
+              { sg.getName() }));
       showText.setState(sg.getDisplayText());
       showColourText.setState(sg.getColourText());
       showBoxes.setState(sg.getDisplayBoxes());
@@ -304,17 +305,18 @@ public class APopupMenu extends java.awt.PopupMenu implements
       seqMenu.setLabel(seq.getName());
       if (seq == ap.av.getAlignment().getSeqrep())
       {
-        makeReferenceSeq.setLabel(MessageManager
-                .getString("action.unmark_as_reference"));// Unmark
-                                                          // representative");
+        makeReferenceSeq.setLabel(
+                MessageManager.getString("action.unmark_as_reference"));// Unmark
+                                                                        // representative");
       }
       else
       {
-        makeReferenceSeq.setLabel(MessageManager
-                .getString("action.set_as_reference")); // );
+        makeReferenceSeq.setLabel(
+                MessageManager.getString("action.set_as_reference")); // );
       }
-      repGroup.setLabel(MessageManager.formatMessage(
-              "label.represent_group_with", new Object[] { seq.getName() }));
+      repGroup.setLabel(MessageManager
+              .formatMessage("label.represent_group_with", new Object[]
+              { seq.getName() }));
     }
     else
     {
@@ -381,7 +383,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
   void addFeatureLinks(final SequenceI seq, List<String> links)
   {
     Menu linkMenu = new Menu(MessageManager.getString("action.link"));
-    Map<String, List<String>> linkset = new LinkedHashMap<String, List<String>>();
+    Map<String, List<String>> linkset = new LinkedHashMap<>();
 
     for (String link : links)
     {
@@ -446,8 +448,9 @@ public class APopupMenu extends java.awt.PopupMenu implements
     /*
      * First for the currently selected sequence (if there is one):
      */
-    final List<SequenceI> selectedSequence = (seq == null ? Collections
-            .<SequenceI> emptyList() : Arrays.asList(seq));
+    final List<SequenceI> selectedSequence = (seq == null
+            ? Collections.<SequenceI> emptyList()
+            : Arrays.asList(seq));
     buildAnnotationTypesMenus(seqShowAnnotationsMenu,
             seqHideAnnotationsMenu, selectedSequence);
     configureReferenceAnnotationsMenu(seqAddReferenceAnnotations,
@@ -456,9 +459,9 @@ public class APopupMenu extends java.awt.PopupMenu implements
     /*
      * and repeat for the current selection group (if there is one):
      */
-    final List<SequenceI> selectedGroup = (ap.av.getSelectionGroup() == null ? Collections
-            .<SequenceI> emptyList() : ap.av.getSelectionGroup()
-            .getSequences());
+    final List<SequenceI> selectedGroup = (ap.av.getSelectionGroup() == null
+            ? Collections.<SequenceI> emptyList()
+            : ap.av.getSelectionGroup().getSequences());
     buildAnnotationTypesMenus(groupShowAnnotationsMenu,
             groupHideAnnotationsMenu, selectedGroup);
     configureReferenceAnnotationsMenu(groupAddReferenceAnnotations,
@@ -482,11 +485,11 @@ public class APopupMenu extends java.awt.PopupMenu implements
      * Temporary store to hold distinct calcId / type pairs for the tooltip.
      * Using TreeMap means calcIds are shown in alphabetical order.
      */
-    SortedMap<String, String> tipEntries = new TreeMap<String, String>();
-    final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<SequenceI, List<AlignmentAnnotation>>();
+    SortedMap<String, String> tipEntries = new TreeMap<>();
+    final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<>();
     AlignmentI al = this.ap.av.getAlignment();
-    AlignmentUtils.findAddableReferenceAnnotations(forSequences,
-            tipEntries, candidates, al);
+    AlignmentUtils.findAddableReferenceAnnotations(forSequences, tipEntries,
+            candidates, al);
     if (!candidates.isEmpty())
     {
       StringBuilder tooltip = new StringBuilder(64);
@@ -751,9 +754,10 @@ public class APopupMenu extends java.awt.PopupMenu implements
           seq = sg.getSequenceAt(0);
         }
 
-        EditNameDialog dialog = new EditNameDialog(seq.getSequenceAsString(
-                sg.getStartRes(), sg.getEndRes() + 1), null,
-                "Edit Sequence ", null,
+        EditNameDialog dialog = new EditNameDialog(
+                seq.getSequenceAsString(sg.getStartRes(),
+                        sg.getEndRes() + 1),
+                null, "Edit Sequence ", null,
 
                 ap.alignFrame, "Edit Sequence", 500, 100, true);
 
@@ -761,16 +765,16 @@ public class APopupMenu extends java.awt.PopupMenu implements
         {
           EditCommand editCommand = new EditCommand(
                   MessageManager.getString("label.edit_sequences"),
-                  Action.REPLACE, dialog.getName().replace(' ',
-                          ap.av.getGapCharacter()),
+                  Action.REPLACE,
+                  dialog.getName().replace(' ', ap.av.getGapCharacter()),
                   sg.getSequencesAsArray(ap.av.getHiddenRepSequences()),
                   sg.getStartRes(), sg.getEndRes() + 1,
                   ap.av.getAlignment());
 
           ap.alignFrame.addHistoryItem(editCommand);
 
-          ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
-                  .getSequences());
+          ap.av.firePropertyChange("alignment", null,
+                  ap.av.getAlignment().getSequences());
         }
       }
     }
@@ -807,8 +811,8 @@ public class APopupMenu extends java.awt.PopupMenu implements
 
         ap.alignFrame.addHistoryItem(caseCommand);
 
-        ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
-                .getSequences());
+        ap.av.firePropertyChange("alignment", null,
+                ap.av.getAlignment().getSequences());
 
       }
     }
@@ -821,8 +825,8 @@ public class APopupMenu extends java.awt.PopupMenu implements
       }
 
       int gSize = sg.getSize();
-      List<SequenceI> seqs = new ArrayList<SequenceI>();
-      List<SequenceFeature> features = new ArrayList<SequenceFeature>();
+      List<SequenceI> seqs = new ArrayList<>();
+      List<SequenceFeature> features = new ArrayList<>();
 
       for (int i = 0; i < gSize; i++)
       {
@@ -831,7 +835,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
         if (start <= end)
         {
           seqs.add(sg.getSequenceAt(i));
-          features.add(new SequenceFeature(null, null, null, start, end,
+          features.add(new SequenceFeature(null, null, start, end,
                   "Jalview"));
         }
       }
@@ -843,7 +847,8 @@ public class APopupMenu extends java.awt.PopupMenu implements
         {
           ap.alignFrame.sequenceFeatures.setState(true);
           ap.av.setShowSequenceFeatures(true);
-          ap.highlightSearchResults(null);
+          ap.av.setSearchResults(null); // clear highlighting
+          ap.repaint(); // draw new/amended features
         }
       }
     }
@@ -860,15 +865,15 @@ public class APopupMenu extends java.awt.PopupMenu implements
 
     Frame frame = new Frame();
     frame.add(cap);
-    JalviewLite.addFrame(frame, MessageManager.formatMessage(
-            "label.selection_output_command",
-            new Object[] { e.getActionCommand() }), 600, 500);
+    JalviewLite.addFrame(frame, MessageManager
+            .formatMessage("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
     // TODO consider using getSequenceSelection instead here
 
-    FileFormatI fileFormat = FileFormats.getInstance().forName(
-            e.getActionCommand());
+    FileFormatI fileFormat = FileFormats.getInstance()
+            .forName(e.getActionCommand());
     cap.setText(new AppletFormatAdapter().formatSequences(fileFormat,
             ap.av.getShowJVSuffix(), ap, true));
 
@@ -892,25 +897,26 @@ public class APopupMenu extends java.awt.PopupMenu implements
     StringBuilder contents = new StringBuilder(128);
     for (SequenceI seq : sequences)
     {
-      contents.append(MessageManager.formatMessage(
-              "label.annotation_for_displayid",
-              new Object[] { seq.getDisplayId(true) }));
+      contents.append(MessageManager
+              .formatMessage("label.annotation_for_displayid", new Object[]
+              { seq.getDisplayId(true) }));
       new SequenceAnnotationReport(null).createSequenceAnnotationReport(
-              contents,
-              seq,
-              true,
-              true,
-              (ap.seqPanel.seqCanvas.fr != null) ? ap.seqPanel.seqCanvas.fr
-                      .getMinMax() : null);
+              contents, seq, true, true,
+              (ap.seqPanel.seqCanvas.fr != null)
+                      ? ap.seqPanel.seqCanvas.fr.getMinMax()
+                      : null);
       contents.append("</p>");
     }
     Frame frame = new Frame();
     frame.add(cap);
-    jalview.bin.JalviewLite.addFrame(frame, "Sequence Details for "
-            + (sequences.length == 1 ? sequences[0].getDisplayId(true)
-                    : "Selection"), 600, 500);
-    cap.setText(MessageManager.formatMessage("label.html_content",
-            new Object[] { contents.toString() }));
+    jalview.bin.JalviewLite.addFrame(frame,
+            "Sequence Details for " + (sequences.length == 1
+                    ? sequences[0].getDisplayId(true)
+                    : "Selection"),
+            600, 500);
+    cap.setText(
+            MessageManager.formatMessage("label.html_content", new Object[]
+            { contents.toString() }));
   }
 
   void editName()
@@ -924,7 +930,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
     {
       seq.setName(dialog.getName());
       seq.setDescription(dialog.getDescription());
-      ap.paintAlignment(false);
+      ap.paintAlignment(false, false);
     }
   }
 
@@ -942,21 +948,22 @@ public class APopupMenu extends java.awt.PopupMenu implements
       }
       else
       {
-        new MCview.AppletPDBViewer(entry, new SequenceI[] { seq }, null,
-                ap, DataSourceType.URL);
+        new MCview.AppletPDBViewer(entry, new SequenceI[] { seq }, null, ap,
+                DataSourceType.URL);
       }
 
     }
     else
     {
-      CutAndPasteTransfer cap = new CutAndPasteTransfer(true, ap.alignFrame);
+      CutAndPasteTransfer cap = new CutAndPasteTransfer(true,
+              ap.alignFrame);
       cap.setText(MessageManager.getString("label.paste_pdb_file"));
       cap.setPDBImport(seq);
       Frame frame = new Frame();
       frame.add(cap);
       JalviewLite.addFrame(frame, MessageManager.formatMessage(
-              "label.paste_pdb_file_for_sequence",
-              new Object[] { seq.getName() }), 400, 300);
+              "label.paste_pdb_file_for_sequence", new Object[]
+              { seq.getName() }), 400, 300);
     }
   }
 
@@ -966,12 +973,12 @@ public class APopupMenu extends java.awt.PopupMenu implements
     sequenceFeature.addActionListener(this);
 
     editGroupName.addActionListener(this);
-    unGroupMenuItem.setLabel(MessageManager
-            .getString("action.remove_group"));
+    unGroupMenuItem
+            .setLabel(MessageManager.getString("action.remove_group"));
     unGroupMenuItem.addActionListener(this);
 
-    createGroupMenuItem.setLabel(MessageManager
-            .getString("action.create_group"));
+    createGroupMenuItem
+            .setLabel(MessageManager.getString("action.create_group"));
     createGroupMenuItem.addActionListener(this);
 
     modifyPID.setEnabled(abovePIDColour.getState());
@@ -983,8 +990,8 @@ public class APopupMenu extends java.awt.PopupMenu implements
     sequenceName.addActionListener(this);
     sequenceDetails.addActionListener(this);
     selSeqDetails.addActionListener(this);
-    displayNonconserved.setLabel(MessageManager
-            .getString("label.show_non_conserved"));
+    displayNonconserved
+            .setLabel(MessageManager.getString("label.show_non_conserved"));
     displayNonconserved.setState(false);
     displayNonconserved.addItemListener(this);
     showText.setLabel(MessageManager.getString("action.text"));
@@ -995,8 +1002,9 @@ public class APopupMenu extends java.awt.PopupMenu implements
     seqMenu.setLabel(MessageManager.getString("label.sequence"));
     pdb.setLabel(MessageManager.getString("label.view_pdb_structure"));
     hideSeqs.setLabel(MessageManager.getString("action.hide_sequences"));
-    repGroup.setLabel(MessageManager.formatMessage(
-            "label.represent_group_with", new Object[] { "" }));
+    repGroup.setLabel(MessageManager
+            .formatMessage("label.represent_group_with", new Object[]
+            { "" }));
     revealAll.setLabel(MessageManager.getString("action.reveal_all"));
     revealSeq.setLabel(MessageManager.getString("action.reveal_sequences"));
     menu1.setLabel(MessageManager.getString("label.group:"));
@@ -1042,28 +1050,28 @@ public class APopupMenu extends java.awt.PopupMenu implements
     /*
      * setName allows setSelectedColour to do its thing
      */
-    clustalColour.setLabel(MessageManager
-            .getString("label.colourScheme_clustal"));
+    clustalColour.setLabel(
+            MessageManager.getString("label.colourScheme_clustal"));
     clustalColour.setName(JalviewColourScheme.Clustal.toString());
     clustalColour.addItemListener(this);
-    BLOSUM62Colour.setLabel(MessageManager
-            .getString("label.colourScheme_blosum62"));
+    BLOSUM62Colour.setLabel(
+            MessageManager.getString("label.colourScheme_blosum62"));
     BLOSUM62Colour.setName(JalviewColourScheme.Blosum62.toString());
     BLOSUM62Colour.addItemListener(this);
-    PIDColour.setLabel(MessageManager
-            .getString("label.colourScheme_%_identity"));
+    PIDColour.setLabel(
+            MessageManager.getString("label.colourScheme_%_identity"));
     PIDColour.setName(JalviewColourScheme.PID.toString());
     PIDColour.addItemListener(this);
-    zappoColour.setLabel(MessageManager
-            .getString("label.colourScheme_zappo"));
+    zappoColour
+            .setLabel(MessageManager.getString("label.colourScheme_zappo"));
     zappoColour.setName(JalviewColourScheme.Zappo.toString());
     zappoColour.addItemListener(this);
-    taylorColour.setLabel(MessageManager
-            .getString("label.colourScheme_taylor"));
+    taylorColour.setLabel(
+            MessageManager.getString("label.colourScheme_taylor"));
     taylorColour.setName(JalviewColourScheme.Taylor.toString());
     taylorColour.addItemListener(this);
-    hydrophobicityColour.setLabel(MessageManager
-            .getString("label.colourScheme_hydrophobic"));
+    hydrophobicityColour.setLabel(
+            MessageManager.getString("label.colourScheme_hydrophobic"));
     hydrophobicityColour
             .setName(JalviewColourScheme.Hydrophobic.toString());
     hydrophobicityColour.addItemListener(this);
@@ -1075,36 +1083,36 @@ public class APopupMenu extends java.awt.PopupMenu implements
             .getString("label.colourScheme_strand_propensity"));
     strandColour.setName(JalviewColourScheme.Strand.toString());
     strandColour.addItemListener(this);
-    turnColour.setLabel(MessageManager
-            .getString("label.colourScheme_turn_propensity"));
+    turnColour.setLabel(
+            MessageManager.getString("label.colourScheme_turn_propensity"));
     turnColour.setName(JalviewColourScheme.Turn.toString());
     turnColour.addItemListener(this);
-    buriedColour.setLabel(MessageManager
-            .getString("label.colourScheme_buried_index"));
+    buriedColour.setLabel(
+            MessageManager.getString("label.colourScheme_buried_index"));
     buriedColour.setName(JalviewColourScheme.Buried.toString());
     buriedColour.addItemListener(this);
-    nucleotideColour.setLabel(MessageManager
-            .getString("label.colourScheme_nucleotide"));
+    nucleotideColour.setLabel(
+            MessageManager.getString("label.colourScheme_nucleotide"));
     nucleotideColour.setName(JalviewColourScheme.Nucleotide.toString());
     nucleotideColour.addItemListener(this);
     purinePyrimidineColour.setLabel(MessageManager
             .getString("label.colourScheme_purine/pyrimidine"));
-    purinePyrimidineColour.setName(JalviewColourScheme.PurinePyrimidine
-            .toString());
+    purinePyrimidineColour
+            .setName(JalviewColourScheme.PurinePyrimidine.toString());
     purinePyrimidineColour.addItemListener(this);
 
-    userDefinedColour.setLabel(MessageManager
-            .getString("action.user_defined"));
+    userDefinedColour
+            .setLabel(MessageManager.getString("action.user_defined"));
     userDefinedColour.addActionListener(this);
 
-    abovePIDColour.setLabel(MessageManager
-            .getString("label.above_identity_threshold"));
+    abovePIDColour.setLabel(
+            MessageManager.getString("label.above_identity_threshold"));
     abovePIDColour.addItemListener(this);
-    modifyPID.setLabel(MessageManager
-            .getString("label.modify_identity_threshold"));
+    modifyPID.setLabel(
+            MessageManager.getString("label.modify_identity_threshold"));
     modifyPID.addActionListener(this);
-    conservationColour.setLabel(MessageManager
-            .getString("action.by_conservation"));
+    conservationColour
+            .setLabel(MessageManager.getString("action.by_conservation"));
     conservationColour.addItemListener(this);
     modifyConservation.setLabel(MessageManager
             .getString("label.modify_conservation_threshold"));
@@ -1155,14 +1163,14 @@ public class APopupMenu extends java.awt.PopupMenu implements
 
   void refresh()
   {
-    ap.paintAlignment(true);
+    ap.paintAlignment(true, true);
   }
 
   protected void clustalColour_actionPerformed()
   {
     SequenceGroup sg = getGroup();
-    sg.cs = new ResidueShader(new ClustalxColourScheme(sg,
-            ap.av.getHiddenRepSequences()));
+    sg.cs = new ResidueShader(
+            new ClustalxColourScheme(sg, ap.av.getHiddenRepSequences()));
     refresh();
   }
 
@@ -1216,8 +1224,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
 
   public void purinePyrimidineColour_actionPerformed()
   {
-    getGroup().cs = new ResidueShader(
-            new PurinePyrimidineColourScheme());
+    getGroup().cs = new ResidueShader(new PurinePyrimidineColourScheme());
     refresh();
   }
 
@@ -1231,10 +1238,11 @@ public class APopupMenu extends java.awt.PopupMenu implements
 
     if (abovePIDColour.getState())
     {
-      sg.cs.setConsensus(AAFrequency.calculate(sg.getSequences(ap.av
-              .getHiddenRepSequences()), 0, ap.av.getAlignment().getWidth()));
-      int threshold = SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup()
-              .getName());
+      sg.cs.setConsensus(AAFrequency.calculate(
+              sg.getSequences(ap.av.getHiddenRepSequences()), 0,
+              ap.av.getAlignment().getWidth()));
+      int threshold = SliderPanel.setPIDSliderSource(ap, sg.cs,
+              getGroup().getName());
 
       sg.cs.setThreshold(threshold, ap.av.isIgnoreGapsConsensus());
 
@@ -1260,8 +1268,9 @@ public class APopupMenu extends java.awt.PopupMenu implements
   {
     SequenceGroup sg = getGroup();
     sg.cs = new ResidueShader(new PIDColourScheme());
-    sg.cs.setConsensus(AAFrequency.calculate(sg.getSequences(ap.av
-            .getHiddenRepSequences()), 0, ap.av.getAlignment().getWidth()));
+    sg.cs.setConsensus(AAFrequency.calculate(
+            sg.getSequences(ap.av.getHiddenRepSequences()), 0,
+            ap.av.getAlignment().getWidth()));
     refresh();
   }
 
@@ -1271,8 +1280,9 @@ public class APopupMenu extends java.awt.PopupMenu implements
 
     sg.cs = new ResidueShader(new Blosum62ColourScheme());
 
-    sg.cs.setConsensus(AAFrequency.calculate(sg.getSequences(ap.av
-            .getHiddenRepSequences()), 0, ap.av.getAlignment().getWidth()));
+    sg.cs.setConsensus(AAFrequency.calculate(
+            sg.getSequences(ap.av.getHiddenRepSequences()), 0,
+            ap.av.getAlignment().getWidth()));
 
     refresh();
   }
@@ -1294,10 +1304,9 @@ public class APopupMenu extends java.awt.PopupMenu implements
     if (conservationColour.getState())
     {
       Conservation conservation = Conservation.calculateConservation(
-              "Group", sg
-              .getSequences(ap.av.getHiddenRepSequences()), 0, ap.av
-              .getAlignment().getWidth(), false, ap.av.getConsPercGaps(),
-              false);
+              "Group", sg.getSequences(ap.av.getHiddenRepSequences()), 0,
+              ap.av.getAlignment().getWidth(), false,
+              ap.av.getConsPercGaps(), false);
       sg.getGroupColourScheme().setConservation(conservation);
       SliderPanel.setConservationSlider(ap, sg.cs, sg.getName());
       SliderPanel.showConservationSlider();
@@ -1330,7 +1339,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
     SequenceGroup sg = ap.av.getSelectionGroup();
     ap.av.getAlignment().deleteGroup(sg);
     ap.av.setSelectionGroup(null);
-    ap.paintAlignment(true);
+    ap.paintAlignment(true, true);
   }
 
   void createGroupMenuItem_actionPerformed()
@@ -1412,9 +1421,11 @@ public class APopupMenu extends java.awt.PopupMenu implements
     showMenu.removeAll();
     hideMenu.removeAll();
 
-    final List<String> all = Arrays.asList(new String[] { MessageManager
-            .getString("label.all") });
-    addAnnotationTypeToShowHide(showMenu, forSequences, "", all, true, true);
+    final List<String> all = Arrays
+            .asList(new String[]
+            { MessageManager.getString("label.all") });
+    addAnnotationTypeToShowHide(showMenu, forSequences, "", all, true,
+            true);
     addAnnotationTypeToShowHide(hideMenu, forSequences, "", all, true,
             false);
     showMenu.addSeparator();
@@ -1429,8 +1440,8 @@ public class APopupMenu extends java.awt.PopupMenu implements
      * the insertion order, which is the order of the annotations on the
      * alignment.
      */
-    Map<String, List<List<String>>> shownTypes = new LinkedHashMap<String, List<List<String>>>();
-    Map<String, List<List<String>>> hiddenTypes = new LinkedHashMap<String, List<List<String>>>();
+    Map<String, List<List<String>>> shownTypes = new LinkedHashMap<>();
+    Map<String, List<List<String>>> hiddenTypes = new LinkedHashMap<>();
     AlignmentAnnotationUtils.getShownHiddenTypes(shownTypes, hiddenTypes,
             AlignmentAnnotationUtils.asList(annotations), forSequences);
 
index 65d652d..ef87671 100644 (file)
@@ -173,15 +173,15 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
   }
 
   public AlignFrame(AlignmentI al, SequenceI[] hiddenSeqs,
-          HiddenColumns hidden, JalviewLite applet,
-          String title, boolean embedded)
+          HiddenColumns hidden, JalviewLite applet, String title,
+          boolean embedded)
   {
     this(al, hiddenSeqs, hidden, applet, title, embedded, true);
   }
 
   public AlignFrame(AlignmentI al, SequenceI[] hiddenSeqs,
-          HiddenColumns hidden, JalviewLite applet,
-          String title, boolean embedded, boolean addToDisplay)
+          HiddenColumns hidden, JalviewLite applet, String title,
+          boolean embedded, boolean addToDisplay)
   {
     if (applet != null)
     {
@@ -343,7 +343,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     createAlignFrameWindow(embedded);
     validate();
     alignPanel.adjustAnnotationHeight();
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, true);
   }
 
   public AlignViewport getAlignViewport()
@@ -390,8 +390,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     {
       Map<String, FeatureColourI> colours = alignPanel.seqPanel.seqCanvas
               .getFeatureRenderer().getFeatureColours();
-      boolean relaxedIdMatching = viewport.applet.getDefaultParameter(
-              "relaxedidmatch", false);
+      boolean relaxedIdMatching = viewport.applet
+              .getDefaultParameter("relaxedidmatch", false);
       featuresFile = new FeaturesFile(file, sourceType).parse(
               viewport.getAlignment(), colours, true, relaxedIdMatching);
     } catch (Exception ex)
@@ -415,7 +415,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
       {
         viewport.featureSettings.refreshTable();
       }
-      alignPanel.paintAlignment(true);
+      alignPanel.paintAlignment(true, true);
       statusBar.setText(MessageManager
               .getString("label.successfully_added_features_alignment"));
     }
@@ -428,9 +428,10 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     ViewportRanges ranges = viewport.getRanges();
 
     if (viewport.cursorMode
-            && ((evt.getKeyCode() >= KeyEvent.VK_0 && evt.getKeyCode() <= KeyEvent.VK_9) || (evt
-                    .getKeyCode() >= KeyEvent.VK_NUMPAD0 && evt
-                    .getKeyCode() <= KeyEvent.VK_NUMPAD9))
+            && ((evt.getKeyCode() >= KeyEvent.VK_0
+                    && evt.getKeyCode() <= KeyEvent.VK_9)
+                    || (evt.getKeyCode() >= KeyEvent.VK_NUMPAD0
+                            && evt.getKeyCode() <= KeyEvent.VK_NUMPAD9))
             && Character.isDigit(evt.getKeyChar()))
     {
       alignPanel.seqPanel.numberPressed(evt.getKeyChar());
@@ -573,9 +574,9 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
 
     case KeyEvent.VK_F2:
       viewport.cursorMode = !viewport.cursorMode;
-      statusBar.setText(MessageManager.formatMessage(
-              "label.keyboard_editing_mode",
-              new String[] { (viewport.cursorMode ? "on" : "off") }));
+      statusBar.setText(MessageManager
+              .formatMessage("label.keyboard_editing_mode", new String[]
+              { (viewport.cursorMode ? "on" : "off") }));
       if (viewport.cursorMode)
       {
         alignPanel.seqPanel.seqCanvas.cursorX = ranges.getStartRes();
@@ -690,7 +691,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
       break;
 
     }
-    alignPanel.paintAlignment(true);
+    // TODO: repaint flags set only if the keystroke warrants it
+    alignPanel.paintAlignment(true, true);
   }
 
   /**
@@ -708,9 +710,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
       // Hide everything by the current selection - this is a hack - we do the
       // invert and then hide
       // first check that there will be visible columns after the invert.
-      if (viewport.hasSelectedColumns()
-              || (sg != null && sg.getSize() > 0 && sg.getStartRes() <= sg
-                      .getEndRes()))
+      if (viewport.hasSelectedColumns() || (sg != null && sg.getSize() > 0
+              && sg.getStartRes() <= sg.getEndRes()))
       {
         // now invert the sequence set, if required - empty selection implies
         // that no hiding is required.
@@ -839,16 +840,18 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     {
       boolean newState = sortAnnBySequence.getState();
       sortAnnByLabel.setState(false);
-      setAnnotationSortOrder(newState ? SequenceAnnotationOrder.SEQUENCE_AND_LABEL
-              : SequenceAnnotationOrder.NONE);
+      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);
+      setAnnotationSortOrder(
+              newState ? SequenceAnnotationOrder.LABEL_AND_SEQUENCE
+                      : SequenceAnnotationOrder.NONE);
       setViewportAnnotationOrder();
     }
     else if (source == showAutoFirst)
@@ -915,7 +918,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     {
       applyAutoAnnotationSettings_actionPerformed();
     }
-    alignPanel.paintAlignment(true);
+    // TODO: repaint flags set only if warranted
+    alignPanel.paintAlignment(true, true);
   }
 
   /**
@@ -1092,7 +1096,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     else if (source == invertColSel)
     {
       viewport.invertColumnSelection();
-      alignPanel.paintAlignment(true);
+      alignPanel.paintAlignment(false, false);
       viewport.sendSelection();
     }
     else if (source == remove2LeftMenuItem)
@@ -1126,34 +1130,34 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     else if (source == showColumns)
     {
       viewport.showAllHiddenColumns();
-      alignPanel.paintAlignment(true);
+      alignPanel.paintAlignment(true, true);
       viewport.sendSelection();
     }
     else if (source == showSeqs)
     {
       viewport.showAllHiddenSeqs();
-      alignPanel.paintAlignment(true);
+      alignPanel.paintAlignment(true, true);
       // uncomment if we want to slave sequence selections in split frame
       // viewport.sendSelection();
     }
     else if (source == hideColumns)
     {
       viewport.hideSelectedColumns();
-      alignPanel.paintAlignment(true);
+      alignPanel.paintAlignment(true, true);
       viewport.sendSelection();
     }
     else if (source == hideSequences
             && viewport.getSelectionGroup() != null)
     {
       viewport.hideAllSelectedSeqs();
-      alignPanel.paintAlignment(true);
+      alignPanel.paintAlignment(true, true);
       // uncomment if we want to slave sequence selections in split frame
       // viewport.sendSelection();
     }
     else if (source == hideAllButSelection)
     {
       toggleHiddenRegions(false, false);
-      alignPanel.paintAlignment(true);
+      alignPanel.paintAlignment(true, true);
       viewport.sendSelection();
     }
     else if (source == hideAllSelection)
@@ -1162,14 +1166,14 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
       viewport.expandColSelection(sg, false);
       viewport.hideAllSelectedSeqs();
       viewport.hideSelectedColumns();
-      alignPanel.paintAlignment(true);
+      alignPanel.paintAlignment(true, true);
       viewport.sendSelection();
     }
     else if (source == showAllHidden)
     {
       viewport.showAllHiddenColumns();
       viewport.showAllHiddenSeqs();
-      alignPanel.paintAlignment(true);
+      alignPanel.paintAlignment(true, true);
       viewport.sendSelection();
     }
     else if (source == showGroupConsensus)
@@ -1208,9 +1212,9 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
       cap.setText(contents.toString());
       Frame frame = new Frame();
       frame.add(cap);
-      jalview.bin.JalviewLite.addFrame(frame, MessageManager.formatMessage(
-              "label.alignment_properties", new String[] { getTitle() }),
-              400, 250);
+      jalview.bin.JalviewLite.addFrame(frame, MessageManager
+              .formatMessage("label.alignment_properties", new String[]
+              { getTitle() }), 400, 250);
     }
     else if (source == overviewMenuItem)
     {
@@ -1371,15 +1375,15 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     CutAndPasteTransfer cap = new CutAndPasteTransfer(true, this);
     Frame frame = new Frame();
     frame.add(cap);
-    JalviewLite.addFrame(frame, MessageManager.formatMessage(
-            "label.alignment_output_command",
-            new Object[] { e.getActionCommand() }), 600, 500);
-
-    FileFormatI fileFormat = FileFormats.getInstance().forName(
-            e.getActionCommand());
-    cap.setText(new AppletFormatAdapter(alignPanel).formatSequences(
-            fileFormat, viewport.getAlignment(),
-            viewport.getShowJVSuffix()));
+    JalviewLite.addFrame(frame, MessageManager
+            .formatMessage("label.alignment_output_command", new Object[]
+            { e.getActionCommand() }), 600, 500);
+
+    FileFormatI fileFormat = FileFormats.getInstance()
+            .forName(e.getActionCommand());
+    cap.setText(
+            new AppletFormatAdapter(alignPanel).formatSequences(fileFormat,
+                    viewport.getAlignment(), viewport.getShowJVSuffix()));
   }
 
   public void loadAnnotations()
@@ -1424,6 +1428,17 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     return null;
   }
 
+  private List<String> getDisplayedFeatureGroups()
+  {
+    if (alignPanel.getFeatureRenderer() != null
+            && viewport.getFeaturesDisplayed() != null)
+    {
+      return alignPanel.getFeatureRenderer().getDisplayedFeatureGroups();
+
+    }
+    return null;
+  }
+
   public String outputFeatures(boolean displayTextbox, String format)
   {
     String features;
@@ -1431,12 +1446,14 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     if (format.equalsIgnoreCase("Jalview"))
     {
       features = formatter.printJalviewFormat(viewport.getAlignment()
-              .getSequencesArray(), getDisplayedFeatureCols());
+              .getSequencesArray(), getDisplayedFeatureCols(),
+              getDisplayedFeatureGroups(), true);
     }
     else
     {
       features = formatter.printGffFormat(viewport.getAlignment()
-              .getSequencesArray(), getDisplayedFeatureCols());
+              .getSequencesArray(), getDisplayedFeatureCols(),
+              getDisplayedFeatureGroups(), true);
     }
 
     if (displayTextbox)
@@ -1479,8 +1496,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
             : "?";
     url.append(firstSep);
 
-    url.append("open="
-            + appendProtocol(viewport.applet.getParameter("file")));
+    url.append(
+            "open=" + appendProtocol(viewport.applet.getParameter("file")));
 
     if (viewport.applet.getParameter("features") != null)
     {
@@ -1491,30 +1508,30 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     if (viewport.applet.getParameter("annotations") != null)
     {
       url.append("&annotations=");
-      url.append(appendProtocol(viewport.applet.getParameter("annotations")));
+      url.append(
+              appendProtocol(viewport.applet.getParameter("annotations")));
     }
 
     if (viewport.applet.getParameter("jnetfile") != null
             || viewport.applet.getParameter("jpredfile") != null)
     {
       url.append("&annotations=");
-      url.append(appendProtocol(viewport.applet.getParameter("jnetfile") != null ? viewport.applet
-              .getParameter("jnetfile") : viewport.applet
-              .getParameter("jpredfile")));
+      url.append(appendProtocol(
+              viewport.applet.getParameter("jnetfile") != null
+                      ? viewport.applet.getParameter("jnetfile")
+                      : viewport.applet.getParameter("jpredfile")));
     }
 
     if (viewport.applet.getParameter("defaultColour") != null)
     {
-      url.append("&colour="
-              + removeWhiteSpace(viewport.applet
-                      .getParameter("defaultColour")));
+      url.append("&colour=" + removeWhiteSpace(
+              viewport.applet.getParameter("defaultColour")));
     }
 
     if (viewport.applet.getParameter("userDefinedColour") != null)
     {
-      url.append("&colour="
-              + removeWhiteSpace(viewport.applet
-                      .getParameter("userDefinedColour")));
+      url.append("&colour=" + removeWhiteSpace(
+              viewport.applet.getParameter("userDefinedColour")));
     }
     if (viewport.applet.getParameter("tree") != null)
     {
@@ -1586,10 +1603,12 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     {
       System.exit(0);
     }
-    else
+
+    viewport = null;
+    if (alignPanel != null && alignPanel.overviewPanel != null)
     {
+      alignPanel.overviewPanel.dispose();
     }
-    viewport = null;
     alignPanel = null;
     this.dispose();
   }
@@ -1604,9 +1623,9 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     {
       undoMenuItem.setEnabled(true);
       CommandI command = viewport.getHistoryList().peek();
-      undoMenuItem.setLabel(MessageManager.formatMessage(
-              "label.undo_command",
-              new Object[] { command.getDescription() }));
+      undoMenuItem.setLabel(MessageManager
+              .formatMessage("label.undo_command", new Object[]
+              { command.getDescription() }));
     }
     else
     {
@@ -1619,9 +1638,9 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
       redoMenuItem.setEnabled(true);
 
       CommandI command = viewport.getRedoList().peek();
-      redoMenuItem.setLabel(MessageManager.formatMessage(
-              "label.redo_command",
-              new Object[] { command.getDescription() }));
+      redoMenuItem.setLabel(MessageManager
+              .formatMessage("label.redo_command", new Object[]
+              { command.getDescription() }));
     }
     else
     {
@@ -1673,8 +1692,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
                                           // viewport.getColumnSelection().getHiddenColumns()
                                           // != null;
     updateEditMenuBar();
-    originalSource.firePropertyChange("alignment", null, originalSource
-            .getAlignment().getSequences());
+    originalSource.firePropertyChange("alignment", null,
+            originalSource.getAlignment().getSequences());
   }
 
   /**
@@ -1706,8 +1725,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
                                           // != null;
 
     updateEditMenuBar();
-    originalSource.firePropertyChange("alignment", null, originalSource
-            .getAlignment().getSequences());
+    originalSource.firePropertyChange("alignment", null,
+            originalSource.getAlignment().getSequences());
   }
 
   AlignmentViewport getOriginatingSource(CommandI command)
@@ -1721,8 +1740,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     {
       EditCommand editCommand = (EditCommand) command;
       al = editCommand.getAlignment();
-      Vector comps = (Vector) PaintRefresher.components.get(viewport
-              .getSequenceSetId());
+      Vector comps = PaintRefresher.components
+              .get(viewport.getSequenceSetId());
       for (int i = 0; i < comps.size(); i++)
       {
         if (comps.elementAt(i) instanceof AlignmentPanel)
@@ -1766,7 +1785,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     }
     viewport.getAlignment().moveSelectedSequencesByOne(sg,
             up ? null : viewport.getHiddenRepSequences(), up);
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, false);
 
     /*
      * Also move cDNA/protein complement sequences
@@ -1778,7 +1797,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
               viewport, complement);
       complement.getAlignment().moveSelectedSequencesByOne(mappedSelection,
               up ? null : complement.getHiddenRepSequences(), up);
-      getSplitFrame().getComplement(this).alignPanel.paintAlignment(true);
+      getSplitFrame().getComplement(this).alignPanel.paintAlignment(true,
+              false);
     }
   }
 
@@ -1787,15 +1807,15 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     List<SequenceI> sg = new Vector<>();
     if (viewport.cursorMode)
     {
-      sg.add(viewport.getAlignment().getSequenceAt(
-              alignPanel.seqPanel.seqCanvas.cursorY));
+      sg.add(viewport.getAlignment()
+              .getSequenceAt(alignPanel.seqPanel.seqCanvas.cursorY));
     }
     else if (viewport.getSelectionGroup() != null
             && viewport.getSelectionGroup().getSize() != viewport
                     .getAlignment().getHeight())
     {
-      sg = viewport.getSelectionGroup().getSequences(
-              viewport.getHiddenRepSequences());
+      sg = viewport.getSelectionGroup()
+              .getSequences(viewport.getHiddenRepSequences());
     }
 
     if (sg.size() < 1)
@@ -1815,8 +1835,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
 
     SequenceI[] seqs1 = sg.toArray(new SequenceI[sg.size()]);
 
-    SequenceI[] seqs2 = invertGroup.toArray(new SequenceI[invertGroup
-            .size()]);
+    SequenceI[] seqs2 = invertGroup
+            .toArray(new SequenceI[invertGroup.size()]);
     for (int i = 0; i < invertGroup.size(); i++)
     {
       seqs2[i] = invertGroup.elementAt(i);
@@ -1825,13 +1845,13 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     SlideSequencesCommand ssc;
     if (right)
     {
-      ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1,
-              size, viewport.getGapCharacter());
+      ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1, size,
+              viewport.getGapCharacter());
     }
     else
     {
-      ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2,
-              size, viewport.getGapCharacter());
+      ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2, size,
+              viewport.getGapCharacter());
     }
 
     int groupAdjustment = 0;
@@ -1871,9 +1891,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     if (historyList != null && historyList.size() > 0
             && historyList.peek() instanceof SlideSequencesCommand)
     {
-      appendHistoryItem = ssc
-              .appendSlideCommand((SlideSequencesCommand) historyList
-                      .peek());
+      appendHistoryItem = ssc.appendSlideCommand(
+              (SlideSequencesCommand) historyList.peek());
     }
 
     if (!appendHistoryItem)
@@ -1964,14 +1983,10 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
         endRes += seq.getStart() - 1;
       }
 
-      copiedSequences.append(seq.getName()
-              + "\t"
-              + startRes
-              + "\t"
-              + endRes
-              + "\t"
-              + seq.getSequenceAsString(sg.getStartRes(),
-                      sg.getEndRes() + 1) + "\n");
+      copiedSequences.append(seq.getName() + "\t" + startRes + "\t" + endRes
+              + "\t" + seq.getSequenceAsString(sg.getStartRes(),
+                      sg.getEndRes() + 1)
+              + "\n");
     }
 
   }
@@ -2022,8 +2037,9 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
         }
         else
         {
-          newtitle = newtitle.concat(MessageManager.formatMessage(
-                  "label.from_msname", new String[] { getTitle() }));
+          newtitle = newtitle.concat(MessageManager
+                  .formatMessage("label.from_msname", new String[]
+                  { getTitle() }));
         }
         AlignFrame af = new AlignFrame(new Alignment(newSeqs),
                 viewport.applet, newtitle, false);
@@ -2065,8 +2081,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
 
     viewport.getRanges().setEndSeq(viewport.getAlignment().getHeight());
     viewport.getAlignment().getWidth();
-    viewport.firePropertyChange("alignment", null, viewport.getAlignment()
-            .getSequences());
+    viewport.firePropertyChange("alignment", null,
+            viewport.getAlignment().getSequences());
 
   }
 
@@ -2098,15 +2114,15 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
      */
     if (sg.getSize() == viewport.getAlignment().getHeight())
     {
-      boolean isEntireAlignWidth = (((sg.getEndRes() - sg.getStartRes()) + 1) == viewport
-              .getAlignment().getWidth()) ? true : false;
+      boolean isEntireAlignWidth = (((sg.getEndRes() - sg.getStartRes())
+              + 1) == viewport.getAlignment().getWidth()) ? true : false;
       if (isEntireAlignWidth)
       {
         String title = MessageManager.getString("label.delete_all");
         Panel infoPanel = new Panel();
         infoPanel.setLayout(new FlowLayout());
-        infoPanel
-                .add(new Label(MessageManager.getString("warn.delete_all")));
+        infoPanel.add(
+                new Label(MessageManager.getString("warn.delete_all")));
 
         final JVDialog dialog = new JVDialog(this, title, true, 400, 200);
         dialog.setMainPanel(infoPanel);
@@ -2140,8 +2156,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     viewport.setSelectionGroup(null);
     viewport.getAlignment().deleteGroup(sg);
 
-    viewport.firePropertyChange("alignment", null, viewport.getAlignment()
-            .getSequences());
+    viewport.firePropertyChange("alignment", null,
+            viewport.getAlignment().getSequences());
 
     if (viewport.getAlignment().getHeight() < 1)
     {
@@ -2215,7 +2231,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     {
       PaintRefresher.Refresh(this, viewport.getSequenceSetId());
       alignPanel.updateAnnotation();
-      alignPanel.paintAlignment(true);
+      alignPanel.paintAlignment(true, true);
     }
   }
 
@@ -2252,7 +2268,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     // JAL-2034 - should delegate to
     // alignPanel to decide if overview needs
     // updating.
-    alignPanel.paintAlignment(false);
+    alignPanel.paintAlignment(false, false);
     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
     viewport.sendSelection();
   }
@@ -2272,7 +2288,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     // JAL-2034 - should delegate to
     // alignPanel to decide if overview needs
     // updating.
-    alignPanel.paintAlignment(false);
+    alignPanel.paintAlignment(false, false);
     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
     viewport.sendSelection();
   }
@@ -2292,7 +2308,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
   public void invertColSel_actionPerformed()
   {
     viewport.invertColumnSelection();
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, false);
     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
     viewport.sendSelection();
   }
@@ -2318,8 +2334,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
       SequenceI[] seqs;
       if (viewport.getSelectionGroup() != null)
       {
-        seqs = viewport.getSelectionGroup().getSequencesAsArray(
-                viewport.getHiddenRepSequences());
+        seqs = viewport.getSelectionGroup()
+                .getSequencesAsArray(viewport.getHiddenRepSequences());
       }
       else
       {
@@ -2339,10 +2355,9 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
                 column, al);
       }
 
-      statusBar.setText(MessageManager.formatMessage(
-              "label.removed_columns",
-              new String[] { Integer.valueOf(trimRegion.getSize())
-                      .toString() }));
+      statusBar.setText(MessageManager
+              .formatMessage("label.removed_columns", new String[]
+              { Integer.valueOf(trimRegion.getSize()).toString() }));
       addHistoryItem(trimRegion);
 
       for (SequenceGroup sg : al.getGroups())
@@ -2368,8 +2383,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     SequenceI[] seqs;
     if (viewport.getSelectionGroup() != null)
     {
-      seqs = viewport.getSelectionGroup().getSequencesAsArray(
-              viewport.getHiddenRepSequences());
+      seqs = viewport.getSelectionGroup()
+              .getSequencesAsArray(viewport.getHiddenRepSequences());
       start = viewport.getSelectionGroup().getStartRes();
       end = viewport.getSelectionGroup().getEndRes();
     }
@@ -2384,10 +2399,9 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
 
     addHistoryItem(removeGapCols);
 
-    statusBar.setText(MessageManager.formatMessage(
-            "label.removed_empty_columns",
-            new String[] { Integer.valueOf(removeGapCols.getSize())
-                    .toString() }));
+    statusBar.setText(MessageManager
+            .formatMessage("label.removed_empty_columns", new String[]
+            { Integer.valueOf(removeGapCols.getSize()).toString() }));
 
     // This is to maintain viewport position on first residue
     // of first sequence
@@ -2413,8 +2427,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     SequenceI[] seqs;
     if (viewport.getSelectionGroup() != null)
     {
-      seqs = viewport.getSelectionGroup().getSequencesAsArray(
-              viewport.getHiddenRepSequences());
+      seqs = viewport.getSelectionGroup()
+              .getSequencesAsArray(viewport.getHiddenRepSequences());
       start = viewport.getSelectionGroup().getStartRes();
       end = viewport.getSelectionGroup().getEndRes();
     }
@@ -2428,8 +2442,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     SequenceI seq = al.getSequenceAt(0);
     int startRes = seq.findPosition(ranges.getStartRes());
 
-    addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,
-            al));
+    addHistoryItem(
+            new RemoveGapsCommand("Remove Gaps", seqs, start, end, al));
 
     ranges.setStartRes(seq.findIndex(startRes) - 1);
 
@@ -2463,12 +2477,14 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
 
     if (viewport.getAlignment().getAlignmentAnnotation() != null)
     {
-      for (int i = 0; i < viewport.getAlignment().getAlignmentAnnotation().length; i++)
+      for (int i = 0; i < viewport.getAlignment()
+              .getAlignmentAnnotation().length; i++)
       {
-        if (!viewport.getAlignment().getAlignmentAnnotation()[i].autoCalculated)
+        if (!viewport.getAlignment()
+                .getAlignmentAnnotation()[i].autoCalculated)
         {
-          newal.addAnnotation(viewport.getAlignment()
-                  .getAlignmentAnnotation()[i]);
+          newal.addAnnotation(
+                  viewport.getAlignment().getAlignmentAnnotation()[i]);
         }
       }
     }
@@ -2485,8 +2501,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     PaintRefresher.Register(newaf.alignPanel.seqPanel.seqCanvas,
             newaf.alignPanel.av.getSequenceSetId());
 
-    Vector comps = (Vector) PaintRefresher.components.get(viewport
-            .getSequenceSetId());
+    Vector comps = PaintRefresher.components
+            .get(viewport.getSequenceSetId());
     int viewSize = -1;
     for (int i = 0; i < comps.size(); i++)
     {
@@ -2584,19 +2600,19 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
   {
     viewport.setShowJVSuffix(seqLimits.getState());
     alignPanel.fontChanged();
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, false);
   }
 
   protected void colourTextMenuItem_actionPerformed()
   {
     viewport.setColourText(colourTextMenuItem.getState());
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(false, false);
   }
 
   protected void displayNonconservedMenuItem_actionPerformed()
   {
     viewport.setShowUnconserved(displayNonconservedMenuItem.getState());
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(false, false);
   }
 
   protected void wrapMenuItem_actionPerformed()
@@ -2606,7 +2622,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     scaleAbove.setEnabled(wrapMenuItem.getState());
     scaleLeft.setEnabled(wrapMenuItem.getState());
     scaleRight.setEnabled(wrapMenuItem.getState());
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, false);
   }
 
   public void overviewMenuItem_actionPerformed()
@@ -2620,9 +2636,9 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     final OverviewPanel overview = new OverviewPanel(alignPanel);
     frame.add(overview);
     // +50 must allow for applet frame window
-    jalview.bin.JalviewLite.addFrame(frame, MessageManager.formatMessage(
-            "label.overview_params", new String[] { this.getTitle() }),
-            overview.getPreferredSize().width,
+    jalview.bin.JalviewLite.addFrame(frame, MessageManager
+            .formatMessage("label.overview_params", new String[]
+            { this.getTitle() }), overview.getPreferredSize().width,
             overview.getPreferredSize().height + 50);
 
     frame.pack();
@@ -2649,7 +2665,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
   {
     viewport.setGlobalColourScheme(cs);
 
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, true);
   }
 
   protected void modifyPID_actionPerformed()
@@ -2719,21 +2735,21 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
   public void sortPairwiseMenuItem_actionPerformed()
   {
     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
-    AlignmentSorter.sortByPID(viewport.getAlignment(), viewport
-            .getAlignment().getSequenceAt(0));
+    AlignmentSorter.sortByPID(viewport.getAlignment(),
+            viewport.getAlignment().getSequenceAt(0));
 
     addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
             viewport.getAlignment()));
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, false);
   }
 
   public void sortIDMenuItem_actionPerformed()
   {
     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
     AlignmentSorter.sortByID(viewport.getAlignment());
-    addHistoryItem(new OrderCommand("ID Sort", oldOrder,
-            viewport.getAlignment()));
-    alignPanel.paintAlignment(true);
+    addHistoryItem(
+            new OrderCommand("ID Sort", oldOrder, viewport.getAlignment()));
+    alignPanel.paintAlignment(true, false);
   }
 
   public void sortLengthMenuItem_actionPerformed()
@@ -2742,7 +2758,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     AlignmentSorter.sortByLength(viewport.getAlignment());
     addHistoryItem(new OrderCommand("Length Sort", oldOrder,
             viewport.getAlignment()));
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, false);
   }
 
   public void sortGroupMenuItem_actionPerformed()
@@ -2751,7 +2767,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     AlignmentSorter.sortByGroup(viewport.getAlignment());
     addHistoryItem(new OrderCommand("Group Sort", oldOrder,
             viewport.getAlignment()));
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, false);
 
   }
 
@@ -2781,7 +2797,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
       SequenceI current;
       int Width = viewport.getAlignment().getWidth();
 
-      for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
+      for (int i = 0; i < viewport.getAlignment().getSequences()
+              .size(); i++)
       {
         current = viewport.getAlignment().getSequenceAt(i);
 
@@ -2790,12 +2807,12 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
           current.insertCharAt(Width - 1, viewport.getGapCharacter());
         }
       }
-      alignPanel.paintAlignment(true);
+      alignPanel.paintAlignment(false, false);
     }
 
     if ((viewport.getSelectionGroup() != null
-            && viewport.getSelectionGroup().getSize() < 4 && viewport
-            .getSelectionGroup().getSize() > 0)
+            && viewport.getSelectionGroup().getSize() < 4
+            && viewport.getSelectionGroup().getSize() > 0)
             || viewport.getAlignment().getHeight() < 4)
     {
       return;
@@ -2824,15 +2841,15 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
 
   protected void njTreeBlosumMenuItem_actionPerformed()
   {
-    newTreePanel(TreeBuilder.NEIGHBOUR_JOINING, ScoreModels.getInstance()
-            .getBlosum62().getName(),
+    newTreePanel(TreeBuilder.NEIGHBOUR_JOINING,
+            ScoreModels.getInstance().getBlosum62().getName(),
             "Neighbour joining tree using BLOSUM62");
   }
 
   protected void avTreeBlosumMenuItem_actionPerformed()
   {
-    newTreePanel(TreeBuilder.AVERAGE_DISTANCE, ScoreModels.getInstance()
-            .getBlosum62().getName(),
+    newTreePanel(TreeBuilder.AVERAGE_DISTANCE,
+            ScoreModels.getInstance().getBlosum62().getName(),
             "Average distance tree using BLOSUM62");
   }
 
@@ -2844,7 +2861,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
       SequenceI current;
       int Width = viewport.getAlignment().getWidth();
 
-      for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
+      for (int i = 0; i < viewport.getAlignment().getSequences()
+              .size(); i++)
       {
         current = viewport.getAlignment().getSequenceAt(i);
 
@@ -2853,12 +2871,12 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
           current.insertCharAt(Width - 1, viewport.getGapCharacter());
         }
       }
-      alignPanel.paintAlignment(true);
+      alignPanel.paintAlignment(false, false);
 
     }
 
-    if ((viewport.getSelectionGroup() != null && viewport
-            .getSelectionGroup().getSize() > 1)
+    if ((viewport.getSelectionGroup() != null
+            && viewport.getSelectionGroup().getSize() > 1)
             || (viewport.getAlignment().getHeight() > 1))
     {
       final TreePanel tp = new TreePanel(alignPanel, type, pwType);
@@ -2899,14 +2917,14 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
   public void sortByTree(TreePanel treePanel, String title)
   {
     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
-    AlignmentSorter
-            .sortByTree(viewport.getAlignment(), treePanel.getTree());
+    AlignmentSorter.sortByTree(viewport.getAlignment(),
+            treePanel.getTree());
     // addHistoryItem(new HistoryItem("Sort", viewport.alignment,
     // HistoryItem.SORT));
-    addHistoryItem(new OrderCommand(MessageManager.formatMessage(
-            "label.order_by_params", new String[] { title }), oldOrder,
-            viewport.getAlignment()));
-    alignPanel.paintAlignment(true);
+    addHistoryItem(new OrderCommand(MessageManager
+            .formatMessage("label.order_by_params", new String[]
+            { title }), oldOrder, viewport.getAlignment()));
+    alignPanel.paintAlignment(true, false);
   }
 
   /**
@@ -2964,7 +2982,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
       addHistoryItem(new OrderCommand(undoname, oldOrder,
               viewport.getAlignment()));
     }
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, false);
     return true;
   }
 
@@ -3001,39 +3019,37 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
         // TODO: update this text for each release or centrally store it for
         // lite and application
         g.setFont(new Font("Helvetica", Font.BOLD, 14));
-        g.drawString(MessageManager.formatMessage(
-                "label.jalviewLite_release", new String[] { version }), x,
-                y += fh);
+        g.drawString(MessageManager
+                .formatMessage("label.jalviewLite_release", new String[]
+                { version }), x, y += fh);
         g.setFont(new Font("Helvetica", Font.BOLD, 12));
-        g.drawString(MessageManager.formatMessage(
-                "label.jaview_build_date", new String[] { builddate }), x,
-                y += fh);
+        g.drawString(MessageManager.formatMessage("label.jaview_build_date",
+                new String[]
+                { builddate }), x, y += fh);
         g.setFont(new Font("Helvetica", Font.PLAIN, 12));
-        g.drawString(MessageManager.getString("label.jalview_authors_1"),
-                x, y += fh * 1.5);
+        g.drawString(MessageManager.getString("label.jalview_authors_1"), x,
+                y += fh * 1.5);
         g.drawString(MessageManager.getString("label.jalview_authors_2"),
                 x + 50, y += fh + 8);
-        g.drawString(
-                MessageManager.getString("label.jalview_dev_managers"), x,
-                y += fh);
+        g.drawString(MessageManager.getString("label.jalview_dev_managers"),
+                x, y += fh);
         g.drawString(MessageManager
                 .getString("label.jalview_distribution_lists"), x, y += fh);
         g.drawString(MessageManager.getString("label.jalview_please_cite"),
                 x, y += fh + 8);
         g.drawString(
-                MessageManager.getString("label.jalview_cite_1_authors"),
-                x, y += fh);
-        g.drawString(
-                MessageManager.getString("label.jalview_cite_1_title"), x,
+                MessageManager.getString("label.jalview_cite_1_authors"), x,
                 y += fh);
+        g.drawString(MessageManager.getString("label.jalview_cite_1_title"),
+                x, y += fh);
         g.drawString(MessageManager.getString("label.jalview_cite_1_ref"),
                 x, y += fh);
       }
     }
 
     Frame frame = new Frame();
-    frame.add(new AboutPanel(JalviewLite.getVersion(), JalviewLite
-            .getBuildDate()));
+    frame.add(new AboutPanel(JalviewLite.getVersion(),
+            JalviewLite.getBuildDate()));
     jalview.bin.JalviewLite.addFrame(frame,
             MessageManager.getString("label.jalview"), 580, 220);
 
@@ -3306,20 +3322,20 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     pasteNew.addActionListener(this);
     pasteThis.setLabel(MessageManager.getString("label.to_this_alignment"));
     pasteThis.addActionListener(this);
-    remove2LeftMenuItem.setLabel(MessageManager
-            .getString("action.remove_left"));
+    remove2LeftMenuItem
+            .setLabel(MessageManager.getString("action.remove_left"));
     remove2LeftMenuItem.addActionListener(this);
-    remove2RightMenuItem.setLabel(MessageManager
-            .getString("action.remove_right"));
+    remove2RightMenuItem
+            .setLabel(MessageManager.getString("action.remove_right"));
     remove2RightMenuItem.addActionListener(this);
-    removeGappedColumnMenuItem.setLabel(MessageManager
-            .getString("action.remove_empty_columns"));
+    removeGappedColumnMenuItem.setLabel(
+            MessageManager.getString("action.remove_empty_columns"));
     removeGappedColumnMenuItem.addActionListener(this);
-    removeAllGapsMenuItem.setLabel(MessageManager
-            .getString("action.remove_all_gaps"));
+    removeAllGapsMenuItem
+            .setLabel(MessageManager.getString("action.remove_all_gaps"));
     removeAllGapsMenuItem.addActionListener(this);
-    removeRedundancyMenuItem.setLabel(MessageManager
-            .getString("action.remove_redundancy"));
+    removeRedundancyMenuItem
+            .setLabel(MessageManager.getString("action.remove_redundancy"));
     removeRedundancyMenuItem.addActionListener(this);
 
     /*
@@ -3329,25 +3345,25 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     findMenuItem.addActionListener(this);
     selectAllSequenceMenuItem.addActionListener(this);
     deselectAllSequenceMenuItem.addActionListener(this);
-    invertSequenceMenuItem.setLabel(MessageManager
-            .getString("action.invert_sequence_selection"));
+    invertSequenceMenuItem.setLabel(
+            MessageManager.getString("action.invert_sequence_selection"));
     invertSequenceMenuItem.addActionListener(this);
-    invertColSel.setLabel(MessageManager
-            .getString("action.invert_column_selection"));
+    invertColSel.setLabel(
+            MessageManager.getString("action.invert_column_selection"));
     invertColSel.addActionListener(this);
-    deleteGroups.setLabel(MessageManager
-            .getString("action.undefine_groups"));
+    deleteGroups
+            .setLabel(MessageManager.getString("action.undefine_groups"));
     deleteGroups.addActionListener(this);
-    grpsFromSelection.setLabel(MessageManager
-            .getString("action.make_groups_selection"));
+    grpsFromSelection.setLabel(
+            MessageManager.getString("action.make_groups_selection"));
     grpsFromSelection.addActionListener(this);
     createGroup.setLabel(MessageManager.getString("action.create_group"));
     createGroup.addActionListener(this);
     unGroup.setLabel(MessageManager.getString("action.remove_group"));
     unGroup.addActionListener(this);
 
-    annotationColumnSelection.setLabel(MessageManager
-            .getString("action.select_by_annotation"));
+    annotationColumnSelection.setLabel(
+            MessageManager.getString("action.select_by_annotation"));
     annotationColumnSelection.addActionListener(this);
 
     /*
@@ -3361,14 +3377,14 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     Menu hideMenu = new Menu(MessageManager.getString("action.hide"));
     hideColumns
             .setLabel(MessageManager.getString("label.selected_columns"));
-    hideSequences.setLabel(MessageManager
-            .getString("label.selected_sequences"));
-    hideAllButSelection.setLabel(MessageManager
-            .getString("label.all_but_selected_region"));
-    hideAllSelection.setLabel(MessageManager
-            .getString("label.selected_region"));
-    showAllHidden.setLabel(MessageManager
-            .getString("label.all_sequences_columns"));
+    hideSequences
+            .setLabel(MessageManager.getString("label.selected_sequences"));
+    hideAllButSelection.setLabel(
+            MessageManager.getString("label.all_but_selected_region"));
+    hideAllSelection
+            .setLabel(MessageManager.getString("label.selected_region"));
+    showAllHidden.setLabel(
+            MessageManager.getString("label.all_sequences_columns"));
     showColumns.addActionListener(this);
     showSeqs.addActionListener(this);
     hideColumns.addActionListener(this);
@@ -3376,39 +3392,39 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     hideAllButSelection.addActionListener(this);
     hideAllSelection.addActionListener(this);
     showAllHidden.addActionListener(this);
-    featureSettings.setLabel(MessageManager
-            .getString("action.feature_settings"));
+    featureSettings
+            .setLabel(MessageManager.getString("action.feature_settings"));
     featureSettings.addActionListener(this);
-    sequenceFeatures.setLabel(MessageManager
-            .getString("label.show_sequence_features"));
+    sequenceFeatures.setLabel(
+            MessageManager.getString("label.show_sequence_features"));
     sequenceFeatures.addItemListener(this);
     sequenceFeatures.setState(false);
-    followMouseOverFlag.setLabel(MessageManager
-            .getString("label.automatic_scrolling"));
+    followMouseOverFlag.setLabel(
+            MessageManager.getString("label.automatic_scrolling"));
     followMouseOverFlag.addItemListener(this);
     alProperties.addActionListener(this);
-    overviewMenuItem.setLabel(MessageManager
-            .getString("label.overview_window"));
+    overviewMenuItem
+            .setLabel(MessageManager.getString("label.overview_window"));
     overviewMenuItem.addActionListener(this);
 
     /*
      * Configure Annotations menu items and actions
      */
-    annotationPanelMenuItem.setLabel(MessageManager
-            .getString("label.show_annotations"));
+    annotationPanelMenuItem
+            .setLabel(MessageManager.getString("label.show_annotations"));
     annotationPanelMenuItem.addItemListener(this);
-    showGroupConsensus.setLabel(MessageManager
-            .getString("label.group_consensus"));
-    showGroupConservation.setLabel(MessageManager
-            .getString("label.group_conservation"));
-    showConsensusHistogram.setLabel(MessageManager
-            .getString("label.show_consensus_histogram"));
-    showSequenceLogo.setLabel(MessageManager
-            .getString("label.show_consensus_logo"));
-    normSequenceLogo.setLabel(MessageManager
-            .getString("label.norm_consensus_logo"));
-    applyAutoAnnotationSettings.setLabel(MessageManager
-            .getString("label.apply_all_groups"));
+    showGroupConsensus
+            .setLabel(MessageManager.getString("label.group_consensus"));
+    showGroupConservation
+            .setLabel(MessageManager.getString("label.group_conservation"));
+    showConsensusHistogram.setLabel(
+            MessageManager.getString("label.show_consensus_histogram"));
+    showSequenceLogo.setLabel(
+            MessageManager.getString("label.show_consensus_logo"));
+    normSequenceLogo.setLabel(
+            MessageManager.getString("label.norm_consensus_logo"));
+    applyAutoAnnotationSettings
+            .setLabel(MessageManager.getString("label.apply_all_groups"));
     applyAutoAnnotationSettings.setState(true);
     Menu autoAnnMenu = new Menu(
             MessageManager.getString("label.autocalculated_annotation"));
@@ -3463,44 +3479,44 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     viewTextMenuItem.setLabel(MessageManager.getString("action.text"));
     viewTextMenuItem.setState(true);
     viewTextMenuItem.addItemListener(this);
-    colourTextMenuItem.setLabel(MessageManager
-            .getString("label.colour_text"));
+    colourTextMenuItem
+            .setLabel(MessageManager.getString("label.colour_text"));
     colourTextMenuItem.addItemListener(this);
-    displayNonconservedMenuItem.setLabel(MessageManager
-            .getString("label.show_non_conserved"));
+    displayNonconservedMenuItem
+            .setLabel(MessageManager.getString("label.show_non_conserved"));
     displayNonconservedMenuItem.addItemListener(this);
     wrapMenuItem.setLabel(MessageManager.getString("action.wrap"));
     wrapMenuItem.addItemListener(this);
-    renderGapsMenuItem.setLabel(MessageManager
-            .getString("action.show_gaps"));
+    renderGapsMenuItem
+            .setLabel(MessageManager.getString("action.show_gaps"));
     renderGapsMenuItem.setState(true);
     renderGapsMenuItem.addItemListener(this);
-    centreColumnLabelFlag.setLabel(MessageManager
-            .getString("label.centre_column_labels"));
+    centreColumnLabelFlag.setLabel(
+            MessageManager.getString("label.centre_column_labels"));
     centreColumnLabelFlag.addItemListener(this);
     seqLimits.setState(true);
-    seqLimits.setLabel(MessageManager
-            .getString("label.show_sequence_limits"));
+    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.setLabel(
+            MessageManager.getString("label.apply_colour_to_all_groups"));
     applyToAllGroups.setState(true);
     applyToAllGroups.addItemListener(this);
-    clustalColour.setLabel(MessageManager
-            .getString("label.colourScheme_clustal"));
+    clustalColour.setLabel(
+            MessageManager.getString("label.colourScheme_clustal"));
     clustalColour.addActionListener(this);
-    zappoColour.setLabel(MessageManager
-            .getString("label.colourScheme_zappo"));
+    zappoColour
+            .setLabel(MessageManager.getString("label.colourScheme_zappo"));
     zappoColour.addActionListener(this);
-    taylorColour.setLabel(MessageManager
-            .getString("label.colourScheme_taylor"));
+    taylorColour.setLabel(
+            MessageManager.getString("label.colourScheme_taylor"));
     taylorColour.addActionListener(this);
-    hydrophobicityColour.setLabel(MessageManager
-            .getString("label.colourScheme_hydrophobic"));
+    hydrophobicityColour.setLabel(
+            MessageManager.getString("label.colourScheme_hydrophobic"));
     hydrophobicityColour.addActionListener(this);
     helixColour.setLabel(MessageManager
             .getString("label.colourScheme_helix_propensity"));
@@ -3508,11 +3524,11 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     strandColour.setLabel(MessageManager
             .getString("label.colourScheme_strand_propensity"));
     strandColour.addActionListener(this);
-    turnColour.setLabel(MessageManager
-            .getString("label.colourScheme_turn_propensity"));
+    turnColour.setLabel(
+            MessageManager.getString("label.colourScheme_turn_propensity"));
     turnColour.addActionListener(this);
-    buriedColour.setLabel(MessageManager
-            .getString("label.colourScheme_buried_index"));
+    buriedColour.setLabel(
+            MessageManager.getString("label.colourScheme_buried_index"));
     buriedColour.addActionListener(this);
     purinePyrimidineColour.setLabel(MessageManager
             .getString("label.colourScheme_purine/pyrimidine"));
@@ -3520,81 +3536,82 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     // RNAInteractionColour.setLabel(MessageManager
     // .getString("label.rna_interaction"));
     // RNAInteractionColour.addActionListener(this);
-    RNAHelixColour.setLabel(MessageManager
-            .getString("label.colourScheme_rna_helices"));
+    RNAHelixColour.setLabel(
+            MessageManager.getString("label.colourScheme_rna_helices"));
     RNAHelixColour.addActionListener(this);
-    userDefinedColour.setLabel(MessageManager
-            .getString("action.user_defined"));
+    userDefinedColour
+            .setLabel(MessageManager.getString("action.user_defined"));
     userDefinedColour.addActionListener(this);
-    PIDColour.setLabel(MessageManager
-            .getString("label.colourScheme_%_identity"));
+    PIDColour.setLabel(
+            MessageManager.getString("label.colourScheme_%_identity"));
     PIDColour.addActionListener(this);
-    BLOSUM62Colour.setLabel(MessageManager
-            .getString("label.colourScheme_blosum62"));
+    BLOSUM62Colour.setLabel(
+            MessageManager.getString("label.colourScheme_blosum62"));
     BLOSUM62Colour.addActionListener(this);
-    tcoffeeColour.setLabel(MessageManager
-            .getString("label.colourScheme_t-coffee_scores"));
+    tcoffeeColour.setLabel(
+            MessageManager.getString("label.colourScheme_t-coffee_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
+            .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.setLabel(
+            MessageManager.getString("label.above_identity_threshold"));
     abovePIDThreshold.addItemListener(this);
-    nucleotideColour.setLabel(MessageManager
-            .getString("label.colourScheme_nucleotide"));
+    nucleotideColour.setLabel(
+            MessageManager.getString("label.colourScheme_nucleotide"));
     nucleotideColour.addActionListener(this);
-    modifyPID.setLabel(MessageManager
-            .getString("label.modify_identity_threshold"));
+    modifyPID.setLabel(
+            MessageManager.getString("label.modify_identity_threshold"));
     modifyPID.setEnabled(abovePIDThreshold.getState());
     modifyPID.addActionListener(this);
     modifyConservation.setLabel(MessageManager
             .getString("label.modify_conservation_threshold"));
     modifyConservation.setEnabled(conservationMenuItem.getState());
     modifyConservation.addActionListener(this);
-    annotationColour.setLabel(MessageManager
-            .getString("action.by_annotation"));
+    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
+            .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
+            .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.setLabel(
+            MessageManager.getString("action.pairwise_alignment"));
     pairwiseAlignmentMenuItem.addActionListener(this);
-    PCAMenuItem.setLabel(MessageManager
-            .getString("label.principal_component_analysis"));
+    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"));
+            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.setLabel(
+            MessageManager.getString("label.neighbour_joining_identity"));
     neighbourTreeMenuItem.addActionListener(this);
-    avDistanceTreeBlosumMenuItem.setLabel(MessageManager
-            .getString("label.average_distance_blosum62"));
+    avDistanceTreeBlosumMenuItem.setLabel(
+            MessageManager.getString("label.average_distance_blosum62"));
     avDistanceTreeBlosumMenuItem.addActionListener(this);
-    njTreeBlosumMenuItem.setLabel(MessageManager
-            .getString("label.neighbour_blosum62"));
+    njTreeBlosumMenuItem
+            .setLabel(MessageManager.getString("label.neighbour_blosum62"));
     njTreeBlosumMenuItem.addActionListener(this);
-    sortByTreeMenu.setLabel(MessageManager
-            .getString("action.by_tree_order"));
+    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"));
@@ -3911,9 +3928,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     theApplet.add(embeddedMenu, BorderLayout.NORTH);
     theApplet.add(statusBar, BorderLayout.SOUTH);
     // TODO should size be left to the layout manager?
-    alignPanel.setSize(theApplet.getSize().width,
-            theApplet.getSize().height - embeddedMenu.getHeight()
-                    - statusBar.getHeight());
+    alignPanel.setSize(theApplet.getSize().width, theApplet.getSize().height
+            - embeddedMenu.getHeight() - statusBar.getHeight());
     theApplet.add(alignPanel, BorderLayout.CENTER);
     final AlignFrame me = this;
     theApplet.addFocusListener(new FocusListener()
@@ -3959,8 +3975,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
       viewer = (Viewer) jmolviewer;
     } catch (ClassCastException ex)
     {
-      System.err.println("Unsupported viewer object :"
-              + jmolviewer.getClass());
+      System.err.println(
+              "Unsupported viewer object :" + jmolviewer.getClass());
     }
     if (viewer == null)
     {
@@ -4055,8 +4071,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
       }
       // resolve data source
       // TODO: this code should be a refactored to an io package
-      DataSourceType protocol = AppletFormatAdapter.resolveProtocol(
-              pdbFile, FileFormat.PDB);
+      DataSourceType protocol = AppletFormatAdapter.resolveProtocol(pdbFile,
+              FileFormat.PDB);
       if (protocol == null)
       {
         return false;
@@ -4081,8 +4097,9 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
       {
         if (seqs[i] != null)
         {
-          sequences.addElement(new Object[] { seqs[i],
-              (chains != null) ? chains[i] : null });
+          sequences
+                  .addElement(new Object[]
+                  { seqs[i], (chains != null) ? chains[i] : null });
         }
       }
       seqs = new SequenceI[sequences.size()];
@@ -4108,8 +4125,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     chains = (String[]) sqch[1];
     if (seqs == null || seqs.length == 0)
     {
-      System.err
-              .println("JalviewLite.AlignFrame:newStructureView: No sequence to bind structure to.");
+      System.err.println(
+              "JalviewLite.AlignFrame:newStructureView: No sequence to bind structure to.");
     }
     if (protocol == null)
     {
@@ -4132,7 +4149,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     {
       // register the association(s) and quit, don't create any windows.
       if (StructureSelectionManager.getStructureSelectionManager(applet)
-              .setMapping(seqs, chains, pdb.getFile(), protocol) == null)
+              .setMapping(seqs, chains, pdb.getFile(), protocol, null) == null)
       {
         System.err.println("Failed to map " + pdb.getFile() + " ("
                 + protocol + ") to any sequences");
@@ -4156,8 +4173,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
       }
       if (ajm != null)
       {
-        System.err
-                .println("Incremental adding and aligning structure to existing Jmol view not yet implemented.");
+        System.err.println(
+                "Incremental adding and aligning structure to existing Jmol view not yet implemented.");
         // try and add the pdb structure
         // ajm.addS
         ajm = null;
@@ -4166,8 +4183,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     // otherwise, create a new window
     if (applet.jmolAvailable)
     {
-      new AppletJmol(pdb, seqs, chains, alignPanel,
-              protocol);
+      new AppletJmol(pdb, seqs, chains, alignPanel, protocol);
       applet.lastFrameX += 40;
       applet.lastFrameY += 40;
     }
@@ -4250,12 +4266,12 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
      */
     AlignmentI aln;
     if ((aln = viewport.getAlignment()) != null
-            && (aln.getHeight() != file.getHeight() || aln.getWidth() != file
-                    .getWidth()))
+            && (aln.getHeight() != file.getHeight()
+                    || aln.getWidth() != file.getWidth()))
     {
       // TODO: raise a dialog box here rather than bomb out.
-      System.err
-              .println("The scores matrix does not match the alignment dimensions");
+      System.err.println(
+              "The scores matrix does not match the alignment dimensions");
 
     }
 
index 1d2c4bc..262948d 100644 (file)
@@ -20,7 +20,6 @@
  */
 package jalview.appletgui;
 
-import jalview.analysis.TreeModel;
 import jalview.api.AlignViewportI;
 import jalview.api.FeatureSettingsModelI;
 import jalview.bin.JalviewLite;
@@ -45,8 +44,8 @@ import jalview.viewmodel.AlignmentViewport;
 import java.awt.Font;
 import java.awt.FontMetrics;
 
-public class AlignViewport extends AlignmentViewport implements
-        SelectionSource
+public class AlignViewport extends AlignmentViewport
+        implements SelectionSource
 {
   boolean cursorMode = false;
 
@@ -54,23 +53,12 @@ public class AlignViewport extends AlignmentViewport implements
 
   boolean validCharWidth = true;
 
-  TreeModel currentTree = null;
-
   public jalview.bin.JalviewLite applet;
 
   boolean MAC = false;
 
   private AnnotationColumnChooser annotationColumnSelectionState;
 
-  @Override
-  public void finalize()
-  {
-    applet = null;
-    quality = null;
-    alignment = null;
-    colSel = null;
-  }
-
   public AlignViewport(AlignmentI al, JalviewLite applet)
   {
     super(al);
@@ -94,15 +82,15 @@ public class AlignViewport extends AlignmentViewport implements
         }
         if (widthScale <= 1.0)
         {
-          System.err
-                  .println("Invalid alignment character width scaling factor ("
+          System.err.println(
+                  "Invalid alignment character width scaling factor ("
                           + widthScale + "). Ignoring.");
           widthScale = 1;
         }
         if (JalviewLite.debug)
         {
-          System.err
-                  .println("Alignment character width scaling factor is now "
+          System.err.println(
+                  "Alignment character width scaling factor is now "
                           + widthScale);
         }
       }
@@ -117,15 +105,15 @@ public class AlignViewport extends AlignmentViewport implements
         }
         if (heightScale <= 1.0)
         {
-          System.err
-                  .println("Invalid alignment character height scaling factor ("
+          System.err.println(
+                  "Invalid alignment character height scaling factor ("
                           + heightScale + "). Ignoring.");
           heightScale = 1;
         }
         if (JalviewLite.debug)
         {
-          System.err
-                  .println("Alignment character height scaling factor is now "
+          System.err.println(
+                  "Alignment character height scaling factor is now "
                           + heightScale);
         }
       }
@@ -136,8 +124,8 @@ public class AlignViewport extends AlignmentViewport implements
 
     if (applet != null)
     {
-      setShowJVSuffix(applet.getDefaultParameter("showFullId",
-              getShowJVSuffix()));
+      setShowJVSuffix(
+              applet.getDefaultParameter("showFullId", getShowJVSuffix()));
 
       setShowAnnotation(applet.getDefaultParameter("showAnnotation",
               isShowAnnotation()));
@@ -156,8 +144,8 @@ public class AlignViewport extends AlignmentViewport implements
       setShowUnconserved(applet.getDefaultParameter("showUnconserved",
               getShowUnconserved()));
 
-      setScaleProteinAsCdna(applet.getDefaultParameter(
-              "scaleProteinAsCdna", isScaleProteinAsCdna()));
+      setScaleProteinAsCdna(applet.getDefaultParameter("scaleProteinAsCdna",
+              isScaleProteinAsCdna()));
 
       String param = applet.getParameter("upperCase");
       if (param != null)
@@ -193,9 +181,9 @@ public class AlignViewport extends AlignmentViewport implements
 
     if (applet != null)
     {
-      String colour = al.isNucleotide() ? applet
-              .getParameter("defaultColourNuc") : applet
-              .getParameter("defaultColourProt");
+      String colour = al.isNucleotide()
+              ? applet.getParameter("defaultColourNuc")
+              : applet.getParameter("defaultColourProt");
       if (colour == null)
       {
         colour = applet.getParameter("defaultColour");
@@ -221,9 +209,8 @@ public class AlignViewport extends AlignmentViewport implements
 
       if (applet.getParameter("userDefinedColour") != null)
       {
-        residueShading = new ResidueShader(
-                new UserColourScheme(
-                        applet.getParameter("userDefinedColour")));
+        residueShading = new ResidueShader(new UserColourScheme(
+                applet.getParameter("userDefinedColour")));
       }
     }
     initAutoAnnotation();
@@ -260,7 +247,8 @@ public class AlignViewport extends AlignmentViewport implements
     {
       Font f2 = new Font(f.getName(), Font.BOLD, f.getSize());
       FontMetrics fm = nullFrame.getGraphics().getFontMetrics(f2);
-      setCharWidth((int) (widthScale * (fm.stringWidth("MMMMMMMMMMM") / 10)));
+      setCharWidth(
+              (int) (widthScale * (fm.stringWidth("MMMMMMMMMMM") / 10)));
     }
   }
 
@@ -274,16 +262,6 @@ public class AlignViewport extends AlignmentViewport implements
     ranges.setEndSeq(height / getCharHeight());
   }
 
-  public void setCurrentTree(TreeModel tree)
-  {
-    currentTree = tree;
-  }
-
-  public TreeModel getCurrentTree()
-  {
-    return currentTree;
-  }
-
   boolean centreColumnLabels;
 
   public boolean getCentreColumnLabels()
index d679217..270b2f7 100644 (file)
@@ -46,8 +46,8 @@ import java.awt.event.ComponentEvent;
 import java.beans.PropertyChangeEvent;
 import java.util.List;
 
-public class AlignmentPanel extends Panel implements AdjustmentListener,
-        AlignmentViewPanel, ViewportListenerI
+public class AlignmentPanel extends Panel
+        implements AdjustmentListener, AlignmentViewPanel, ViewportListenerI
 {
 
   public AlignViewport av;
@@ -73,23 +73,6 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
   // this value is set false when selection area being dragged
   boolean fastPaint = true;
 
-  @Override
-  public void finalize() throws Throwable
-  {
-    alignFrame = null;
-    av = null;
-    vpRanges = null;
-    seqPanel = null;
-    seqPanelHolder = null;
-    sequenceHolderPanel = null;
-    scalePanel = null;
-    scalePanelHolder = null;
-    annotationPanel = null;
-    annotationPanelHolder = null;
-    annotationSpaceFillerHolder = null;
-    super.finalize();
-  }
-
   public AlignmentPanel(AlignFrame af, final AlignViewport av)
   {
     try
@@ -234,10 +217,10 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
     idPanel.idCanvas.image = null;
     FontMetrics fm = getFontMetrics(av.getFont());
 
-    scalePanel.setSize(new Dimension(10, av.getCharHeight()
-            + fm.getDescent()));
-    idwidthAdjuster.setSize(new Dimension(10, av.getCharHeight()
-            + fm.getDescent()));
+    scalePanel.setSize(
+            new Dimension(10, av.getCharHeight() + fm.getDescent()));
+    idwidthAdjuster.setSize(
+            new Dimension(10, av.getCharHeight() + fm.getDescent()));
     av.updateSequenceIdColours();
     annotationPanel.image = null;
     int ap = annotationPanel.adjustPanelHeight(false);
@@ -358,8 +341,7 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
    * @return false if results were not found
    */
   public boolean scrollToPosition(SearchResultsI results,
-          int verticalOffset,
-          boolean redrawOverview, boolean centre)
+          int verticalOffset, boolean redrawOverview, boolean centre)
   {
     // do we need to scroll the panel?
     if (results != null && results.getSize() > 0)
@@ -380,8 +362,8 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
       {
         if (JalviewLite.debug)
         {// DEBUG
-          System.out
-                  .println("DEBUG: scroll didn't happen - results not within alignment : "
+          System.out.println(
+                  "DEBUG: scroll didn't happen - results not within alignment : "
                           + seq.getStart() + "," + seq.getEnd());
         }
         return false;
@@ -405,7 +387,8 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
        */
       if (centre)
       {
-        int offset = (vpRanges.getEndRes() - vpRanges.getStartRes() + 1) / 2 - 1;
+        int offset = (vpRanges.getEndRes() - vpRanges.getStartRes() + 1) / 2
+                - 1;
         start = Math.max(start - offset, 0);
         end = end + offset - 1;
         // end = Math.min(end + offset, seq.getEnd() - 1);
@@ -518,8 +501,8 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
         /*
          * Scroll down to make end of search results visible
          */
-        setScrollValues(vpRanges.getStartRes(), starts + seqIndex - ends
-                + 1);
+        setScrollValues(vpRanges.getStartRes(),
+                starts + seqIndex - ends + 1);
       }
       /*
        * Else results are already visible - no need to scroll
@@ -530,7 +513,7 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
       vpRanges.scrollToWrappedVisible(start);
     }
 
-    paintAlignment(redrawOverview);
+    paintAlignment(redrawOverview, false);
     return true;
   }
 
@@ -571,15 +554,15 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
     // this is called after loading new annotation onto alignment
     if (alignFrame.getSize().height == 0)
     {
-      System.out
-              .println("adjustAnnotationHeight frame size zero NEEDS FIXING");
+      System.out.println(
+              "adjustAnnotationHeight frame size zero NEEDS FIXING");
     }
     fontChanged();
     validateAnnotationDimensions(true);
     apvscroll.addNotify();
     hscroll.addNotify();
     validate();
-    paintAlignment(true);
+    paintAlignment(true, false);
   }
 
   /**
@@ -605,8 +588,8 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
        */
       if (annotationHeight + alignmentHeight > availableHeight)
       {
-        annotationHeight = Math.min(annotationHeight, availableHeight - 2
-                * rowHeight);
+        annotationHeight = Math.min(annotationHeight,
+                availableHeight - 2 * rowHeight);
       }
     }
     else
@@ -623,13 +606,13 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
     annotationPanel.setSize(new Dimension(d.width, annotationHeight));
     annotationPanelHolder.setSize(new Dimension(d.width, annotationHeight));
     // seqPanelHolder.setSize(d.width, seqandannot - height);
-    seqPanel.seqCanvas
-            .setSize(d.width, seqPanel.seqCanvas.getSize().height);
+    seqPanel.seqCanvas.setSize(d.width,
+            seqPanel.seqCanvas.getSize().height);
 
     Dimension e = idPanel.getSize();
     alabels.setSize(new Dimension(e.width, annotationHeight));
-    annotationSpaceFillerHolder.setSize(new Dimension(e.width,
-            annotationHeight));
+    annotationSpaceFillerHolder
+            .setSize(new Dimension(e.width, annotationHeight));
 
     int s = apvscroll.getValue();
     if (s > mheight - annotationHeight)
@@ -930,7 +913,8 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
    * Repaint the alignment and annotations, and, optionally, any overview window
    */
   @Override
-  public void paintAlignment(boolean updateOverview)
+  public void paintAlignment(boolean updateOverview,
+          boolean updateStructures)
   {
     final AnnotationSorter sorter = new AnnotationSorter(getAlignment(),
             av.isShowAutocalculatedAbove());
@@ -938,13 +922,14 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
             av.getSortAnnotationsBy());
     repaint();
 
-    if (updateOverview)
+    if (updateStructures)
     {
-      // TODO: determine if this paintAlignment changed structure colours
       jalview.structure.StructureSelectionManager
               .getStructureSelectionManager(av.applet)
               .sequenceColoursChanged(this);
-
+    }
+    if (updateOverview)
+    {
       if (overviewPanel != null)
       {
         overviewPanel.updateOverviewImage();
@@ -1156,7 +1141,7 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
 
   @Override
   /**
-   * Property change event fired when a change is made to the viewport ranges 
+   * Property change event fired when a change is made to the viewport ranges
    * object associated with this alignment panel's viewport
    */
   public void propertyChange(PropertyChangeEvent evt)
index f516bc9..533226e 100644 (file)
@@ -85,7 +85,7 @@ public class AnnotationColourChooser extends Panel implements
     oldcs = av.getGlobalColourScheme();
     if (av.getAlignment().getGroups() != null)
     {
-      oldgroupColours = new HashMap<SequenceGroup, ColourSchemeI>();
+      oldgroupColours = new HashMap<>();
       for (SequenceGroup sg : ap.av.getAlignment().getGroups())
       {
         oldgroupColours.put(sg, sg.getColourScheme());
@@ -109,8 +109,8 @@ public class AnnotationColourChooser extends Panel implements
     if (oldcs instanceof AnnotationColourGradient)
     {
       AnnotationColourGradient acg = (AnnotationColourGradient) oldcs;
-      currentColours.setState(acg.isPredefinedColours()
-              || acg.getBaseColour() != null);
+      currentColours.setState(
+              acg.isPredefinedColours() || acg.getBaseColour() != null);
       if (!acg.isPredefinedColours() && acg.getBaseColour() == null)
       {
         minColour.setBackground(acg.getMinColour());
@@ -150,9 +150,8 @@ public class AnnotationColourChooser extends Panel implements
         threshold.select(1);
         break;
       default:
-        throw new Error(
-                MessageManager
-                        .getString("error.implementation_error_dont_know_threshold_annotationcolourgradient"));
+        throw new Error(MessageManager.getString(
+                "error.implementation_error_dont_know_threshold_annotationcolourgradient"));
       }
       thresholdIsMin.setState(acg.isThresholdIsMinMax());
       thresholdValue.setText("" + acg.getAnnotationThreshold());
@@ -181,8 +180,8 @@ public class AnnotationColourChooser extends Panel implements
     // TODO remove duplication with gui.AnnotationRowFilter
     // TODO add 'per sequence only' option / parameter
 
-    annotationLabels = new HashMap<AlignmentAnnotation, String>();
-    Vector<String> list = new Vector<String>();
+    annotationLabels = new HashMap<>();
+    Vector<String> list = new Vector<>();
     AlignmentAnnotation[] anns = av.getAlignment().getAlignmentAnnotation();
     if (anns == null)
     {
@@ -219,8 +218,8 @@ public class AnnotationColourChooser extends Panel implements
   {
     minColour.setBackground(av.applet.getDefaultColourParameter(
             "ANNOTATIONCOLOUR_MIN", Color.orange));
-    maxColour.setBackground(av.applet.getDefaultColourParameter(
-            "ANNOTATIONCOLOUR_MAX", Color.red));
+    maxColour.setBackground(av.applet
+            .getDefaultColourParameter("ANNOTATIONCOLOUR_MAX", Color.red));
 
   }
 
@@ -265,13 +264,13 @@ public class AnnotationColourChooser extends Panel implements
     thresholdValue.setEnabled(false);
     thresholdValue.setColumns(5);
     currentColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
-    currentColours.setLabel(MessageManager
-            .getString("label.use_original_colours"));
+    currentColours.setLabel(
+            MessageManager.getString("label.use_original_colours"));
     currentColours.addItemListener(this);
 
     thresholdIsMin.setBackground(Color.white);
-    thresholdIsMin.setLabel(MessageManager
-            .getString("label.threshold_minmax"));
+    thresholdIsMin
+            .setLabel(MessageManager.getString("label.threshold_minmax"));
 
     this.setLayout(borderLayout1);
 
@@ -377,7 +376,7 @@ public class AnnotationColourChooser extends Panel implements
     else if (evt.getSource() == cancel)
     {
       reset();
-      ap.paintAlignment(true);
+      ap.paintAlignment(true, true);
       frame.setVisible(false);
     }
 
@@ -411,14 +410,14 @@ public class AnnotationColourChooser extends Panel implements
     if (!adjusting)
     {
       thresholdValue.setText((slider.getValue() / 1000f) + "");
-      if (currentColours.getState()
-              && !(av.getGlobalColourScheme() instanceof AnnotationColourGradient))
+      if (currentColours.getState() && !(av
+              .getGlobalColourScheme() instanceof AnnotationColourGradient))
       {
         changeColour();
       }
 
       currentAnnotation.threshold.value = slider.getValue() / 1000f;
-      ap.paintAlignment(false);
+      ap.paintAlignment(false, false);
     }
   }
 
@@ -467,8 +466,8 @@ public class AnnotationColourChooser extends Panel implements
       return;
     }
 
-    currentAnnotation = av.getAlignment().getAlignmentAnnotation()[annotations
-            .getSelectedIndex()];
+    currentAnnotation = av.getAlignment()
+            .getAlignmentAnnotation()[annotations.getSelectedIndex()];
 
     int aboveThreshold = -1;
     if (threshold.getSelectedIndex() == 1)
@@ -494,10 +493,10 @@ public class AnnotationColourChooser extends Panel implements
     else if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD
             && currentAnnotation.threshold == null)
     {
-      currentAnnotation
-              .setThreshold(new jalview.datamodel.GraphLine(
-                      (currentAnnotation.graphMax - currentAnnotation.graphMin) / 2f,
-                      "Threshold", Color.black));
+      currentAnnotation.setThreshold(new jalview.datamodel.GraphLine(
+              (currentAnnotation.graphMax - currentAnnotation.graphMin)
+                      / 2f,
+              "Threshold", Color.black));
     }
 
     if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
@@ -546,21 +545,21 @@ public class AnnotationColourChooser extends Panel implements
 
         if (currentColours.getState())
         {
-          sg.setColourScheme(new AnnotationColourGradient(
-                  currentAnnotation, sg.getColourScheme(), aboveThreshold));
+          sg.setColourScheme(new AnnotationColourGradient(currentAnnotation,
+                  sg.getColourScheme(), aboveThreshold));
         }
         else
         {
-          sg.setColourScheme(new AnnotationColourGradient(
-                  currentAnnotation, minColour.getBackground(), maxColour
-                          .getBackground(), aboveThreshold));
+          sg.setColourScheme(new AnnotationColourGradient(currentAnnotation,
+                  minColour.getBackground(), maxColour.getBackground(),
+                  aboveThreshold));
         }
       }
     }
 
     // update colours in linked windows
     ap.alignmentChanged();
-    ap.paintAlignment(true);
+    ap.paintAlignment(true, true);
   }
 
   void reset()
@@ -573,7 +572,7 @@ public class AnnotationColourChooser extends Panel implements
         sg.setColourScheme(oldgroupColours.get(sg));
       }
     }
-    ap.paintAlignment(true);
+    ap.paintAlignment(true, true);
   }
 
   @Override
@@ -589,7 +588,7 @@ public class AnnotationColourChooser extends Panel implements
   @Override
   public void mouseReleased(MouseEvent evt)
   {
-    ap.paintAlignment(true);
+    ap.paintAlignment(true, true);
   }
 
   @Override
index 3a7188e..206b132 100644 (file)
@@ -46,7 +46,6 @@ import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.awt.event.TextEvent;
 import java.awt.event.TextListener;
-import java.util.ArrayList;
 import java.util.Vector;
 
 //import javax.swing.JPanel;
@@ -172,16 +171,12 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
     // restore Object state from the previous session if one exists
     if (lastChooser != null)
     {
-      currentSearchPanel = lastChooser
-              .getCurrentSearchPanel();
+      currentSearchPanel = lastChooser.getCurrentSearchPanel();
       currentStructureFilterPanel = lastChooser
               .getCurrentStructureFilterPanel();
-      annotations.select(lastChooser
-              .getAnnotations().getSelectedIndex());
-      threshold.select(lastChooser
-              .getThreshold().getSelectedIndex());
-      actionOption = lastChooser
-              .getActionOption();
+      annotations.select(lastChooser.getAnnotations().getSelectedIndex());
+      threshold.select(lastChooser.getThreshold().getSelectedIndex());
+      actionOption = lastChooser.getActionOption();
       percentThreshold.setState(lastChooser.percentThreshold.getState());
     }
 
@@ -295,23 +290,12 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
 
       if (av.getAnnotationColumnSelectionState() != null)
       {
-        HiddenColumns oldHidden = av
-                .getAnnotationColumnSelectionState()
+        HiddenColumns oldHidden = av.getAnnotationColumnSelectionState()
                 .getOldHiddenColumns();
-        if (oldHidden != null)
-        {
-          ArrayList<int[]> regions = oldHidden.getHiddenColumnsCopy();
-          for (int[] positions : regions)
-          {
-            av.hideColumns(positions[0], positions[1]);
-          }
-        }
-        // TODO not clear why we need to hide all the columns (above) if we are
-        // going to copy the hidden columns over wholesale anyway
         av.getAlignment().setHiddenColumns(oldHidden);
       }
       av.sendSelection();
-      ap.paintAlignment(true);
+      ap.paintAlignment(true, true);
     }
 
   }
@@ -353,7 +337,7 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
           sliderDragging = false;
           valueChanged(true);
         }
-        ap.paintAlignment(true);
+        ap.paintAlignment(true, true);
       }
     });
   }
@@ -364,8 +348,7 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
     if (slider.isEnabled())
     {
       getCurrentAnnotation().threshold.value = slider.getValue() / 1000f;
-      updateView();
-      ap.paintAlignment(false);
+      updateView(); // this also calls paintAlignment(true,true)
     }
   }
 
@@ -399,11 +382,11 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
     }
 
     AnnotationFilterParameter filterParams = new AnnotationFilterParameter();
-    setCurrentAnnotation(av.getAlignment().getAlignmentAnnotation()[getAnnotations()
-            .getSelectedIndex()]);
+    setCurrentAnnotation(av.getAlignment()
+            .getAlignmentAnnotation()[getAnnotations().getSelectedIndex()]);
 
-    int selectedThresholdItem = getSelectedThresholdItem(getThreshold()
-            .getSelectedIndex());
+    int selectedThresholdItem = getSelectedThresholdItem(
+            getThreshold().getSelectedIndex());
 
     slider.setEnabled(true);
     thresholdValue.setEnabled(true);
@@ -421,11 +404,10 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
     {
       if (getCurrentAnnotation().threshold == null)
       {
-        getCurrentAnnotation()
-                .setThreshold(
-                        new jalview.datamodel.GraphLine(
-                                (getCurrentAnnotation().graphMax - getCurrentAnnotation().graphMin) / 2f,
-                                "Threshold", Color.black));
+        getCurrentAnnotation().setThreshold(new jalview.datamodel.GraphLine(
+                (getCurrentAnnotation().graphMax
+                        - getCurrentAnnotation().graphMin) / 2f,
+                "Threshold", Color.black));
       }
 
       adjusting = true;
@@ -434,7 +416,8 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
 
       slider.setMinimum((int) (getCurrentAnnotation().graphMin * 1000));
       slider.setMaximum((int) (getCurrentAnnotation().graphMax * 1000));
-      slider.setValue((int) (getCurrentAnnotation().threshold.value * 1000));
+      slider.setValue(
+              (int) (getCurrentAnnotation().threshold.value * 1000));
       setThresholdValueText();
       // slider.setMajorTickSpacing((int) (range / 10f));
       slider.setEnabled(true);
@@ -443,8 +426,8 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
       adjusting = false;
 
       // build filter params
-      filterParams
-              .setThresholdType(AnnotationFilterParameter.ThresholdType.NO_THRESHOLD);
+      filterParams.setThresholdType(
+              AnnotationFilterParameter.ThresholdType.NO_THRESHOLD);
       if (getCurrentAnnotation().isQuantitative())
       {
         filterParams
@@ -452,13 +435,13 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
 
         if (selectedThresholdItem == AnnotationColourGradient.ABOVE_THRESHOLD)
         {
-          filterParams
-                  .setThresholdType(AnnotationFilterParameter.ThresholdType.ABOVE_THRESHOLD);
+          filterParams.setThresholdType(
+                  AnnotationFilterParameter.ThresholdType.ABOVE_THRESHOLD);
         }
         else if (selectedThresholdItem == AnnotationColourGradient.BELOW_THRESHOLD)
         {
-          filterParams
-                  .setThresholdType(AnnotationFilterParameter.ThresholdType.BELOW_THRESHOLD);
+          filterParams.setThresholdType(
+                  AnnotationFilterParameter.ThresholdType.BELOW_THRESHOLD);
         }
       }
     }
@@ -489,13 +472,13 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
         filterParams.setRegexString(currentSearchPanel.searchBox.getText());
         if (currentSearchPanel.displayName.getState())
         {
-          filterParams
-                  .addRegexSearchField(AnnotationFilterParameter.SearchableAnnotationField.DISPLAY_STRING);
+          filterParams.addRegexSearchField(
+                  AnnotationFilterParameter.SearchableAnnotationField.DISPLAY_STRING);
         }
         if (currentSearchPanel.description.getState())
         {
-          filterParams
-                  .addRegexSearchField(AnnotationFilterParameter.SearchableAnnotationField.DESCRIPTION);
+          filterParams.addRegexSearchField(
+                  AnnotationFilterParameter.SearchableAnnotationField.DESCRIPTION);
         }
       }
       else
@@ -520,7 +503,7 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
     filterParams = null;
     av.setAnnotationColumnSelectionState(this);
     av.sendSelection();
-    ap.paintAlignment(true);
+    ap.paintAlignment(true, true);
   }
 
   public HiddenColumns getOldHiddenColumns()
@@ -642,7 +625,8 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
 
     public void syncState()
     {
-      if (aColChooser.getActionOption() == AnnotationColumnChooser.ACTION_OPTION_HIDE)
+      if (aColChooser
+              .getActionOption() == AnnotationColumnChooser.ACTION_OPTION_HIDE)
       {
         furtherAction.select("Hide");
       }
@@ -670,8 +654,8 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
     }
   }
 
-  public class StructureFilterPanel extends TitledPanel implements
-          ItemListener
+  public class StructureFilterPanel extends TitledPanel
+          implements ItemListener
   {
     private AnnotationColumnChooser aColChooser;
 
index 3f7e523..d8f65a5 100755 (executable)
@@ -52,8 +52,8 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.Vector;
 
-public class AnnotationLabels extends Panel implements ActionListener,
-        MouseListener, MouseMotionListener
+public class AnnotationLabels extends Panel
+        implements ActionListener, MouseListener, MouseMotionListener
 {
   Image image;
 
@@ -201,8 +201,9 @@ public class AnnotationLabels extends Panel implements ActionListener,
               ap.alignFrame);
       Frame frame = new Frame();
       frame.add(cap);
-      jalview.bin.JalviewLite.addFrame(frame, ap.alignFrame.getTitle()
-              + " - " + aa[selectedRow].label, 500, 100);
+      jalview.bin.JalviewLite.addFrame(frame,
+              ap.alignFrame.getTitle() + " - " + aa[selectedRow].label, 500,
+              100);
       cap.setText(aa[selectedRow].toString());
     }
     else if (evt.getActionCommand().equals(COPYCONS_SEQ))
@@ -225,13 +226,15 @@ public class AnnotationLabels extends Panel implements ActionListener,
     ap.annotationPanel.adjustPanelHeight();
     setSize(getSize().width, ap.annotationPanel.getSize().height);
     ap.validate();
-    ap.paintAlignment(true);
+    // TODO: only paint if we needed to
+    ap.paintAlignment(true, true);
   }
 
   boolean editLabelDescription(AlignmentAnnotation annotation)
   {
-    Checkbox padGaps = new Checkbox("Fill Empty Gaps With \""
-            + ap.av.getGapCharacter() + "\"", annotation.padGaps);
+    Checkbox padGaps = new Checkbox(
+            "Fill Empty Gaps With \"" + ap.av.getGapCharacter() + "\"",
+            annotation.padGaps);
 
     EditNameDialog dialog = new EditNameDialog(annotation.label,
             annotation.description, "      Annotation Label",
@@ -320,8 +323,9 @@ public class AnnotationLabels extends Panel implements ActionListener,
 
     if (resizePanel)
     {
-      Dimension d = ap.annotationPanelHolder.getSize(), e = ap.annotationSpaceFillerHolder
-              .getSize(), f = ap.seqPanelHolder.getSize();
+      Dimension d = ap.annotationPanelHolder.getSize(),
+              e = ap.annotationSpaceFillerHolder.getSize(),
+              f = ap.seqPanelHolder.getSize();
       int dif = evt.getY() - oldY;
 
       dif /= ap.av.getCharHeight();
@@ -331,16 +335,16 @@ public class AnnotationLabels extends Panel implements ActionListener,
       {
         ap.annotationPanel.setSize(d.width, d.height - dif);
         setSize(new Dimension(e.width, d.height - dif));
-        ap.annotationSpaceFillerHolder.setSize(new Dimension(e.width,
-                d.height - dif));
-        ap.annotationPanelHolder.setSize(new Dimension(d.width, d.height
-                - dif));
+        ap.annotationSpaceFillerHolder
+                .setSize(new Dimension(e.width, d.height - dif));
+        ap.annotationPanelHolder
+                .setSize(new Dimension(d.width, d.height - dif));
         ap.apvscroll.setValues(ap.apvscroll.getValue(), d.height - dif, 0,
                 av.calcPanelHeight());
         f.height += dif;
         ap.seqPanelHolder.setPreferredSize(f);
-        ap.setScrollValues(av.getRanges().getStartRes(), av.getRanges()
-                .getStartSeq());
+        ap.setScrollValues(av.getRanges().getStartRes(),
+                av.getRanges().getStartSeq());
         ap.validate();
         // ap.paintAlignment(true);
         ap.addNotify();
@@ -451,7 +455,8 @@ public class AnnotationLabels extends Panel implements ActionListener,
             .getAlignmentAnnotation();
 
     // DETECT RIGHT MOUSE BUTTON IN AWT
-    if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
+    if ((evt.getModifiers()
+            & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
     {
 
       PopupMenu popup = new PopupMenu(
@@ -525,9 +530,10 @@ public class AnnotationLabels extends Panel implements ActionListener,
             popup.addSeparator();
             final CheckboxMenuItem cbmi = new CheckboxMenuItem(
                     MessageManager.getString("label.ignore_gaps_consensus"),
-                    (aa[selectedRow].groupRef != null) ? aa[selectedRow].groupRef
-                            .getIgnoreGapsConsensus() : ap.av
-                            .isIgnoreGapsConsensus());
+                    (aa[selectedRow].groupRef != null)
+                            ? aa[selectedRow].groupRef
+                                    .getIgnoreGapsConsensus()
+                            : ap.av.isIgnoreGapsConsensus());
             final AlignmentAnnotation aaa = aa[selectedRow];
             cbmi.addItemListener(new ItemListener()
             {
@@ -543,7 +549,7 @@ public class AnnotationLabels extends Panel implements ActionListener,
                 {
                   ap.av.setIgnoreGapsConsensus(cbmi.getState(), ap);
                 }
-                ap.paintAlignment(true);
+                ap.paintAlignment(true, true);
               }
             });
             popup.add(cbmi);
@@ -631,10 +637,10 @@ public class AnnotationLabels extends Panel implements ActionListener,
                   // can be
                   // updated.
                   av.setShowConsensusHistogram(chist.getState());
-                  ap.alignFrame.showConsensusHistogram.setState(chist
-                          .getState()); // TODO: implement
-                                        // ap.updateGUI()/alignFrame.updateGUI
-                                        // for applet
+                  ap.alignFrame.showConsensusHistogram
+                          .setState(chist.getState()); // TODO: implement
+                                                       // ap.updateGUI()/alignFrame.updateGUI
+                                                       // for applet
                   ap.repaint();
                   // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
                 }
@@ -680,11 +686,12 @@ public class AnnotationLabels extends Panel implements ActionListener,
                   // can be
                   // updated.
                   av.setShowSequenceLogo(true);
-                  ap.alignFrame.normSequenceLogo.setState(cprofn.getState()); // TODO:
-                                                                              // implement
-                                                                              // ap.updateGUI()/alignFrame.updateGUI
-                                                                              // for
-                                                                              // applet
+                  ap.alignFrame.normSequenceLogo
+                          .setState(cprofn.getState()); // TODO:
+                                                        // implement
+                                                        // ap.updateGUI()/alignFrame.updateGUI
+                                                        // for
+                                                        // applet
                   av.setNormaliseSequenceLogo(cprofn.getState());
                   ap.repaint();
                   // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
@@ -715,17 +722,16 @@ public class AnnotationLabels extends Panel implements ActionListener,
             ap.seqPanel.ap.idPanel.highlightSearchResults(null);
             // process modifiers
             SequenceGroup sg = ap.av.getSelectionGroup();
-            if (sg == null
-                    || sg == aa[selectedRow].groupRef
-                    || !(jalview.util.Platform.isControlDown(evt) || evt
-                            .isShiftDown()))
+            if (sg == null || sg == aa[selectedRow].groupRef
+                    || !(jalview.util.Platform.isControlDown(evt)
+                            || evt.isShiftDown()))
             {
               if (jalview.util.Platform.isControlDown(evt)
                       || evt.isShiftDown())
               {
                 // clone a new selection group from the associated group
-                ap.av.setSelectionGroup(new SequenceGroup(
-                        aa[selectedRow].groupRef));
+                ap.av.setSelectionGroup(
+                        new SequenceGroup(aa[selectedRow].groupRef));
               }
               else
               {
@@ -751,15 +757,14 @@ public class AnnotationLabels extends Panel implements ActionListener,
                 }
               }
             }
-            ap.paintAlignment(false);
+            ap.paintAlignment(false, false);
             PaintRefresher.Refresh(ap, ap.av.getSequenceSetId());
             ap.av.sendSelection();
           }
           else
           {
-            ap.seqPanel.ap.idPanel
-                    .highlightSearchResults(aa[selectedRow].groupRef
-                            .getSequences(null));
+            ap.seqPanel.ap.idPanel.highlightSearchResults(
+                    aa[selectedRow].groupRef.getSequences(null));
           }
           return;
         }
@@ -768,8 +773,8 @@ public class AnnotationLabels extends Panel implements ActionListener,
           if (evt.getClickCount() == 1)
           {
             ap.seqPanel.ap.idPanel
-                    .highlightSearchResults(Arrays
-                            .asList(new SequenceI[] { aa[selectedRow].sequenceRef }));
+                    .highlightSearchResults(Arrays.asList(new SequenceI[]
+                    { aa[selectedRow].sequenceRef }));
           }
           else if (evt.getClickCount() >= 2)
           {
@@ -780,8 +785,8 @@ public class AnnotationLabels extends Panel implements ActionListener,
               // we make a copy rather than edit the current selection if no
               // modifiers pressed
               // see Enhancement JAL-1557
-              if (!(jalview.util.Platform.isControlDown(evt) || evt
-                      .isShiftDown()))
+              if (!(jalview.util.Platform.isControlDown(evt)
+                      || evt.isShiftDown()))
               {
                 sg = new SequenceGroup(sg);
                 sg.clear();
@@ -809,7 +814,7 @@ public class AnnotationLabels extends Panel implements ActionListener,
               sg.addSequence(aa[selectedRow].sequenceRef, false);
             }
             ap.av.setSelectionGroup(sg);
-            ap.paintAlignment(false);
+            ap.paintAlignment(false, false);
             PaintRefresher.Refresh(ap, ap.av.getSequenceSetId());
             ap.av.sendSelection();
           }
@@ -833,14 +838,13 @@ public class AnnotationLabels extends Panel implements ActionListener,
       return;
     }
     jalview.appletgui.AlignFrame.copiedSequences = new StringBuffer();
-    jalview.appletgui.AlignFrame.copiedSequences.append(sq.getName() + "\t"
-            + sq.getStart() + "\t" + sq.getEnd() + "\t"
-            + sq.getSequenceAsString() + "\n");
+    jalview.appletgui.AlignFrame.copiedSequences
+            .append(sq.getName() + "\t" + sq.getStart() + "\t" + sq.getEnd()
+                    + "\t" + sq.getSequenceAsString() + "\n");
     if (av.hasHiddenColumns())
     {
       jalview.appletgui.AlignFrame.copiedHiddenColumns = new Vector<>(
-              av.getAlignment().getHiddenColumns()
-                      .getHiddenColumnsCopy());
+              av.getAlignment().getHiddenColumns().getHiddenColumnsCopy());
     }
   }
 
index 417bb06..50a9e33 100755 (executable)
@@ -51,9 +51,9 @@ import java.awt.event.MouseListener;
 import java.awt.event.MouseMotionListener;
 import java.beans.PropertyChangeEvent;
 
-public class AnnotationPanel extends Panel implements AwtRenderPanelI,
-        AdjustmentListener, ActionListener, MouseListener,
-        MouseMotionListener, ViewportListenerI
+public class AnnotationPanel extends Panel
+        implements AwtRenderPanelI, AdjustmentListener, ActionListener,
+        MouseListener, MouseMotionListener, ViewportListenerI
 {
   AlignViewport av;
 
@@ -153,7 +153,8 @@ public class AnnotationPanel extends Panel implements AwtRenderPanelI,
 
     if (anot.length < av.getColumnSelection().getMax())
     {
-      Annotation[] temp = new Annotation[av.getColumnSelection().getMax() + 2];
+      Annotation[] temp = new Annotation[av.getColumnSelection().getMax()
+              + 2];
       System.arraycopy(anot, 0, temp, 0, anot.length);
       anot = temp;
       aa[activeRow].annotations = anot;
@@ -287,8 +288,8 @@ public class AnnotationPanel extends Panel implements AwtRenderPanelI,
           anot[index] = new Annotation(label, "", type, 0);
         }
 
-        anot[index].secondaryStructure = type != 'S' ? type : label
-                .length() == 0 ? ' ' : label.charAt(0);
+        anot[index].secondaryStructure = type != 'S' ? type
+                : label.length() == 0 ? ' ' : label.charAt(0);
         anot[index].displayCharacter = label;
       }
     }
@@ -353,7 +354,8 @@ public class AnnotationPanel extends Panel implements AwtRenderPanelI,
       }
     }
 
-    if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK
+    if ((evt.getModifiers()
+            & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK
             && activeRow != -1)
     {
       if (av.getColumnSelection() == null
@@ -425,16 +427,20 @@ public class AnnotationPanel extends Panel implements AwtRenderPanelI,
   {
     if (graphStretch > -1)
     {
-      av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight += graphStretchY
-              - evt.getY();
-      if (av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight < 0)
+      av.getAlignment()
+              .getAlignmentAnnotation()[graphStretch].graphHeight += graphStretchY
+                      - evt.getY();
+      if (av.getAlignment()
+              .getAlignmentAnnotation()[graphStretch].graphHeight < 0)
       {
-        av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight = 0;
+        av.getAlignment()
+                .getAlignmentAnnotation()[graphStretch].graphHeight = 0;
       }
       graphStretchY = evt.getY();
       av.calcPanelHeight();
       needValidating = true;
-      ap.paintAlignment(true);
+      // TODO: only update overview visible geometry
+      ap.paintAlignment(true, false);
     }
     else
     {
@@ -509,18 +515,19 @@ public class AnnotationPanel extends Panel implements AwtRenderPanelI,
             String name;
             if (av.getAlignment().isNucleotide())
             {
-              name = ResidueProperties.nucleotideName.get(String
-                      .valueOf(residue));
-              text.append(" Nucleotide: ").append(
-                      name != null ? name : residue);
+              name = ResidueProperties.nucleotideName
+                      .get(String.valueOf(residue));
+              text.append(" Nucleotide: ")
+                      .append(name != null ? name : residue);
             }
             else
             {
-              name = 'X' == residue ? "X" : ('*' == residue ? "STOP"
-                      : ResidueProperties.aa2Triplet.get(String
-                              .valueOf(residue)));
-              text.append(" Residue: ").append(
-                      name != null ? name : residue);
+              name = 'X' == residue ? "X"
+                      : ('*' == residue ? "STOP"
+                              : ResidueProperties.aa2Triplet
+                                      .get(String.valueOf(residue)));
+              text.append(" Residue: ")
+                      .append(name != null ? name : residue);
             }
             int residuePos = seqref.findPosition(column);
             text.append(" (").append(residuePos).append(")");
@@ -626,8 +633,8 @@ public class AnnotationPanel extends Panel implements AwtRenderPanelI,
 
     gg.setColor(Color.white);
     gg.fillRect(0, 0, getSize().width, getSize().height);
-    drawComponent(gg, av.getRanges().getStartRes(), av.getRanges()
-            .getEndRes() + 1);
+    drawComponent(gg, av.getRanges().getStartRes(),
+            av.getRanges().getEndRes() + 1);
 
     g.drawImage(image, 0, 0, this);
   }
@@ -644,7 +651,8 @@ public class AnnotationPanel extends Panel implements AwtRenderPanelI,
 
     gg.copyArea(0, 0, imgWidth, getSize().height,
             -horizontal * av.getCharWidth(), 0);
-    int sr = av.getRanges().getStartRes(), er = av.getRanges().getEndRes() + 1, transX = 0;
+    int sr = av.getRanges().getStartRes(),
+            er = av.getRanges().getEndRes() + 1, transX = 0;
 
     if (horizontal > 0) // scrollbar pulled right, image to the left
     {
@@ -770,5 +778,14 @@ public class AnnotationPanel extends Panel implements AwtRenderPanelI,
     {
       fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
     }
+    else if (evt.getPropertyName().equals(ViewportRanges.STARTRESANDSEQ))
+    {
+      fastPaint(((int[]) evt.getNewValue())[0]
+              - ((int[]) evt.getOldValue())[0]);
+    }
+    else if (evt.getPropertyName().equals(ViewportRanges.MOVE_VIEWPORT))
+    {
+      repaint();
+    }
   }
 }
index 315ce3b..c96dbab 100644 (file)
@@ -114,7 +114,7 @@ public abstract class AnnotationRowFilter extends Panel
   public void cancel_actionPerformed(ActionEvent e)
   {
     reset();
-    ap.paintAlignment(true);
+    ap.paintAlignment(true, true);
     frame.setVisible(false);
   }
 
@@ -154,7 +154,7 @@ public abstract class AnnotationRowFilter extends Panel
     thresholdValue.setCaretPosition(0);
     adjusting = oldadj;
   }
-  
+
   public void thresholdValue_actionPerformed(ActionEvent e)
   {
     try
@@ -163,7 +163,8 @@ public abstract class AnnotationRowFilter extends Panel
       if (percentThreshold.getState())
       {
         int pos = slider.getMinimum()
-                + (int) ((slider.getMaximum() - slider.getMinimum()) * f / 100f);
+                + (int) ((slider.getMaximum() - slider.getMinimum()) * f
+                        / 100f);
         slider.setValue(pos);
       }
       else
index c0b4ff0..3d1442d 100644 (file)
@@ -65,7 +65,7 @@ import java.util.List;
 import java.util.Vector;
 
 public class AppletJmol extends EmbmenuFrame implements
-// StructureListener,
+        // StructureListener,
         KeyListener, ActionListener, ItemListener
 
 {
@@ -88,7 +88,8 @@ public class AppletJmol extends EmbmenuFrame implements
   CheckboxMenuItem jmolColour = new CheckboxMenuItem(
           MessageManager.getString("action.using_jmol"), false);
 
-  MenuItem chain = new MenuItem(MessageManager.getString("action.by_chain"));
+  MenuItem chain = new MenuItem(
+          MessageManager.getString("action.by_chain"));
 
   MenuItem charge = new MenuItem(
           MessageManager.getString("label.charge_cysteine"));
@@ -133,7 +134,7 @@ public class AppletJmol extends EmbmenuFrame implements
 
   AlignmentPanel ap;
 
-  List<AlignmentPanel> _aps = new ArrayList<AlignmentPanel>(); // remove? never
+  List<AlignmentPanel> _aps = new ArrayList<>(); // remove? never
                                                                // added to
 
   String fileLoadingError;
@@ -182,15 +183,15 @@ public class AppletJmol extends EmbmenuFrame implements
   {
     this.ap = ap;
     jmb = new AppletJmolBinding(this, ap.getStructureSelectionManager(),
-            new PDBEntry[] { pdbentry }, new SequenceI[][] { seq },
-            protocol);
+            new PDBEntry[]
+            { pdbentry }, new SequenceI[][] { seq }, protocol);
     jmb.setColourBySequence(true);
     if (pdbentry.getId() == null || pdbentry.getId().length() < 1)
     {
       if (protocol == DataSourceType.PASTE)
       {
-        pdbentry.setId("PASTED PDB"
-                + (chains == null ? "_" : chains.toString()));
+        pdbentry.setId(
+                "PASTED PDB" + (chains == null ? "_" : chains.toString()));
       }
       else
       {
@@ -210,9 +211,9 @@ public class AppletJmol extends EmbmenuFrame implements
     StructureFile reader = null;
     if (alreadyMapped != null)
     {
-      reader = StructureSelectionManager.getStructureSelectionManager(
-              ap.av.applet).setMapping(seq, chains, pdbentry.getFile(),
-              protocol);
+      reader = StructureSelectionManager
+              .getStructureSelectionManager(ap.av.applet)
+              .setMapping(seq, chains, pdbentry.getFile(), protocol, null);
       // PROMPT USER HERE TO ADD TO NEW OR EXISTING VIEW?
       // FOR NOW, LETS JUST OPEN A NEW WINDOW
     }
@@ -268,15 +269,15 @@ public class AppletJmol extends EmbmenuFrame implements
 
     try
     {
-      jmb.allocateViewer(renderPanel, true, ap.av.applet.getName()
-              + "_jmol_", ap.av.applet.getDocumentBase(),
-              ap.av.applet.getCodeBase(), "-applet", scriptWindow, null);
+      jmb.allocateViewer(renderPanel, true,
+              ap.av.applet.getName() + "_jmol_",
+              ap.av.applet.getDocumentBase(), ap.av.applet.getCodeBase(),
+              "-applet", scriptWindow, null);
     } catch (Exception e)
     {
-      System.err
-              .println("Couldn't create a jmol viewer. Args to allocate viewer were:\nDocumentBase="
-                      + ap.av.applet.getDocumentBase()
-                      + "\nCodebase="
+      System.err.println(
+              "Couldn't create a jmol viewer. Args to allocate viewer were:\nDocumentBase="
+                      + ap.av.applet.getDocumentBase() + "\nCodebase="
                       + ap.av.applet.getCodeBase());
       e.printStackTrace();
       dispose();
@@ -294,7 +295,7 @@ public class AppletJmol extends EmbmenuFrame implements
     });
     pdbentry.setProperty("protocol", protocol);
     if (pdbentry.getFile() != null)
-    
+
     {
       // import structure data from pdbentry.getFile based on given protocol
       if (protocol == DataSourceType.PASTE)
@@ -319,8 +320,8 @@ public class AppletJmol extends EmbmenuFrame implements
           {
             if (jalview.bin.JalviewLite.debug)
             {
-              System.err
-                      .println("AppletJmol:Trying to reuse existing PDBfile IO parser.");
+              System.err.println(
+                      "AppletJmol:Trying to reuse existing PDBfile IO parser.");
             }
             // re-use the one we opened earlier
             freader = reader.getReader();
@@ -329,8 +330,8 @@ public class AppletJmol extends EmbmenuFrame implements
           {
             if (jalview.bin.JalviewLite.debug)
             {
-              System.err
-                      .println("AppletJmol:Creating new PDBfile IO parser.");
+              System.err.println(
+                      "AppletJmol:Creating new PDBfile IO parser.");
             }
             FileParse fp = new FileParse(pdbentry.getFile(), protocol);
             fp.mark();
@@ -346,9 +347,8 @@ public class AppletJmol extends EmbmenuFrame implements
           }
           if (freader == null)
           {
-            throw new Exception(
-                    MessageManager
-                            .getString("exception.invalid_datasource_couldnt_obtain_reader"));
+            throw new Exception(MessageManager.getString(
+                    "exception.invalid_datasource_couldnt_obtain_reader"));
           }
           jmb.viewer.openReader(pdbentry.getFile(), pdbentry.getId(),
                   freader);
@@ -394,7 +394,7 @@ public class AppletJmol extends EmbmenuFrame implements
 
   void centerViewer()
   {
-    Vector<String> toshow = new Vector<String>();
+    Vector<String> toshow = new Vector<>();
     for (int i = 0; i < chainMenu.getItemCount(); i++)
     {
       if (chainMenu.getItem(i) instanceof CheckboxMenuItem)
@@ -433,8 +433,8 @@ public class AppletJmol extends EmbmenuFrame implements
       } catch (OutOfMemoryError ex)
       {
         frame.dispose();
-        System.err
-                .println("Out of memory when trying to create dialog box with sequence-structure mapping.");
+        System.err.println(
+                "Out of memory when trying to create dialog box with sequence-structure mapping.");
         return;
       }
       jalview.bin.JalviewLite.addFrame(frame,
@@ -500,10 +500,10 @@ public class AppletJmol extends EmbmenuFrame implements
     {
       try
       {
-        ap.av.applet.getAppletContext().showDocument(
-                new java.net.URL(
+        ap.av.applet.getAppletContext()
+                .showDocument(new java.net.URL(
                         "http://jmol.sourceforge.net/docs/JmolUserGuide/"),
-                "jmolHelp");
+                        "jmolHelp");
       } catch (java.net.MalformedURLException ex)
       {
       }
index 9b8a235..2f61b24 100644 (file)
@@ -24,6 +24,7 @@ import jalview.api.AlignmentViewPanel;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SequenceI;
 import jalview.ext.jmol.JalviewJmolBinding;
+import jalview.gui.IProgressIndicator;
 import jalview.io.DataSourceType;
 import jalview.structure.StructureSelectionManager;
 
@@ -110,8 +111,8 @@ class AppletJmolBinding extends JalviewJmolBinding
   {
     try
     {
-      appletJmolBinding.ap.av.applet.getAppletContext().showDocument(
-              new java.net.URL(url), "jmol");
+      appletJmolBinding.ap.av.applet.getAppletContext()
+              .showDocument(new java.net.URL(url), "jmol");
     } catch (java.net.MalformedURLException ex)
     {
     }
@@ -183,4 +184,11 @@ class AppletJmolBinding extends JalviewJmolBinding
     // TODO Auto-generated method stub
     return null;
   }
+
+  @Override
+  protected IProgressIndicator getIProgressIndicator()
+  {
+    // no progress indicators on the applet
+    return null;
+  }
 }
index 1e806a5..22a49cd 100644 (file)
@@ -55,8 +55,8 @@ import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.io.IOException;
 
-public class CutAndPasteTransfer extends Panel implements ActionListener,
-        MouseListener
+public class CutAndPasteTransfer extends Panel
+        implements ActionListener, MouseListener
 {
   boolean pdbImport = false;
 
@@ -211,8 +211,8 @@ public class CutAndPasteTransfer extends Panel implements ActionListener,
       // TODO: JAL-1102 - should have a warning message in dialog, not simply
       // overwrite the broken input data with the exception
       textarea.setText(MessageManager.formatMessage(
-              "label.could_not_parse_newick_file",
-              new Object[] { ex.getMessage() }));
+              "label.could_not_parse_newick_file", new Object[]
+              { ex.getMessage() }));
       return false;
     }
     return false;
@@ -238,65 +238,64 @@ public class CutAndPasteTransfer extends Panel implements ActionListener,
       al = afa.readFile(text, DataSourceType.PASTE, format);
       source = afa.getAlignFile();
 
-    if (al != null)
-    {
-      al.setDataset(null); // set dataset on alignment/sequences
-
-      /*
-       * SplitFrame option dependent on applet parameter for now.
-       */
-      boolean allowSplitFrame = alignFrame.viewport.applet
-              .getDefaultParameter("enableSplitFrame", false);
-      if (allowSplitFrame && openSplitFrame(al, format))
+      if (al != null)
       {
-        return;
-      }
-      if (newWindow)
-      {
-        AlignFrame af;
-
-        if (source instanceof ComplexAlignFile)
+        al.setDataset(null); // set dataset on alignment/sequences
+
+        /*
+         * SplitFrame option dependent on applet parameter for now.
+         */
+        boolean allowSplitFrame = alignFrame.viewport.applet
+                .getDefaultParameter("enableSplitFrame", false);
+        if (allowSplitFrame && openSplitFrame(al, format))
         {
+          return;
+        }
+        if (newWindow)
+        {
+          AlignFrame af;
+
+          if (source instanceof ComplexAlignFile)
+          {
             HiddenColumns colSel = ((ComplexAlignFile) source)
                     .getHiddenColumns();
-          SequenceI[] hiddenSeqs = ((ComplexAlignFile) source)
-                  .getHiddenSequences();
-          boolean showSeqFeatures = ((ComplexAlignFile) source)
-                  .isShowSeqFeatures();
-          String colourSchemeName = ((ComplexAlignFile) source)
-                  .getGlobalColourScheme();
-          af = new AlignFrame(al, hiddenSeqs, colSel,
-                  alignFrame.viewport.applet, "Cut & Paste input - "
-                          + format, false);
-          af.getAlignViewport().setShowSequenceFeatures(showSeqFeatures);
-          ColourSchemeI cs = ColourSchemeMapper.getJalviewColourScheme(
-                  colourSchemeName, al);
-          if (cs != null)
+            SequenceI[] hiddenSeqs = ((ComplexAlignFile) source)
+                    .getHiddenSequences();
+            boolean showSeqFeatures = ((ComplexAlignFile) source)
+                    .isShowSeqFeatures();
+            String colourSchemeName = ((ComplexAlignFile) source)
+                    .getGlobalColourScheme();
+            af = new AlignFrame(al, hiddenSeqs, colSel,
+                    alignFrame.viewport.applet,
+                    "Cut & Paste input - " + format, false);
+            af.getAlignViewport().setShowSequenceFeatures(showSeqFeatures);
+            ColourSchemeI cs = ColourSchemeMapper
+                    .getJalviewColourScheme(colourSchemeName, al);
+            if (cs != null)
+            {
+              af.changeColour(cs);
+            }
+          }
+          else
           {
-            af.changeColour(cs);
+            af = new AlignFrame(al, alignFrame.viewport.applet,
+                    "Cut & Paste input - " + format, false);
+            if (source instanceof FeaturesSourceI)
+            {
+              af.getAlignViewport().setShowSequenceFeatures(true);
+            }
           }
+
+          af.statusBar.setText(MessageManager.getString(
+                  "label.successfully_pasted_annotation_to_alignment"));
         }
         else
         {
-          af = new AlignFrame(al, alignFrame.viewport.applet,
-                  "Cut & Paste input - " + format, false);
-          if (source instanceof FeaturesSourceI)
-          {
-            af.getAlignViewport().setShowSequenceFeatures(true);
-          }
+          alignFrame.addSequences(al.getSequencesArray());
+          alignFrame.statusBar.setText(MessageManager
+                  .getString("label.successfully_pasted_alignment_file"));
         }
-
-        af.statusBar
-                .setText(MessageManager
-                        .getString("label.successfully_pasted_annotation_to_alignment"));
       }
-      else
-      {
-        alignFrame.addSequences(al.getSequencesArray());
-        alignFrame.statusBar.setText(MessageManager
-                .getString("label.successfully_pasted_alignment_file"));
-      }
-    }
     } catch (IOException ex)
     {
       ex.printStackTrace();
@@ -390,17 +389,17 @@ public class CutAndPasteTransfer extends Panel implements ActionListener,
           alignFrame.alignPanel.fontChanged();
           alignFrame.changeColour(new TCoffeeColourScheme(
                   alignFrame.viewport.getAlignment()));
-          alignFrame.statusBar
-                  .setText(MessageManager
-                          .getString("label.successfully_pasted_tcoffee_scores_to_alignment"));
+          alignFrame.statusBar.setText(MessageManager.getString(
+                  "label.successfully_pasted_tcoffee_scores_to_alignment"));
         }
         else
         {
           // file valid but didn't get added to alignment for some reason
           alignFrame.statusBar.setText(MessageManager.formatMessage(
-                  "label.failed_add_tcoffee_scores",
-                  new Object[] { (tcf.getWarningMessage() != null ? tcf
-                          .getWarningMessage() : "") }));
+                  "label.failed_add_tcoffee_scores", new Object[]
+                  { (tcf.getWarningMessage() != null
+                          ? tcf.getWarningMessage()
+                          : "") }));
         }
       }
       else
@@ -418,9 +417,8 @@ public class CutAndPasteTransfer extends Panel implements ActionListener,
       {
         alignFrame.alignPanel.fontChanged();
         alignFrame.alignPanel.setScrollValues(0, 0);
-        alignFrame.statusBar
-                .setText(MessageManager
-                        .getString("label.successfully_pasted_annotation_to_alignment"));
+        alignFrame.statusBar.setText(MessageManager.getString(
+                "label.successfully_pasted_annotation_to_alignment"));
 
       }
       else
@@ -428,9 +426,8 @@ public class CutAndPasteTransfer extends Panel implements ActionListener,
         if (!alignFrame.parseFeaturesFile(textarea.getText(),
                 jalview.io.DataSourceType.PASTE))
         {
-          alignFrame.statusBar
-                  .setText(MessageManager
-                          .getString("label.couldnt_parse_pasted_text_as_valid_annotation_feature_GFF_tcoffee_file"));
+          alignFrame.statusBar.setText(MessageManager.getString(
+                  "label.couldnt_parse_pasted_text_as_valid_annotation_feature_GFF_tcoffee_file"));
         }
       }
     }
@@ -487,8 +484,8 @@ public class CutAndPasteTransfer extends Panel implements ActionListener,
   private void jbInit() throws Exception
   {
     textarea.setFont(new java.awt.Font("Monospaced", Font.PLAIN, 10));
-    textarea.setText(MessageManager
-            .getString("label.paste_your_alignment_file"));
+    textarea.setText(
+            MessageManager.getString("label.paste_your_alignment_file"));
     textarea.addMouseListener(this);
     this.setLayout(borderLayout1);
     accept.addActionListener(this);
@@ -504,8 +501,8 @@ public class CutAndPasteTransfer extends Panel implements ActionListener,
   @Override
   public void mousePressed(MouseEvent evt)
   {
-    if (textarea.getText().startsWith(
-            MessageManager.getString("label.paste_your")))
+    if (textarea.getText()
+            .startsWith(MessageManager.getString("label.paste_your")))
     {
       textarea.setText("");
     }
index f61077a..53782c0 100644 (file)
@@ -207,8 +207,8 @@ public class EmbmenuFrame extends Frame implements MouseListener
     if (popup != null)
     {
       embeddedMenu.add(popup);
-      popup.show(embeddedMenu, source.getBounds().x, source.getBounds().y
-              + source.getBounds().getSize().height);
+      popup.show(embeddedMenu, source.getBounds().x,
+              source.getBounds().y + source.getBounds().getSize().height);
     }
   }
 
index b369318..89228d5 100644 (file)
@@ -26,6 +26,7 @@ import jalview.api.SequenceRenderer;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SequenceI;
 import jalview.ext.jmol.JalviewJmolBinding;
+import jalview.gui.IProgressIndicator;
 import jalview.io.DataSourceType;
 
 import java.awt.Container;
@@ -49,9 +50,8 @@ public class ExtJmol extends JalviewJmolBinding
 
   private AlignmentPanel ap;
 
-  protected ExtJmol(AlignFrame alframe,
-          PDBEntry[] pdbentry, SequenceI[][] seq,
-          DataSourceType protocol)
+  protected ExtJmol(AlignFrame alframe, PDBEntry[] pdbentry,
+          SequenceI[][] seq, DataSourceType protocol)
   {
     super(alframe.alignPanel.getStructureSelectionManager(), pdbentry, seq,
             protocol);
@@ -66,6 +66,13 @@ public class ExtJmol extends JalviewJmolBinding
   }
 
   @Override
+  protected IProgressIndicator getIProgressIndicator()
+  {
+    // no progress indicators on applet (could access javascript for this)
+    return null;
+  }
+
+  @Override
   public void updateColours(Object source)
   {
 
@@ -93,6 +100,7 @@ public class ExtJmol extends JalviewJmolBinding
     }
   }
 
+
   @Override
   public SequenceRenderer getSequenceRenderer(AlignmentViewPanel alignment)
   {
@@ -138,8 +146,8 @@ public class ExtJmol extends JalviewJmolBinding
   @Override
   public void refreshPdbEntries()
   {
-    List<PDBEntry> pdbe = new ArrayList<PDBEntry>();
-    List<String> fileids = new ArrayList<String>();
+    List<PDBEntry> pdbe = new ArrayList<>();
+    List<String> fileids = new ArrayList<>();
     SequenceI[] sq = ap.av.getAlignment().getSequencesArray();
     for (int s = 0; s < sq.length; s++)
     {
@@ -173,8 +181,8 @@ public class ExtJmol extends JalviewJmolBinding
   {
     // This never gets called because we haven't overriden the associated Jmol's
     // console
-    System.err
-            .println("WARNING: unexpected call to ExtJmol's showConsole method. (showConsole="
+    System.err.println(
+            "WARNING: unexpected call to ExtJmol's showConsole method. (showConsole="
                     + show);
   }
 
index 72fa982..5a073c6 100644 (file)
@@ -42,6 +42,8 @@ import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.AdjustmentEvent;
 import java.awt.event.AdjustmentListener;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
 import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
 import java.awt.event.MouseEvent;
@@ -156,8 +158,8 @@ public class FeatureColourChooser extends Panel implements ActionListener,
     } catch (Exception ex)
     {
     }
-    threshold.select(cs.isAboveThreshold() ? 1 : (cs.isBelowThreshold() ? 2
-            : 0));
+    threshold.select(
+            cs.isAboveThreshold() ? 1 : (cs.isBelowThreshold() ? 2 : 0));
 
     adjusting = false;
     changeColour(true);
@@ -165,9 +167,9 @@ public class FeatureColourChooser extends Panel implements ActionListener,
     slider.addAdjustmentListener(this);
     slider.addMouseListener(this);
     owner = (af != null) ? af : fs.frame;
-    frame = new JVDialog(owner, MessageManager.formatMessage(
-            "label.graduated_color_for_params", new String[] { type }),
-            true, 480, 248);
+    frame = new JVDialog(owner, MessageManager
+            .formatMessage("label.graduated_color_for_params", new String[]
+            { type }), true, 480, 248);
     frame.setMainPanel(this);
     validate();
     frame.setVisible(true);
@@ -196,8 +198,8 @@ public class FeatureColourChooser extends Panel implements ActionListener,
 
   private void jbInit() throws Exception
   {
-    Label minLabel = new Label(MessageManager.getString("label.min")), maxLabel = new Label(
-            MessageManager.getString("label.max"));
+    Label minLabel = new Label(MessageManager.getString("label.min")),
+            maxLabel = new Label(MessageManager.getString("label.max"));
     minLabel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
     maxLabel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
     // minColour.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
@@ -232,6 +234,14 @@ public class FeatureColourChooser extends Panel implements ActionListener,
     threshold.addItem(MessageManager
             .getString("label.threshold_feature_below_threshold"));
     thresholdValue.addActionListener(this);
+    thresholdValue.addFocusListener(new FocusAdapter()
+    {
+      @Override
+      public void focusLost(FocusEvent e)
+      {
+        thresholdValue_actionPerformed();
+      }
+    });
     slider.setBackground(Color.white);
     slider.setEnabled(false);
     slider.setSize(new Dimension(93, 21));
@@ -243,13 +253,13 @@ public class FeatureColourChooser extends Panel implements ActionListener,
     jPanel3.setBackground(Color.white);
 
     colourFromLabel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
-    colourFromLabel.setLabel(MessageManager
-            .getString("label.colour_by_label"));
+    colourFromLabel
+            .setLabel(MessageManager.getString("label.colour_by_label"));
     colourFromLabel.setSize(new Dimension(139, 22));
     // threshold.setBounds(new Rectangle(11, 3, 139, 22));
     thresholdIsMin.setBackground(Color.white);
-    thresholdIsMin.setLabel(MessageManager
-            .getString("label.threshold_minmax"));
+    thresholdIsMin
+            .setLabel(MessageManager.getString("label.threshold_minmax"));
     thresholdIsMin.setSize(new Dimension(135, 23));
     // thresholdIsMin.setBounds(new Rectangle(328, 3, 135, 23));
     jPanel1.add(minLabel);
@@ -272,19 +282,7 @@ public class FeatureColourChooser extends Panel implements ActionListener,
   {
     if (evt.getSource() == thresholdValue)
     {
-      try
-      {
-        float f = new Float(thresholdValue.getText()).floatValue();
-        slider.setValue((int) (f * SCALE_FACTOR_1K));
-        adjustmentValueChanged(null);
-
-        /*
-         * force repaint of any Overview window or structure
-         */
-        changeColour(true);
-      } catch (NumberFormatException ex)
-      {
-      }
+      thresholdValue_actionPerformed();
     }
     else if (evt.getSource() == minColour)
     {
@@ -300,6 +298,26 @@ public class FeatureColourChooser extends Panel implements ActionListener,
     }
   }
 
+  /**
+   * Action on input of a value for colour score threshold
+   */
+  protected void thresholdValue_actionPerformed()
+  {
+    try
+    {
+      float f = new Float(thresholdValue.getText()).floatValue();
+      slider.setValue((int) (f * SCALE_FACTOR_1K));
+      adjustmentValueChanged(null);
+
+      /*
+       * force repaint of any Overview window or structure
+       */
+      changeColour(true);
+    } catch (NumberFormatException ex)
+    {
+    }
+  }
+
   @Override
   public void itemStateChanged(ItemEvent evt)
   {
@@ -338,9 +356,9 @@ public class FeatureColourChooser extends Panel implements ActionListener,
   {
     if (newCol == null)
     {
-      new UserDefinedColours(this,
-              minColour.getBackground(), owner,
-              MessageManager.getString("label.select_colour_minimum_value"));
+      new UserDefinedColours(this, minColour.getBackground(), owner,
+              MessageManager
+                      .getString("label.select_colour_minimum_value"));
     }
     else
     {
@@ -356,9 +374,9 @@ public class FeatureColourChooser extends Panel implements ActionListener,
   {
     if (newCol == null)
     {
-      new UserDefinedColours(this,
-              maxColour.getBackground(), owner,
-              MessageManager.getString("label.select_colour_maximum_value"));
+      new UserDefinedColours(this, maxColour.getBackground(), owner,
+              MessageManager
+                      .getString("label.select_colour_maximum_value"));
     }
     else
     {
@@ -416,8 +434,10 @@ public class FeatureColourChooser extends Panel implements ActionListener,
       adjusting = false;
     }
 
-    acg.setAboveThreshold(thresholdOption == AnnotationColourGradient.ABOVE_THRESHOLD);
-    acg.setBelowThreshold(thresholdOption == AnnotationColourGradient.BELOW_THRESHOLD);
+    acg.setAboveThreshold(
+            thresholdOption == AnnotationColourGradient.ABOVE_THRESHOLD);
+    acg.setBelowThreshold(
+            thresholdOption == AnnotationColourGradient.BELOW_THRESHOLD);
 
     if (thresholdIsMin.getState()
             && thresholdOption != AnnotationColourGradient.NO_THRESHOLD)
index 3c2715f..df407d6 100644 (file)
@@ -61,8 +61,8 @@ import java.util.List;
  * @author $author$
  * @version $Revision$
  */
-public class FeatureRenderer extends
-        jalview.renderer.seqfeatures.FeatureRenderer
+public class FeatureRenderer
+        extends jalview.renderer.seqfeatures.FeatureRenderer
 {
   /*
    * creating a new feature defaults to the type and group as
@@ -269,8 +269,8 @@ public class FeatureRenderer extends
           FeatureColourI col = getFeatureStyle(name.getText());
           if (col == null)
           {
-            Color generatedColour = ColorUtils.createColourFromName(name
-                    .getText());
+            Color generatedColour = ColorUtils
+                    .createColourFromName(name.getText());
             col = new FeatureColour(generatedColour);
           }
 
@@ -285,17 +285,20 @@ public class FeatureRenderer extends
 
     tmp = new Panel();
     panel.add(tmp);
-    tmp.add(new Label(MessageManager.getString("label.name:"), Label.RIGHT));
+    tmp.add(new Label(MessageManager.getString("label.name:"),
+            Label.RIGHT));
     tmp.add(name);
 
     tmp = new Panel();
     panel.add(tmp);
-    tmp.add(new Label(MessageManager.getString("label.group:"), Label.RIGHT));
+    tmp.add(new Label(MessageManager.getString("label.group:"),
+            Label.RIGHT));
     tmp.add(group);
 
     tmp = new Panel();
     panel.add(tmp);
-    tmp.add(new Label(MessageManager.getString("label.colour"), Label.RIGHT));
+    tmp.add(new Label(MessageManager.getString("label.colour"),
+            Label.RIGHT));
     tmp.add(colourPanel);
 
     bigPanel.add(panel, BorderLayout.NORTH);
@@ -330,15 +333,16 @@ public class FeatureRenderer extends
      */
     SequenceFeature firstFeature = features.get(0);
     boolean useLastDefaults = firstFeature.getType() == null;
-    String featureType = useLastDefaults ? lastFeatureAdded : firstFeature
-            .getType();
+    String featureType = useLastDefaults ? lastFeatureAdded
+            : firstFeature.getType();
     String featureGroup = useLastDefaults ? lastFeatureGroupAdded
             : firstFeature.getFeatureGroup();
 
-    String title = create ? MessageManager
-            .getString("label.create_new_sequence_features")
+    String title = create
+            ? MessageManager.getString("label.create_new_sequence_features")
             : MessageManager.formatMessage("label.amend_delete_features",
-                    new String[] { sequences.get(0).getName() });
+                    new String[]
+                    { sequences.get(0).getName() });
 
     final JVDialog dialog = new JVDialog(ap.alignFrame, title, true, 385,
             240);
@@ -395,11 +399,14 @@ public class FeatureRenderer extends
     /*
      * only update default type and group if we used defaults
      */
-    String enteredType = name.getText().trim();
+    final String enteredType = name.getText().trim();
+    final String enteredGroup = group.getText().trim();
+    final String enteredDesc = description.getText().replace('\n', ' ');
+
     if (dialog.accept && useLastDefaults)
     {
       lastFeatureAdded = enteredType;
-      lastFeatureGroupAdded = group.getText().trim();
+      lastFeatureGroupAdded = enteredGroup;
     }
 
     if (!create)
@@ -407,28 +414,36 @@ public class FeatureRenderer extends
       SequenceFeature sf = features.get(featureIndex);
       if (dialog.accept)
       {
-        sf.type = enteredType;
-        sf.featureGroup = group.getText().trim();
-        if (sf.featureGroup != null && sf.featureGroup.length() < 1)
-        {
-          sf.featureGroup = null;
-        }
-        sf.description = description.getText().replace('\n', ' ');
         if (!colourPanel.isGcol)
         {
           // update colour - otherwise its already done.
-          setColour(sf.type, new FeatureColour(colourPanel.getBackground()));
+          setColour(enteredType,
+                  new FeatureColour(colourPanel.getBackground()));
         }
+        int newBegin = sf.begin;
+        int newEnd = sf.end;
         try
         {
-          sf.begin = Integer.parseInt(start.getText());
-          sf.end = Integer.parseInt(end.getText());
+          newBegin = Integer.parseInt(start.getText());
+          newEnd = Integer.parseInt(end.getText());
         } catch (NumberFormatException ex)
         {
-          //
+          // 
         }
-        boolean typeOrGroupChanged = (!featureType.equals(sf.type) || !featureGroup
-                .equals(sf.featureGroup));
+
+        /*
+         * replace the feature by deleting it and adding a new one
+         * (to ensure integrity of SequenceFeatures data store)
+         */
+        sequences.get(0).deleteFeature(sf);
+        SequenceFeature newSf = new SequenceFeature(sf, enteredType,
+                newBegin, newEnd, enteredGroup, sf.getScore());
+        newSf.setDescription(enteredDesc);
+        ffile.parseDescriptionHTML(newSf, false);
+        // amend features dialog only updates one sequence at a time
+        sequences.get(0).addSequenceFeature(newSf);
+        boolean typeOrGroupChanged = (!featureType.equals(newSf.getType()) || !featureGroup
+                .equals(newSf.getFeatureGroup()));
 
         ffile.parseDescriptionHTML(sf, false);
         if (typeOrGroupChanged)
@@ -452,12 +467,11 @@ public class FeatureRenderer extends
       {
         for (int i = 0; i < sequences.size(); i++)
         {
-          features.get(i).type = enteredType;
-          features.get(i).featureGroup = group.getText().trim();
-          features.get(i).description = description.getText()
-                  .replace('\n', ' ');
-          sequences.get(i).addSequenceFeature(features.get(i));
-          ffile.parseDescriptionHTML(features.get(i), false);
+          SequenceFeature sf = features.get(i);
+          SequenceFeature sf2 = new SequenceFeature(enteredType,
+                  enteredDesc, sf.getBegin(), sf.getEnd(), enteredGroup);
+          ffile.parseDescriptionHTML(sf2, false);
+          sequences.get(i).addSequenceFeature(sf2);
         }
 
         Color newColour = colourPanel.getBackground();
@@ -479,7 +493,7 @@ public class FeatureRenderer extends
     }
     // findAllFeatures();
 
-    ap.paintAlignment(true);
+    ap.paintAlignment(true, true);
 
     return true;
   }
index 7d00afd..9a67499 100755 (executable)
@@ -23,7 +23,7 @@ package jalview.appletgui;
 import jalview.api.FeatureColourI;
 import jalview.api.FeatureSettingsControllerI;
 import jalview.datamodel.AlignmentI;
-import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceI;
 import jalview.util.MessageManager;
 
 import java.awt.BorderLayout;
@@ -56,17 +56,16 @@ import java.awt.event.MouseListener;
 import java.awt.event.MouseMotionListener;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
+import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.Vector;
 
-public class FeatureSettings extends Panel implements ItemListener,
-        MouseListener, MouseMotionListener, ActionListener,
-        AdjustmentListener, FeatureSettingsControllerI
+public class FeatureSettings extends Panel
+        implements ItemListener, MouseListener, MouseMotionListener,
+        ActionListener, AdjustmentListener, FeatureSettingsControllerI
 {
   FeatureRenderer fr;
 
@@ -136,11 +135,18 @@ public class FeatureSettings extends Panel implements ItemListener,
 
     add(lowerPanel, BorderLayout.SOUTH);
 
-    groupPanel.setLayout(new GridLayout(
-            (fr.getFeatureGroupsSize()) / 4 + 1, 4)); // JBPNote - this was
-                                                      // scaled on number of
-                                                      // visible groups. seems
-                                                      // broken
+    groupPanel.setLayout(
+            new GridLayout((fr.getFeatureGroupsSize()) / 4 + 1, 4)); // JBPNote
+                                                                     // - this
+                                                                     // was
+                                                                     // scaled
+                                                                     // on
+                                                                     // number
+                                                                     // of
+                                                                     // visible
+                                                                     // groups.
+                                                                     // seems
+                                                                     // broken
     groupPanel.validate();
 
     add(groupPanel, BorderLayout.NORTH);
@@ -175,14 +181,12 @@ public class FeatureSettings extends Panel implements ItemListener,
   public void paint(Graphics g)
   {
     g.setColor(Color.black);
-    g.drawString(MessageManager
-            .getString("label.no_features_added_to_this_alignment"), 10, 20);
-    g.drawString(MessageManager
-            .getString("label.features_can_be_added_from_searches_1"), 10,
-            40);
-    g.drawString(MessageManager
-            .getString("label.features_can_be_added_from_searches_2"), 10,
-            60);
+    g.drawString(MessageManager.getString(
+            "label.no_features_added_to_this_alignment"), 10, 20);
+    g.drawString(MessageManager.getString(
+            "label.features_can_be_added_from_searches_1"), 10, 40);
+    g.drawString(MessageManager.getString(
+            "label.features_can_be_added_from_searches_2"), 10, 60);
   }
 
   protected void popupSort(final MyCheckbox check,
@@ -190,8 +194,9 @@ public class FeatureSettings extends Panel implements ItemListener,
   {
     final String type = check.type;
     final FeatureColourI typeCol = fr.getFeatureStyle(type);
-    PopupMenu men = new PopupMenu(MessageManager.formatMessage(
-            "label.settings_for_type", new String[] { type }));
+    PopupMenu men = new PopupMenu(MessageManager
+            .formatMessage("label.settings_for_type", new String[]
+            { type }));
     java.awt.MenuItem scr = new MenuItem(
             MessageManager.getString("label.sort_by_score"));
     men.add(scr);
@@ -202,8 +207,9 @@ public class FeatureSettings extends Panel implements ItemListener,
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        me.ap.alignFrame.avc.sortAlignmentByFeatureScore(Arrays
-                .asList(new String[] { type }));
+        me.ap.alignFrame.avc
+                .sortAlignmentByFeatureScore(Arrays.asList(new String[]
+                { type }));
       }
 
     });
@@ -215,8 +221,9 @@ public class FeatureSettings extends Panel implements ItemListener,
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        me.ap.alignFrame.avc.sortAlignmentByFeatureDensity(Arrays
-                .asList(new String[] { type }));
+        me.ap.alignFrame.avc
+                .sortAlignmentByFeatureDensity(Arrays.asList(new String[]
+                { type }));
       }
 
     });
@@ -280,8 +287,8 @@ public class FeatureSettings extends Panel implements ItemListener,
     });
     men.add(selectContaining);
 
-    MenuItem selectNotContaining = new MenuItem(
-            MessageManager.getString("label.select_columns_not_containing"));
+    MenuItem selectNotContaining = new MenuItem(MessageManager
+            .getString("label.select_columns_not_containing"));
     selectNotContaining.addActionListener(new ActionListener()
     {
       @Override
@@ -370,36 +377,38 @@ public class FeatureSettings extends Panel implements ItemListener,
   // Group selection states
   void resetTable(boolean groupsChanged)
   {
-    SequenceFeature[] tmpfeatures;
-    String group = null, type;
-    Vector<String> visibleChecks = new Vector<String>();
-    Set<String> foundGroups = new HashSet<String>();
+    List<String> displayableTypes = new ArrayList<>();
+    Set<String> foundGroups = new HashSet<>();
+
     AlignmentI alignment = av.getAlignment();
 
     for (int i = 0; i < alignment.getHeight(); i++)
     {
-      if (alignment.getSequenceAt(i).getSequenceFeatures() == null)
-      {
-        continue;
-      }
+      SequenceI seq = alignment.getSequenceAt(i);
 
-      tmpfeatures = alignment.getSequenceAt(i).getSequenceFeatures();
-      int index = 0;
-      while (index < tmpfeatures.length)
+      /*
+       * get the sequence's groups for positional features
+       * and keep track of which groups are visible
+       */
+      Set<String> groups = seq.getFeatures().getFeatureGroups(true);
+      Set<String> visibleGroups = new HashSet<>();
+      for (String group : groups)
       {
-        group = tmpfeatures[index].featureGroup;
-        foundGroups.add(group);
-
+        // if (group == null || fr.checkGroupVisibility(group, true))
         if (group == null || checkGroupState(group))
         {
-          type = tmpfeatures[index].getType();
-          if (!visibleChecks.contains(type))
-          {
-            visibleChecks.addElement(type);
-          }
+          visibleGroups.add(group);
         }
-        index++;
       }
+      foundGroups.addAll(groups);
+
+      /*
+       * get distinct feature types for visible groups
+       * record distinct visible types
+       */
+      Set<String> types = seq.getFeatures().getFeatureTypesForGroups(true,
+              visibleGroups.toArray(new String[visibleGroups.size()]));
+      displayableTypes.addAll(types);
     }
 
     /*
@@ -416,7 +425,7 @@ public class FeatureSettings extends Panel implements ItemListener,
     {
       comps = featurePanel.getComponents();
       check = (MyCheckbox) comps[i];
-      if (!visibleChecks.contains(check.type))
+      if (!displayableTypes.contains(check.type))
       {
         featurePanel.remove(i);
         cSize--;
@@ -433,28 +442,28 @@ public class FeatureSettings extends Panel implements ItemListener,
       {
         String item = rol.get(ro);
 
-        if (!visibleChecks.contains(item))
+        if (!displayableTypes.contains(item))
         {
           continue;
         }
 
-        visibleChecks.removeElement(item);
+        displayableTypes.remove(item);
 
         addCheck(false, item);
       }
     }
 
-    // now add checkboxes which should be visible,
-    // if they have not already been added
-    Enumeration<String> en = visibleChecks.elements();
-
-    while (en.hasMoreElements())
+    /*
+     * now add checkboxes which should be visible,
+     * if they have not already been added
+     */
+    for (String type : displayableTypes)
     {
-      addCheck(groupsChanged, en.nextElement().toString());
+      addCheck(groupsChanged, type);
     }
 
-    featurePanel.setLayout(new GridLayout(featurePanel.getComponentCount(),
-            1, 10, 5));
+    featurePanel.setLayout(
+            new GridLayout(featurePanel.getComponentCount(), 1, 10, 5));
     featurePanel.validate();
 
     if (scrollPane != null)
@@ -591,7 +600,7 @@ public class FeatureSettings extends Panel implements ItemListener,
 
     fr.setFeaturePriority(data);
 
-    ap.paintAlignment(updateOverview);
+    ap.paintAlignment(updateOverview, updateOverview);
   }
 
   MyCheckbox selectedCheck;
@@ -633,8 +642,8 @@ public class FeatureSettings extends Panel implements ItemListener,
     }
     else
     {
-      comp = featurePanel.getComponentAt(evt.getX(), evt.getY()
-              + evt.getComponent().getLocation().y);
+      comp = featurePanel.getComponentAt(evt.getX(),
+              evt.getY() + evt.getComponent().getLocation().y);
     }
 
     if (comp != null && comp instanceof Checkbox)
@@ -671,7 +680,7 @@ public class FeatureSettings extends Panel implements ItemListener,
   {
     featurePanel.removeAll();
     resetTable(false);
-    ap.paintAlignment(true);
+    ap.paintAlignment(true, true);
   }
 
   @Override
@@ -723,7 +732,7 @@ public class FeatureSettings extends Panel implements ItemListener,
   public void adjustmentValueChanged(AdjustmentEvent evt)
   {
     fr.setTransparency((100 - transparency.getValue()) / 100f);
-    ap.paintAlignment(true);
+    ap.paintAlignment(true, true);
   }
 
   class MyCheckbox extends Checkbox
index f7ebab6..675b862 100644 (file)
@@ -122,9 +122,8 @@ public class Finder extends Panel implements ActionListener
     for (SearchResultMatchI match : searchResults.getResults())
     {
       seqs.add(match.getSequence().getDatasetSequence());
-      features.add(new SequenceFeature(searchString,
-              "Search Results", null, match.getStart(), match.getEnd(),
- "Search Results"));
+      features.add(new SequenceFeature(searchString, "Search Results",
+              match.getStart(), match.getEnd(), "Search Results"));
     }
 
     if (ap.seqPanel.seqCanvas.getFeatureRenderer().amendFeatures(seqs,
@@ -187,8 +186,8 @@ public class Finder extends Panel implements ActionListener
     // 'SelectRegion' selection
     if (!haveResults)
     {
-      ap.alignFrame.statusBar.setText(MessageManager
-              .getString("label.finished_searching"));
+      ap.alignFrame.statusBar.setText(
+              MessageManager.getString("label.finished_searching"));
       resIndex = -1;
       seqIndex = 0;
     }
@@ -196,8 +195,8 @@ public class Finder extends Panel implements ActionListener
     {
       if (findAll)
       {
-        String message = (idMatch.size() > 0) ? "" + idMatch.size()
-                + " IDs" : "";
+        String message = (idMatch.size() > 0) ? "" + idMatch.size() + " IDs"
+                : "";
         if (idMatch.size() > 0 && searchResults != null
                 && searchResults.getSize() > 0)
         {
@@ -207,16 +206,17 @@ public class Finder extends Panel implements ActionListener
         {
           message += searchResults.getSize() + " subsequence matches.";
         }
-        ap.alignFrame.statusBar.setText(MessageManager.formatMessage(
-                "label.search_results", new String[] { searchString,
-                    message }));
+        ap.alignFrame.statusBar.setText(MessageManager
+                .formatMessage("label.search_results", new String[]
+                { searchString, message }));
 
       }
       else
       {
         // TODO: indicate sequence and matching position in status bar
-        ap.alignFrame.statusBar.setText(MessageManager.formatMessage(
-                "label.found_match_for", new String[] { searchString }));
+        ap.alignFrame.statusBar.setText(MessageManager
+                .formatMessage("label.found_match_for", new String[]
+                { searchString }));
       }
     }
   }
@@ -276,8 +276,8 @@ public class Finder extends Panel implements ActionListener
     caseSensitive.setLabel(MessageManager.getString("label.match_case"));
     caseSensitive.setBounds(new Rectangle(30, 39, 126, 23));
 
-    searchDescription.setLabel(MessageManager
-            .getString("label.include_description"));
+    searchDescription.setLabel(
+            MessageManager.getString("label.include_description"));
     searchDescription.setBounds(new Rectangle(30, 59, 170, 23));
     actionsPanel.add(findNext, null);
     actionsPanel.add(findAll, null);
index 991fb96..443ebce 100644 (file)
@@ -261,7 +261,7 @@ public class FontChooser extends Panel implements ItemListener
       {
         ap.av.setCharWidth(oldCharWidth);
       }
-      ap.paintAlignment(true);
+      ap.paintAlignment(true, false);
     }
     else if (tp != null)
     {
@@ -290,11 +290,11 @@ public class FontChooser extends Panel implements ItemListener
     }
 
     Font newFont = new Font(fontName.getSelectedItem().toString(),
-            fontStyle.getSelectedIndex(), Integer.parseInt(fontSize
-                    .getSelectedItem().toString()));
+            fontStyle.getSelectedIndex(),
+            Integer.parseInt(fontSize.getSelectedItem().toString()));
     FontMetrics fm = getGraphics().getFontMetrics(newFont);
-    double mw = fm.getStringBounds("M", getGraphics()).getWidth(), iw = fm
-            .getStringBounds("I", getGraphics()).getWidth();
+    double mw = fm.getStringBounds("M", getGraphics()).getWidth(),
+            iw = fm.getStringBounds("I", getGraphics()).getWidth();
     if (mw < 1 || iw < 1)
     {
       // TODO: JAL-1100
@@ -481,8 +481,8 @@ public class FontChooser extends Panel implements ItemListener
   protected void scaleAsCdna_actionPerformed()
   {
     ap.av.setScaleProteinAsCdna(scaleAsCdna.getState());
-    ap.av.getCodingComplement().setScaleProteinAsCdna(
-            scaleAsCdna.getState());
+    ap.av.getCodingComplement()
+            .setScaleProteinAsCdna(scaleAsCdna.getState());
     changeFont();
   }
 
index 48c0c40..f5ea12e 100755 (executable)
@@ -118,7 +118,7 @@ public class IdCanvas extends Panel implements ViewportListenerI
       ss = es - vertical;
       if (ss < ranges.getStartSeq()) // ie scrolling too fast, more than a page
                                      // at a
-                                 // time
+      // time
       {
         ss = ranges.getStartSeq();
       }
@@ -183,8 +183,8 @@ public class IdCanvas extends Panel implements ViewportListenerI
 
     // Fill in the background
     gg.setColor(Color.white);
-    Font italic = new Font(av.getFont().getName(), Font.ITALIC, av
-            .getFont().getSize());
+    Font italic = new Font(av.getFont().getName(), Font.ITALIC,
+            av.getFont().getSize());
     gg.setFont(italic);
 
     gg.fillRect(0, 0, getSize().width, getSize().height);
@@ -224,8 +224,8 @@ public class IdCanvas extends Panel implements ViewportListenerI
         continue;
       }
       // hardwired italic IDs in applet currently
-      Font italic = new Font(av.getFont().getName(), Font.ITALIC, av
-              .getFont().getSize());
+      Font italic = new Font(av.getFont().getName(), Font.ITALIC,
+              av.getFont().getSize());
       gg.setFont(italic);
       // boolean isrep=false;
       if (doHiddenCheck)
@@ -309,8 +309,8 @@ public class IdCanvas extends Panel implements ViewportListenerI
     int rowSize = av.getRanges().getViewportWidth();
 
     // hardwired italic IDs in applet currently
-    Font italic = new Font(av.getFont().getName(), Font.ITALIC, av
-            .getFont().getSize());
+    Font italic = new Font(av.getFont().getName(), Font.ITALIC,
+            av.getFont().getSize());
     gg.setFont(italic);
 
     /*
@@ -352,7 +352,8 @@ public class IdCanvas extends Panel implements ViewportListenerI
 
   void drawMarker(int i, int starty, int yoffset)
   {
-    SequenceI[] hseqs = av.getAlignment().getHiddenSequences().hiddenSequences;
+    SequenceI[] hseqs = av.getAlignment()
+            .getHiddenSequences().hiddenSequences;
     // Use this method here instead of calling hiddenSeq adjust
     // 3 times.
     int hSize = hseqs.length;
@@ -386,27 +387,36 @@ public class IdCanvas extends Panel implements ViewportListenerI
     gg.setColor(Color.blue);
     if (below)
     {
-      gg.fillPolygon(new int[] { getSize().width - avcharHeight,
-          getSize().width - avcharHeight, getSize().width }, new int[] {
-          (i - starty) * avcharHeight + yoffset,
-          (i - starty) * avcharHeight + yoffset + avcharHeight / 4,
-          (i - starty) * avcharHeight + yoffset }, 3);
+      gg.fillPolygon(
+              new int[]
+              { getSize().width - avcharHeight,
+                  getSize().width - avcharHeight, getSize().width },
+              new int[]
+              { (i - starty) * avcharHeight + yoffset,
+                  (i - starty) * avcharHeight + yoffset + avcharHeight / 4,
+                  (i - starty) * avcharHeight + yoffset },
+              3);
     }
     if (above)
     {
-      gg.fillPolygon(new int[] { getSize().width - avcharHeight,
-          getSize().width - avcharHeight, getSize().width }, new int[] {
-          (i - starty + 1) * avcharHeight + yoffset,
-          (i - starty + 1) * avcharHeight + yoffset - avcharHeight / 4,
-          (i - starty + 1) * avcharHeight + yoffset }, 3);
+      gg.fillPolygon(
+              new int[]
+              { getSize().width - avcharHeight,
+                  getSize().width - avcharHeight, getSize().width },
+              new int[]
+              { (i - starty + 1) * avcharHeight + yoffset,
+                  (i - starty + 1) * avcharHeight + yoffset
+                          - avcharHeight / 4,
+                  (i - starty + 1) * avcharHeight + yoffset },
+              3);
 
     }
   }
 
   boolean setHiddenFont(SequenceI seq)
   {
-    Font bold = new Font(av.getFont().getName(), Font.BOLD, av.getFont()
-            .getSize());
+    Font bold = new Font(av.getFont().getName(), Font.BOLD,
+            av.getFont().getSize());
 
     if (av.isReferenceSeq(seq) || av.isHiddenRepSequence(seq))
     {
@@ -433,10 +443,19 @@ public class IdCanvas extends Panel implements ViewportListenerI
   {
     String propertyName = evt.getPropertyName();
     if (propertyName.equals(ViewportRanges.STARTSEQ)
-            || (av.getWrapAlignment() && propertyName
-                    .equals(ViewportRanges.STARTRES)))
+            || (av.getWrapAlignment()
+                    && propertyName.equals(ViewportRanges.STARTRES)))
     {
       fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
     }
+    else if (propertyName.equals(ViewportRanges.STARTRESANDSEQ))
+    {
+      fastPaint(((int[]) evt.getNewValue())[1]
+              - ((int[]) evt.getOldValue())[1]);
+    }
+    else if (propertyName.equals(ViewportRanges.MOVE_VIEWPORT))
+    {
+      repaint();
+    }
   }
 }
index 66eb053..15e269c 100755 (executable)
@@ -20,7 +20,6 @@
  */
 package jalview.appletgui;
 
-import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
@@ -39,8 +38,8 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 
-public class IdPanel extends Panel implements MouseListener,
-        MouseMotionListener
+public class IdPanel extends Panel
+        implements MouseListener, MouseMotionListener
 {
 
   protected IdCanvas idCanvas;
@@ -57,11 +56,11 @@ public class IdPanel extends Panel implements MouseListener,
 
   UrlProviderI urlProvider = null;
 
-  public IdPanel(AlignViewport av, AlignmentPanel parent)
+  public IdPanel(AlignViewport viewport, AlignmentPanel parent)
   {
-    this.av = av;
+    this.av = viewport;
     alignPanel = parent;
-    idCanvas = new IdCanvas(av);
+    idCanvas = new IdCanvas(viewport);
     setLayout(new BorderLayout());
     add(idCanvas, BorderLayout.CENTER);
     idCanvas.addMouseListener(this);
@@ -71,13 +70,13 @@ public class IdPanel extends Panel implements MouseListener,
     // TODO: add in group link parameter
 
     // make a list of label,url pairs
-    HashMap<String, String> urlList = new HashMap<String, String>();
-    if (av.applet != null)
+    HashMap<String, String> urlList = new HashMap<>();
+    if (viewport.applet != null)
     {
       for (int i = 1; i < 10; i++)
       {
-        label = av.applet.getParameter("linkLabel_" + i);
-        url = av.applet.getParameter("linkURL_" + i);
+        label = viewport.applet.getParameter("linkLabel_" + i);
+        url = viewport.applet.getParameter("linkURL_" + i);
 
         // only add non-null parameters
         if (label != null)
@@ -89,7 +88,7 @@ public class IdPanel extends Panel implements MouseListener,
       if (!urlList.isEmpty())
       {
         // set default as first entry in list
-        String defaultUrl = av.applet.getParameter("linkLabel_1");
+        String defaultUrl = viewport.applet.getParameter("linkLabel_1");
         UrlProviderFactoryI factory = new AppletUrlProviderFactory(
                 defaultUrl, urlList);
         urlProvider = factory.createUrlProvider();
@@ -106,64 +105,57 @@ public class IdPanel extends Panel implements MouseListener,
 
     SequenceI sequence = av.getAlignment().getSequenceAt(seq);
 
-    // look for non-pos features
     StringBuffer tooltiptext = new StringBuffer();
-    if (sequence != null)
+    if (sequence == null)
     {
-      if (sequence.getDescription() != null)
+      return;
+    }
+    if (sequence.getDescription() != null)
+    {
+      tooltiptext.append(sequence.getDescription());
+      tooltiptext.append("\n");
+    }
+
+    for (SequenceFeature sf : sequence.getFeatures()
+            .getNonPositionalFeatures())
+    {
+      boolean nl = false;
+      if (sf.getFeatureGroup() != null)
       {
-        tooltiptext.append(sequence.getDescription());
-        tooltiptext.append("\n");
+        tooltiptext.append(sf.getFeatureGroup());
+        nl = true;
       }
-
-      SequenceFeature sf[] = sequence.getSequenceFeatures();
-      for (int sl = 0; sf != null && sl < sf.length; sl++)
+      if (sf.getType() != null)
       {
-        if (sf[sl].begin == sf[sl].end && sf[sl].begin == 0)
-        {
-          boolean nl = false;
-          if (sf[sl].getFeatureGroup() != null)
-          {
-            tooltiptext.append(sf[sl].getFeatureGroup());
-            nl = true;
-          }
-          ;
-          if (sf[sl].getType() != null)
-          {
-            tooltiptext.append(" ");
-            tooltiptext.append(sf[sl].getType());
-            nl = true;
-          }
-          ;
-          if (sf[sl].getDescription() != null)
-          {
-            tooltiptext.append(" ");
-            tooltiptext.append(sf[sl].getDescription());
-            nl = true;
-          }
-          ;
-          if (!Float.isNaN(sf[sl].getScore()) && sf[sl].getScore() != 0f)
-          {
-            tooltiptext.append(" Score = ");
-            tooltiptext.append(sf[sl].getScore());
-            nl = true;
-          }
-          ;
-          if (sf[sl].getStatus() != null && sf[sl].getStatus().length() > 0)
-          {
-            tooltiptext.append(" (");
-            tooltiptext.append(sf[sl].getStatus());
-            tooltiptext.append(")");
-            nl = true;
-          }
-          ;
-          if (nl)
-          {
-            tooltiptext.append("\n");
-          }
-        }
+        tooltiptext.append(" ");
+        tooltiptext.append(sf.getType());
+        nl = true;
+      }
+      if (sf.getDescription() != null)
+      {
+        tooltiptext.append(" ");
+        tooltiptext.append(sf.getDescription());
+        nl = true;
+      }
+      if (!Float.isNaN(sf.getScore()) && sf.getScore() != 0f)
+      {
+        tooltiptext.append(" Score = ");
+        tooltiptext.append(sf.getScore());
+        nl = true;
+      }
+      if (sf.getStatus() != null && sf.getStatus().length() > 0)
+      {
+        tooltiptext.append(" (");
+        tooltiptext.append(sf.getStatus());
+        tooltiptext.append(")");
+        nl = true;
+      }
+      if (nl)
+      {
+        tooltiptext.append("\n");
       }
     }
+
     if (tooltiptext.length() == 0)
     {
       // nothing to display - so clear tooltip if one is visible
@@ -177,13 +169,14 @@ public class IdPanel extends Panel implements MouseListener,
     }
     if (tooltip == null)
     {
-      tooltip = new Tooltip(sequence.getDisplayId(true) + "\n"
-              + tooltiptext.toString(), idCanvas);
+      tooltip = new Tooltip(
+              sequence.getDisplayId(true) + "\n" + tooltiptext.toString(),
+              idCanvas);
     }
     else
     {
-      tooltip.setTip(sequence.getDisplayId(true) + "\n"
-              + tooltiptext.toString());
+      tooltip.setTip(
+              sequence.getDisplayId(true) + "\n" + tooltiptext.toString());
     }
     tooltiptext = null;
   }
@@ -205,7 +198,7 @@ public class IdPanel extends Panel implements MouseListener,
     }
 
     lastid = seq;
-    alignPanel.paintAlignment(false);
+    alignPanel.paintAlignment(false, false);
   }
 
   @Override
@@ -286,12 +279,15 @@ public class IdPanel extends Panel implements MouseListener,
 
     int seq = alignPanel.seqPanel.findSeq(e);
 
-    if ((e.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
+    if ((e.getModifiers()
+            & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
     {
-      Sequence sq = (Sequence) av.getAlignment().getSequenceAt(seq);
+      SequenceI sq = av.getAlignment().getSequenceAt(seq);
 
-      // build a new links menu based on the current links + any non-positional
-      // features
+      /*
+       *  build a new links menu based on the current links
+       *  and any non-positional features
+       */
       List<String> nlinks;
       if (urlProvider != null)
       {
@@ -299,19 +295,16 @@ public class IdPanel extends Panel implements MouseListener,
       }
       else
       {
-        nlinks = new ArrayList<String>();
+        nlinks = new ArrayList<>();
       }
-      SequenceFeature sf[] = sq == null ? null : sq.getSequenceFeatures();
-      for (int sl = 0; sf != null && sl < sf.length; sl++)
+
+      for (SequenceFeature sf : sq.getFeatures().getNonPositionalFeatures())
       {
-        if (sf[sl].begin == sf[sl].end && sf[sl].begin == 0)
+        if (sf.links != null)
         {
-          if (sf[sl].links != null && sf[sl].links.size() > 0)
+          for (String link : sf.links)
           {
-            for (int l = 0, lSize = sf[sl].links.size(); l < lSize; l++)
-            {
-              nlinks.add(sf[sl].links.elementAt(l));
-            }
+            nlinks.add(link);
           }
         }
       }
@@ -323,8 +316,8 @@ public class IdPanel extends Panel implements MouseListener,
     }
 
     if ((av.getSelectionGroup() == null)
-            || ((!jalview.util.Platform.isControlDown(e) && !e
-                    .isShiftDown()) && av.getSelectionGroup() != null))
+            || ((!jalview.util.Platform.isControlDown(e)
+                    && !e.isShiftDown()) && av.getSelectionGroup() != null))
     {
       av.setSelectionGroup(new SequenceGroup());
       av.getSelectionGroup().setStartRes(0);
@@ -340,7 +333,7 @@ public class IdPanel extends Panel implements MouseListener,
       selectSeq(seq);
     }
 
-    alignPanel.paintAlignment(false);
+    alignPanel.paintAlignment(false, false);
   }
 
   void selectSeq(int seq)
@@ -373,8 +366,8 @@ public class IdPanel extends Panel implements MouseListener,
     }
     for (int i = start; i <= end; i++)
     {
-      av.getSelectionGroup().addSequence(
-              av.getAlignment().getSequenceAt(i), i == end);
+      av.getSelectionGroup().addSequence(av.getAlignment().getSequenceAt(i),
+              i == end);
     }
 
   }
@@ -424,9 +417,9 @@ public class IdPanel extends Panel implements MouseListener,
 
     boolean up = true;
 
-    public ScrollThread(boolean up)
+    public ScrollThread(boolean isUp)
     {
-      this.up = up;
+      this.up = isUp;
       start();
     }
 
@@ -466,7 +459,7 @@ public class IdPanel extends Panel implements MouseListener,
           running = false;
         }
 
-        alignPanel.paintAlignment(true);
+        alignPanel.paintAlignment(true, false);
         try
         {
           Thread.sleep(100);
index b537112..75e3243 100755 (executable)
@@ -29,8 +29,8 @@ import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.awt.event.MouseMotionListener;
 
-public class IdwidthAdjuster extends Panel implements MouseListener,
-        MouseMotionListener
+public class IdwidthAdjuster extends Panel
+        implements MouseListener, MouseMotionListener
 {
   boolean active = false;
 
index a7cc83f..9853d98 100644 (file)
@@ -58,8 +58,8 @@ public class JVDialog extends Dialog implements ActionListener
             width, height);
   }
 
-  public JVDialog(Frame owner, Panel mainPanel, String title,
-          boolean modal, int width, int height)
+  public JVDialog(Frame owner, Panel mainPanel, String title, boolean modal,
+          int width, int height)
   {
     super(owner, title, modal);
     this.owner = owner;
index a0466d3..9597b44 100644 (file)
@@ -21,6 +21,7 @@
 package jalview.appletgui;
 
 import jalview.renderer.OverviewRenderer;
+import jalview.renderer.OverviewResColourFinder;
 import jalview.viewmodel.OverviewDimensions;
 
 import java.awt.Color;
@@ -48,10 +49,6 @@ public class OverviewCanvas extends Component
 
   private AlignViewport av;
 
-  // Can set different properties in this seqCanvas than
-  // main visible SeqCanvas
-  private SequenceRenderer sr;
-
   private jalview.renderer.seqfeatures.FeatureRenderer fr;
 
   private Frame nullFrame;
@@ -65,10 +62,6 @@ public class OverviewCanvas extends Component
     nullFrame = new Frame();
     nullFrame.addNotify();
 
-    sr = new SequenceRenderer(av);
-    sr.graphics = nullFrame.getGraphics();
-    sr.renderGaps = false;
-    sr.forOverview = true;
     fr = new jalview.renderer.seqfeatures.FeatureRenderer(av);
   }
 
@@ -119,7 +112,8 @@ public class OverviewCanvas extends Component
 
     setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
 
-    or = new OverviewRenderer(sr, fr, od);
+    or = new OverviewRenderer(fr, od, av.getAlignment(),
+            av.getResidueShading(), new OverviewResColourFinder());
     miniMe = nullFrame.createImage(od.getWidth(), od.getHeight());
     offscreen = nullFrame.createImage(od.getWidth(), od.getHeight());
 
index 456a38c..8ce597d 100755 (executable)
@@ -31,6 +31,7 @@ import java.awt.BorderLayout;
 import java.awt.CheckboxMenuItem;
 import java.awt.Cursor;
 import java.awt.Dimension;
+import java.awt.Frame;
 import java.awt.Panel;
 import java.awt.PopupMenu;
 import java.awt.event.ComponentAdapter;
@@ -67,7 +68,8 @@ public class OverviewPanel extends Panel implements Runnable,
     setLayout(null);
 
     od = new OverviewDimensionsShowHidden(av.getRanges(),
-            (av.isShowAnnotation() && av.getSequenceConsensusHash() != null));
+            (av.isShowAnnotation()
+                    && av.getSequenceConsensusHash() != null));
 
     oviewCanvas = new OverviewCanvas(od, av);
     setLayout(new BorderLayout());
@@ -112,7 +114,8 @@ public class OverviewPanel extends Panel implements Runnable,
   @Override
   public void mouseClicked(MouseEvent evt)
   {
-    if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
+    if ((evt.getModifiers()
+            & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
     {
       showPopupMenu(evt);
     }
@@ -146,11 +149,12 @@ public class OverviewPanel extends Panel implements Runnable,
     }
     else
     {
+      // don't do anything if the mouse press is in the overview's box
+      // (wait to see if it's a drag instead)
+      // otherwise update the viewport
       if (!od.isPositionInBox(evt.getX(), evt.getY()))
-      {
-        // don't do anything if the mouse press is in the overview's box
-        // (wait to see if it's a drag instead)
-        // otherwise update the viewport
+      { 
+       draggingBox = false;
         od.updateViewportFromMouse(evt.getX(), evt.getY(),
                 av.getAlignment().getHiddenSequences(),
                 av.getAlignment().getHiddenColumns());
@@ -168,16 +172,13 @@ public class OverviewPanel extends Panel implements Runnable,
   @Override
   public void mouseReleased(MouseEvent evt)
   {
-    if (draggingBox)
-    {
-      draggingBox = false;
-    }
   }
 
   @Override
   public void mouseDragged(MouseEvent evt)
   {
-    if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
+    if ((evt.getModifiers()
+            & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
     {
       if (!Platform.isAMac())
       {
@@ -200,7 +201,7 @@ public class OverviewPanel extends Panel implements Runnable,
                 av.getAlignment().getHiddenSequences(),
                 av.getAlignment().getHiddenColumns());
       }
-      ap.paintAlignment(false);
+      ap.paintAlignment(false, false);
     }
   }
 
@@ -244,8 +245,8 @@ public class OverviewPanel extends Panel implements Runnable,
   public void run()
   {
     oviewCanvas.draw(av.isShowSequenceFeatures(),
-            (av.isShowAnnotation() && av
-                    .getAlignmentConservationAnnotation() != null),
+            (av.isShowAnnotation()
+                    && av.getAlignmentConservationAnnotation() != null),
             ap.seqPanel.seqCanvas.getFeatureRenderer());
     setBoxPosition();
   }
@@ -257,9 +258,8 @@ public class OverviewPanel extends Panel implements Runnable,
    */
   private void setBoxPosition()
   {
-    od.setBoxPosition(av.getAlignment()
-.getHiddenSequences(), av
-            .getAlignment().getHiddenColumns());
+    od.setBoxPosition(av.getAlignment().getHiddenSequences(),
+            av.getAlignment().getHiddenColumns());
     repaint();
   }
 
@@ -301,15 +301,15 @@ public class OverviewPanel extends Panel implements Runnable,
     {
       showHidden = false;
       od = new OverviewDimensionsHideHidden(av.getRanges(),
-              (av.isShowAnnotation() && av
-                      .getAlignmentConservationAnnotation() != null));
+              (av.isShowAnnotation()
+                      && av.getAlignmentConservationAnnotation() != null));
     }
     else
     {
       showHidden = true;
       od = new OverviewDimensionsShowHidden(av.getRanges(),
-              (av.isShowAnnotation() && av
-                      .getAlignmentConservationAnnotation() != null));
+              (av.isShowAnnotation()
+                      && av.getAlignmentConservationAnnotation() != null));
     }
     oviewCanvas.resetOviewDims(od);
     updateOverviewImage();
@@ -323,6 +323,9 @@ public class OverviewPanel extends Panel implements Runnable,
     try
     {
       av.getRanges().removePropertyChangeListener(this);
+      Frame parent = (Frame) getParent();
+      parent.dispose();
+      parent.setVisible(false);
     } finally
     {
       av = null;
index 5dc57f9..fc1d359 100644 (file)
@@ -48,8 +48,8 @@ import java.awt.event.ActionListener;
 import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
 
-public class PCAPanel extends EmbmenuFrame implements Runnable,
-        ActionListener, ItemListener
+public class PCAPanel extends EmbmenuFrame
+        implements Runnable, ActionListener, ItemListener
 {
   RotatableCanvas rc;
 
@@ -88,7 +88,8 @@ public class PCAPanel extends EmbmenuFrame implements Runnable,
     }
     else
     {
-      seqs = viewport.getSelectionGroup().getSequencesInOrder(viewport.getAlignment());
+      seqs = viewport.getSelectionGroup()
+              .getSequencesInOrder(viewport.getAlignment());
     }
     SeqCigar sq[] = seqstrings.getSequences();
     int length = sq[0].getWidth();
@@ -103,8 +104,8 @@ public class PCAPanel extends EmbmenuFrame implements Runnable,
       }
     }
 
-    ScoreModelI scoreModel = ScoreModels.getInstance().getDefaultModel(
-            !nucleotide);
+    ScoreModelI scoreModel = ScoreModels.getInstance()
+            .getDefaultModel(!nucleotide);
     pcaModel = new PCAModel(seqstrings, seqs, nucleotide, scoreModel,
             SimilarityParams.SeqSpace);
 
@@ -216,8 +217,8 @@ public class PCAPanel extends EmbmenuFrame implements Runnable,
       if (!pcaModel.isNucleotide())
       {
         pcaModel.setNucleotide(true);
-        ScoreModelI scoreModel = ScoreModels.getInstance().getDefaultModel(
-                false);
+        ScoreModelI scoreModel = ScoreModels.getInstance()
+                .getDefaultModel(false);
         pcaModel.setScoreModel(scoreModel);
         new Thread(this).start();
       }
@@ -227,8 +228,8 @@ public class PCAPanel extends EmbmenuFrame implements Runnable,
       if (pcaModel.isNucleotide())
       {
         pcaModel.setNucleotide(false);
-        ScoreModelI scoreModel = ScoreModels.getInstance().getDefaultModel(
-                true);
+        ScoreModelI scoreModel = ScoreModels.getInstance()
+                .getDefaultModel(true);
         pcaModel.setScoreModel(scoreModel);
         new Thread(this).start();
       }
@@ -286,11 +287,11 @@ public class PCAPanel extends EmbmenuFrame implements Runnable,
     if (alAndColsel != null && alAndColsel[0] != null)
     {
       Alignment al = new Alignment((SequenceI[]) alAndColsel[0]);
-      AlignFrame af = new AlignFrame(al, av.applet,
-              "Original Data for PCA", false);
+      AlignFrame af = new AlignFrame(al, av.applet, "Original Data for PCA",
+              false);
 
-      af.viewport.getAlignment().setHiddenColumns(
-              (HiddenColumns) alAndColsel[1]);
+      af.viewport.getAlignment()
+              .setHiddenColumns((HiddenColumns) alAndColsel[1]);
     }
   }
 
@@ -366,8 +367,8 @@ public class PCAPanel extends EmbmenuFrame implements Runnable,
     values.setLabel(MessageManager.getString("label.output_values"));
     values.addActionListener(this);
     inputData.setLabel(MessageManager.getString("label.input_data"));
-    nuclSetting.setLabel(MessageManager
-            .getString("label.nucleotide_matrix"));
+    nuclSetting
+            .setLabel(MessageManager.getString("label.nucleotide_matrix"));
     nuclSetting.addItemListener(this);
     protSetting.setLabel(MessageManager.getString("label.protein_matrix"));
     protSetting.addItemListener(this);
index 32507fe..fe99187 100755 (executable)
@@ -24,8 +24,8 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.SequenceI;
 
 import java.awt.Component;
-import java.util.Enumeration;
 import java.util.Hashtable;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Vector;
@@ -78,13 +78,14 @@ public class PaintRefresher
       return;
     }
 
-    for (String id : components.keySet())
+    Iterator<String> it = components.keySet().iterator();
+    while (it.hasNext())
     {
-      Vector<Component> comps = components.get(id);
+      Vector<Component> comps = components.get(it.next());
       comps.removeElement(comp);
-      if (comps.size() == 0)
+      if (comps.isEmpty())
       {
-        components.remove(id);
+        it.remove();
       }
     }
   }
@@ -110,10 +111,10 @@ public class PaintRefresher
       return;
     }
 
-    Enumeration<Component> e = comps.elements();
-    while (e.hasMoreElements())
+    Iterator<Component> it = comps.iterator();
+    while (it.hasNext())
     {
-      comp = e.nextElement();
+      comp = it.next();
 
       if (comp == source)
       {
@@ -122,7 +123,7 @@ public class PaintRefresher
 
       if (!comp.isValid())
       {
-        comps.removeElement(comp);
+        it.remove();
       }
       else if (validateSequences && comp instanceof AlignmentPanel
               && source instanceof AlignmentPanel)
index 7574802..bc775c6 100644 (file)
@@ -62,8 +62,8 @@ public class PairwiseAlignPanel extends Panel implements ActionListener
     }
     else
     {
-      seqs = ap.av.getSelectionGroup().getSequencesInOrder(
-              ap.av.getAlignment());
+      seqs = ap.av.getSelectionGroup()
+              .getSequencesInOrder(ap.av.getAlignment());
     }
 
     float scores[][] = new float[seqs.length][seqs.length];
@@ -102,13 +102,13 @@ public class PairwiseAlignPanel extends Panel implements ActionListener
 
     if (count > 2)
     {
-      System.out
-              .println("Pairwise alignment scaled similarity score matrix\n");
+      System.out.println(
+              "Pairwise alignment scaled similarity score matrix\n");
 
       for (int i = 0; i < count; i++)
       {
-        jalview.util.Format.print(System.out, "%s \n", ("" + i) + " "
-                + seqs[i].getName());
+        jalview.util.Format.print(System.out, "%s \n",
+                ("" + i) + " " + seqs[i].getName());
       }
 
       System.out.println("\n");
@@ -117,8 +117,8 @@ public class PairwiseAlignPanel extends Panel implements ActionListener
       {
         for (int j = 0; j < i; j++)
         {
-          jalview.util.Format.print(System.out, "%7.3f", scores[i][j]
-                  / totscore);
+          jalview.util.Format.print(System.out, "%7.3f",
+                  scores[i][j] / totscore);
         }
       }
 
@@ -165,8 +165,8 @@ public class PairwiseAlignPanel extends Panel implements ActionListener
     textarea.setFont(new java.awt.Font("Monospaced", 0, 12));
     textarea.setText("");
     viewInEditorButton.setFont(new java.awt.Font("Verdana", 0, 12));
-    viewInEditorButton.setLabel(MessageManager
-            .getString("label.view_alignment_editor"));
+    viewInEditorButton.setLabel(
+            MessageManager.getString("label.view_alignment_editor"));
     viewInEditorButton.addActionListener(this);
     this.add(scrollPane, BorderLayout.CENTER);
     scrollPane.add(textarea);
index 6be416c..bd36b0d 100644 (file)
@@ -40,8 +40,8 @@ import java.util.List;
 import java.util.Stack;
 import java.util.Vector;
 
-public class RedundancyPanel extends SliderPanel implements Runnable,
-        WindowListener
+public class RedundancyPanel extends SliderPanel
+        implements Runnable, WindowListener
 {
   Stack historyList = new Stack(); // simpler than synching with alignFrame.
 
@@ -63,8 +63,8 @@ public class RedundancyPanel extends SliderPanel implements Runnable,
     applyButton.setVisible(true);
     allGroupsCheck.setVisible(false);
 
-    label.setText(MessageManager
-            .getString("label.enter_redundancy_threshold"));
+    label.setText(
+            MessageManager.getString("label.enter_redundancy_threshold"));
     valueField.setText("100");
 
     slider.setVisibleAmount(1);
@@ -140,8 +140,8 @@ public class RedundancyPanel extends SliderPanel implements Runnable,
 
     redundancy = AlignSeq.computeRedundancyMatrix(originalSequences,
             omitHidden, start, end, false);
-    label.setText(MessageManager
-            .getString("label.enter_redundancy_threshold"));
+    label.setText(
+            MessageManager.getString("label.enter_redundancy_threshold"));
     slider.setVisible(true);
     applyButton.setEnabled(true);
     valueField.setVisible(true);
@@ -160,7 +160,7 @@ public class RedundancyPanel extends SliderPanel implements Runnable,
 
     float value = slider.getValue();
 
-    List<SequenceI> redundantSequences = new ArrayList<SequenceI>();
+    List<SequenceI> redundantSequences = new ArrayList<>();
     for (int i = 0; i < redundancy.length; i++)
     {
       if (value <= redundancy[i])
@@ -227,8 +227,8 @@ public class RedundancyPanel extends SliderPanel implements Runnable,
       ap.alignFrame.addHistoryItem(cut);
 
       PaintRefresher.Refresh(this, ap.av.getSequenceSetId(), true, true);
-      ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
-              .getSequences());
+      ap.av.firePropertyChange("alignment", null,
+              ap.av.getAlignment().getSequences());
     }
 
   }
@@ -243,11 +243,11 @@ public class RedundancyPanel extends SliderPanel implements Runnable,
     {
       ap.av.getHistoryList().remove(command);
       ap.alignFrame.updateEditMenuBar();
-      ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
-              .getSequences());
+      ap.av.firePropertyChange("alignment", null,
+              ap.av.getAlignment().getSequences());
     }
 
-    ap.paintAlignment(true);
+    ap.paintAlignment(true, true);
 
     if (historyList.size() == 0)
     {
index 5c91ea8..afb4e95 100755 (executable)
@@ -331,8 +331,9 @@ public class RotatableCanvas extends Panel implements MouseListener,
     if (points == null)
     {
       g.setFont(new Font("Verdana", Font.PLAIN, 18));
-      g.drawString(MessageManager.getString("label.calculating_pca")
-              + "....", 20, getSize().height / 2);
+      g.drawString(
+              MessageManager.getString("label.calculating_pca") + "....",
+              20, getSize().height / 2);
     }
     else
     {
@@ -609,8 +610,10 @@ public class RotatableCanvas extends Panel implements MouseListener,
     for (int i = 0; i < npoint; i++)
     {
       SequencePoint sp = (SequencePoint) points.elementAt(i);
-      int tmp1 = (int) ((sp.coord[0] - centre[0]) * scale + (float) getSize().width / 2.0);
-      int tmp2 = (int) ((sp.coord[1] - centre[1]) * scale + (float) getSize().height / 2.0);
+      int tmp1 = (int) ((sp.coord[0] - centre[0]) * scale
+              + (float) getSize().width / 2.0);
+      int tmp2 = (int) ((sp.coord[1] - centre[1]) * scale
+              + (float) getSize().height / 2.0);
 
       if (tmp1 > x1 && tmp1 < x2 && tmp2 > y1 && tmp2 < y2)
       {
index 5e0a2fd..04fb22b 100755 (executable)
@@ -44,8 +44,8 @@ import java.awt.event.MouseMotionListener;
 import java.beans.PropertyChangeEvent;
 import java.util.List;
 
-public class ScalePanel extends Panel implements MouseMotionListener,
-        MouseListener, ViewportListenerI
+public class ScalePanel extends Panel
+        implements MouseMotionListener, MouseListener, ViewportListenerI
 {
 
   protected int offy = 4;
@@ -95,7 +95,8 @@ public class ScalePanel extends Panel implements MouseMotionListener,
 
     min = res;
     max = res;
-    if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
+    if ((evt.getModifiers()
+            & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
     {
       rightMouseButtonPressed(evt, res);
     }
@@ -140,7 +141,7 @@ public class ScalePanel extends Panel implements MouseMotionListener,
       sg.setStartRes(min);
       sg.setEndRes(max);
     }
-    ap.paintAlignment(false);
+    ap.paintAlignment(false, false);
     av.sendSelection();
   }
 
@@ -157,7 +158,8 @@ public class ScalePanel extends Panel implements MouseMotionListener,
     PopupMenu pop = new PopupMenu();
     if (reveal != null)
     {
-      MenuItem item = new MenuItem(MessageManager.getString("label.reveal"));
+      MenuItem item = new MenuItem(
+              MessageManager.getString("label.reveal"));
       item.addActionListener(new ActionListener()
       {
         @Override
@@ -165,7 +167,7 @@ public class ScalePanel extends Panel implements MouseMotionListener,
         {
           av.showColumn(reveal[0]);
           reveal = null;
-          ap.paintAlignment(true);
+          ap.paintAlignment(true, true);
           av.sendSelection();
         }
       });
@@ -181,7 +183,7 @@ public class ScalePanel extends Panel implements MouseMotionListener,
           {
             av.showAllHiddenColumns();
             reveal = null;
-            ap.paintAlignment(true);
+            ap.paintAlignment(true, true);
             av.sendSelection();
           }
         });
@@ -200,14 +202,13 @@ public class ScalePanel extends Panel implements MouseMotionListener,
         public void actionPerformed(ActionEvent e)
         {
           av.hideColumns(res, res);
-          if (av.getSelectionGroup() != null
-                  && av.getSelectionGroup().getSize() == av.getAlignment()
-                          .getHeight())
+          if (av.getSelectionGroup() != null && av.getSelectionGroup()
+                  .getSize() == av.getAlignment().getHeight())
           {
             av.setSelectionGroup(null);
           }
 
-          ap.paintAlignment(true);
+          ap.paintAlignment(true, true);
           av.sendSelection();
         }
       });
@@ -238,7 +239,7 @@ public class ScalePanel extends Panel implements MouseMotionListener,
 
     if (!stretchingGroup)
     {
-      ap.paintAlignment(false);
+      ap.paintAlignment(false, false);
 
       return;
     }
@@ -255,7 +256,7 @@ public class ScalePanel extends Panel implements MouseMotionListener,
     }
 
     stretchingGroup = false;
-    ap.paintAlignment(false);
+    ap.paintAlignment(false, false);
     av.sendSelection();
   }
 
@@ -284,7 +285,7 @@ public class ScalePanel extends Panel implements MouseMotionListener,
     {
       stretchingGroup = true;
       cs.stretchGroup(res, sg, min, max);
-      ap.paintAlignment(false);
+      ap.paintAlignment(false, false);
     }
   }
 
@@ -344,8 +345,8 @@ public class ScalePanel extends Panel implements MouseMotionListener,
      */
     if (!av.getWrapAlignment())
     {
-      drawScale(g, av.getRanges().getStartRes(),
-              av.getRanges().getEndRes(), getSize().width, getSize().height);
+      drawScale(g, av.getRanges().getStartRes(), av.getRanges().getEndRes(),
+              getSize().width, getSize().height);
     }
   }
 
@@ -446,10 +447,13 @@ public class ScalePanel extends Panel implements MouseMotionListener,
             continue;
           }
 
-          gg.fillPolygon(new int[] {
-              -1 + res * avCharWidth - avcharHeight / 4,
-              -1 + res * avCharWidth + avcharHeight / 4,
-              -1 + res * avCharWidth }, new int[] { y, y, y + 2 * yOf }, 3);
+          gg.fillPolygon(
+                  new int[]
+                  { -1 + res * avCharWidth - avcharHeight / 4,
+                      -1 + res * avCharWidth + avcharHeight / 4,
+                      -1 + res * avCharWidth },
+                  new int[]
+                  { y, y, y + 2 * yOf }, 3);
         }
       }
     }
@@ -464,7 +468,9 @@ public class ScalePanel extends Panel implements MouseMotionListener,
     // Here we only want to fastpaint on a scroll, with resize using a normal
     // paint, so scroll events are identified as changes to the horizontal or
     // vertical start value.
-    if (evt.getPropertyName().equals(ViewportRanges.STARTRES))
+    if (evt.getPropertyName().equals(ViewportRanges.STARTRES)
+            || evt.getPropertyName().equals(ViewportRanges.STARTRESANDSEQ)
+            || evt.getPropertyName().equals(ViewportRanges.MOVE_VIEWPORT))
     {
       // scroll event, repaint panel
       repaint();
index 9de5452..2420cf7 100755 (executable)
@@ -113,12 +113,12 @@ public class SeqCanvas extends Panel implements ViewportListenerI
       {
         if (mstring != null)
         {
-          g.drawString(mstring, mpos * avcharWidth, ypos
-                  - (avcharHeight / 2));
+          g.drawString(mstring, mpos * avcharWidth,
+                  ypos - (avcharHeight / 2));
         }
-        g.drawLine((mpos * avcharWidth) + (avcharWidth / 2), (ypos + 2)
-                - (avcharHeight / 2), (mpos * avcharWidth)
-                + (avcharWidth / 2), ypos - 2);
+        g.drawLine((mpos * avcharWidth) + (avcharWidth / 2),
+                (ypos + 2) - (avcharHeight / 2),
+                (mpos * avcharWidth) + (avcharWidth / 2), ypos - 2);
       }
     }
   }
@@ -167,8 +167,8 @@ public class SeqCanvas extends Panel implements ViewportListenerI
       {
         int x = LABEL_WEST - fm.stringWidth(String.valueOf(value))
                 - avcharWidth / 2;
-        g.drawString(value + "", x, (ypos + (i * avcharHeight))
-                - (avcharHeight / 5));
+        g.drawString(value + "", x,
+                (ypos + (i * avcharHeight)) - (avcharHeight / 5));
       }
     }
   }
@@ -207,8 +207,8 @@ public class SeqCanvas extends Panel implements ViewportListenerI
 
       if (value != -1)
       {
-        g.drawString(String.valueOf(value), 0, (ypos + (i * avcharHeight))
-                - (avcharHeight / 5));
+        g.drawString(String.valueOf(value), 0,
+                (ypos + (i * avcharHeight)) - (avcharHeight / 5));
       }
     }
   }
@@ -237,14 +237,14 @@ public class SeqCanvas extends Panel implements ViewportListenerI
     lastsr = ranges.getStartRes();
 
     fastPaint = true;
-    gg.copyArea(horizontal * avcharWidth, vertical * avcharHeight, imgWidth
-            - horizontal * avcharWidth,
+    gg.copyArea(horizontal * avcharWidth, vertical * avcharHeight,
+            imgWidth - horizontal * avcharWidth,
             imgHeight - vertical * avcharHeight, -horizontal * avcharWidth,
             -vertical * avcharHeight);
 
-    int sr = ranges.getStartRes(), er = ranges.getEndRes(), ss = ranges
-            .getStartSeq(), es = ranges
-            .getEndSeq(), transX = 0, transY = 0;
+    int sr = ranges.getStartRes(), er = ranges.getEndRes(),
+            ss = ranges.getStartSeq(), es = ranges.getEndSeq(), transX = 0,
+            transY = 0;
 
     if (horizontal > 0) // scrollbar pulled right, image to the left
     {
@@ -261,7 +261,7 @@ public class SeqCanvas extends Panel implements ViewportListenerI
       ss = es - vertical;
       if (ss < ranges.getStartSeq()) // ie scrolling too fast, more than a page
                                      // at a
-                                 // time
+      // time
       {
         ss = ranges.getStartSeq();
       }
@@ -307,8 +307,8 @@ public class SeqCanvas extends Panel implements ViewportListenerI
   {
 
     if (img != null
-            && (fastPaint || (getSize().width != g.getClipBounds().width) || (getSize().height != g
-                    .getClipBounds().height)))
+            && (fastPaint || (getSize().width != g.getClipBounds().width)
+                    || (getSize().height != g.getClipBounds().height)))
     {
       g.drawImage(img, 0, 0, this);
       fastPaint = false;
@@ -501,11 +501,15 @@ public class SeqCanvas extends Panel implements ViewportListenerI
             continue;
           }
 
-          gg.fillPolygon(new int[] { res * avcharWidth - avcharHeight / 4,
-              res * avcharWidth + avcharHeight / 4, res * avcharWidth },
-                  new int[] { ypos - (avcharHeight / 2),
-                      ypos - (avcharHeight / 2),
-                      ypos - (avcharHeight / 2) + 8 }, 3);
+          gg.fillPolygon(
+                  new int[]
+                  { res * avcharWidth - avcharHeight / 4,
+                      res * avcharWidth + avcharHeight / 4,
+                      res * avcharWidth },
+                  new int[]
+                  { ypos - (avcharHeight / 2), ypos - (avcharHeight / 2),
+                      ypos - (avcharHeight / 2) + 8 },
+                  3);
 
         }
       }
@@ -555,8 +559,8 @@ public class SeqCanvas extends Panel implements ViewportListenerI
     return annotations.adjustPanelHeight();
   }
 
-  private void drawPanel(Graphics g1, int startRes, int endRes,
-          int startSeq, int endSeq, int offset)
+  private void drawPanel(Graphics g1, final int startRes, final int endRes,
+          final int startSeq, final int endSeq, final int offset)
   {
 
     if (!av.hasHiddenColumns())
@@ -565,8 +569,8 @@ public class SeqCanvas extends Panel implements ViewportListenerI
     }
     else
     {
-
       int screenY = 0;
+      final int screenYMax = endRes - startRes;
       int blockStart = startRes;
       int blockEnd = endRes;
 
@@ -584,33 +588,42 @@ public class SeqCanvas extends Panel implements ViewportListenerI
             continue;
           }
 
-          blockEnd = hideStart - 1;
+          /*
+           * draw up to just before the next hidden region, or the end of
+           * the visible region, whichever comes first
+           */
+          blockEnd = Math.min(hideStart - 1, blockStart + screenYMax
+                  - screenY);
 
           g1.translate(screenY * avcharWidth, 0);
 
           draw(g1, blockStart, blockEnd, startSeq, endSeq, offset);
 
-          if (av.getShowHiddenMarkers())
+          /*
+           * draw the downline of the hidden column marker (ScalePanel draws the
+           * triangle on top) if we reached it
+           */
+          if (av.getShowHiddenMarkers() && blockEnd == hideStart - 1)
           {
             g1.setColor(Color.blue);
             g1.drawLine((blockEnd - blockStart + 1) * avcharWidth - 1,
-                    0 + offset, (blockEnd - blockStart + 1) * avcharWidth
-                            - 1, (endSeq - startSeq + 1) * avcharHeight
-                            + offset);
+                    0 + offset,
+                    (blockEnd - blockStart + 1) * avcharWidth - 1,
+                    (endSeq - startSeq + 1) * avcharHeight + offset);
           }
 
           g1.translate(-screenY * avcharWidth, 0);
           screenY += blockEnd - blockStart + 1;
           blockStart = hideEnd + 1;
 
-          if (screenY > (endRes - startRes))
+          if (screenY > screenYMax)
           {
             // already rendered last block
             return;
           }
         }
       }
-      if (screenY <= (endRes - startRes))
+      if (screenY <= screenYMax)
       {
         // remaining visible region to render
         blockEnd = blockStart + (endRes - startRes) - screenY;
@@ -649,8 +662,8 @@ public class SeqCanvas extends Panel implements ViewportListenerI
 
       if (av.isShowSequenceFeatures())
       {
-        fr.drawSequence(g, nextSeq, startRes, endRes, offset
-                + ((i - startSeq) * avcharHeight), false);
+        fr.drawSequence(g, nextSeq, startRes, endRes,
+                offset + ((i - startSeq) * avcharHeight), false);
       }
 
       // / Highlight search Results once all sequences have been drawn
@@ -658,16 +671,15 @@ public class SeqCanvas extends Panel implements ViewportListenerI
       if (av.hasSearchResults())
       {
         int[] visibleResults = av.getSearchResults().getResults(nextSeq,
-                startRes,
-                endRes);
+                startRes, endRes);
         if (visibleResults != null)
         {
           for (int r = 0; r < visibleResults.length; r += 2)
           {
             sr.drawHighlightedText(nextSeq, visibleResults[r],
-                    visibleResults[r + 1], (visibleResults[r] - startRes)
-                            * avcharWidth, offset
-                            + ((i - startSeq) * avcharHeight));
+                    visibleResults[r + 1],
+                    (visibleResults[r] - startRes) * avcharWidth,
+                    offset + ((i - startSeq) * avcharHeight));
           }
         }
       }
@@ -723,7 +735,8 @@ public class SeqCanvas extends Panel implements ViewportListenerI
         {
           sx = (group.getStartRes() - startRes) * avcharWidth;
           sy = offset + ((i - startSeq) * avcharHeight);
-          ex = (((group.getEndRes() + 1) - group.getStartRes()) * avcharWidth) - 1;
+          ex = (((group.getEndRes() + 1) - group.getStartRes())
+                  * avcharWidth) - 1;
 
           if (sx + ex < 0 || sx > imgWidth)
           {
@@ -731,22 +744,20 @@ public class SeqCanvas extends Panel implements ViewportListenerI
           }
 
           if ((sx <= (endRes - startRes) * avcharWidth)
-                  && group.getSequences(null).contains(
-                          av.getAlignment().getSequenceAt(i)))
+                  && group.getSequences(null)
+                          .contains(av.getAlignment().getSequenceAt(i)))
           {
             if ((bottom == -1)
-                    && (i >= alHeight || !group.getSequences(null)
-                            .contains(
-                                    av.getAlignment().getSequenceAt(i + 1))))
+                    && (i >= alHeight || !group.getSequences(null).contains(
+                            av.getAlignment().getSequenceAt(i + 1))))
             {
               bottom = sy + avcharHeight;
             }
 
             if (!inGroup)
             {
-              if (((top == -1) && (i == 0))
-                      || !group.getSequences(null).contains(
-                              av.getAlignment().getSequenceAt(i - 1)))
+              if (((top == -1) && (i == 0)) || !group.getSequences(null)
+                      .contains(av.getAlignment().getSequenceAt(i - 1)))
               {
                 top = sy;
               }
@@ -878,15 +889,37 @@ public class SeqCanvas extends Panel implements ViewportListenerI
   {
     String eventName = evt.getPropertyName();
 
+    if (eventName.equals(SequenceGroup.SEQ_GROUP_CHANGED))
+    {
+      fastPaint = true;
+      repaint();
+      return;
+    }
+    else if (eventName.equals(ViewportRanges.MOVE_VIEWPORT))
+    {
+      fastPaint = false;
+      repaint();
+      return;
+    }
+
     if (!av.getWrapAlignment())
     {
       int scrollX = 0;
-      if (eventName.equals(ViewportRanges.STARTRES))
+      if (eventName.equals(ViewportRanges.STARTRES)
+              || eventName.equals(ViewportRanges.STARTRESANDSEQ))
       {
         // Make sure we're not trying to draw a panel
         // larger than the visible window
+        if (eventName.equals(ViewportRanges.STARTRES))
+        {
+          scrollX = (int) evt.getNewValue() - (int) evt.getOldValue();
+        }
+        else
+        {
+          scrollX = ((int[]) evt.getNewValue())[0]
+                  - ((int[]) evt.getOldValue())[0];
+        }
         ViewportRanges vpRanges = av.getRanges();
-        scrollX = (int) evt.getNewValue() - (int) evt.getOldValue();
         int range = vpRanges.getEndRes() - vpRanges.getStartRes();
         if (scrollX > range)
         {
@@ -913,6 +946,10 @@ public class SeqCanvas extends Panel implements ViewportListenerI
         // scroll
         fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue());
       }
+      else if (eventName.equals(ViewportRanges.STARTRESANDSEQ))
+      {
+        fastPaint(scrollX, 0);
+      }
     }
   }
 
index d000c73..d74bbb7 100644 (file)
@@ -43,7 +43,6 @@ import jalview.util.Comparison;
 import jalview.util.MappingUtils;
 import jalview.util.MessageManager;
 import jalview.viewmodel.AlignmentViewport;
-import jalview.viewmodel.ViewportRanges;
 
 import java.awt.BorderLayout;
 import java.awt.Font;
@@ -54,10 +53,8 @@ import java.awt.event.InputEvent;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.awt.event.MouseMotionListener;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import java.util.ListIterator;
 import java.util.Vector;
 
 public class SeqPanel extends Panel implements MouseMotionListener,
@@ -134,8 +131,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     if (editCommand != null && editCommand.getSize() > 0)
     {
       ap.alignFrame.addHistoryItem(editCommand);
-      av.firePropertyChange("alignment", null, av.getAlignment()
-              .getSequences());
+      av.firePropertyChange("alignment", null,
+              av.getAlignment().getSequences());
     }
 
     startseq = -1;
@@ -150,13 +147,13 @@ public class SeqPanel extends Panel implements MouseMotionListener,
   void setCursorRow()
   {
     seqCanvas.cursorY = getKeyboardNo1() - 1;
-    scrollToVisible();
+    scrollToVisible(true);
   }
 
   void setCursorColumn()
   {
     seqCanvas.cursorX = getKeyboardNo1() - 1;
-    scrollToVisible();
+    scrollToVisible(true);
   }
 
   void setCursorRowAndColumn()
@@ -169,7 +166,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     {
       seqCanvas.cursorX = getKeyboardNo1() - 1;
       seqCanvas.cursorY = getKeyboardNo2() - 1;
-      scrollToVisible();
+      scrollToVisible(true);
     }
   }
 
@@ -178,38 +175,42 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     SequenceI sequence = av.getAlignment().getSequenceAt(seqCanvas.cursorY);
 
     seqCanvas.cursorX = sequence.findIndex(getKeyboardNo1()) - 1;
-    scrollToVisible();
+    scrollToVisible(true);
   }
 
   void moveCursor(int dx, int dy)
   {
     seqCanvas.cursorX += dx;
     seqCanvas.cursorY += dy;
-    if (av.hasHiddenColumns()
-            && !av.getAlignment().getHiddenColumns()
-                    .isVisible(seqCanvas.cursorX))
+    if (av.hasHiddenColumns() && !av.getAlignment().getHiddenColumns()
+            .isVisible(seqCanvas.cursorX))
     {
       int original = seqCanvas.cursorX - dx;
       int maxWidth = av.getAlignment().getWidth();
 
       while (!av.getAlignment().getHiddenColumns()
-              .isVisible(seqCanvas.cursorX)
-              && seqCanvas.cursorX < maxWidth && seqCanvas.cursorX > 0)
+              .isVisible(seqCanvas.cursorX) && seqCanvas.cursorX < maxWidth
+              && seqCanvas.cursorX > 0)
       {
         seqCanvas.cursorX += dx;
       }
 
-      if (seqCanvas.cursorX >= maxWidth
-              || !av.getAlignment().getHiddenColumns()
-                      .isVisible(seqCanvas.cursorX))
+      if (seqCanvas.cursorX >= maxWidth || !av.getAlignment()
+              .getHiddenColumns().isVisible(seqCanvas.cursorX))
       {
         seqCanvas.cursorX = original;
       }
     }
-    scrollToVisible();
+    scrollToVisible(false);
   }
 
-  void scrollToVisible()
+  /**
+   * Scroll to make the cursor visible in the viewport.
+   * 
+   * @param jump
+   *          just jump to the location rather than scrolling
+   */
+  void scrollToVisible(boolean jump)
   {
     if (seqCanvas.cursorX < 0)
     {
@@ -230,44 +231,34 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     }
 
     endEditing();
-    if (av.getWrapAlignment())
+
+    boolean repaintNeeded = true;
+    if (jump)
     {
-      av.getRanges().scrollToWrappedVisible(seqCanvas.cursorX);
+      // only need to repaint if the viewport did not move, as otherwise it will
+      // get a repaint
+      repaintNeeded = !av.getRanges().setViewportLocation(seqCanvas.cursorX,
+              seqCanvas.cursorY);
     }
     else
     {
-      ViewportRanges ranges = av.getRanges();
-      HiddenColumns hidden = av.getAlignment().getHiddenColumns();
-      while (seqCanvas.cursorY < ranges.getStartSeq())
-      {
-        ranges.scrollUp(true);
-      }
-      while (seqCanvas.cursorY > ranges.getEndSeq())
+      if (av.getWrapAlignment())
       {
-        ranges.scrollUp(false);
+        av.getRanges().scrollToWrappedVisible(seqCanvas.cursorX);
       }
-      while (seqCanvas.cursorX < hidden.adjustForHiddenColumns(ranges
-              .getStartRes()))
-      {
-
-        if (!ranges.scrollRight(false))
-        {
-          break;
-        }
-      }
-      while (seqCanvas.cursorX > hidden.adjustForHiddenColumns(ranges
-              .getEndRes()))
+      else
       {
-        if (!ranges.scrollRight(true))
-        {
-          break;
-        }
+        av.getRanges().scrollToVisible(seqCanvas.cursorX,
+                seqCanvas.cursorY);
       }
     }
     setStatusMessage(av.getAlignment().getSequenceAt(seqCanvas.cursorY),
             seqCanvas.cursorX, seqCanvas.cursorY);
 
-    seqCanvas.repaint();
+    if (repaintNeeded)
+    {
+      seqCanvas.repaint();
+    }
   }
 
   void setSelectionAreaAtCursor(boolean topLeft)
@@ -339,7 +330,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
       sg.addSequence(sequence, false);
       av.setSelectionGroup(sg);
     }
-    ap.paintAlignment(false);
+    ap.paintAlignment(false, false);
     av.sendSelection();
   }
 
@@ -421,7 +412,6 @@ public class SeqPanel extends Panel implements MouseMotionListener,
    *          alignment column
    * @param seq
    *          index of sequence in alignment
-   * @return position of column in sequence or -1 if at gap
    */
   void setStatusMessage(SequenceI sequence, int column, int seq)
   {
@@ -445,9 +435,9 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     }
     else
     {
-      residue = "X".equalsIgnoreCase(displayChar) ? "X" : ("*"
-              .equals(displayChar) ? "STOP" : ResidueProperties.aa2Triplet
-              .get(displayChar));
+      residue = "X".equalsIgnoreCase(displayChar) ? "X"
+              : ("*".equals(displayChar) ? "STOP"
+                      : ResidueProperties.aa2Triplet.get(displayChar));
       if (residue != null)
       {
         text.append(" Residue: ").append(residue);
@@ -509,7 +499,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
 
     // For now, ignore the mouseWheel font resizing on Macs
     // As the Button2_mask always seems to be true
-    if ((evt.getModifiers() & InputEvent.BUTTON2_MASK) == InputEvent.BUTTON2_MASK
+    if ((evt.getModifiers()
+            & InputEvent.BUTTON2_MASK) == InputEvent.BUTTON2_MASK
             && !av.MAC)
     {
       mouseWheelPressed = true;
@@ -531,7 +522,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     }
 
     int seq = findSeq(evt);
-    int res = findRes(evt);
+    int res = findColumn(evt);
 
     if (seq < 0 || res < 0)
     {
@@ -567,25 +558,20 @@ public class SeqPanel extends Panel implements MouseMotionListener,
         av.setSelectionGroup(null);
       }
 
-      int column = findRes(evt);
-      boolean isGapped = Comparison.isGap(sequence.getCharAt(column));
-      List<SequenceFeature> features = findFeaturesAtRes(sequence,
-              sequence.findPosition(column));
-      if (isGapped)
-      {
-        removeAdjacentFeatures(features, column + 1, sequence);
-      }
+      int column = findColumn(evt);
+      List<SequenceFeature> features = findFeaturesAtColumn(sequence,
+              column + 1);
 
       if (!features.isEmpty())
       {
         SearchResultsI highlight = new SearchResults();
-        highlight.addResult(sequence, features.get(0).getBegin(), features
-                .get(0).getEnd());
+        highlight.addResult(sequence, features.get(0).getBegin(),
+                features.get(0).getEnd());
         seqCanvas.highlightSearchResults(highlight);
         seqCanvas.getFeatureRenderer().amendFeatures(
                 Collections.singletonList(sequence), features, false, ap);
-
-        seqCanvas.highlightSearchResults(null);
+        av.setSearchResults(null); // clear highlighting
+        seqCanvas.repaint(); // draw new/amended features
       }
     }
   }
@@ -611,7 +597,14 @@ public class SeqPanel extends Panel implements MouseMotionListener,
 
   int wrappedBlock = -1;
 
-  int findRes(MouseEvent evt)
+  /**
+   * Returns the aligned sequence position (base 0) at the mouse position, or
+   * the closest visible one
+   * 
+   * @param evt
+   * @return
+   */
+  int findColumn(MouseEvent evt)
   {
     int res = 0;
     int x = evt.getX();
@@ -690,8 +683,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
 
       y -= hgap;
 
-      seq = Math.min((y % cHeight) / av.getCharHeight(), av.getAlignment()
-              .getHeight() - 1);
+      seq = Math.min((y % cHeight) / av.getCharHeight(),
+              av.getAlignment().getHeight() - 1);
       if (seq < 0)
       {
         seq = -1;
@@ -699,10 +692,9 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     }
     else
     {
-      seq = Math.min((y / av.getCharHeight())
-              + av.getRanges().getStartSeq(),
-              av
-              .getAlignment().getHeight() - 1);
+      seq = Math.min(
+              (y / av.getCharHeight()) + av.getRanges().getStartSeq(),
+              av.getAlignment().getHeight() - 1);
       if (seq < 0)
       {
         seq = -1;
@@ -716,7 +708,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
   {
 
     int seq = findSeq(evt);
-    int res = findRes(evt);
+    int res = findColumn(evt);
 
     if (seq < av.getAlignment().getHeight()
             && res < av.getAlignment().getSequenceAt(seq).getLength())
@@ -788,7 +780,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
   @Override
   public void mouseMoved(MouseEvent evt)
   {
-    final int column = findRes(evt);
+    final int column = findColumn(evt);
     int seq = findSeq(evt);
 
     if (seq >= av.getAlignment().getHeight() || seq < 0 || column < 0)
@@ -834,8 +826,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
       else
       {
         String residue = (ch == 'x' || ch == 'X') ? "X"
-                : ResidueProperties.aa2Triplet
-                .get(String.valueOf(ch));
+                : ResidueProperties.aa2Triplet.get(String.valueOf(ch));
         text.append(" Residue: ").append(residue == null ? ch : residue);
       }
       text.append(" (").append(Integer.toString(respos)).append(")");
@@ -849,7 +840,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     {
       for (int g = 0; g < groups.length; g++)
       {
-        if (groups[g].getStartRes() <= column && groups[g].getEndRes() >= column)
+        if (groups[g].getStartRes() <= column
+                && groups[g].getEndRes() >= column)
         {
           if (!groups[g].getName().startsWith("JTreeGroup")
                   && !groups[g].getName().startsWith("JGroup"))
@@ -871,12 +863,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
      */
     if (av.isShowSequenceFeatures())
     {
-      List<SequenceFeature> allFeatures = findFeaturesAtRes(sequence,
-              sequence.findPosition(column));
-      if (isGapped)
-      {
-        removeAdjacentFeatures(allFeatures, column + 1, sequence);
-      }
+      List<SequenceFeature> allFeatures = findFeaturesAtColumn(sequence,
+              column + 1);
       for (SequenceFeature sf : allFeatures)
       {
         tooltipText.append(sf.getType() + " " + sf.begin + ":" + sf.end);
@@ -909,65 +897,18 @@ public class SeqPanel extends Panel implements MouseMotionListener,
   }
 
   /**
-   * Removes from the list of features any that start after, or end before, the
-   * given column position. This allows us to retain only those features
-   * adjacent to a gapped position that straddle the position. Contact features
-   * that 'straddle' the position are also removed, since they are not 'at' the
-   * position.
+   * Returns features at the specified aligned column on the given sequence.
+   * Non-positional features are not included. If the column has a gap, then
+   * enclosing features are included (but not contact features).
    * 
-   * @param features
-   * @param column
-   *          alignment column (1..)
    * @param sequence
+   * @param column
+   *          (1..)
+   * @return
    */
-  protected void removeAdjacentFeatures(List<SequenceFeature> features,
-          int column, SequenceI sequence)
+  List<SequenceFeature> findFeaturesAtColumn(SequenceI sequence, int column)
   {
-    // TODO should this be an AlignViewController method (shared by gui)?
-    ListIterator<SequenceFeature> it = features.listIterator();
-    while (it.hasNext())
-    {
-      SequenceFeature sf = it.next();
-      if (sf.isContactFeature()
-              || sequence.findIndex(sf.getBegin()) > column
-              || sequence.findIndex(sf.getEnd()) < column)
-      {
-        it.remove();
-      }
-    }
-  }
-
-  List<SequenceFeature> findFeaturesAtRes(SequenceI sequence, int res)
-  {
-    List<SequenceFeature> result = new ArrayList<>();
-    SequenceFeature[] features = sequence.getSequenceFeatures();
-    if (features != null)
-    {
-      for (int i = 0; i < features.length; i++)
-      {
-        if (av.getFeaturesDisplayed() == null
-                || !av.getFeaturesDisplayed().isVisible(
-                        features[i].getType()))
-        {
-          continue;
-        }
-
-        if (features[i].featureGroup != null
-                && !seqCanvas.fr.checkGroupVisibility(
-                        features[i].featureGroup, false))
-        {
-          continue;
-        }
-
-        if ((features[i].getBegin() <= res)
-                && (features[i].getEnd() >= res))
-        {
-          result.add(features[i]);
-        }
-      }
-    }
-
-    return result;
+    return seqCanvas.getFeatureRenderer().findFeaturesAtColumn(sequence, column);
   }
 
   Tooltip tooltip;
@@ -988,8 +929,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
       int oldWidth = av.getCharWidth();
 
       // Which is bigger, left-right or up-down?
-      if (Math.abs(evt.getY() - lastMousePress.y) > Math.abs(evt.getX()
-              - lastMousePress.x))
+      if (Math.abs(evt.getY() - lastMousePress.y) > Math
+              .abs(evt.getX() - lastMousePress.x))
       {
         int fontSize = av.font.getSize();
 
@@ -1036,7 +977,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
 
       lastMousePress = evt.getPoint();
 
-      ap.paintAlignment(false);
+      ap.paintAlignment(false, false);
       ap.annotationPanel.image = null;
       return;
     }
@@ -1047,7 +988,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
       return;
     }
 
-    int res = findRes(evt);
+    int res = findColumn(evt);
 
     if (res < 0)
     {
@@ -1098,8 +1039,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     StringBuffer message = new StringBuffer();
     if (groupEditing)
     {
-      message.append(MessageManager.getString("action.edit_group")).append(
-              ":");
+      message.append(MessageManager.getString("action.edit_group"))
+              .append(":");
       if (editCommand == null)
       {
         editCommand = new EditCommand(
@@ -1117,8 +1058,9 @@ public class SeqPanel extends Panel implements MouseMotionListener,
       }
       if (editCommand == null)
       {
-        editCommand = new EditCommand(MessageManager.formatMessage(
-                "label.edit_params", new String[] { label }));
+        editCommand = new EditCommand(MessageManager
+                .formatMessage("label.edit_params", new String[]
+                { label }));
       }
     }
 
@@ -1135,9 +1077,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     ap.alignFrame.statusBar.setText(message.toString());
 
     // Are we editing within a selection group?
-    if (groupEditing
-            || (sg != null && sg.getSequences(av.getHiddenRepSequences())
-                    .contains(seq)))
+    if (groupEditing || (sg != null
+            && sg.getSequences(av.getHiddenRepSequences()).contains(seq)))
     {
       fixedColumns = true;
 
@@ -1229,7 +1170,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
         // Find the next gap before the end
         // of the visible region boundary
         boolean blank = false;
-        for (fixedRight = fixedRight; fixedRight > lastres; fixedRight--)
+        for (; fixedRight > lastres; fixedRight--)
         {
           blank = true;
 
@@ -1237,8 +1178,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
           {
             for (int j = 0; j < startres - lastres; j++)
             {
-              if (!jalview.util.Comparison.isGap(gs.getCharAt(fixedRight
-                      - j)))
+              if (!jalview.util.Comparison
+                      .isGap(gs.getCharAt(fixedRight - j)))
               {
                 blank = false;
                 break;
@@ -1359,9 +1300,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
         }
         else
         {
-          editCommand.appendEdit(Action.INSERT_GAP,
-                  new SequenceI[] { seq }, lastres, startres - lastres,
-                  av.getAlignment(), true);
+          editCommand.appendEdit(Action.INSERT_GAP, new SequenceI[] { seq },
+                  lastres, startres - lastres, av.getAlignment(), true);
         }
       }
       else
@@ -1395,8 +1335,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
           if (max > 0)
           {
             editCommand.appendEdit(Action.DELETE_GAP,
-                    new SequenceI[] { seq }, startres, max,
-                    av.getAlignment(), true);
+                    new SequenceI[]
+                    { seq }, startres, max, av.getAlignment(), true);
           }
         }
       }
@@ -1456,11 +1396,11 @@ public class SeqPanel extends Panel implements MouseMotionListener,
   {
     if (scrollThread != null)
     {
-      scrollThread.running = false;
+      scrollThread.threadRunning = false;
       scrollThread = null;
     }
 
-    int res = findRes(evt);
+    int column = findColumn(evt);
     int seq = findSeq(evt);
     oldSeq = seq;
     startWrapBlock = wrappedBlock;
@@ -1472,16 +1412,16 @@ public class SeqPanel extends Panel implements MouseMotionListener,
 
     SequenceI sequence = av.getAlignment().getSequenceAt(seq);
 
-    if (sequence == null || res > sequence.getLength())
+    if (sequence == null || column > sequence.getLength())
     {
       return;
     }
 
     stretchGroup = av.getSelectionGroup();
 
-    if (stretchGroup == null || !stretchGroup.contains(sequence, res))
+    if (stretchGroup == null || !stretchGroup.contains(sequence, column))
     {
-      stretchGroup = av.getAlignment().findGroup(sequence, res);
+      stretchGroup = av.getAlignment().findGroup(sequence, column);
       if (stretchGroup != null)
       {
         // only update the current selection if the popup menu has a group to
@@ -1491,10 +1431,11 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     }
 
     // DETECT RIGHT MOUSE BUTTON IN AWT
-    if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
+    if ((evt.getModifiers()
+            & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
     {
-      List<SequenceFeature> allFeatures = findFeaturesAtRes(sequence,
-              sequence.findPosition(res));
+      List<SequenceFeature> allFeatures = findFeaturesAtColumn(sequence,
+              sequence.findPosition(column + 1));
 
       Vector<String> links = null;
       for (SequenceFeature sf : allFeatures)
@@ -1505,10 +1446,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
           {
             links = new Vector<>();
           }
-          for (int j = 0; j < sf.links.size(); j++)
-          {
-            links.addElement(sf.links.elementAt(j));
-          }
+          links.addAll(sf.links);
         }
       }
       APopupMenu popup = new APopupMenu(ap, null, links);
@@ -1519,7 +1457,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
 
     if (av.cursorMode)
     {
-      seqCanvas.cursorX = findRes(evt);
+      seqCanvas.cursorX = findColumn(evt);
       seqCanvas.cursorY = findSeq(evt);
       seqCanvas.repaint();
       return;
@@ -1531,8 +1469,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     {
       // define a new group here
       SequenceGroup sg = new SequenceGroup();
-      sg.setStartRes(res);
-      sg.setEndRes(res);
+      sg.setStartRes(column);
+      sg.setEndRes(column);
       sg.addSequence(sequence, false);
       av.setSelectionGroup(sg);
       stretchGroup = sg;
@@ -1580,7 +1518,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
       }
     }
     PaintRefresher.Refresh(ap, av.getSequenceSetId());
-    ap.paintAlignment(needOverviewUpdate);
+    ap.paintAlignment(needOverviewUpdate, needOverviewUpdate);
     needOverviewUpdate = false;
     changeEndRes = false;
     changeStartRes = false;
@@ -1590,7 +1528,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
 
   public void doMouseDraggedDefineMode(MouseEvent evt)
   {
-    int res = findRes(evt);
+    int res = findColumn(evt);
     int y = findSeq(evt);
 
     if (wrappedBlock != startWrapBlock)
@@ -1705,7 +1643,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
       mouseExited(evt);
     }
 
-    if (scrollThread != null)
+    if ((scrollThread != null) && (scrollThread.isRunning()))
     {
       scrollThread.setEvent(evt);
     }
@@ -1721,9 +1659,9 @@ public class SeqPanel extends Panel implements MouseMotionListener,
       oldSeq = 0;
     }
 
-    if (scrollThread != null)
+    if ((scrollThread != null) && (scrollThread.isRunning()))
     {
-      scrollThread.running = false;
+      scrollThread.stopScrolling();
       scrollThread = null;
     }
   }
@@ -1746,9 +1684,9 @@ public class SeqPanel extends Panel implements MouseMotionListener,
   {
     if (evt == null)
     {
-      if (scrollThread != null)
+      if ((scrollThread != null) && (scrollThread.isRunning()))
       {
-        scrollThread.running = false;
+        scrollThread.stopScrolling();
         scrollThread = null;
       }
       mouseDragging = false;
@@ -1771,7 +1709,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
   {
     MouseEvent evt;
 
-    boolean running = false;
+    private volatile boolean threadRunning = true;
 
     public ScrollThread()
     {
@@ -1785,14 +1723,18 @@ public class SeqPanel extends Panel implements MouseMotionListener,
 
     public void stopScrolling()
     {
-      running = false;
+      threadRunning = false;
+    }
+
+    public boolean isRunning()
+    {
+      return threadRunning;
     }
 
     @Override
     public void run()
     {
-      running = true;
-      while (running)
+      while (threadRunning)
       {
 
         if (evt != null)
@@ -1801,24 +1743,23 @@ public class SeqPanel extends Panel implements MouseMotionListener,
           if (mouseDragging && evt.getY() < 0
                   && av.getRanges().getStartSeq() > 0)
           {
-            running = av.getRanges().scrollUp(true);
+            av.getRanges().scrollUp(true);
           }
 
-          if (mouseDragging && evt.getY() >= getSize().height
-                  && av.getAlignment().getHeight() > av.getRanges()
-                          .getEndSeq())
+          if (mouseDragging && evt.getY() >= getSize().height && av
+                  .getAlignment().getHeight() > av.getRanges().getEndSeq())
           {
-            running = av.getRanges().scrollUp(false);
+            av.getRanges().scrollUp(false);
           }
 
           if (mouseDragging && evt.getX() < 0)
           {
-            running = av.getRanges().scrollRight(false);
+            av.getRanges().scrollRight(false);
           }
 
           else if (mouseDragging && evt.getX() >= getSize().width)
           {
-            running = av.getRanges().scrollRight(true);
+            av.getRanges().scrollRight(true);
           }
         }
 
@@ -1843,9 +1784,10 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     // handles selection messages...
     // TODO: extend config options to allow user to control if selections may be
     // shared between viewports.
-    if (av != null
-            && (av == source || !av.followSelection || (source instanceof AlignViewport && ((AlignmentViewport) source)
-                    .getSequenceSetId().equals(av.getSequenceSetId()))))
+    if (av != null && (av == source || !av.followSelection
+            || (source instanceof AlignViewport
+                    && ((AlignmentViewport) source).getSequenceSetId()
+                            .equals(av.getSequenceSetId()))))
     {
       return;
     }
@@ -1874,11 +1816,9 @@ public class SeqPanel extends Panel implements MouseMotionListener,
       {
         if (av.getAlignment() == null)
         {
-          System.out
-                  .println("Selection message: alignviewport av SeqSetId="
-                          + av.getSequenceSetId() + " ViewId="
-                          + av.getViewId()
-                          + " 's alignment is NULL! returning immediatly.");
+          System.out.println("Selection message: alignviewport av SeqSetId="
+                  + av.getSequenceSetId() + " ViewId=" + av.getViewId()
+                  + " 's alignment is NULL! returning immediatly.");
           return;
         }
         sgroup = seqsel.intersect(av.getAlignment(),
@@ -1898,9 +1838,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
       }
       repaint = av.isSelectionGroupChanged(true);
     }
-    if (copycolsel
-            && (av.getColumnSelection() == null || !av
-                    .isColSelChanged(true)))
+    if (copycolsel && (av.getColumnSelection() == null
+            || !av.isColSelChanged(true)))
     {
       // the current selection is unset or from a previous message
       // so import the new colsel.
@@ -1926,8 +1865,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
       }
       repaint |= av.isColSelChanged(true);
     }
-    if (copycolsel
-            && av.hasHiddenColumns()
+    if (copycolsel && av.hasHiddenColumns()
             && (av.getColumnSelection() == null))
     {
       System.err.println("Bad things");
@@ -1962,8 +1900,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
   {
 
     row = row < 0 ? ap.av.getRanges().getStartSeq() : row;
-    ap.scrollTo(ap.av.getRanges().getStartRes(), ap.av.getRanges()
-            .getStartRes(), row, true, true);
+    ap.scrollTo(ap.av.getRanges().getStartRes(),
+            ap.av.getRanges().getStartRes(), row, true, true);
   }
 
   /**
@@ -1975,7 +1913,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
   {
 
     column = column < 0 ? ap.av.getRanges().getStartRes() : column;
-    ap.scrollTo(column, column, ap.av.getRanges().getStartSeq(), true, true);
+    ap.scrollTo(column, column, ap.av.getRanges().getStartSeq(), true,
+            true);
   }
 
   /**
index 38031e4..e55f2a5 100755 (executable)
@@ -22,7 +22,7 @@ package jalview.appletgui;
 
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
-import jalview.renderer.ResidueShaderI;
+import jalview.renderer.ResidueColourFinder;
 import jalview.renderer.seqfeatures.FeatureColourFinder;
 
 import java.awt.Color;
@@ -40,19 +40,18 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
 
   boolean renderGaps = true;
 
-  SequenceGroup currentSequenceGroup = null;
-
   SequenceGroup[] allGroups = null;
 
   Color resBoxColour;
 
   Graphics graphics;
 
-  boolean forOverview = false;
+  ResidueColourFinder resColourFinder;
 
   public SequenceRenderer(AlignViewport av)
   {
     this.av = av;
+    resColourFinder = new ResidueColourFinder();
   }
 
   /**
@@ -69,25 +68,6 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
     this.renderGaps = renderGaps;
   }
 
-  protected Color getResidueBoxColour(SequenceI seq, int i)
-  {
-    allGroups = av.getAlignment().findAllGroups(seq);
-
-    if (inCurrentSequenceGroup(i))
-    {
-      if (currentSequenceGroup.getDisplayBoxes())
-      {
-        getBoxColour(currentSequenceGroup.getGroupColourScheme(), seq, i);
-      }
-    }
-    else if (av.getShowBoxes())
-    {
-      getBoxColour(av.getResidueShading(), seq, i);
-    }
-
-    return resBoxColour;
-  }
-
   /**
    * Get the residue colour at the given sequence position - as determined by
    * the sequence group colour (if any), else the colour scheme, possibly
@@ -104,31 +84,9 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
   {
     // TODO replace 8 or so code duplications with calls to this method
     // (refactored as needed)
-    Color col = getResidueBoxColour(seq, position);
-
-    if (finder != null)
-    {
-      col = finder.findFeatureColour(col, seq, position);
-    }
-    return col;
-  }
-
-  void getBoxColour(ResidueShaderI shader, SequenceI seq, int i)
-  {
-    if (shader.getColourScheme() != null)
-    {
-      resBoxColour = shader.findColour(seq.getCharAt(i), i, seq);
-    }
-    else if (forOverview
-            && !jalview.util.Comparison.isGap(seq.getCharAt(i)))
-    {
-      resBoxColour = Color.lightGray;
-    }
-    else
-    {
-      resBoxColour = Color.white;
-    }
-
+    return resColourFinder.getResidueColour(av.getShowBoxes(),
+            av.getResidueShading(),
+            allGroups, seq, position, finder);
   }
 
   public Color findSequenceColour(SequenceI seq, int i)
@@ -162,26 +120,31 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
     int length = seq.getLength();
 
     int curStart = -1;
-    int curWidth = av.getCharWidth(), avCharWidth = av.getCharWidth(), avCharHeight = av
-            .getCharHeight();
+    int curWidth = av.getCharWidth(), avCharWidth = av.getCharWidth(),
+            avCharHeight = av.getCharHeight();
 
+    Color resBoxColour = Color.white;
     Color tempColour = null;
     while (i <= end)
     {
       resBoxColour = Color.white;
       if (i < length)
       {
-        if (inCurrentSequenceGroup(i))
+        SequenceGroup currentSequenceGroup = resColourFinder
+                .getCurrentSequenceGroup(allGroups, i);
+        if (currentSequenceGroup != null)
         {
           if (currentSequenceGroup.getDisplayBoxes())
           {
-            getBoxColour(currentSequenceGroup.getGroupColourScheme(), seq,
+            resBoxColour = resColourFinder.getBoxColour(
+                    currentSequenceGroup.getGroupColourScheme(), seq,
                     i);
           }
         }
         else if (av.getShowBoxes())
         {
-          getBoxColour(av.getResidueShading(), seq, i);
+          resBoxColour = resColourFinder
+                  .getBoxColour(av.getResidueShading(), seq, i);
         }
       }
 
@@ -245,7 +208,9 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
         continue;
       }
 
-      if (inCurrentSequenceGroup(i))
+      SequenceGroup currentSequenceGroup = resColourFinder
+              .getCurrentSequenceGroup(allGroups, i);
+      if (currentSequenceGroup != null)
       {
         if (!currentSequenceGroup.getDisplayText())
         {
@@ -254,7 +219,8 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
 
         if (currentSequenceGroup.getColourText())
         {
-          getBoxColour(currentSequenceGroup.getGroupColourScheme(), seq, i);
+          resBoxColour = resColourFinder.getBoxColour(
+                  currentSequenceGroup.getGroupColourScheme(), seq, i);
           graphics.setColor(resBoxColour.darker());
         }
         if (currentSequenceGroup.getShowNonconserved())
@@ -271,7 +237,8 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
 
         if (av.getColourText())
         {
-          getBoxColour(av.getResidueShading(), seq, i);
+          resBoxColour = resColourFinder
+                  .getBoxColour(av.getResidueShading(), seq, i);
           if (av.getShowBoxes())
           {
             graphics.setColor(resBoxColour.darker());
@@ -309,8 +276,8 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
       }
 
       charOffset = (avCharWidth - fm.charWidth(s)) / 2;
-      graphics.drawString(String.valueOf(s), charOffset + avCharWidth
-              * (i - start), y1);
+      graphics.drawString(String.valueOf(s),
+              charOffset + avCharWidth * (i - start), y1);
     }
 
   }
@@ -333,47 +300,31 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
     // currentSequenceGroup.getConsensus()
     char conschar = (usesrep) ? (currentGroup == null
             || position < currentGroup.getStartRes()
-            || position > currentGroup.getEndRes() ? av.getAlignment()
-            .getSeqrep().getCharAt(position)
-            : (currentGroup.getSeqrep() != null ? currentGroup.getSeqrep()
-                    .getCharAt(position) : av.getAlignment().getSeqrep()
-                    .getCharAt(position)))
+            || position > currentGroup.getEndRes()
+                    ? av.getAlignment().getSeqrep().getCharAt(position)
+                    : (currentGroup.getSeqrep() != null
+                            ? currentGroup.getSeqrep().getCharAt(position)
+                            : av.getAlignment().getSeqrep()
+                                    .getCharAt(position)))
             : (currentGroup != null && currentGroup.getConsensus() != null
                     && position >= currentGroup.getStartRes()
-                    && position <= currentGroup.getEndRes() && currentGroup
-                    .getConsensus().annotations.length > position) ? currentGroup
-                    .getConsensus().annotations[position].displayCharacter
-                    .charAt(0)
-                    : av.getAlignmentConsensusAnnotation().annotations[position].displayCharacter
-                            .charAt(0);
+                    && position <= currentGroup.getEndRes()
+                    && currentGroup
+                            .getConsensus().annotations.length > position)
+                                    ? currentGroup
+                                            .getConsensus().annotations[position].displayCharacter
+                                                    .charAt(0)
+                                    : av.getAlignmentConsensusAnnotation().annotations[position].displayCharacter
+                                            .charAt(0);
     if (!jalview.util.Comparison.isGap(conschar)
-            && (sequenceChar == conschar || sequenceChar + CHAR_TO_UPPER == conschar))
+            && (sequenceChar == conschar
+                    || sequenceChar + CHAR_TO_UPPER == conschar))
     {
       sequenceChar = conservedChar;
     }
     return sequenceChar;
   }
 
-  boolean inCurrentSequenceGroup(int res)
-  {
-    if (allGroups == null)
-    {
-      return false;
-    }
-
-    for (int i = 0; i < allGroups.length; i++)
-    {
-      if (allGroups[i].getStartRes() <= res
-              && allGroups[i].getEndRes() >= res)
-      {
-        currentSequenceGroup = allGroups[i];
-        return true;
-      }
-    }
-
-    return false;
-  }
-
   public void drawHighlightedText(SequenceI seq, int start, int end,
           int x1, int y1)
   {
@@ -381,7 +332,8 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
     int pady = avCharHeight / 5;
     int charOffset = 0;
     graphics.setColor(Color.black);
-    graphics.fillRect(x1, y1, avCharWidth * (end - start + 1), avCharHeight);
+    graphics.fillRect(x1, y1, avCharWidth * (end - start + 1),
+            avCharHeight);
     graphics.setColor(Color.white);
 
     char s = '~';
@@ -396,8 +348,9 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
         }
 
         charOffset = (avCharWidth - fm.charWidth(s)) / 2;
-        graphics.drawString(String.valueOf(s), charOffset + x1
-                + avCharWidth * (i - start), y1 + avCharHeight - pady);
+        graphics.drawString(String.valueOf(s),
+                charOffset + x1 + avCharWidth * (i - start),
+                y1 + avCharHeight - pady);
       }
     }
   }
index 47a0669..5841e80 100644 (file)
@@ -47,8 +47,8 @@ import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
 import java.util.List;
 
-public class SliderPanel extends Panel implements ActionListener,
-        AdjustmentListener, MouseListener
+public class SliderPanel extends Panel
+        implements ActionListener, AdjustmentListener, MouseListener
 {
   private static final String BACKGROUND = "Background";
 
@@ -81,8 +81,8 @@ public class SliderPanel extends Panel implements ActionListener,
     }
 
     conservationSlider.setTitle(MessageManager.formatMessage(
-            "label.conservation_colour_increment",
-            new String[] { source == null ? BACKGROUND : source }));
+            "label.conservation_colour_increment", new String[]
+            { source == null ? BACKGROUND : source }));
     List<SequenceGroup> groups = ap.av.getAlignment().getGroups();
     if (groups != null && !groups.isEmpty())
     {
@@ -140,8 +140,8 @@ public class SliderPanel extends Panel implements ActionListener,
       pid.valueField.setText(String.valueOf(ccs.getThreshold()));
     }
     PIDSlider.setTitle(MessageManager.formatMessage(
-            "label.percentage_identity_threshold",
-            new String[] { source == null ? BACKGROUND : source }));
+            "label.percentage_identity_threshold", new String[]
+            { source == null ? BACKGROUND : source }));
 
     if (ap.av.getAlignment().getGroups() != null)
     {
@@ -168,8 +168,8 @@ public class SliderPanel extends Panel implements ActionListener,
 
     if (!PIDSlider.isVisible())
     {
-      jalview.bin.JalviewLite.addFrame(PIDSlider, PIDSlider.getTitle(),
-              420, 100);
+      jalview.bin.JalviewLite.addFrame(PIDSlider, PIDSlider.getTitle(), 420,
+              100);
       PIDSlider.addWindowListener(new WindowAdapter()
       {
         @Override
@@ -205,6 +205,7 @@ public class SliderPanel extends Panel implements ActionListener,
       conservationSlider = null;
     }
   }
+
   public SliderPanel(AlignmentPanel ap, int value, boolean forConserve,
           ResidueShaderI shader)
   {
@@ -394,7 +395,7 @@ public class SliderPanel extends Panel implements ActionListener,
         valueChanged(slider.getValue());
       }
     });
-    
+
     label.setFont(new java.awt.Font("Verdana", 0, 11));
     label.setText(MessageManager.getString("label.set_this_label_text"));
     jPanel1.setLayout(borderLayout1);
@@ -408,10 +409,10 @@ public class SliderPanel extends Panel implements ActionListener,
     undoButton.addActionListener(this);
     allGroupsCheck.setEnabled(false);
     allGroupsCheck.setFont(new java.awt.Font("Verdana", 0, 11));
-    allGroupsCheck.setLabel(MessageManager
-            .getString("action.apply_threshold_all_groups"));
-    allGroupsCheck.setName(MessageManager
-            .getString("action.apply_all_groups"));
+    allGroupsCheck.setLabel(
+            MessageManager.getString("action.apply_threshold_all_groups"));
+    allGroupsCheck
+            .setName(MessageManager.getString("action.apply_all_groups"));
     this.setBackground(Color.white);
     this.setForeground(Color.black);
     jPanel2.add(label, null);
@@ -440,7 +441,7 @@ public class SliderPanel extends Panel implements ActionListener,
   @Override
   public void mouseReleased(MouseEvent evt)
   {
-    ap.paintAlignment(true);
+    ap.paintAlignment(true, true);
   }
 
   @Override
index cbad148..777e307 100644 (file)
@@ -87,7 +87,8 @@ public class SplitFrame extends EmbmenuFrame
      * Compute cDNA consensus on protein alignment
      */
     protein.initComplementConsensus();
-    AlignmentViewPanel ap = topAlignment.isNucleotide() ? bottomFrame.alignPanel
+    AlignmentViewPanel ap = topAlignment.isNucleotide()
+            ? bottomFrame.alignPanel
             : topFrame.alignPanel;
     protein.updateConsensus(ap);
 
@@ -118,7 +119,8 @@ public class SplitFrame extends EmbmenuFrame
   {
     AlignmentViewport cdna = topFrame.getAlignViewport().getAlignment()
             .isNucleotide() ? topFrame.viewport : bottomFrame.viewport;
-    AlignmentViewport protein = cdna == topFrame.viewport ? bottomFrame.viewport
+    AlignmentViewport protein = cdna == topFrame.viewport
+            ? bottomFrame.viewport
             : topFrame.viewport;
 
     /*
@@ -132,14 +134,14 @@ public class SplitFrame extends EmbmenuFrame
     if (w1 != w3)
     {
       Dimension d = topFrame.alignPanel.idPanel.idCanvas.getSize();
-      topFrame.alignPanel.idPanel.idCanvas.setSize(new Dimension(w3,
-              d.height));
+      topFrame.alignPanel.idPanel.idCanvas
+              .setSize(new Dimension(w3, d.height));
     }
     if (w2 != w3)
     {
       Dimension d = bottomFrame.alignPanel.idPanel.idCanvas.getSize();
-      bottomFrame.alignPanel.idPanel.idCanvas.setSize(new Dimension(w3,
-              d.height));
+      bottomFrame.alignPanel.idPanel.idCanvas
+              .setSize(new Dimension(w3, d.height));
     }
 
     /*
@@ -165,8 +167,8 @@ public class SplitFrame extends EmbmenuFrame
   private void addAlignFrameComponents(AlignFrame af, Panel panel)
   {
     panel.setLayout(new BorderLayout());
-    Panel menuPanel = af
-            .makeEmbeddedPopupMenu(af.getMenuBar(), true, false);
+    Panel menuPanel = af.makeEmbeddedPopupMenu(af.getMenuBar(), true,
+            false);
     panel.add(menuPanel, BorderLayout.NORTH);
     panel.add(af.statusBar, BorderLayout.SOUTH);
     panel.add(af.alignPanel, BorderLayout.CENTER);
@@ -185,9 +187,9 @@ public class SplitFrame extends EmbmenuFrame
     createSplitFrameWindow(embedded, applet);
     validate();
     topFrame.alignPanel.adjustAnnotationHeight();
-    topFrame.alignPanel.paintAlignment(true);
+    topFrame.alignPanel.paintAlignment(true, true);
     bottomFrame.alignPanel.adjustAnnotationHeight();
-    bottomFrame.alignPanel.paintAlignment(true);
+    bottomFrame.alignPanel.paintAlignment(true, true);
   }
 
   /**
@@ -209,8 +211,8 @@ public class SplitFrame extends EmbmenuFrame
       this.add(outermost);
       int width = Math.max(topFrame.frameWidth, bottomFrame.frameWidth);
       int height = topFrame.frameHeight + bottomFrame.frameHeight;
-      jalview.bin.JalviewLite
-              .addFrame(this, this.getTitle(), width, height);
+      jalview.bin.JalviewLite.addFrame(this, this.getTitle(), width,
+              height);
     }
   }
 
index 7a65ec3..d629cf6 100755 (executable)
@@ -35,8 +35,8 @@ import java.awt.event.MouseListener;
 import java.awt.event.MouseMotionListener;
 import java.util.StringTokenizer;
 
-public class Tooltip extends Canvas implements MouseListener,
-        MouseMotionListener
+public class Tooltip extends Canvas
+        implements MouseListener, MouseMotionListener
 {
   private String[] tip;
 
@@ -91,8 +91,8 @@ public class Tooltip extends Canvas implements MouseListener,
       {
         if (lindex > 0)
         {
-          g.drawString(tip[i].substring(0, lindex), 3, (i + 1) * fontHeight
-                  - 3);
+          g.drawString(tip[i].substring(0, lindex), 3,
+                  (i + 1) * fontHeight - 3);
           x += fm.stringWidth(tip[i].substring(0, lindex) + 3);
         }
         g.drawImage(linkImage, x, i * fontHeight + 1, this);
@@ -155,11 +155,11 @@ public class Tooltip extends Canvas implements MouseListener,
       return;
     }
     setLocation(
-            (owner.getLocationOnScreen().x - mainContainer.getLocationOnScreen().x)
-                    + evt.getX(),
+            (owner.getLocationOnScreen().x
+                    - mainContainer.getLocationOnScreen().x) + evt.getX(),
             (owner.getLocationOnScreen().y
-                    - mainContainer.getLocationOnScreen().y + VERTICAL_OFFSET)
-                    + evt.getY());
+                    - mainContainer.getLocationOnScreen().y
+                    + VERTICAL_OFFSET) + evt.getY());
 
     // correction, whole tool tip must be visible
     if (mainContainer.getSize().width < (getLocation().x + getSize().width))
index 272a2b3..6ee75bd 100755 (executable)
@@ -51,8 +51,8 @@ import java.util.Hashtable;
 import java.util.List;
 import java.util.Vector;
 
-public class TreeCanvas extends Panel implements MouseListener,
-        MouseMotionListener
+public class TreeCanvas extends Panel
+        implements MouseListener, MouseMotionListener
 {
   TreeModel tree;
 
@@ -210,8 +210,9 @@ public class TreeCanvas extends Panel implements MouseListener,
         g.drawString(nodeLabel, xstart + 2, ypos - 2);
       }
 
-      String name = (markPlaceholders && node.isPlaceholder()) ? (PLACEHOLDER + node
-              .getName()) : node.getName();
+      String name = (markPlaceholders && node.isPlaceholder())
+              ? (PLACEHOLDER + node.getName())
+              : node.getName();
       FontMetrics fm = g.getFontMetrics(font);
       int charWidth = fm.stringWidth(name) + 3;
       int charHeight = fm.getHeight();
@@ -261,11 +262,10 @@ public class TreeCanvas extends Panel implements MouseListener,
         g.fillRect(xend - 2, ypos - 2, 4, 4);
       }
 
-      int ystart = (int) (node.left() == null ? 0 : (((SequenceNode) node
-              .left()).ycount * chunk))
-              + offy;
-      int yend = (int) (node.right() == null ? 0 : (((SequenceNode) node
-              .right()).ycount * chunk)) + offy;
+      int ystart = (int) (node.left() == null ? 0
+              : (((SequenceNode) node.left()).ycount * chunk)) + offy;
+      int yend = (int) (node.right() == null ? 0
+              : (((SequenceNode) node.right()).ycount * chunk)) + offy;
 
       Rectangle pos = new Rectangle(xend - 2, ypos - 2, 5, 5);
       nodeHash.put(node, pos);
@@ -491,7 +491,8 @@ public class TreeCanvas extends Panel implements MouseListener,
         g.setColor(Color.gray);
       }
 
-      int x = (int) (threshold * (getSize().width - labelLength - 2 * offx) + offx);
+      int x = (int) (threshold * (getSize().width - labelLength - 2 * offx)
+              + offx);
 
       g.drawLine(x, 0, x, getSize().height);
     }
@@ -656,9 +657,8 @@ public class TreeCanvas extends Panel implements MouseListener,
         }
         else
         {
-          cs = ColourSchemeProperty.getColourScheme(sg,
-                  ColourSchemeProperty.getColourName(av
-                          .getGlobalColourScheme()));
+          cs = ColourSchemeProperty.getColourScheme(sg, ColourSchemeProperty
+                  .getColourName(av.getGlobalColourScheme()));
         }
         // cs is null if shading is an annotationColourGradient
         // if (cs != null)
index c7bf6aa..b5e3342 100644 (file)
@@ -45,8 +45,8 @@ import java.awt.event.ActionListener;
 import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
 
-public class TreePanel extends EmbmenuFrame implements ActionListener,
-        ItemListener
+public class TreePanel extends EmbmenuFrame
+        implements ActionListener, ItemListener
 {
   SequenceI[] seq;
 
@@ -160,8 +160,8 @@ public class TreePanel extends EmbmenuFrame implements ActionListener,
         AlignFrame af = new AlignFrame(al, av.applet,
                 "Original Data for Tree", false);
 
-        af.viewport.getAlignment().setHiddenColumns(
-                (HiddenColumns) alAndColsel[1]);
+        af.viewport.getAlignment()
+                .setHiddenColumns((HiddenColumns) alAndColsel[1]);
       }
     }
     else
@@ -194,8 +194,8 @@ public class TreePanel extends EmbmenuFrame implements ActionListener,
         ScoreModelI sm1 = ScoreModels.getInstance().getScoreModel(pwtype,
                 treeCanvas.ap);
         ScoreModelI sm = sm1;
-        TreeBuilder njtree = type.equals(TreeBuilder.NEIGHBOUR_JOINING) ? new NJTree(
-                av, sm, SimilarityParams.Jalview)
+        TreeBuilder njtree = type.equals(TreeBuilder.NEIGHBOUR_JOINING)
+                ? new NJTree(av, sm, SimilarityParams.Jalview)
                 : new AverageDistanceTree(av, sm, SimilarityParams.Jalview);
         tree = new TreeModel(njtree);
       }
@@ -217,8 +217,8 @@ public class TreePanel extends EmbmenuFrame implements ActionListener,
         bootstrapMenu.setState(showBoots);
         treeCanvas.setShowBootstrap(showBoots);
         treeCanvas.setShowDistances(showDist);
-        treeCanvas.setMarkPlaceholders(av.applet.getDefaultParameter(
-                "showUnlinkedTreeNodes", false));
+        treeCanvas.setMarkPlaceholders(av.applet
+                .getDefaultParameter("showUnlinkedTreeNodes", false));
       }
 
       treeCanvas.repaint();
@@ -336,13 +336,13 @@ public class TreePanel extends EmbmenuFrame implements ActionListener,
     jMenu2.setLabel(MessageManager.getString("action.view"));
     fontSize.setLabel(MessageManager.getString("action.font"));
     fontSize.addActionListener(this);
-    bootstrapMenu.setLabel(MessageManager
-            .getString("label.show_bootstrap_values"));
+    bootstrapMenu.setLabel(
+            MessageManager.getString("label.show_bootstrap_values"));
     bootstrapMenu.addItemListener(this);
     distanceMenu.setLabel(MessageManager.getString("label.show_distances"));
     distanceMenu.addItemListener(this);
-    placeholdersMenu.setLabel(MessageManager
-            .getString("label.mark_unassociated_leaves"));
+    placeholdersMenu.setLabel(
+            MessageManager.getString("label.mark_unassociated_leaves"));
     placeholdersMenu.addItemListener(this);
     fitToWindow.setState(true);
     fitToWindow.setLabel(MessageManager.getString("label.fit_to_window"));
index 845110e..6831a73 100644 (file)
@@ -54,8 +54,8 @@ import java.awt.event.FocusListener;
 import java.awt.event.MouseEvent;
 import java.util.Vector;
 
-public class UserDefinedColours extends Panel implements ActionListener,
-        AdjustmentListener, FocusListener
+public class UserDefinedColours extends Panel
+        implements ActionListener, AdjustmentListener, FocusListener
 {
 
   AlignmentPanel ap;
@@ -64,7 +64,7 @@ public class UserDefinedColours extends Panel implements ActionListener,
 
   Button selectedButton;
 
-  Vector<Color> oldColours = new Vector<Color>();
+  Vector<Color> oldColours = new Vector<>();
 
   ColourSchemeI oldColourScheme;
 
@@ -214,9 +214,8 @@ public class UserDefinedColours extends Panel implements ActionListener,
       // // not 1.1 compatible!
       // dialog = new Dialog(((JVDialog)alignframe), title, true);
       // } else {
-      throw new Error(
-              MessageManager
-                      .getString("label.error_unsupported_owwner_user_colour_scheme"));
+      throw new Error(MessageManager.getString(
+              "label.error_unsupported_owwner_user_colour_scheme"));
     }
 
     dialog.add(this);
@@ -225,11 +224,12 @@ public class UserDefinedColours extends Panel implements ActionListener,
     int height = 160 + alignframe.getInsets().top + getInsets().bottom;
     int width = 400;
 
-    dialog.setBounds(alignframe.getBounds().x
-            + (alignframe.getSize().width - width) / 2,
+    dialog.setBounds(
+            alignframe.getBounds().x
+                    + (alignframe.getSize().width - width) / 2,
             alignframe.getBounds().y
-                    + (alignframe.getSize().height - height) / 2, width,
-            height);
+                    + (alignframe.getSize().height - height) / 2,
+            width, height);
 
   }
 
@@ -520,7 +520,7 @@ public class UserDefinedColours extends Panel implements ActionListener,
                 ap.av.isIgnoreGapsConsensus());
       }
       ap.seqPanel.seqCanvas.img = null;
-      ap.paintAlignment(true);
+      ap.paintAlignment(true, true);
     }
     else if (jmol != null)
     {
@@ -599,7 +599,7 @@ public class UserDefinedColours extends Panel implements ActionListener,
       {
         ap.av.setGlobalColourScheme(oldColourScheme);
       }
-      ap.paintAlignment(true);
+      ap.paintAlignment(true, true);
     }
 
     frame.setVisible(false);
index da3cb92..dc50843 100755 (executable)
@@ -77,7 +77,8 @@ import org.apache.log4j.SimpleLayout;
  * <li>SHOW_FULLSCREEN boolean</li>
  * <li>FONT_NAME java font name for alignment text display</li>
  * <li>FONT_SIZE size of displayed alignment text</li>
- * <li>FONT_STYLE style of font displayed (sequence labels are always italic)</li>
+ * <li>FONT_STYLE style of font displayed (sequence labels are always
+ * italic)</li>
  * <li>GAP_SYMBOL character to treat as gap symbol (usually -,.,' ')</li>
  * <li>LAST_DIRECTORY last directory for browsing alignment</li>
  * <li>USER_DEFINED_COLOURS list of user defined colour scheme files</li>
@@ -237,8 +238,7 @@ public class Cache
    * Sifts settings
    */
   public static final String DEFAULT_SIFTS_DOWNLOAD_DIR = System
-          .getProperty("user.home")
-          + File.separatorChar
+          .getProperty("user.home") + File.separatorChar
           + ".sifts_downloads" + File.separatorChar;
 
   private final static String DEFAULT_CACHE_THRESHOLD_IN_DAYS = "2";
@@ -310,8 +310,8 @@ public class Cache
       Logger lcastor = Logger.getLogger("org.exolab.castor");
       jalview.bin.Cache.log = Logger.getLogger("jalview.bin.Jalview");
 
-      laxis.setLevel(Level.toLevel(Cache.getDefault("logs.Axis.Level",
-              Level.INFO.toString())));
+      laxis.setLevel(Level.toLevel(
+              Cache.getDefault("logs.Axis.Level", Level.INFO.toString())));
       lcastor.setLevel(Level.toLevel(Cache.getDefault("logs.Castor.Level",
               Level.INFO.toString())));
       lcastor = Logger.getLogger("org.exolab.castor.xml");
@@ -320,8 +320,8 @@ public class Cache
       // lcastor = Logger.getLogger("org.exolab.castor.xml.Marshaller");
       // lcastor.setLevel(Level.toLevel(Cache.getDefault("logs.Castor.Level",
       // Level.INFO.toString())));
-      jalview.bin.Cache.log.setLevel(Level.toLevel(Cache.getDefault(
-              "logs.Jalview.level", Level.INFO.toString())));
+      jalview.bin.Cache.log.setLevel(Level.toLevel(Cache
+              .getDefault("logs.Jalview.level", Level.INFO.toString())));
       // laxis.addAppender(ap);
       // lcastor.addAppender(ap);
       // jalview.bin.Cache.log.addAppender(ap);
@@ -355,10 +355,10 @@ public class Cache
       try
       {
         fis = new java.net.URL(propertiesFile).openStream();
-        System.out.println("Loading jalview properties from : "
-                + propertiesFile);
-        System.out
-                .println("Disabling Jalview writing to user's local properties file.");
+        System.out.println(
+                "Loading jalview properties from : " + propertiesFile);
+        System.out.println(
+                "Disabling Jalview writing to user's local properties file.");
         propsAreReadOnly = true;
 
       } catch (Exception ex)
@@ -382,8 +382,8 @@ public class Cache
 
     if (getDefault("USE_PROXY", false))
     {
-      String proxyServer = getDefault("PROXY_SERVER", ""), proxyPort = getDefault(
-              "PROXY_PORT", "8080");
+      String proxyServer = getDefault("PROXY_SERVER", ""),
+              proxyPort = getDefault("PROXY_PORT", "8080");
 
       System.out.println("Using proxyServer: " + proxyServer
               + " proxyPort: " + proxyPort);
@@ -395,9 +395,9 @@ public class Cache
     // LOAD THE AUTHORS FROM THE authors.props file
     try
     {
-      String authorDetails = "jar:".concat(Cache.class
-              .getProtectionDomain().getCodeSource().getLocation()
-              .toString().concat("!/authors.props"));
+      String authorDetails = "jar:"
+              .concat(Cache.class.getProtectionDomain().getCodeSource()
+                      .getLocation().toString().concat("!/authors.props"));
 
       java.net.URL localJarFileURL = new java.net.URL(authorDetails);
 
@@ -451,16 +451,16 @@ public class Cache
     SiftsSettings
             .setMapWithSifts(Cache.getDefault("MAP_WITH_SIFTS", false));
 
-    SiftsSettings.setSiftDownloadDirectory(jalview.bin.Cache.getDefault(
-            "sifts_download_dir", DEFAULT_SIFTS_DOWNLOAD_DIR));
+    SiftsSettings.setSiftDownloadDirectory(jalview.bin.Cache
+            .getDefault("sifts_download_dir", DEFAULT_SIFTS_DOWNLOAD_DIR));
 
-    SiftsSettings.setFailSafePIDThreshold(jalview.bin.Cache.getDefault(
-            "sifts_fail_safe_pid_threshold",
-            DEFAULT_FAIL_SAFE_PID_THRESHOLD));
+    SiftsSettings.setFailSafePIDThreshold(
+            jalview.bin.Cache.getDefault("sifts_fail_safe_pid_threshold",
+                    DEFAULT_FAIL_SAFE_PID_THRESHOLD));
 
-    SiftsSettings.setCacheThresholdInDays(jalview.bin.Cache.getDefault(
-            "sifts_cache_threshold_in_days",
-            DEFAULT_CACHE_THRESHOLD_IN_DAYS));
+    SiftsSettings.setCacheThresholdInDays(
+            jalview.bin.Cache.getDefault("sifts_cache_threshold_in_days",
+                    DEFAULT_CACHE_THRESHOLD_IN_DAYS));
 
     IdOrgSettings.setUrl(getDefault("ID_ORG_HOSTURL",
             "http://www.jalview.org/services/identifiers"));
@@ -478,8 +478,7 @@ public class Cache
     // "DEFAULT_PDB_FILE_PARSER", DEFAULT_PDB_FILE_PARSER));
     // jnlpVersion will be null if we're using InstallAnywhere
     // Dont do this check if running in headless mode
-    if (jnlpVersion == null
-            && getDefault("VERSION_CHECK", true)
+    if (jnlpVersion == null && getDefault("VERSION_CHECK", true)
             && (System.getProperty("java.awt.headless") == null || System
                     .getProperty("java.awt.headless").equals("false")))
     {
@@ -502,11 +501,11 @@ public class Cache
           {
             System.setProperty("sun.net.client.defaultConnectTimeout",
                     "5000");
-            java.net.URL url = new java.net.URL(Cache.getDefault(
-                    "www.jalview.org", "http://www.jalview.org")
+            java.net.URL url = new java.net.URL(Cache
+                    .getDefault("www.jalview.org", "http://www.jalview.org")
                     + "/webstart/jalview.jnlp");
-            BufferedReader in = new BufferedReader(new InputStreamReader(
-                    url.openStream()));
+            BufferedReader in = new BufferedReader(
+                    new InputStreamReader(url.openStream()));
             String line = null;
             while ((line = in.readLine()) != null)
             {
@@ -522,8 +521,8 @@ public class Cache
             }
           } catch (Exception ex)
           {
-            System.out
-                    .println("Non-fatal exception when checking version at www.jalview.org :");
+            System.out.println(
+                    "Non-fatal exception when checking version at www.jalview.org :");
             System.out.println(ex);
             remoteVersion = getProperty("VERSION");
           }
@@ -638,8 +637,8 @@ public class Cache
       }
     } catch (Exception ex)
     {
-      System.out.println("Error setting property: " + key + " " + obj
-              + "\n" + ex);
+      System.out.println(
+              "Error setting property: " + key + " " + obj + "\n" + ex);
     }
     return obj;
   }
@@ -690,15 +689,15 @@ public class Cache
     {
       try
       {
-        if (jalview.jbgui.GDesktop.class.getClassLoader().loadClass(
-                "uk.ac.vamsas.client.VorbaId") != null)
+        if (jalview.jbgui.GDesktop.class.getClassLoader()
+                .loadClass("uk.ac.vamsas.client.VorbaId") != null)
         {
-          jalview.bin.Cache.log
-                  .debug("Found Vamsas Classes (uk.ac..vamsas.client.VorbaId can be loaded)");
+          jalview.bin.Cache.log.debug(
+                  "Found Vamsas Classes (uk.ac..vamsas.client.VorbaId can be loaded)");
           vamsasJarsArePresent = 1;
           Logger lvclient = Logger.getLogger("uk.ac.vamsas");
-          lvclient.setLevel(Level.toLevel(Cache.getDefault(
-                  "logs.Vamsas.Level", Level.INFO.toString())));
+          lvclient.setLevel(Level.toLevel(Cache
+                  .getDefault("logs.Vamsas.Level", Level.INFO.toString())));
 
           lvclient.addAppender(log.getAppender("JalviewLogger"));
           // Tell the user that debug is enabled
@@ -729,15 +728,15 @@ public class Cache
     {
       try
       {
-        if (Cache.class.getClassLoader().loadClass(
-                "groovy.lang.GroovyObject") != null)
+        if (Cache.class.getClassLoader()
+                .loadClass("groovy.lang.GroovyObject") != null)
         {
-          jalview.bin.Cache.log
-                  .debug("Found Groovy (groovy.lang.GroovyObject can be loaded)");
+          jalview.bin.Cache.log.debug(
+                  "Found Groovy (groovy.lang.GroovyObject can be loaded)");
           groovyJarsArePresent = 1;
           Logger lgclient = Logger.getLogger("groovy");
-          lgclient.setLevel(Level.toLevel(Cache.getDefault(
-                  "logs.Groovy.Level", Level.INFO.toString())));
+          lgclient.setLevel(Level.toLevel(Cache
+                  .getDefault("logs.Groovy.Level", Level.INFO.toString())));
 
           lgclient.addAppender(log.getAppender("JalviewLogger"));
           // Tell the user that debug is enabled
@@ -778,15 +777,14 @@ public class Cache
         // try to get the tracker class
         try
         {
-          jgoogleanalyticstracker = Cache.class
-                  .getClassLoader()
-                  .loadClass(
-                          "com.boxysystems.jgoogleanalytics.JGoogleAnalyticsTracker");
-          trackerfocus = Cache.class.getClassLoader().loadClass(
-                  "com.boxysystems.jgoogleanalytics.FocusPoint");
+          jgoogleanalyticstracker = Cache.class.getClassLoader().loadClass(
+                  "com.boxysystems.jgoogleanalytics.JGoogleAnalyticsTracker");
+          trackerfocus = Cache.class.getClassLoader()
+                  .loadClass("com.boxysystems.jgoogleanalytics.FocusPoint");
         } catch (Exception e)
         {
-          log.debug("com.boxysystems.jgoogleanalytics package is not present - tracking not enabled.");
+          log.debug(
+                  "com.boxysystems.jgoogleanalytics package is not present - tracking not enabled.");
           tracker = null;
           jgoogleanalyticstracker = null;
           trackerfocus = null;
@@ -800,22 +798,22 @@ public class Cache
       try
       {
         // Google analytics tracking code for Library Finder
-        tracker = jgoogleanalyticstracker.getConstructor(
-                new Class[] { String.class, String.class, String.class })
-                .newInstance(
-                        new Object[] {
-                            "Jalview Desktop",
-                            (vrs = jalview.bin.Cache.getProperty("VERSION")
-                                    + "_"
-                                    + jalview.bin.Cache.getDefault(
-                                            "BUILD_DATE", "unknown")),
-                            "UA-9060947-1" });
-        jgoogleanalyticstracker.getMethod("trackAsynchronously",
-                new Class[] { trackerfocus }).invoke(
-                tracker,
-                new Object[] { trackerfocus.getConstructor(
-                        new Class[] { String.class }).newInstance(
-                        new Object[] { "Application Started." }) });
+        tracker = jgoogleanalyticstracker
+                .getConstructor(new Class[]
+                { String.class, String.class, String.class })
+                .newInstance(new Object[]
+                { "Jalview Desktop",
+                    (vrs = jalview.bin.Cache.getProperty("VERSION") + "_"
+                            + jalview.bin.Cache.getDefault("BUILD_DATE",
+                                    "unknown")),
+                    "UA-9060947-1" });
+        jgoogleanalyticstracker
+                .getMethod("trackAsynchronously", new Class[]
+                { trackerfocus })
+                .invoke(tracker, new Object[]
+                { trackerfocus.getConstructor(new Class[] { String.class })
+                        .newInstance(new Object[]
+                        { "Application Started." }) });
       } catch (RuntimeException e)
       {
         re = e;
@@ -832,42 +830,45 @@ public class Cache
         {
           if (re != null)
           {
-            log.debug("Caught runtime exception in googletracker init:", re);
+            log.debug("Caught runtime exception in googletracker init:",
+                    re);
           }
           if (ex != null)
           {
             log.warn(
                     "Failed to initialise GoogleTracker for Jalview Desktop with version "
-                            + vrs, ex);
+                            + vrs,
+                    ex);
           }
           if (err != null)
           {
             log.error(
                     "Whilst initing GoogleTracker for Jalview Desktop version "
-                            + vrs, err);
+                            + vrs,
+                    err);
           }
         }
         else
         {
           if (re != null)
           {
-            System.err
-                    .println("Debug: Caught runtime exception in googletracker init:"
+            System.err.println(
+                    "Debug: Caught runtime exception in googletracker init:"
                             + vrs);
             re.printStackTrace();
           }
           if (ex != null)
           {
-            System.err
-                    .println("Warning:  Failed to initialise GoogleTracker for Jalview Desktop with version "
+            System.err.println(
+                    "Warning:  Failed to initialise GoogleTracker for Jalview Desktop with version "
                             + vrs);
             ex.printStackTrace();
           }
 
           if (err != null)
           {
-            System.err
-                    .println("ERROR: Whilst initing GoogleTracker for Jalview Desktop version "
+            System.err.println(
+                    "ERROR: Whilst initing GoogleTracker for Jalview Desktop version "
                             + vrs);
             err.printStackTrace();
           }
@@ -1028,7 +1029,7 @@ public class Cache
     {
       return;
     }
-  
+
     // In case colours can't be loaded, we'll remove them
     // from the default list here.
     StringBuffer coloursFound = new StringBuffer();
@@ -1057,11 +1058,13 @@ public class Cache
     {
       if (coloursFound.toString().length() > 1)
       {
-        setProperty(UserDefinedColours.USER_DEFINED_COLOURS, coloursFound.toString());
+        setProperty(UserDefinedColours.USER_DEFINED_COLOURS,
+                coloursFound.toString());
       }
       else
       {
-        applicationProperties.remove(UserDefinedColours.USER_DEFINED_COLOURS);
+        applicationProperties
+                .remove(UserDefinedColours.USER_DEFINED_COLOURS);
       }
     }
   }
index 954bb34..9ec0033 100755 (executable)
@@ -188,8 +188,8 @@ public class Jalview
   void doMain(String[] args)
   {
     System.setSecurityManager(null);
-    System.out.println("Java version: "
-            + System.getProperty("java.version"));
+    System.out
+            .println("Java version: " + System.getProperty("java.version"));
     System.out.println(System.getProperty("os.arch") + " "
             + System.getProperty("os.name") + " "
             + System.getProperty("os.version"));
@@ -212,8 +212,8 @@ public class Jalview
     Cache.loadProperties(usrPropsFile); // must do this before
     if (usrPropsFile != null)
     {
-      System.out.println("CMD [-props " + usrPropsFile
-              + "] executed successfully!");
+      System.out.println(
+              "CMD [-props " + usrPropsFile + "] executed successfully!");
     }
 
     // anything else!
@@ -224,12 +224,12 @@ public class Jalview
       try
       {
         Jws2Discoverer.getDiscoverer().setPreferredUrl(jabawsUrl);
-        System.out.println("CMD [-jabaws " + jabawsUrl
-                + "] executed successfully!");
+        System.out.println(
+                "CMD [-jabaws " + jabawsUrl + "] executed successfully!");
       } catch (MalformedURLException e)
       {
-        System.err.println("Invalid jabaws parameter: " + jabawsUrl
-                + " ignored");
+        System.err.println(
+                "Invalid jabaws parameter: " + jabawsUrl + " ignored");
       }
     }
 
@@ -263,9 +263,8 @@ public class Jalview
     } catch (NoClassDefFoundError error)
     {
       error.printStackTrace();
-      System.out
-              .println("\nEssential logging libraries not found."
-                      + "\nUse: java -Djava.ext.dirs=$PATH_TO_LIB$ jalview.bin.Jalview");
+      System.out.println("\nEssential logging libraries not found."
+              + "\nUse: java -Djava.ext.dirs=$PATH_TO_LIB$ jalview.bin.Jalview");
       System.exit(0);
     }
 
@@ -284,12 +283,12 @@ public class Jalview
       System.setProperty("apple.laf.useScreenMenuBar", "true");
       try
       {
-        UIManager.setLookAndFeel(ch.randelshofer.quaqua.QuaquaManager
-                .getLookAndFeel());
+        UIManager.setLookAndFeel(
+                ch.randelshofer.quaqua.QuaquaManager.getLookAndFeel());
       } catch (Throwable e)
       {
-        System.err.println("Failed to set QuaQua look and feel: "
-                + e.toString());
+        System.err.println(
+                "Failed to set QuaQua look and feel: " + e.toString());
       }
     }
 
@@ -326,8 +325,8 @@ public class Jalview
           // questionnaire
           Cache.log.debug("Starting questionnaire url at " + url);
           desktop.checkForQuestionnaire(url);
-          System.out.println("CMD questionnaire[-" + url
-                  + "] executed successfully!");
+          System.out.println(
+                  "CMD questionnaire[-" + url + "] executed successfully!");
         }
         else
         {
@@ -339,8 +338,8 @@ public class Jalview
             // "http://anaplog.compbio.dundee.ac.uk/cgi-bin/questionnaire.pl";
             // //
             String defurl = "http://www.jalview.org/cgi-bin/questionnaire.pl";
-            Cache.log.debug("Starting questionnaire with default url: "
-                    + defurl);
+            Cache.log.debug(
+                    "Starting questionnaire with default url: " + defurl);
             desktop.checkForQuestionnaire(defurl);
           }
         }
@@ -383,8 +382,8 @@ public class Jalview
     {
       if (desktop == null || headless)
       {
-        System.out
-                .println("Headless vamsas sessions not yet supported. Sorry.");
+        System.out.println(
+                "Headless vamsas sessions not yet supported. Sorry.");
         System.exit(1);
       }
       // if we have a file, start a new session and import it.
@@ -434,8 +433,8 @@ public class Jalview
         {
           if (desktop.joinVamsasSession(vamsasSession))
           {
-            System.out.println("Successfully joined vamsas session "
-                    + vamsasSession);
+            System.out.println(
+                    "Successfully joined vamsas session " + vamsasSession);
           }
           else
           {
@@ -444,16 +443,16 @@ public class Jalview
           }
         } catch (Exception e)
         {
-          System.err.println("ERROR: Failed to join vamsas session "
-                  + vamsasSession);
+          System.err.println(
+                  "ERROR: Failed to join vamsas session " + vamsasSession);
           e.printStackTrace();
         }
         if (vamsasImport != null)
         {
           // the Jalview specific remnants can now be imported into the new
           // session at the user's leisure.
-          Cache.log
-                  .info("Skipping Push for import of data into existing vamsas session."); // TODO:
+          Cache.log.info(
+                  "Skipping Push for import of data into existing vamsas session."); // TODO:
           // enable
           // this
           // when
@@ -468,8 +467,9 @@ public class Jalview
     {
       if (!headless)
       {
-        desktop.setProgressBar(MessageManager
-                .getString("status.processing_commandline_args"),
+        desktop.setProgressBar(
+                MessageManager
+                        .getString("status.processing_commandline_args"),
                 progress = System.currentTimeMillis());
       }
       System.out.println("CMD [-open " + file + "] executed successfully!");
@@ -510,13 +510,13 @@ public class Jalview
         {
           data.replaceAll("%20", " ");
 
-          ColourSchemeI cs = ColourSchemeProperty.getColourScheme(af
-                  .getViewport().getAlignment(), data);
+          ColourSchemeI cs = ColourSchemeProperty
+                  .getColourScheme(af.getViewport().getAlignment(), data);
 
           if (cs != null)
           {
-            System.out.println("CMD [-color " + data
-                    + "] executed successfully!");
+            System.out.println(
+                    "CMD [-color " + data + "] executed successfully!");
           }
           af.changeColour(cs);
         }
@@ -528,8 +528,8 @@ public class Jalview
           af.parseFeaturesFile(data,
                   AppletFormatAdapter.checkProtocol(data));
           // System.out.println("Added " + data);
-          System.out.println("CMD groups[-" + data
-                  + "]  executed successfully!");
+          System.out.println(
+                  "CMD groups[-" + data + "]  executed successfully!");
         }
         data = aparser.getValue("features", true);
         if (data != null)
@@ -537,8 +537,8 @@ public class Jalview
           af.parseFeaturesFile(data,
                   AppletFormatAdapter.checkProtocol(data));
           // System.out.println("Added " + data);
-          System.out.println("CMD [-features " + data
-                  + "]  executed successfully!");
+          System.out.println(
+                  "CMD [-features " + data + "]  executed successfully!");
         }
 
         data = aparser.getValue("annotations", true);
@@ -546,8 +546,8 @@ public class Jalview
         {
           af.loadJalviewDataFile(data, null, null, null);
           // System.out.println("Added " + data);
-          System.out.println("CMD [-annotations " + data
-                  + "] executed successfully!");
+          System.out.println(
+                  "CMD [-annotations " + data + "] executed successfully!");
         }
         // set or clear the sortbytree flag.
         if (aparser.contains("sortbytree"))
@@ -580,12 +580,12 @@ public class Jalview
         {
           try
           {
-            System.out.println("CMD [-tree " + data
-                    + "] executed successfully!");
+            System.out.println(
+                    "CMD [-tree " + data + "] executed successfully!");
             NewickFile nf = new NewickFile(data,
                     AppletFormatAdapter.checkProtocol(data));
-            af.getViewport().setCurrentTree(
-                    af.showNewickTree(nf, data).getTree());
+            af.getViewport()
+                    .setCurrentTree(af.showNewickTree(nf, data).getTree());
           } catch (IOException ex)
           {
             System.err.println("Couldn't add tree " + data);
@@ -666,16 +666,16 @@ public class Jalview
             }
             try
             {
-              BioJsHTMLOutput
-                      .refreshVersionInfo(BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
+              BioJsHTMLOutput.refreshVersionInfo(
+                      BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
             } catch (URISyntaxException e)
             {
               e.printStackTrace();
             }
             BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
             bjs.exportHTML(file);
-            System.out.println("Creating BioJS MSA Viwer HTML file: "
-                    + file);
+            System.out
+                    .println("Creating BioJS MSA Viwer HTML file: " + file);
             continue;
           }
           else if (outputFormat.equalsIgnoreCase("imgMap"))
@@ -687,8 +687,8 @@ public class Jalview
           else if (outputFormat.equalsIgnoreCase("eps"))
           {
             File outputFile = new File(file);
-            System.out.println("Creating EPS file: "
-                    + outputFile.getAbsolutePath());
+            System.out.println(
+                    "Creating EPS file: " + outputFile.getAbsolutePath());
             af.createEPS(outputFile);
             continue;
           }
@@ -720,12 +720,12 @@ public class Jalview
     if (!headless && file == null && vamsasImport == null
             && jalview.bin.Cache.getDefault("SHOW_STARTUP_FILE", true))
     {
-      file = jalview.bin.Cache.getDefault(
-              "STARTUP_FILE",
+      file = jalview.bin.Cache.getDefault("STARTUP_FILE",
               jalview.bin.Cache.getDefault("www.jalview.org",
                       "http://www.jalview.org")
                       + "/examples/exampleFile_2_7.jar");
-      if (file.equals("http://www.jalview.org/examples/exampleFile_2_3.jar"))
+      if (file.equals(
+              "http://www.jalview.org/examples/exampleFile_2_3.jar"))
       {
         // hardwire upgrade of the startup file
         file.replace("_2_3.jar", "_2_7.jar");
@@ -781,8 +781,8 @@ public class Jalview
       }
       else
       {
-        System.err
-                .println("Sorry. Groovy Support is not available, so ignoring the provided groovy script "
+        System.err.println(
+                "Sorry. Groovy Support is not available, so ignoring the provided groovy script "
                         + groovyscript);
       }
     }
@@ -799,8 +799,8 @@ public class Jalview
 
   private static void showUsage()
   {
-    System.out
-            .println("Usage: jalview -open [FILE] [OUTPUT_FORMAT] [OUTPUT_FILE]\n\n"
+    System.out.println(
+            "Usage: jalview -open [FILE] [OUTPUT_FORMAT] [OUTPUT_FILE]\n\n"
                     + "-nodisplay\tRun Jalview without User Interface.\n"
                     + "-props FILE\tUse the given Jalview properties file instead of users default.\n"
                     + "-colour COLOURSCHEME\tThe colourscheme to be applied to the alignment\n"
@@ -828,14 +828,18 @@ public class Jalview
                     + "-nousagestats\tTurn off google analytics tracking for this session.\n"
                     + "-sortbytree OR -nosortbytree\tEnable or disable sorting of the given alignment by the given tree\n"
                     // +
-                    // "-setprop PROPERTY=VALUE\tSet the given Jalview property, after all other properties files have been read\n\t (quote the 'PROPERTY=VALUE' pair to ensure spaces are passed in correctly)"
+                    // "-setprop PROPERTY=VALUE\tSet the given Jalview property,
+                    // after all other properties files have been read\n\t
+                    // (quote the 'PROPERTY=VALUE' pair to ensure spaces are
+                    // passed in correctly)"
                     + "-jabaws URL\tSpecify URL for Jabaws services (e.g. for a local installation).\n"
                     + "-dasserver nickname=URL\tAdd and enable a das server with given nickname\n\t\t\t(alphanumeric or underscores only) for retrieval of features for all alignments.\n"
                     + "\t\t\tSources that also support the sequence command may be specified by prepending the URL with sequence:\n"
                     + "\t\t\t e.g. sequence:http://localdas.somewhere.org/das/source)\n"
                     + "-fetchfrom nickname\tQuery nickname for features for the alignments and display them.\n"
                     // +
-                    // "-vdoc vamsas-document\tImport vamsas document into new session or join existing session with same URN\n"
+                    // "-vdoc vamsas-document\tImport vamsas document into new
+                    // session or join existing session with same URN\n"
                     // + "-vses vamsas-session\tJoin session with given URN\n"
                     + "-groovy FILE\tExecute groovy script in FILE, after all other arguments have been processed (if FILE is the text 'STDIN' then the file will be read from STDIN)\n"
                     + "\n~Read documentation in Application or visit http://www.jalview.org for description of Features and Annotations file~\n\n");
@@ -846,10 +850,8 @@ public class Jalview
     /**
      * start a User Config prompt asking if we can log usage statistics.
      */
-    PromptUserConfig prompter = new PromptUserConfig(
-            Desktop.desktop,
-            "USAGESTATS",
-            "Jalview Usage Statistics",
+    PromptUserConfig prompter = new PromptUserConfig(Desktop.desktop,
+            "USAGESTATS", "Jalview Usage Statistics",
             "Do you want to help make Jalview better by enabling "
                     + "the collection of usage statistics with Google Analytics ?"
                     + "\n\n(you can enable or disable usage tracking in the preferences)",
@@ -858,8 +860,8 @@ public class Jalview
               @Override
               public void run()
               {
-                Cache.log
-                        .debug("Initialising googletracker for usage stats.");
+                Cache.log.debug(
+                        "Initialising googletracker for usage stats.");
                 Cache.initGoogleTracker();
                 Cache.log.debug("Tracking enabled.");
               }
@@ -899,10 +901,10 @@ public class Jalview
       try
       {
         tfile = File.createTempFile("jalview", "groovy");
-        PrintWriter outfile = new PrintWriter(new OutputStreamWriter(
-                new FileOutputStream(tfile)));
-        BufferedReader br = new BufferedReader(new InputStreamReader(
-                System.in));
+        PrintWriter outfile = new PrintWriter(
+                new OutputStreamWriter(new FileOutputStream(tfile)));
+        BufferedReader br = new BufferedReader(
+                new InputStreamReader(System.in));
         String line = null;
         while ((line = br.readLine()) != null)
         {
@@ -915,8 +917,8 @@ public class Jalview
       } catch (Exception ex)
       {
         System.err.println("Failed to read from STDIN into tempfile "
-                + ((tfile == null) ? "(tempfile wasn't created)" : tfile
-                        .toString()));
+                + ((tfile == null) ? "(tempfile wasn't created)"
+                        : tfile.toString()));
         ex.printStackTrace();
         return;
       }
@@ -925,8 +927,8 @@ public class Jalview
         sfile = tfile.toURI().toURL();
       } catch (Exception x)
       {
-        System.err
-                .println("Unexpected Malformed URL Exception for temporary file created from STDIN: "
+        System.err.println(
+                "Unexpected Malformed URL Exception for temporary file created from STDIN: "
                         + tfile.toURI());
         x.printStackTrace();
         return;
@@ -1013,9 +1015,8 @@ public class Jalview
         nickname = data.substring(0, pos);
       }
       url = data.substring(pos + 1);
-      if (url != null
-              && (url.startsWith("http:") || url
-                      .startsWith("sequence:http:")))
+      if (url != null && (url.startsWith("http:")
+              || url.startsWith("sequence:http:")))
       {
         if (nickname == null)
         {
@@ -1030,8 +1031,8 @@ public class Jalview
           locsources += "\t";
         }
         locsources = locsources + nickname + "|" + url;
-        System.err
-                .println("NOTE! dasserver parameter not yet really supported (got args of "
+        System.err.println(
+                "NOTE! dasserver parameter not yet really supported (got args of "
                         + nickname + "|" + url);
         if (source == null)
         {
@@ -1039,8 +1040,8 @@ public class Jalview
         }
         source.addElement(nickname);
       }
-      System.out.println("CMD [-dasserver " + data
-              + "] executed successfully!");
+      System.out.println(
+              "CMD [-dasserver " + data + "] executed successfully!");
     } // loop until no more server entries are found.
     if (locsources != null && locsources.indexOf('|') > -1)
     {
index dbc707d..6504290 100644 (file)
@@ -85,8 +85,8 @@ import netscape.javascript.JSObject;
  * @author $author$
  * @version $Revision: 1.92 $
  */
-public class JalviewLite extends Applet implements
-        StructureSelectionManagerProvider, JalviewLiteJsApi
+public class JalviewLite extends Applet
+        implements StructureSelectionManagerProvider, JalviewLiteJsApi
 {
 
   private static final String TRUE = "true";
@@ -208,9 +208,8 @@ public class JalviewLite extends Applet implements
       final StructureSelectionManagerProvider me = this;
       final int pos = apos;
       // use vamsas listener to broadcast to all listeners in scope
-      if (alignedPosition != null
-              && (alignedPosition.trim().length() == 0 || alignedPosition
-                      .toLowerCase().indexOf("false") > -1))
+      if (alignedPosition != null && (alignedPosition.trim().length() == 0
+              || alignedPosition.toLowerCase().indexOf("false") > -1))
       {
         java.awt.EventQueue.invokeLater(new Runnable()
         {
@@ -343,8 +342,8 @@ public class JalviewLite extends Applet implements
             from--;
           } catch (NumberFormatException ex)
           {
-            System.err
-                    .println("ERROR: Couldn't parse first integer in range element column selection string '"
+            System.err.println(
+                    "ERROR: Couldn't parse first integer in range element column selection string '"
                             + cl + "' - format is 'from-to'");
             return;
           }
@@ -354,8 +353,8 @@ public class JalviewLite extends Applet implements
             to--;
           } catch (NumberFormatException ex)
           {
-            System.err
-                    .println("ERROR: Couldn't parse second integer in range element column selection string '"
+            System.err.println(
+                    "ERROR: Couldn't parse second integer in range element column selection string '"
                             + cl + "' - format is 'from-to'");
             return;
           }
@@ -421,8 +420,8 @@ public class JalviewLite extends Applet implements
             }
             else
             {
-              System.err
-                      .println("ERROR: Couldn't parse integer from point selection element of column selection string '"
+              System.err.println(
+                      "ERROR: Couldn't parse integer from point selection element of column selection string '"
                               + cl + "'");
               return;
             }
@@ -486,8 +485,8 @@ public class JalviewLite extends Applet implements
         @Override
         public void run()
         {
-          alf.select(sel, csel, alf.getAlignViewport().getAlignment()
-                  .getHiddenColumns());
+          alf.select(sel, csel,
+                  alf.getAlignViewport().getAlignment().getHiddenColumns());
         }
       });
     }
@@ -501,7 +500,8 @@ public class JalviewLite extends Applet implements
    * String, java.lang.String)
    */
   @Override
-  public String getSelectedSequencesAsAlignment(String format, String suffix)
+  public String getSelectedSequencesAsAlignment(String format,
+          String suffix)
   {
     return getSelectedSequencesAsAlignmentFrom(getDefaultTargetFrame(),
             format, suffix);
@@ -938,8 +938,8 @@ public class JalviewLite extends Applet implements
       listener = listener.trim();
       if (listener.length() == 0)
       {
-        System.err
-                .println("jalview Javascript error: Ignoring empty function for mouseover listener.");
+        System.err.println(
+                "jalview Javascript error: Ignoring empty function for mouseover listener.");
         return;
       }
     }
@@ -951,8 +951,9 @@ public class JalviewLite extends Applet implements
     if (debug)
     {
       System.err.println("Added a mouseover listener for "
-              + ((af == null) ? "All frames" : "Just views for "
-                      + af.getAlignViewport().getSequenceSetId()));
+              + ((af == null) ? "All frames"
+                      : "Just views for "
+                              + af.getAlignViewport().getSequenceSetId()));
       System.err.println("There are now " + javascriptListeners.size()
               + " listeners in total.");
     }
@@ -984,8 +985,8 @@ public class JalviewLite extends Applet implements
       listener = listener.trim();
       if (listener.length() == 0)
       {
-        System.err
-                .println("jalview Javascript error: Ignoring empty function for selection listener.");
+        System.err.println(
+                "jalview Javascript error: Ignoring empty function for selection listener.");
         return;
       }
     }
@@ -997,8 +998,9 @@ public class JalviewLite extends Applet implements
     if (debug)
     {
       System.err.println("Added a selection listener for "
-              + ((af == null) ? "All frames" : "Just views for "
-                      + af.getAlignViewport().getSequenceSetId()));
+              + ((af == null) ? "All frames"
+                      : "Just views for "
+                              + af.getAlignViewport().getSequenceSetId()));
       System.err.println("There are now " + javascriptListeners.size()
               + " listeners in total.");
     }
@@ -1023,8 +1025,8 @@ public class JalviewLite extends Applet implements
       listener = listener.trim();
       if (listener.length() == 0)
       {
-        System.err
-                .println("jalview Javascript error: Ignoring empty function for selection listener.");
+        System.err.println(
+                "jalview Javascript error: Ignoring empty function for selection listener.");
         return;
       }
     }
@@ -1065,9 +1067,8 @@ public class JalviewLite extends Applet implements
     {
       Object lstn = javascriptListeners.elementAt(ms);
       JsCallBack lstner = (JsCallBack) lstn;
-      if ((af == null || lstner.getAlignFrame() == af)
-              && (listener == null || lstner.getListenerFunction().equals(
-                      listener)))
+      if ((af == null || lstner.getAlignFrame() == af) && (listener == null
+              || lstner.getListenerFunction().equals(listener)))
       {
         javascriptListeners.removeElement(lstner);
         msSize--;
@@ -1164,8 +1165,8 @@ public class JalviewLite extends Applet implements
    * java.lang.String, java.lang.String)
    */
   @Override
-  public void mouseOverStructure(final String pdbResNum,
-          final String chain, final String pdbfile)
+  public void mouseOverStructure(final String pdbResNum, final String chain,
+          final String pdbfile)
   {
     final StructureSelectionManagerProvider me = this;
     java.awt.EventQueue.invokeLater(new Runnable()
@@ -1180,9 +1181,9 @@ public class JalviewLite extends Applet implements
                           chain, pdbfile);
           if (debug)
           {
-            System.err.println("mouseOver for '" + pdbResNum
-                    + "' in chain '" + chain + "' in structure '" + pdbfile
-                    + "'");
+            System.err
+                    .println("mouseOver for '" + pdbResNum + "' in chain '"
+                            + chain + "' in structure '" + pdbfile + "'");
           }
         } catch (NumberFormatException e)
         {
@@ -1212,8 +1213,8 @@ public class JalviewLite extends Applet implements
       {
         try
         {
-          alf.scrollTo(new Integer(topRow).intValue(), new Integer(
-                  leftHandColumn).intValue());
+          alf.scrollTo(new Integer(topRow).intValue(),
+                  new Integer(leftHandColumn).intValue());
 
         } catch (Exception ex)
         {
@@ -1280,8 +1281,8 @@ public class JalviewLite extends Applet implements
 
         } catch (Exception ex)
         {
-          System.err
-                  .println("Couldn't parse integer arguments (leftHandColumn='"
+          System.err.println(
+                  "Couldn't parse integer arguments (leftHandColumn='"
                           + leftHandColumn + "')");
           ex.printStackTrace();
         }
@@ -1355,8 +1356,8 @@ public class JalviewLite extends Applet implements
       {
         try
         {
-          BufferedReader reader = new BufferedReader(new InputStreamReader(
-                  url.openStream()));
+          BufferedReader reader = new BufferedReader(
+                  new InputStreamReader(url.openStream()));
           String line;
           while ((line = reader.readLine()) != null)
           {
@@ -1423,8 +1424,8 @@ public class JalviewLite extends Applet implements
 
     } catch (Exception ex)
     {
-      System.err
-              .println("Warning: No JalviewLite javascript callbacks available.");
+      System.err.println(
+              "Warning: No JalviewLite javascript callbacks available.");
       if (debug)
       {
         ex.printStackTrace();
@@ -1466,9 +1467,8 @@ public class JalviewLite extends Applet implements
       }
       else
       {
-        throw new Error(
-                MessageManager
-                        .getString("error.invalid_separator_parameter"));
+        throw new Error(MessageManager
+                .getString("error.invalid_separator_parameter"));
       }
     }
     int r = 255;
@@ -1625,8 +1625,8 @@ public class JalviewLite extends Applet implements
         {
           // do onInit with the JS executor thread
           new JSFunctionExec(this).executeJavascriptFunction(true,
-                  initjscallback, null, "Calling oninit callback '"
-                          + initjscallback + "'.");
+                  initjscallback, null,
+                  "Calling oninit callback '" + initjscallback + "'.");
         } catch (Exception e)
         {
           System.err.println("Exception when executing _oninit callback '"
@@ -1737,8 +1737,8 @@ public class JalviewLite extends Applet implements
       g.fillRect(0, 0, getSize().width, getSize().height);
       g.setColor(Color.red);
       g.drawString(
-              MessageManager.getString("label.jalview_cannot_open_file"),
-              5, 15);
+              MessageManager.getString("label.jalview_cannot_open_file"), 5,
+              15);
       g.drawString("\"" + file + "\"", 5, 30);
     }
     else if (embedded)
@@ -1798,8 +1798,8 @@ public class JalviewLite extends Applet implements
           }
           if (!jmolAvailable)
           {
-            System.out
-                    .println("Jmol not available - Using MCview for structures");
+            System.out.println(
+                    "Jmol not available - Using MCview for structures");
           }
         } catch (java.lang.ClassNotFoundException ex)
         {
@@ -1810,8 +1810,8 @@ public class JalviewLite extends Applet implements
         jmolAvailable = false;
         if (debug)
         {
-          System.err
-                  .println("Skipping Jmol check. Will use MCView (probably)");
+          System.err.println(
+                  "Skipping Jmol check. Will use MCView (probably)");
         }
       }
       checkedForJmol = true;
@@ -1949,7 +1949,8 @@ public class JalviewLite extends Applet implements
      */
     private void startLoading()
     {
-      dbgMsg("Loading thread started with:\n>>file\n" + _file + ">>endfile");
+      dbgMsg("Loading thread started with:\n>>file\n" + _file
+              + ">>endfile");
 
       dbgMsg("Loading started.");
 
@@ -2050,14 +2051,14 @@ public class JalviewLite extends Applet implements
 
           if (protocol == DataSourceType.PASTE)
           {
-            newAlignFrame.setTitle(MessageManager.formatMessage(
-                    "label.sequences_from", new Object[] { applet
-                            .getDocumentBase().toString() }));
+            newAlignFrame.setTitle(MessageManager
+                    .formatMessage("label.sequences_from", new Object[]
+                    { applet.getDocumentBase().toString() }));
           }
 
           newAlignFrame.statusBar.setText(MessageManager.formatMessage(
-                  "label.successfully_loaded_file",
-                  new Object[] { resolvedFile }));
+                  "label.successfully_loaded_file", new Object[]
+                  { resolvedFile }));
 
           return newAlignFrame;
         }
@@ -2080,8 +2081,8 @@ public class JalviewLite extends Applet implements
             dbgMsg(">>>Dump finished.");
           } catch (Exception e)
           {
-            System.err
-                    .println("Exception when trying to dump the content of the file parameter.");
+            System.err.println(
+                    "Exception when trying to dump the content of the file parameter.");
             e.printStackTrace();
           }
         }
@@ -2104,8 +2105,8 @@ public class JalviewLite extends Applet implements
        * related to JAL-434
        */
 
-      applet.setAlignPdbStructures(getDefaultParameter("alignpdbfiles",
-              false));
+      applet.setAlignPdbStructures(
+              getDefaultParameter("alignpdbfiles", false));
       /*
        * <param name="PDBfile" value="1gaq.txt PDB|1GAQ|1GAQ|A PDB|1GAQ|1GAQ|B
        * PDB|1GAQ|1GAQ|C">
@@ -2121,9 +2122,11 @@ public class JalviewLite extends Applet implements
       Vector pdbs = new Vector();
       // create a lazy matcher if we're asked to
       jalview.analysis.SequenceIdMatcher matcher = (applet
-              .getDefaultParameter("relaxedidmatch", false)) ? new jalview.analysis.SequenceIdMatcher(
-              alignFrame.getAlignViewport().getAlignment()
-                      .getSequencesArray()) : null;
+              .getDefaultParameter("relaxedidmatch", false))
+                      ? new jalview.analysis.SequenceIdMatcher(
+                              alignFrame.getAlignViewport().getAlignment()
+                                      .getSequencesArray())
+                      : null;
 
       String param;
       do
@@ -2152,8 +2155,9 @@ public class JalviewLite extends Applet implements
             String sequence = applet.getParameter("PDBSEQ");
             if (sequence != null)
             {
-              seqs = new SequenceI[] { matcher == null ? (Sequence) alignFrame
-                      .getAlignViewport().getAlignment().findName(sequence)
+              seqs = new SequenceI[] { matcher == null
+                      ? (Sequence) alignFrame.getAlignViewport()
+                              .getAlignment().findName(sequence)
                       : matcher.findIdMatch(sequence) };
             }
 
@@ -2174,9 +2178,10 @@ public class JalviewLite extends Applet implements
                 tmp2.add(st2.nextToken());
                 seqstring = st2.nextToken();
               }
-              tmp.add(matcher == null ? (Sequence) alignFrame
-                      .getAlignViewport().getAlignment()
-                      .findName(seqstring) : matcher.findIdMatch(seqstring));
+              tmp.add(matcher == null
+                      ? (Sequence) alignFrame.getAlignViewport()
+                              .getAlignment().findName(seqstring)
+                      : matcher.findIdMatch(seqstring));
             }
 
             seqs = tmp.toArray(new SequenceI[tmp.size()]);
@@ -2196,8 +2201,9 @@ public class JalviewLite extends Applet implements
               if (seqs[i] != null)
               {
                 ((Sequence) seqs[i]).addPDBId(pdb);
-                StructureSelectionManager.getStructureSelectionManager(
-                        applet).registerPDBEntry(pdb);
+                StructureSelectionManager
+                        .getStructureSelectionManager(applet)
+                        .registerPDBEntry(pdb);
               }
               else
               {
@@ -2205,8 +2211,8 @@ public class JalviewLite extends Applet implements
                 {
                   // this may not really be a problem but we give a warning
                   // anyway
-                  System.err
-                          .println("Warning: Possible input parsing error: Null sequence for attachment of PDB (sequence "
+                  System.err.println(
+                          "Warning: Possible input parsing error: Null sequence for attachment of PDB (sequence "
                                   + i + ")");
                 }
               }
@@ -2232,7 +2238,8 @@ public class JalviewLite extends Applet implements
         PDBEntry[] pdb = new PDBEntry[pdbs.size()];
         String[][] chains = new String[pdbs.size()][];
         String[] protocols = new String[pdbs.size()];
-        for (int pdbsi = 0, pdbsiSize = pdbs.size(); pdbsi < pdbsiSize; pdbsi++)
+        for (int pdbsi = 0, pdbsiSize = pdbs
+                .size(); pdbsi < pdbsiSize; pdbsi++)
         {
           Object[] o = (Object[]) pdbs.elementAt(pdbsi);
           pdb[pdbsi] = (PDBEntry) o[0];
@@ -2313,8 +2320,8 @@ public class JalviewLite extends Applet implements
         }
         else
         {
-          System.err
-                  .println("Annotations were not added from annotation file '"
+          System.err.println(
+                  "Annotations were not added from annotation file '"
                           + param + "'");
         }
       }
@@ -2385,14 +2392,14 @@ public class JalviewLite extends Applet implements
         {
           if (debug)
           {
-            System.err
-                    .println("Attempting to load T-COFFEE score file from the scoreFile parameter");
+            System.err.println(
+                    "Attempting to load T-COFFEE score file from the scoreFile parameter");
           }
           result = alignFrame.loadScoreFile(sScoreFile);
           if (!result)
           {
-            System.err
-                    .println("Failed to parse T-COFFEE parameter as a valid score file ('"
+            System.err.println(
+                    "Failed to parse T-COFFEE parameter as a valid score file ('"
                             + sScoreFile + "')");
           }
         } catch (Exception e)
@@ -2489,8 +2496,8 @@ public class JalviewLite extends Applet implements
     {
       return initialAlignFrame;
     }
-    System.err
-            .println("Implementation error: Jalview Applet API cannot work out which AlignFrame to use.");
+    System.err.println(
+            "Implementation error: Jalview Applet API cannot work out which AlignFrame to use.");
     return null;
   }
 
@@ -2568,8 +2575,8 @@ public class JalviewLite extends Applet implements
     }
     if (debug)
     {
-      System.err.println("Empty Array from '" + separator
-              + "' separated List");
+      System.err.println(
+              "Empty Array from '" + separator + "' separated List");
     }
     return null;
   }
@@ -2611,16 +2618,16 @@ public class JalviewLite extends Applet implements
       }
       if (debug)
       {
-        System.err.println("Returning '" + separator
-                + "' separated List:\n");
+        System.err
+                .println("Returning '" + separator + "' separated List:\n");
         System.err.println(v);
       }
       return v.toString();
     }
     if (debug)
     {
-      System.err.println("Returning empty '" + separator
-              + "' separated List\n");
+      System.err.println(
+              "Returning empty '" + separator + "' separated List\n");
     }
     return "" + separator;
   }
@@ -2633,8 +2640,8 @@ public class JalviewLite extends Applet implements
   @Override
   public String getFeatureGroups()
   {
-    String lst = arrayToSeparatorList(getDefaultTargetFrame()
-            .getFeatureGroups());
+    String lst = arrayToSeparatorList(
+            getDefaultTargetFrame().getFeatureGroups());
     return lst;
   }
 
@@ -2660,8 +2667,8 @@ public class JalviewLite extends Applet implements
   @Override
   public String getFeatureGroupsOfState(boolean visible)
   {
-    return arrayToSeparatorList(getDefaultTargetFrame()
-            .getFeatureGroupsOfState(visible));
+    return arrayToSeparatorList(
+            getDefaultTargetFrame().getFeatureGroupsOfState(visible));
   }
 
   /*
@@ -2894,8 +2901,8 @@ public class JalviewLite extends Applet implements
     Color col = ColorUtils.parseColourString(colprop);
     if (col == null)
     {
-      System.err.println("Couldn't parse '" + colprop
-              + "' as a colour for " + colparam);
+      System.err.println("Couldn't parse '" + colprop + "' as a colour for "
+              + colparam);
     }
     return (col == null) ? defcolour : col;
   }
@@ -2930,8 +2937,7 @@ public class JalviewLite extends Applet implements
       String codebase = localref.toString();
       String localfile = localref.getFile();
       resolvedPath = codebase.substring(0,
-              codebase.length() - localfile.length())
-              + targetPath;
+              codebase.length() - localfile.length()) + targetPath;
       return resolvedPath;
     }
 
@@ -2965,8 +2971,8 @@ public class JalviewLite extends Applet implements
     }
     if (debug)
     {
-      System.err.println("resolveUrlForLocalOrAbsolute returning "
-              + resolvedPath);
+      System.err.println(
+              "resolveUrlForLocalOrAbsolute returning " + resolvedPath);
     }
     return resolvedPath;
   }
@@ -2988,17 +2994,15 @@ public class JalviewLite extends Applet implements
         // form valid URL
         // Should really use docbase, not codebase.
         URL prepend;
-        url = resolveUrlForLocalOrAbsolute(
-                url,
-                prepend = getDefaultParameter("resolvetocodebase", false) ? getCodeBase()
+        url = resolveUrlForLocalOrAbsolute(url,
+                prepend = getDefaultParameter("resolvetocodebase", false)
+                        ? getCodeBase()
                         : getDocumentBase());
         if (debug)
         {
-          System.err
-                  .println("Show url (prepended "
-                          + prepend
-                          + " - toggle resolvetocodebase if code/docbase resolution is wrong): "
-                          + url);
+          System.err.println("Show url (prepended " + prepend
+                  + " - toggle resolvetocodebase if code/docbase resolution is wrong): "
+                  + url);
         }
       }
       else
index d6fb090..f2ffda5 100644 (file)
@@ -86,8 +86,8 @@ public class JalviewLiteURLRetrieve extends Applet
 
       } catch (Exception ex)
       {
-        System.out.println("Exception checking resources: " + file + " "
-                + ex);
+        System.out.println(
+                "Exception checking resources: " + file + " " + ex);
       }
       if (file.indexOf("://") > -1)
       {
@@ -116,8 +116,8 @@ public class JalviewLiteURLRetrieve extends Applet
                 + " cannot be read with protocol==" + protocol);
         return;
       }
-      FileFormatI format = FileFormats.getInstance().forName(
-              getParameter("format"));
+      FileFormatI format = FileFormats.getInstance()
+              .forName(getParameter("format"));
       if (format == null)
       {
         format = new IdentifyFile().identify(file, protocol);
@@ -138,8 +138,8 @@ public class JalviewLiteURLRetrieve extends Applet
       }
       if (al != null)
       {
-        System.out.println(new AppletFormatAdapter().formatSequences(
-                FileFormat.Fasta, al, false));
+        System.out.println(new AppletFormatAdapter()
+                .formatSequences(FileFormat.Fasta, al, false));
       }
     } catch (Exception e)
     {
index b8fcb2c..0116b44 100644 (file)
@@ -161,8 +161,8 @@ public class Alignment implements java.io.Serializable
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.Alignment) Unmarshaller.unmarshal(
-            jalview.binding.Alignment.class, reader);
+    return (jalview.binding.Alignment) Unmarshaller
+            .unmarshal(jalview.binding.Alignment.class, reader);
   }
 
   /**
index 86f1a63..2c9414b 100644 (file)
@@ -440,8 +440,8 @@ public class Annotation implements java.io.Serializable
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.Annotation) Unmarshaller.unmarshal(
-            jalview.binding.Annotation.class, reader);
+    return (jalview.binding.Annotation) Unmarshaller
+            .unmarshal(jalview.binding.Annotation.class, reader);
   }
 
   /**
index 1f583c7..505d91e 100644 (file)
@@ -286,8 +286,8 @@ public class AnnotationElement implements java.io.Serializable
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.AnnotationElement) Unmarshaller.unmarshal(
-            jalview.binding.AnnotationElement.class, reader);
+    return (jalview.binding.AnnotationElement) Unmarshaller
+            .unmarshal(jalview.binding.AnnotationElement.class, reader);
   }
 
   /**
index c1de152..25cf9bf 100644 (file)
@@ -475,12 +475,13 @@ public class Colour implements java.io.Serializable
    *           if this object is an invalid instance according to the schema
    * @return the unmarshaled jalview.binding.Colour
    */
-  public static jalview.binding.Colour unmarshal(final java.io.Reader reader)
+  public static jalview.binding.Colour unmarshal(
+          final java.io.Reader reader)
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.Colour) Unmarshaller.unmarshal(
-            jalview.binding.Colour.class, reader);
+    return (jalview.binding.Colour) Unmarshaller
+            .unmarshal(jalview.binding.Colour.class, reader);
   }
 
   /**
index 1cb6eee..d72b29c 100644 (file)
@@ -285,8 +285,8 @@ public class Feature implements java.io.Serializable
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.Feature) Unmarshaller.unmarshal(
-            jalview.binding.Feature.class, reader);
+    return (jalview.binding.Feature) Unmarshaller
+            .unmarshal(jalview.binding.Feature.class, reader);
   }
 
   /**
index c4d5c4f..321536d 100644 (file)
@@ -97,9 +97,9 @@ public class FeatureSettings implements java.io.Serializable
     // check bounds for index
     if (index < 0 || index >= this._settingList.size())
     {
-      throw new IndexOutOfBoundsException("getSetting: Index value '"
-              + index + "' not in range [0.."
-              + (this._settingList.size() - 1) + "]");
+      throw new IndexOutOfBoundsException(
+              "getSetting: Index value '" + index + "' not in range [0.."
+                      + (this._settingList.size() - 1) + "]");
     }
 
     return (jalview.binding.Setting) _settingList.get(index);
@@ -230,9 +230,9 @@ public class FeatureSettings implements java.io.Serializable
     // check bounds for index
     if (index < 0 || index >= this._settingList.size())
     {
-      throw new IndexOutOfBoundsException("setSetting: Index value '"
-              + index + "' not in range [0.."
-              + (this._settingList.size() - 1) + "]");
+      throw new IndexOutOfBoundsException(
+              "setSetting: Index value '" + index + "' not in range [0.."
+                      + (this._settingList.size() - 1) + "]");
     }
 
     this._settingList.set(index, vSetting);
@@ -270,8 +270,8 @@ public class FeatureSettings implements java.io.Serializable
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.FeatureSettings) Unmarshaller.unmarshal(
-            jalview.binding.FeatureSettings.class, reader);
+    return (jalview.binding.FeatureSettings) Unmarshaller
+            .unmarshal(jalview.binding.FeatureSettings.class, reader);
   }
 
   /**
index c730f4b..bf283df 100644 (file)
@@ -105,8 +105,8 @@ public class Features extends Feature implements java.io.Serializable
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.Feature) Unmarshaller.unmarshal(
-            jalview.binding.Features.class, reader);
+    return (jalview.binding.Feature) Unmarshaller
+            .unmarshal(jalview.binding.Features.class, reader);
   }
 
   /**
index 477cc30..555c2fd 100644 (file)
@@ -737,12 +737,13 @@ public class JGroup implements java.io.Serializable
    *           if this object is an invalid instance according to the schema
    * @return the unmarshaled jalview.binding.JGroup
    */
-  public static jalview.binding.JGroup unmarshal(final java.io.Reader reader)
+  public static jalview.binding.JGroup unmarshal(
+          final java.io.Reader reader)
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.JGroup) Unmarshaller.unmarshal(
-            jalview.binding.JGroup.class, reader);
+    return (jalview.binding.JGroup) Unmarshaller
+            .unmarshal(jalview.binding.JGroup.class, reader);
   }
 
   /**
index 996a807..49334e1 100644 (file)
@@ -229,9 +229,9 @@ public class JSeq implements java.io.Serializable
     // check bounds for index
     if (index < 0 || index >= this._featuresList.size())
     {
-      throw new IndexOutOfBoundsException("getFeatures: Index value '"
-              + index + "' not in range [0.."
-              + (this._featuresList.size() - 1) + "]");
+      throw new IndexOutOfBoundsException(
+              "getFeatures: Index value '" + index + "' not in range [0.."
+                      + (this._featuresList.size() - 1) + "]");
     }
 
     return (jalview.binding.Features) _featuresList.get(index);
@@ -286,9 +286,9 @@ public class JSeq implements java.io.Serializable
     // check bounds for index
     if (index < 0 || index >= this._pdbidsList.size())
     {
-      throw new IndexOutOfBoundsException("getPdbids: Index value '"
-              + index + "' not in range [0.."
-              + (this._pdbidsList.size() - 1) + "]");
+      throw new IndexOutOfBoundsException(
+              "getPdbids: Index value '" + index + "' not in range [0.."
+                      + (this._pdbidsList.size() - 1) + "]");
     }
 
     return (jalview.binding.Pdbids) _pdbidsList.get(index);
@@ -524,9 +524,9 @@ public class JSeq implements java.io.Serializable
     // check bounds for index
     if (index < 0 || index >= this._featuresList.size())
     {
-      throw new IndexOutOfBoundsException("setFeatures: Index value '"
-              + index + "' not in range [0.."
-              + (this._featuresList.size() - 1) + "]");
+      throw new IndexOutOfBoundsException(
+              "setFeatures: Index value '" + index + "' not in range [0.."
+                      + (this._featuresList.size() - 1) + "]");
     }
 
     this._featuresList.set(index, vFeatures);
@@ -575,9 +575,9 @@ public class JSeq implements java.io.Serializable
     // check bounds for index
     if (index < 0 || index >= this._pdbidsList.size())
     {
-      throw new IndexOutOfBoundsException("setPdbids: Index value '"
-              + index + "' not in range [0.."
-              + (this._pdbidsList.size() - 1) + "]");
+      throw new IndexOutOfBoundsException(
+              "setPdbids: Index value '" + index + "' not in range [0.."
+                      + (this._pdbidsList.size() - 1) + "]");
     }
 
     this._pdbidsList.set(index, vPdbids);
@@ -626,8 +626,8 @@ public class JSeq implements java.io.Serializable
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.JSeq) Unmarshaller.unmarshal(
-            jalview.binding.JSeq.class, reader);
+    return (jalview.binding.JSeq) Unmarshaller
+            .unmarshal(jalview.binding.JSeq.class, reader);
   }
 
   /**
index 7141b27..28645e0 100644 (file)
@@ -214,8 +214,8 @@ public class JalviewModel implements java.io.Serializable
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.JalviewModel) Unmarshaller.unmarshal(
-            jalview.binding.JalviewModel.class, reader);
+    return (jalview.binding.JalviewModel) Unmarshaller
+            .unmarshal(jalview.binding.JalviewModel.class, reader);
   }
 
   /**
index eb0716d..9020ce2 100644 (file)
@@ -286,9 +286,9 @@ public class JalviewModelSequence implements java.io.Serializable
     // check bounds for index
     if (index < 0 || index >= this._JGroupList.size())
     {
-      throw new IndexOutOfBoundsException("getJGroup: Index value '"
-              + index + "' not in range [0.."
-              + (this._JGroupList.size() - 1) + "]");
+      throw new IndexOutOfBoundsException(
+              "getJGroup: Index value '" + index + "' not in range [0.."
+                      + (this._JGroupList.size() - 1) + "]");
     }
 
     return (jalview.binding.JGroup) _JGroupList.get(index);
@@ -473,9 +473,9 @@ public class JalviewModelSequence implements java.io.Serializable
     // check bounds for index
     if (index < 0 || index >= this._viewportList.size())
     {
-      throw new IndexOutOfBoundsException("getViewport: Index value '"
-              + index + "' not in range [0.."
-              + (this._viewportList.size() - 1) + "]");
+      throw new IndexOutOfBoundsException(
+              "getViewport: Index value '" + index + "' not in range [0.."
+                      + (this._viewportList.size() - 1) + "]");
     }
 
     return (jalview.binding.Viewport) _viewportList.get(index);
@@ -743,9 +743,9 @@ public class JalviewModelSequence implements java.io.Serializable
     // check bounds for index
     if (index < 0 || index >= this._JGroupList.size())
     {
-      throw new IndexOutOfBoundsException("setJGroup: Index value '"
-              + index + "' not in range [0.."
-              + (this._JGroupList.size() - 1) + "]");
+      throw new IndexOutOfBoundsException(
+              "setJGroup: Index value '" + index + "' not in range [0.."
+                      + (this._JGroupList.size() - 1) + "]");
     }
 
     this._JGroupList.set(index, vJGroup);
@@ -896,9 +896,9 @@ public class JalviewModelSequence implements java.io.Serializable
     // check bounds for index
     if (index < 0 || index >= this._viewportList.size())
     {
-      throw new IndexOutOfBoundsException("setViewport: Index value '"
-              + index + "' not in range [0.."
-              + (this._viewportList.size() - 1) + "]");
+      throw new IndexOutOfBoundsException(
+              "setViewport: Index value '" + index + "' not in range [0.."
+                      + (this._viewportList.size() - 1) + "]");
     }
 
     this._viewportList.set(index, vViewport);
@@ -936,8 +936,8 @@ public class JalviewModelSequence implements java.io.Serializable
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.JalviewModelSequence) Unmarshaller.unmarshal(
-            jalview.binding.JalviewModelSequence.class, reader);
+    return (jalview.binding.JalviewModelSequence) Unmarshaller
+            .unmarshal(jalview.binding.JalviewModelSequence.class, reader);
   }
 
   /**
index 02bb12e..6709487 100644 (file)
@@ -107,9 +107,9 @@ public class JalviewUserColours implements java.io.Serializable
     // check bounds for index
     if (index < 0 || index >= this._colourList.size())
     {
-      throw new IndexOutOfBoundsException("getColour: Index value '"
-              + index + "' not in range [0.."
-              + (this._colourList.size() - 1) + "]");
+      throw new IndexOutOfBoundsException(
+              "getColour: Index value '" + index + "' not in range [0.."
+                      + (this._colourList.size() - 1) + "]");
     }
 
     return (Colour) _colourList.get(index);
@@ -261,9 +261,9 @@ public class JalviewUserColours implements java.io.Serializable
     // check bounds for index
     if (index < 0 || index >= this._colourList.size())
     {
-      throw new IndexOutOfBoundsException("setColour: Index value '"
-              + index + "' not in range [0.."
-              + (this._colourList.size() - 1) + "]");
+      throw new IndexOutOfBoundsException(
+              "setColour: Index value '" + index + "' not in range [0.."
+                      + (this._colourList.size() - 1) + "]");
     }
 
     this._colourList.set(index, vColour);
@@ -325,8 +325,8 @@ public class JalviewUserColours implements java.io.Serializable
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.JalviewUserColours) Unmarshaller.unmarshal(
-            jalview.binding.JalviewUserColours.class, reader);
+    return (jalview.binding.JalviewUserColours) Unmarshaller
+            .unmarshal(jalview.binding.JalviewUserColours.class, reader);
   }
 
   /**
index 6c0e745..77bb446 100644 (file)
@@ -325,8 +325,8 @@ public class Pdbentry implements java.io.Serializable
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.Pdbentry) Unmarshaller.unmarshal(
-            jalview.binding.Pdbentry.class, reader);
+    return (jalview.binding.Pdbentry) Unmarshaller
+            .unmarshal(jalview.binding.Pdbentry.class, reader);
   }
 
   /**
index 93c46e0..30a0512 100644 (file)
@@ -90,9 +90,9 @@ public class PdbentryItem implements java.io.Serializable
     // check bounds for index
     if (index < 0 || index >= this._propertyList.size())
     {
-      throw new IndexOutOfBoundsException("getProperty: Index value '"
-              + index + "' not in range [0.."
-              + (this._propertyList.size() - 1) + "]");
+      throw new IndexOutOfBoundsException(
+              "getProperty: Index value '" + index + "' not in range [0.."
+                      + (this._propertyList.size() - 1) + "]");
     }
 
     return (jalview.binding.Property) _propertyList.get(index);
@@ -169,9 +169,9 @@ public class PdbentryItem implements java.io.Serializable
     // check bounds for index
     if (index < 0 || index >= this._propertyList.size())
     {
-      throw new IndexOutOfBoundsException("setProperty: Index value '"
-              + index + "' not in range [0.."
-              + (this._propertyList.size() - 1) + "]");
+      throw new IndexOutOfBoundsException(
+              "setProperty: Index value '" + index + "' not in range [0.."
+                      + (this._propertyList.size() - 1) + "]");
     }
 
     this._propertyList.set(index, vProperty);
index d821a6a..79cae6c 100644 (file)
@@ -105,8 +105,8 @@ public class Pdbids extends Pdbentry implements java.io.Serializable
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.Pdbentry) Unmarshaller.unmarshal(
-            jalview.binding.Pdbids.class, reader);
+    return (jalview.binding.Pdbentry) Unmarshaller
+            .unmarshal(jalview.binding.Pdbids.class, reader);
   }
 
   /**
index df3decf..5823fed 100644 (file)
@@ -161,8 +161,8 @@ public class Property implements java.io.Serializable
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.Property) Unmarshaller.unmarshal(
-            jalview.binding.Property.class, reader);
+    return (jalview.binding.Property) Unmarshaller
+            .unmarshal(jalview.binding.Property.class, reader);
   }
 
   /**
index 5ab8a37..845f224 100644 (file)
@@ -105,8 +105,8 @@ public class Sequence extends SequenceType implements java.io.Serializable
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.SequenceType) Unmarshaller.unmarshal(
-            jalview.binding.Sequence.class, reader);
+    return (jalview.binding.SequenceType) Unmarshaller
+            .unmarshal(jalview.binding.Sequence.class, reader);
   }
 
   /**
index c12934d..3d81bae 100644 (file)
@@ -173,9 +173,9 @@ public class SequenceSet implements java.io.Serializable
     // check bounds for index
     if (index < 0 || index >= this._annotationList.size())
     {
-      throw new IndexOutOfBoundsException("getAnnotation: Index value '"
-              + index + "' not in range [0.."
-              + (this._annotationList.size() - 1) + "]");
+      throw new IndexOutOfBoundsException(
+              "getAnnotation: Index value '" + index + "' not in range [0.."
+                      + (this._annotationList.size() - 1) + "]");
     }
 
     return (jalview.binding.Annotation) _annotationList.get(index);
@@ -231,9 +231,9 @@ public class SequenceSet implements java.io.Serializable
     // check bounds for index
     if (index < 0 || index >= this._sequenceList.size())
     {
-      throw new IndexOutOfBoundsException("getSequence: Index value '"
-              + index + "' not in range [0.."
-              + (this._sequenceList.size() - 1) + "]");
+      throw new IndexOutOfBoundsException(
+              "getSequence: Index value '" + index + "' not in range [0.."
+                      + (this._sequenceList.size() - 1) + "]");
     }
 
     return (jalview.binding.Sequence) _sequenceList.get(index);
@@ -428,9 +428,9 @@ public class SequenceSet implements java.io.Serializable
     // check bounds for index
     if (index < 0 || index >= this._annotationList.size())
     {
-      throw new IndexOutOfBoundsException("setAnnotation: Index value '"
-              + index + "' not in range [0.."
-              + (this._annotationList.size() - 1) + "]");
+      throw new IndexOutOfBoundsException(
+              "setAnnotation: Index value '" + index + "' not in range [0.."
+                      + (this._annotationList.size() - 1) + "]");
     }
 
     this._annotationList.set(index, vAnnotation);
@@ -479,9 +479,9 @@ public class SequenceSet implements java.io.Serializable
     // check bounds for index
     if (index < 0 || index >= this._sequenceList.size())
     {
-      throw new IndexOutOfBoundsException("setSequence: Index value '"
-              + index + "' not in range [0.."
-              + (this._sequenceList.size() - 1) + "]");
+      throw new IndexOutOfBoundsException(
+              "setSequence: Index value '" + index + "' not in range [0.."
+                      + (this._sequenceList.size() - 1) + "]");
     }
 
     this._sequenceList.set(index, vSequence);
@@ -519,8 +519,8 @@ public class SequenceSet implements java.io.Serializable
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.SequenceSet) Unmarshaller.unmarshal(
-            jalview.binding.SequenceSet.class, reader);
+    return (jalview.binding.SequenceSet) Unmarshaller
+            .unmarshal(jalview.binding.SequenceSet.class, reader);
   }
 
   /**
index d725405..7f10bca 100644 (file)
@@ -187,8 +187,8 @@ public class SequenceType implements java.io.Serializable
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.SequenceType) Unmarshaller.unmarshal(
-            jalview.binding.SequenceType.class, reader);
+    return (jalview.binding.SequenceType) Unmarshaller
+            .unmarshal(jalview.binding.SequenceType.class, reader);
   }
 
   /**
index 6641429..d098303 100644 (file)
@@ -243,8 +243,8 @@ public class Setting implements java.io.Serializable
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.Setting) Unmarshaller.unmarshal(
-            jalview.binding.Setting.class, reader);
+    return (jalview.binding.Setting) Unmarshaller
+            .unmarshal(jalview.binding.Setting.class, reader);
   }
 
   /**
index 04ea0a4..7005c93 100644 (file)
@@ -824,8 +824,8 @@ public class Tree implements java.io.Serializable
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.Tree) Unmarshaller.unmarshal(
-            jalview.binding.Tree.class, reader);
+    return (jalview.binding.Tree) Unmarshaller
+            .unmarshal(jalview.binding.Tree.class, reader);
   }
 
   /**
index 555693c..e1a1a2f 100644 (file)
@@ -19,8 +19,8 @@ import org.exolab.castor.xml.Unmarshaller;
  * 
  * @version $Revision$ $Date$
  */
-public class UserColourScheme extends JalviewUserColours implements
-        java.io.Serializable
+public class UserColourScheme extends JalviewUserColours
+        implements java.io.Serializable
 {
 
   // ----------------/
@@ -106,8 +106,8 @@ public class UserColourScheme extends JalviewUserColours implements
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.JalviewUserColours) Unmarshaller.unmarshal(
-            jalview.binding.UserColourScheme.class, reader);
+    return (jalview.binding.JalviewUserColours) Unmarshaller
+            .unmarshal(jalview.binding.UserColourScheme.class, reader);
   }
 
   /**
index 6a8d73c..9dbcc9e 100644 (file)
@@ -162,8 +162,8 @@ public class UserColours implements java.io.Serializable
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.UserColours) Unmarshaller.unmarshal(
-            jalview.binding.UserColours.class, reader);
+    return (jalview.binding.UserColours) Unmarshaller
+            .unmarshal(jalview.binding.UserColours.class, reader);
   }
 
   /**
index c06de29..b5a32da 100644 (file)
@@ -105,7 +105,8 @@ public class VAMSAS implements java.io.Serializable
    * @throws java.lang.IndexOutOfBoundsException
    *           if the index given is outside the bounds of the collection
    */
-  public void addSequenceSet(final int index, final SequenceSet vSequenceSet)
+  public void addSequenceSet(final int index,
+          final SequenceSet vSequenceSet)
           throws java.lang.IndexOutOfBoundsException
   {
     this._sequenceSetList.add(index, vSequenceSet);
@@ -182,9 +183,9 @@ public class VAMSAS implements java.io.Serializable
     // check bounds for index
     if (index < 0 || index >= this._alignmentList.size())
     {
-      throw new IndexOutOfBoundsException("getAlignment: Index value '"
-              + index + "' not in range [0.."
-              + (this._alignmentList.size() - 1) + "]");
+      throw new IndexOutOfBoundsException(
+              "getAlignment: Index value '" + index + "' not in range [0.."
+                      + (this._alignmentList.size() - 1) + "]");
     }
 
     return (Alignment) _alignmentList.get(index);
@@ -469,9 +470,9 @@ public class VAMSAS implements java.io.Serializable
     // check bounds for index
     if (index < 0 || index >= this._alignmentList.size())
     {
-      throw new IndexOutOfBoundsException("setAlignment: Index value '"
-              + index + "' not in range [0.."
-              + (this._alignmentList.size() - 1) + "]");
+      throw new IndexOutOfBoundsException(
+              "setAlignment: Index value '" + index + "' not in range [0.."
+                      + (this._alignmentList.size() - 1) + "]");
     }
 
     this._alignmentList.set(index, vAlignment);
@@ -501,7 +502,8 @@ public class VAMSAS implements java.io.Serializable
    * @throws java.lang.IndexOutOfBoundsException
    *           if the index given is outside the bounds of the collection
    */
-  public void setSequenceSet(final int index, final SequenceSet vSequenceSet)
+  public void setSequenceSet(final int index,
+          final SequenceSet vSequenceSet)
           throws java.lang.IndexOutOfBoundsException
   {
     // check bounds for index
@@ -579,12 +581,13 @@ public class VAMSAS implements java.io.Serializable
    *           if this object is an invalid instance according to the schema
    * @return the unmarshaled jalview.binding.VAMSAS
    */
-  public static jalview.binding.VAMSAS unmarshal(final java.io.Reader reader)
+  public static jalview.binding.VAMSAS unmarshal(
+          final java.io.Reader reader)
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.VAMSAS) Unmarshaller.unmarshal(
-            jalview.binding.VAMSAS.class, reader);
+    return (jalview.binding.VAMSAS) Unmarshaller
+            .unmarshal(jalview.binding.VAMSAS.class, reader);
   }
 
   /**
index e4c5e0d..d3c90cf 100644 (file)
@@ -100,12 +100,13 @@ public class VamsasModel extends VAMSAS implements java.io.Serializable
    *           if this object is an invalid instance according to the schema
    * @return the unmarshaled jalview.binding.VAMSAS
    */
-  public static jalview.binding.VAMSAS unmarshal(final java.io.Reader reader)
+  public static jalview.binding.VAMSAS unmarshal(
+          final java.io.Reader reader)
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.VAMSAS) Unmarshaller.unmarshal(
-            jalview.binding.VamsasModel.class, reader);
+    return (jalview.binding.VAMSAS) Unmarshaller
+            .unmarshal(jalview.binding.VamsasModel.class, reader);
   }
 
   /**
index d144378..183e048 100644 (file)
@@ -1444,8 +1444,8 @@ public class Viewport implements java.io.Serializable
           throws org.exolab.castor.xml.MarshalException,
           org.exolab.castor.xml.ValidationException
   {
-    return (jalview.binding.Viewport) Unmarshaller.unmarshal(
-            jalview.binding.Viewport.class, reader);
+    return (jalview.binding.Viewport) Unmarshaller
+            .unmarshal(jalview.binding.Viewport.class, reader);
   }
 
   /**
index 21ff841..cac843f 100644 (file)
@@ -122,15 +122,15 @@ public class EditCommand implements CommandI
   {
   }
 
-  public EditCommand(String description)
+  public EditCommand(String desc)
   {
-    this.description = description;
+    this.description = desc;
   }
 
-  public EditCommand(String description, Action command, SequenceI[] seqs,
+  public EditCommand(String desc, Action command, SequenceI[] seqs,
           int position, int number, AlignmentI al)
   {
-    this.description = description;
+    this.description = desc;
     if (command == Action.CUT || command == Action.PASTE)
     {
       setEdit(new Edit(command, seqs, position, number, al));
@@ -139,10 +139,10 @@ public class EditCommand implements CommandI
     performEdit(0, null);
   }
 
-  public EditCommand(String description, Action command, String replace,
+  public EditCommand(String desc, Action command, String replace,
           SequenceI[] seqs, int position, int number, AlignmentI al)
   {
-    this.description = description;
+    this.description = desc;
     if (command == Action.REPLACE)
     {
       setEdit(new Edit(command, seqs, position, number, al, replace));
@@ -222,14 +222,16 @@ public class EditCommand implements CommandI
     /**
      * Check a contiguous edit; either
      * <ul>
-     * <li>a new Insert <n> positions to the right of the last <insert n>, or</li>
+     * <li>a new Insert <n> positions to the right of the last <insert n>,
+     * or</li>
      * <li>a new Delete <n> gaps which is <n> positions to the left of the last
      * delete.</li>
      * </ul>
      */
-    boolean contiguous = (action == Action.INSERT_GAP && e.position == lastEdit.position
-            + lastEdit.number)
-            || (action == Action.DELETE_GAP && e.position + e.number == lastEdit.position);
+    boolean contiguous = (action == Action.INSERT_GAP
+            && e.position == lastEdit.position + lastEdit.number)
+            || (action == Action.DELETE_GAP
+                    && e.position + e.number == lastEdit.position);
     if (contiguous)
     {
       /*
@@ -475,7 +477,8 @@ public class EditCommand implements CommandI
     {
       command.seqs[s].insertCharAt(command.position, command.number,
               command.gapChar);
-      // System.out.println("pos: "+command.position+" number: "+command.number);
+      // System.out.println("pos: "+command.position+" number:
+      // "+command.number);
     }
 
     adjustAnnotations(command, true, false, null);
@@ -504,8 +507,8 @@ public class EditCommand implements CommandI
   {
     for (int s = 0; s < command.seqs.length; s++)
     {
-      command.seqs[s].deleteChars(command.position, command.position
-              + command.number);
+      command.seqs[s].deleteChars(command.position,
+              command.position + command.number);
     }
 
     adjustAnnotations(command, false, false, null);
@@ -536,8 +539,8 @@ public class EditCommand implements CommandI
           // we are redoing an undone cut.
           sequence.setDatasetSequence(null);
         }
-        sequence.deleteChars(command.position, command.position
-                + command.number);
+        sequence.deleteChars(command.position,
+                command.position + command.number);
         if (command.oldds != null && command.oldds[i] != null)
         {
           // oldds entry contains the cut dataset sequence.
@@ -548,13 +551,14 @@ public class EditCommand implements CommandI
         {
           // modify the oldds if necessary
           if (oldds != sequence.getDatasetSequence()
-                  || sequence.getSequenceFeatures() != null)
+                  || sequence.getFeatures().hasFeatures())
           {
             if (command.oldds == null)
             {
               command.oldds = new SequenceI[command.seqs.length];
             }
             command.oldds[i] = oldds;
+            // FIXME JAL-2541 JAL-2526 get correct positions if on a gap
             adjustFeatures(
                     command,
                     i,
@@ -646,8 +650,8 @@ public class EditCommand implements CommandI
             {
               newDSNeeded = true;
               start = command.seqs[i].findPosition(command.position);
-              end = command.seqs[i].findPosition(command.position
-                      + command.number);
+              end = command.seqs[i]
+                      .findPosition(command.position + command.number);
             }
             if (command.seqs[i].getStart() == start)
             {
@@ -731,16 +735,16 @@ public class EditCommand implements CommandI
       tmp = new StringBuffer(oldstring.substring(0, start));
       tmp.append(command.string[i]);
       String nogaprep = jalview.analysis.AlignSeq.extractGaps(
-              jalview.util.Comparison.GapChars, new String(
-                      command.string[i]));
+              jalview.util.Comparison.GapChars,
+              new String(command.string[i]));
       int ipos = command.seqs[i].findPosition(start)
               - command.seqs[i].getStart();
       tmp.append(oldstring.substring(end));
       command.seqs[i].setSequence(tmp.toString());
       command.string[i] = oldstring.substring(start, end).toCharArray();
       String nogapold = jalview.analysis.AlignSeq.extractGaps(
-              jalview.util.Comparison.GapChars, new String(
-                      command.string[i]));
+              jalview.util.Comparison.GapChars,
+              new String(command.string[i]));
       if (!nogaprep.toLowerCase().equals(nogapold.toLowerCase()))
       {
         if (newDSWasNeeded)
@@ -797,6 +801,8 @@ public class EditCommand implements CommandI
       AlignmentAnnotation[] tmp;
       for (int s = 0; s < command.seqs.length; s++)
       {
+        command.seqs[s].sequenceChanged();
+
         if (modifyVisibility)
         {
           // Rows are only removed or added to sequence object.
@@ -833,7 +839,8 @@ public class EditCommand implements CommandI
                 tmp = saved;
                 command.deletedAnnotationRows.put(command.seqs[s], saved);
                 // and then remove any annotation in the other views
-                for (int alview = 0; views != null && alview < views.length; alview++)
+                for (int alview = 0; views != null
+                        && alview < views.length; alview++)
                 {
                   if (views[alview] != command.al)
                   {
@@ -885,7 +892,8 @@ public class EditCommand implements CommandI
                 }
                 // and then duplicate added annotation on every other alignment
                 // view
-                for (int vnum = 0; views != null && vnum < views.length; vnum++)
+                for (int vnum = 0; views != null
+                        && vnum < views.length; vnum++)
                 {
                   if (views[vnum] != command.al)
                   {
@@ -1012,8 +1020,8 @@ public class EditCommand implements CommandI
           }
 
           System.arraycopy(annotations[a].annotations, command.position,
-                  temp, command.position + command.number, aSize
-                          - command.position);
+                  temp, command.position + command.number,
+                  aSize - command.position);
         }
         else
         {
@@ -1056,8 +1064,8 @@ public class EditCommand implements CommandI
                     annotations[a].annotations.length - command.position);
             if (copylen > 0)
             {
-              System.arraycopy(annotations[a].annotations,
-                      command.position, deleted, 0, copylen); // command.number);
+              System.arraycopy(annotations[a].annotations, command.position,
+                      deleted, 0, copylen); // command.number);
             }
           }
 
@@ -1066,10 +1074,10 @@ public class EditCommand implements CommandI
           if (annotations[a].annotations.length > command.position
                   + command.number)
           {
-            System.arraycopy(annotations[a].annotations, command.position
-                    + command.number, temp, command.position,
-                    annotations[a].annotations.length - command.position
-                            - command.number); // aSize
+            System.arraycopy(annotations[a].annotations,
+                    command.position + command.number, temp,
+                    command.position, annotations[a].annotations.length
+                            - command.position - command.number); // aSize
           }
         }
         else
@@ -1101,8 +1109,8 @@ public class EditCommand implements CommandI
     }
   }
 
-  final static void adjustFeatures(Edit command, int index, int i, int j,
-          boolean insert)
+  final static void adjustFeatures(Edit command, int index, final int i,
+          final int j, boolean insert)
   {
     SequenceI seq = command.seqs[index];
     SequenceI sequence = seq.getDatasetSequence();
@@ -1122,56 +1130,73 @@ public class EditCommand implements CommandI
       return;
     }
 
-    SequenceFeature[] sf = sequence.getSequenceFeatures();
+    List<SequenceFeature> sf = sequence.getFeatures()
+            .getPositionalFeatures();
 
-    if (sf == null)
+    if (sf.isEmpty())
     {
       return;
     }
 
-    SequenceFeature[] oldsf = new SequenceFeature[sf.length];
+    List<SequenceFeature> oldsf = new ArrayList<SequenceFeature>();
 
     int cSize = j - i;
 
-    for (int s = 0; s < sf.length; s++)
+    for (SequenceFeature feature : sf)
     {
-      SequenceFeature copy = new SequenceFeature(sf[s]);
+      SequenceFeature copy = new SequenceFeature(feature);
 
-      oldsf[s] = copy;
+      oldsf.add(copy);
 
-      if (sf[s].getEnd() < i)
+      if (feature.getEnd() < i)
       {
         continue;
       }
 
-      if (sf[s].getBegin() > j)
+      if (feature.getBegin() > j)
       {
-        sf[s].setBegin(copy.getBegin() - cSize);
-        sf[s].setEnd(copy.getEnd() - cSize);
+        int newBegin = copy.getBegin() - cSize;
+        int newEnd = copy.getEnd() - cSize;
+        SequenceFeature newSf = new SequenceFeature(feature, newBegin,
+                newEnd, feature.getFeatureGroup(), feature.getScore());
+        sequence.deleteFeature(feature);
+        sequence.addSequenceFeature(newSf);
+        // feature.setBegin(newBegin);
+        // feature.setEnd(newEnd);
         continue;
       }
 
-      if (sf[s].getBegin() >= i)
+      int newBegin = feature.getBegin();
+      int newEnd = feature.getEnd();
+      if (newBegin >= i)
       {
-        sf[s].setBegin(i);
+        newBegin = i;
+        // feature.setBegin(i);
       }
 
-      if (sf[s].getEnd() < j)
+      if (newEnd < j)
       {
-        sf[s].setEnd(j - 1);
+        newEnd = j - 1;
+        // feature.setEnd(j - 1);
       }
+      newEnd = newEnd - cSize;
+      // feature.setEnd(feature.getEnd() - (cSize));
 
-      sf[s].setEnd(sf[s].getEnd() - (cSize));
-
-      if (sf[s].getBegin() > sf[s].getEnd())
+      sequence.deleteFeature(feature);
+      if (newEnd >= newBegin)
       {
-        sequence.deleteFeature(sf[s]);
+        sequence.addSequenceFeature(new SequenceFeature(feature, newBegin,
+                newEnd, feature.getFeatureGroup(), feature.getScore()));
       }
+      // if (feature.getBegin() > feature.getEnd())
+      // {
+      // sequence.deleteFeature(feature);
+      // }
     }
 
     if (command.editedFeatures == null)
     {
-      command.editedFeatures = new Hashtable<SequenceI, SequenceFeature[]>();
+      command.editedFeatures = new Hashtable<SequenceI, List<SequenceFeature>>();
     }
 
     command.editedFeatures.put(seq, oldsf);
@@ -1298,7 +1323,7 @@ public class EditCommand implements CommandI
 
     Hashtable<String, Annotation[]> deletedAnnotations;
 
-    Hashtable<SequenceI, SequenceFeature[]> editedFeatures;
+    Hashtable<SequenceI, List<SequenceFeature>> editedFeatures;
 
     AlignmentI al;
 
@@ -1314,51 +1339,51 @@ public class EditCommand implements CommandI
 
     char gapChar;
 
-    public Edit(Action command, SequenceI[] seqs, int position, int number,
-            char gapChar)
+    public Edit(Action cmd, SequenceI[] sqs, int pos, int count,
+            char gap)
     {
-      this.command = command;
-      this.seqs = seqs;
-      this.position = position;
-      this.number = number;
-      this.gapChar = gapChar;
+      this.command = cmd;
+      this.seqs = sqs;
+      this.position = pos;
+      this.number = count;
+      this.gapChar = gap;
     }
 
-    Edit(Action command, SequenceI[] seqs, int position, int number,
-            AlignmentI al)
+    Edit(Action cmd, SequenceI[] sqs, int pos, int count,
+            AlignmentI align)
     {
-      this.gapChar = al.getGapCharacter();
-      this.command = command;
-      this.seqs = seqs;
-      this.position = position;
-      this.number = number;
-      this.al = al;
-
-      alIndex = new int[seqs.length];
-      for (int i = 0; i < seqs.length; i++)
+      this.gapChar = align.getGapCharacter();
+      this.command = cmd;
+      this.seqs = sqs;
+      this.position = pos;
+      this.number = count;
+      this.al = align;
+
+      alIndex = new int[sqs.length];
+      for (int i = 0; i < sqs.length; i++)
       {
-        alIndex[i] = al.findIndex(seqs[i]);
+        alIndex[i] = align.findIndex(sqs[i]);
       }
 
-      fullAlignmentHeight = (al.getHeight() == seqs.length);
+      fullAlignmentHeight = (align.getHeight() == sqs.length);
     }
 
-    Edit(Action command, SequenceI[] seqs, int position, int number,
-            AlignmentI al, String replace)
+    Edit(Action cmd, SequenceI[] sqs, int pos, int count,
+            AlignmentI align, String replace)
     {
-      this.command = command;
-      this.seqs = seqs;
-      this.position = position;
-      this.number = number;
-      this.al = al;
-      this.gapChar = al.getGapCharacter();
-      string = new char[seqs.length][];
-      for (int i = 0; i < seqs.length; i++)
+      this.command = cmd;
+      this.seqs = sqs;
+      this.position = pos;
+      this.number = count;
+      this.al = align;
+      this.gapChar = align.getGapCharacter();
+      string = new char[sqs.length][];
+      for (int i = 0; i < sqs.length; i++)
       {
         string[i] = replace.toCharArray();
       }
 
-      fullAlignmentHeight = (al.getHeight() == seqs.length);
+      fullAlignmentHeight = (align.getHeight() == sqs.length);
     }
 
     public SequenceI[] getSequences()
index 3266874..32e5fb4 100644 (file)
  */
 package jalview.commands;
 
-/*
- * Jalview - A Sequence Alignment Editor and Viewer Copyright (C) 2007 AM
- * Waterhouse, J Procter, G Barton, M Clamp, S Searle
- * 
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option) any later
- * version.
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- * 
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.SequenceI;
 
@@ -110,6 +91,7 @@ public class RemoveGapColCommand extends EditCommand
     performEdit(0, null);
   }
 
+  @Override
   public int getSize()
   {
     // We're interested in the number of columns deleted,
index c8dadfa..27831dd 100644 (file)
  */
 package jalview.commands;
 
-/*
- * Jalview - A Sequence Alignment Editor and Viewer Copyright (C) 2007 AM
- * Waterhouse, J Procter, G Barton, M Clamp, S Searle
- * 
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option) any later
- * version.
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- * 
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.SequenceI;
 
@@ -109,9 +90,10 @@ public class RemoveGapsCommand extends EditCommand
 
         if (!delete && startCol > -1)
         {
-          this.appendEdit(Action.DELETE_GAP, new SequenceI[] { seqs[s] },
-                  start + startCol - deletedCols, endCol - startCol, al,
-                  false, null);
+          this.appendEdit(
+                  Action.DELETE_GAP, new SequenceI[]
+                  { seqs[s] }, start + startCol - deletedCols,
+                  endCol - startCol, al, false, null);
 
           deletedCols += (endCol - startCol);
           startCol = -1;
@@ -120,9 +102,10 @@ public class RemoveGapsCommand extends EditCommand
       }
       if (delete && startCol > -1)
       {
-        this.appendEdit(Action.DELETE_GAP, new SequenceI[] { seqs[s] },
-                start + startCol - deletedCols, jSize - startCol, al,
-                false, null);
+        this.appendEdit(
+                Action.DELETE_GAP, new SequenceI[]
+                { seqs[s] }, start + startCol - deletedCols,
+                jSize - startCol, al, false, null);
       }
 
     }
index bc7f212..460c2b3 100644 (file)
@@ -52,14 +52,6 @@ public class AlignViewController implements AlignViewControllerI
    */
   private AlignViewControllerGuiI avcg;
 
-  @Override
-  protected void finalize() throws Throwable
-  {
-    viewport = null;
-    alignPanel = null;
-    avcg = null;
-  };
-
   public AlignViewController(AlignViewControllerGuiI alignFrame,
           AlignViewportI viewport, AlignmentViewPanel alignPanel)
   {
@@ -85,10 +77,11 @@ public class AlignViewController implements AlignViewControllerI
     SequenceGroup[] gps = null;
     if (sg != null && (cs == null || cs.isEmpty()))
     {
-      gps = jalview.analysis.Grouping.makeGroupsFrom(viewport
-              .getSequenceSelection(), viewport.getAlignmentView(true)
-              .getSequenceStrings(viewport.getGapCharacter()), viewport
-              .getAlignment().getGroups());
+      gps = jalview.analysis.Grouping.makeGroupsFrom(
+              viewport.getSequenceSelection(),
+              viewport.getAlignmentView(true)
+                      .getSequenceStrings(viewport.getGapCharacter()),
+              viewport.getAlignment().getGroups());
     }
     else
     {
@@ -96,8 +89,8 @@ public class AlignViewController implements AlignViewControllerI
       {
         gps = jalview.analysis.Grouping.makeGroupsFromCols(
                 (sg == null) ? viewport.getAlignment().getSequencesArray()
-                        : sg.getSequences().toArray(new SequenceI[0]), cs,
-                viewport.getAlignment().getGroups());
+                        : sg.getSequences().toArray(new SequenceI[0]),
+                cs, viewport.getAlignment().getGroups());
       }
     }
     if (gps != null)
@@ -170,8 +163,9 @@ public class AlignViewController implements AlignViewControllerI
     // JBPNote this routine could also mark rows, not just columns.
     // need a decent query structure to allow all types of feature searches
     BitSet bs = new BitSet();
-    SequenceCollectionI sqcol = (viewport.getSelectionGroup() == null || extendCurrent) ? viewport
-            .getAlignment() : viewport.getSelectionGroup();
+    SequenceCollectionI sqcol = (viewport.getSelectionGroup() == null
+            || extendCurrent) ? viewport.getAlignment()
+                    : viewport.getSelectionGroup();
 
     int nseq = findColumnsWithFeature(featureType, sqcol, bs);
 
@@ -188,15 +182,15 @@ public class AlignViewController implements AlignViewControllerI
       if (changed)
       {
         viewport.setColumnSelection(cs);
-        alignPanel.paintAlignment(true);
-        int columnCount = invert ? (sqcol.getEndRes() - sqcol.getStartRes() + 1)
-                - bs.cardinality()
+        alignPanel.paintAlignment(false, false);
+        int columnCount = invert
+                ? (sqcol.getEndRes() - sqcol.getStartRes() + 1)
+                        - bs.cardinality()
                 : bs.cardinality();
         avcg.setStatus(MessageManager.formatMessage(
-                "label.view_controller_toggled_marked",
-                new String[] {
-                    toggle ? MessageManager.getString("label.toggled")
-                            : MessageManager.getString("label.marked"),
+                "label.view_controller_toggled_marked", new String[]
+                { toggle ? MessageManager.getString("label.toggled")
+                        : MessageManager.getString("label.marked"),
                     String.valueOf(columnCount),
                     invert ? MessageManager
                             .getString("label.not_containing")
@@ -207,13 +201,13 @@ public class AlignViewController implements AlignViewControllerI
     }
     else
     {
-      avcg.setStatus(MessageManager.formatMessage(
-              "label.no_feature_of_type_found",
-              new String[] { featureType }));
+      avcg.setStatus(MessageManager
+              .formatMessage("label.no_feature_of_type_found", new String[]
+              { featureType }));
       if (!extendCurrent)
       {
         cs.clear();
-        alignPanel.paintAlignment(true);
+        alignPanel.paintAlignment(false, false);
       }
     }
     return false;
@@ -232,91 +226,66 @@ public class AlignViewController implements AlignViewControllerI
   static int findColumnsWithFeature(String featureType,
           SequenceCollectionI sqcol, BitSet bs)
   {
-    final int startPosition = sqcol.getStartRes() + 1; // converted to base 1
-    final int endPosition = sqcol.getEndRes() + 1;
+    final int startColumn = sqcol.getStartRes() + 1; // converted to base 1
+    final int endColumn = sqcol.getEndRes() + 1;
     List<SequenceI> seqs = sqcol.getSequences();
     int nseq = 0;
     for (SequenceI sq : seqs)
     {
-      boolean sequenceHasFeature = false;
       if (sq != null)
       {
-        SequenceFeature[] sfs = sq.getSequenceFeatures();
-        if (sfs != null)
+        // int ist = sq.findPosition(sqcol.getStartRes());
+        List<SequenceFeature> sfs = sq.findFeatures(startColumn,
+                endColumn, featureType);
+
+        if (!sfs.isEmpty())
         {
-          int ist = sq.findIndex(sq.getStart());
-          int iend = sq.findIndex(sq.getEnd());
-          if (iend < startPosition || ist > endPosition)
-          {
-            // sequence not in region
-            continue;
-          }
-          for (SequenceFeature sf : sfs)
+          nseq++;
+        }
+
+        for (SequenceFeature sf : sfs)
+        {
+          int sfStartCol = sq.findIndex(sf.getBegin());
+          int sfEndCol = sq.findIndex(sf.getEnd());
+
+          if (sf.isContactFeature())
           {
-            // future functionality - featureType == null means mark columns
-            // containing all displayed features
-            if (sf != null && (featureType.equals(sf.getType())))
+            /*
+             * 'contact' feature - check for 'start' or 'end'
+             * position within the selected region
+             */
+            if (sfStartCol >= startColumn && sfStartCol <= endColumn)
             {
-              // optimisation - could consider 'spos,apos' like cursor argument
-              // - findIndex wastes time by starting from first character and
-              // counting
-
-              int sfStartCol = sq.findIndex(sf.getBegin());
-              int sfEndCol = sq.findIndex(sf.getEnd());
-
-              if (sf.isContactFeature())
-              {
-                /*
-                 * 'contact' feature - check for 'start' or 'end'
-                 * position within the selected region
-                 */
-                if (sfStartCol >= startPosition
-                        && sfStartCol <= endPosition)
-                {
-                  bs.set(sfStartCol - 1);
-                  sequenceHasFeature = true;
-                }
-                if (sfEndCol >= startPosition && sfEndCol <= endPosition)
-                {
-                  bs.set(sfEndCol - 1);
-                  sequenceHasFeature = true;
-                }
-                continue;
-              }
-
-              /*
-               * contiguous feature - select feature positions (if any) 
-               * within the selected region
-               */
-              if (sfStartCol > endPosition || sfEndCol < startPosition)
-              {
-                // feature is outside selected region
-                continue;
-              }
-              sequenceHasFeature = true;
-              if (sfStartCol < startPosition)
-              {
-                sfStartCol = startPosition;
-              }
-              if (sfStartCol < ist)
-              {
-                sfStartCol = ist;
-              }
-              if (sfEndCol > endPosition)
-              {
-                sfEndCol = endPosition;
-              }
-              for (; sfStartCol <= sfEndCol; sfStartCol++)
-              {
-                bs.set(sfStartCol - 1); // convert to base 0
-              }
+              bs.set(sfStartCol - 1);
             }
+            if (sfEndCol >= startColumn && sfEndCol <= endColumn)
+            {
+              bs.set(sfEndCol - 1);
+            }
+            continue;
           }
-        }
 
-        if (sequenceHasFeature)
-        {
-          nseq++;
+          /*
+           * contiguous feature - select feature positions (if any) 
+           * within the selected region
+           */
+          if (sfStartCol < startColumn)
+          {
+            sfStartCol = startColumn;
+          }
+          // not sure what the point of this is
+          // if (sfStartCol < ist)
+          // {
+          // sfStartCol = ist;
+          // }
+          if (sfEndCol > endColumn)
+          {
+            sfEndCol = endColumn;
+          }
+          for (; sfStartCol <= sfEndCol; sfStartCol++)
+          {
+            bs.set(sfStartCol - 1); // convert to base 0
+          }
         }
       }
     }
@@ -358,9 +327,9 @@ public class AlignViewController implements AlignViewControllerI
     }
     SequenceI[] oldOrder = al.getSequencesArray();
     AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
-    avcg.addHistoryItem(new OrderCommand(methodText, oldOrder, viewport
-            .getAlignment()));
-    alignPanel.paintAlignment(true);
+    avcg.addHistoryItem(new OrderCommand(methodText, oldOrder,
+            viewport.getAlignment()));
+    alignPanel.paintAlignment(true, false);
 
   }
 
@@ -377,9 +346,10 @@ public class AlignViewController implements AlignViewControllerI
     boolean featuresFile = false;
     try
     {
-      featuresFile = new FeaturesFile(false, file, protocol).parse(viewport
-              .getAlignment().getDataset(), alignPanel.getFeatureRenderer()
-              .getFeatureColours(), false, relaxedIdMatching);
+      featuresFile = new FeaturesFile(false, file, protocol).parse(
+              viewport.getAlignment().getDataset(),
+              alignPanel.getFeatureRenderer().getFeatureColours(), false,
+              relaxedIdMatching);
     } catch (Exception ex)
     {
       ex.printStackTrace();
@@ -397,7 +367,7 @@ public class AlignViewController implements AlignViewControllerI
       {
         avcg.getFeatureSettingsUI().discoverAllFeatureData();
       }
-      alignPanel.paintAlignment(true);
+      alignPanel.paintAlignment(true, true);
     }
 
     return featuresFile;
@@ -415,8 +385,9 @@ public class AlignViewController implements AlignViewControllerI
     }
     // JBPNote this routine could also mark rows, not just columns.
     BitSet bs = new BitSet();
-    SequenceCollectionI sqcol = (viewport.getSelectionGroup() == null || extendCurrent) ? viewport
-            .getAlignment() : viewport.getSelectionGroup();
+    SequenceCollectionI sqcol = (viewport.getSelectionGroup() == null
+            || extendCurrent) ? viewport.getAlignment()
+                    : viewport.getSelectionGroup();
 
     // this could be a lambda... - the remains of the method is boilerplate,
     // except for the different messages for reporting selection.
@@ -435,15 +406,15 @@ public class AlignViewController implements AlignViewControllerI
       if (changed)
       {
         viewport.setColumnSelection(cs);
-        alignPanel.paintAlignment(true);
-        int columnCount = invert ? (sqcol.getEndRes() - sqcol.getStartRes() + 1)
-                - bs.cardinality()
+        alignPanel.paintAlignment(false, false);
+        int columnCount = invert
+                ? (sqcol.getEndRes() - sqcol.getStartRes() + 1)
+                        - bs.cardinality()
                 : bs.cardinality();
         avcg.setStatus(MessageManager.formatMessage(
-                "label.view_controller_toggled_marked",
-                new String[] {
-                    toggle ? MessageManager.getString("label.toggled")
-                            : MessageManager.getString("label.marked"),
+                "label.view_controller_toggled_marked", new String[]
+                { toggle ? MessageManager.getString("label.toggled")
+                        : MessageManager.getString("label.marked"),
                     String.valueOf(columnCount),
                     invert ? MessageManager
                             .getString("label.not_containing")
@@ -459,7 +430,7 @@ public class AlignViewController implements AlignViewControllerI
       if (!extendCurrent)
       {
         cs.clear();
-        alignPanel.paintAlignment(true);
+        alignPanel.paintAlignment(false, false);
       }
     }
     return false;
index 4fbfd62..ec11fc1 100644 (file)
@@ -90,10 +90,11 @@ public class AlignedCodonFrame
         return that.mapping == null;
       }
       // TODO: can simplify by asserting fromSeq is a dataset sequence
-      return (this.fromSeq == that.fromSeq || (this.fromSeq != null
-              && that.fromSeq != null
-              && this.fromSeq.getDatasetSequence() != null && this.fromSeq
-              .getDatasetSequence() == that.fromSeq.getDatasetSequence()))
+      return (this.fromSeq == that.fromSeq
+              || (this.fromSeq != null && that.fromSeq != null
+                      && this.fromSeq.getDatasetSequence() != null
+                      && this.fromSeq.getDatasetSequence() == that.fromSeq
+                              .getDatasetSequence()))
               && this.mapping.equals(that.mapping);
     }
 
@@ -149,8 +150,8 @@ public class AlignedCodonFrame
 
     SequenceI fromSeq = (dnaseq.getDatasetSequence() == null) ? dnaseq
             : dnaseq.getDatasetSequence();
-    SequenceI toSeq = (aaseq.getDatasetSequence() == null) ? aaseq : aaseq
-            .getDatasetSequence();
+    SequenceI toSeq = (aaseq.getDatasetSequence() == null) ? aaseq
+            : aaseq.getDatasetSequence();
 
     /*
      * if we already hold a mapping between these sequences, just add to it 
@@ -434,8 +435,8 @@ public class AlignedCodonFrame
   {
     SequenceI targetDs = target.getDatasetSequence() == null ? target
             : target.getDatasetSequence();
-    SequenceI queryDs = query.getDatasetSequence() == null ? query : query
-            .getDatasetSequence();
+    SequenceI queryDs = query.getDatasetSequence() == null ? query
+            : query.getDatasetSequence();
     if (targetDs == null || queryDs == null /*|| dnaToProt == null*/)
     {
       return null;
@@ -504,10 +505,11 @@ public class AlignedCodonFrame
          * Read off the mapped nucleotides (converting to position base 0)
          */
         codonPos = MappingUtils.flattenRanges(codonPos);
-        char[] dna = dnaSeq.getSequence();
         int start = dnaSeq.getStart();
-        result.add(new char[] { dna[codonPos[0] - start],
-            dna[codonPos[1] - start], dna[codonPos[2] - start] });
+        char c1 = dnaSeq.getCharAt(codonPos[0] - start);
+        char c2 = dnaSeq.getCharAt(codonPos[1] - start);
+        char c3 = dnaSeq.getCharAt(codonPos[2] - start);
+        result.add(new char[] { c1, c2, c3 });
       }
     }
     return result.isEmpty() ? null : result;
@@ -579,8 +581,9 @@ public class AlignedCodonFrame
    */
   protected int realiseWith(SequenceI seq, boolean doUpdate)
   {
-    SequenceI ds = seq.getDatasetSequence() != null ? seq
-            .getDatasetSequence() : seq;
+    SequenceI ds = seq.getDatasetSequence() != null
+            ? seq.getDatasetSequence()
+            : seq;
     int count = 0;
 
     /*
@@ -654,8 +657,8 @@ public class AlignedCodonFrame
     {
       int start = replacement.getStart();
       int end = replacement.getEnd();
-      boolean mappingOverlapsSequence = (mapStart >= start && mapStart <= end)
-              || (mapEnd >= start && mapEnd <= end);
+      boolean mappingOverlapsSequence = (mapStart >= start
+              && mapStart <= end) || (mapEnd >= start && mapEnd <= end);
       if (mappingOverlapsSequence)
       {
         return true;
@@ -732,8 +735,8 @@ public class AlignedCodonFrame
   {
     SequenceI dssFrom = fromSeq.getDatasetSequence() == null ? fromSeq
             : fromSeq.getDatasetSequence();
-    SequenceI dssTo = toSeq.getDatasetSequence() == null ? toSeq : toSeq
-            .getDatasetSequence();
+    SequenceI dssTo = toSeq.getDatasetSequence() == null ? toSeq
+            : toSeq.getDatasetSequence();
 
     for (SequenceToSequenceMapping mapping : mappings)
     {
index 098222f..f268d37 100755 (executable)
@@ -28,6 +28,7 @@ import jalview.util.LinkedIdentityHashSet;
 import jalview.util.MessageManager;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashSet;
@@ -143,9 +144,8 @@ public class Alignment implements AlignmentI
    */
   public static AlignmentI createAlignment(CigarArray compactAlignment)
   {
-    throw new Error(
-            MessageManager
-                    .getString("error.alignment_cigararray_not_implemented"));
+    throw new Error(MessageManager
+            .getString("error.alignment_cigararray_not_implemented"));
     // this(compactAlignment.refCigars);
   }
 
@@ -188,7 +188,6 @@ public class Alignment implements AlignmentI
     return AlignmentUtils.getSequencesByName(this);
   }
 
-
   @Override
   public SequenceI getSequenceAt(int i)
   {
@@ -475,7 +474,9 @@ public class Alignment implements AlignmentI
       return;
     }
     // remove annotation very quickly
-    AlignmentAnnotation[] t, todelete = new AlignmentAnnotation[annotations.length], tokeep = new AlignmentAnnotation[annotations.length];
+    AlignmentAnnotation[] t,
+            todelete = new AlignmentAnnotation[annotations.length],
+            tokeep = new AlignmentAnnotation[annotations.length];
     int i, p, k;
     if (gp == null)
     {
@@ -608,7 +609,7 @@ public class Alignment implements AlignmentI
       sqname = sq.getName();
       if (sqname.equals(token) // exact match
               || (b && // allow imperfect matches - case varies
-              (sqname.equalsIgnoreCase(token))))
+                      (sqname.equalsIgnoreCase(token))))
       {
         return getSequenceAt(i);
       }
@@ -689,7 +690,6 @@ public class Alignment implements AlignmentI
     return -1;
   }
 
-
   @Override
   public int getHeight()
   {
@@ -1096,10 +1096,9 @@ public class Alignment implements AlignmentI
             }
             if (dbr.getMap().getTo().getDatasetSequence() != null)
             {
-              throw new Error(
-                      "Implementation error: Map.getTo() for dbref " + dbr
-                              + " from " + curDs.getName()
-                              + " is not a dataset sequence.");
+              throw new Error("Implementation error: Map.getTo() for dbref "
+                      + dbr + " from " + curDs.getName()
+                      + " is not a dataset sequence.");
             }
             // we recurse to add all forward references to dataset sequences via
             // DBRefs/etc
@@ -1236,8 +1235,8 @@ public class Alignment implements AlignmentI
       current = getSequenceAt(i);
       // This should really be a sequence method
       ends[i * 2] = current.findIndex(current.getStart());
-      ends[i * 2 + 1] = current.findIndex(current.getStart()
-              + current.getLength());
+      ends[i * 2 + 1] = current
+              .findIndex(current.getStart() + current.getLength());
       boolean hitres = false;
       for (int j = 0, rs = 0, ssiz = current.getLength(); j < ssiz; j++)
       {
@@ -1473,13 +1472,15 @@ public class Alignment implements AlignmentI
   {
     // TODO JAL-1270 needs test coverage
     // currently tested for use in jalview.gui.SequenceFetcher
-    boolean samegap = toappend.getGapCharacter() == getGapCharacter();
     char oldc = toappend.getGapCharacter();
+    boolean samegap = oldc == getGapCharacter();
     boolean hashidden = toappend.getHiddenSequences() != null
             && toappend.getHiddenSequences().hiddenSequences != null;
     // get all sequences including any hidden ones
-    List<SequenceI> sqs = (hashidden) ? toappend.getHiddenSequences()
-            .getFullAlignment().getSequences() : toappend.getSequences();
+    List<SequenceI> sqs = (hashidden)
+            ? toappend.getHiddenSequences().getFullAlignment()
+                    .getSequences()
+            : toappend.getSequences();
     if (sqs != null)
     {
       // avoid self append deadlock by
@@ -1490,14 +1491,7 @@ public class Alignment implements AlignmentI
         {
           if (!samegap)
           {
-            char[] oldseq = addedsq.getSequence();
-            for (int c = 0; c < oldseq.length; c++)
-            {
-              if (oldseq[c] == oldc)
-              {
-                oldseq[c] = gapCharacter;
-              }
-            }
+            addedsq.replace(oldc, gapCharacter);
           }
           toappendsq.add(addedsq);
         }
@@ -1561,8 +1555,8 @@ public class Alignment implements AlignmentI
             if (ourval instanceof String)
             {
               // append strings
-              this.setProperty(k, ((String) ourval) + "; "
-                      + ((String) toapprop));
+              this.setProperty(k,
+                      ((String) ourval) + "; " + ((String) toapprop));
             }
             else
             {
@@ -1624,40 +1618,21 @@ public class Alignment implements AlignmentI
   @Override
   public Iterable<AlignmentAnnotation> findAnnotation(String calcId)
   {
-    List<AlignmentAnnotation> aa = new ArrayList<>();
     AlignmentAnnotation[] alignmentAnnotation = getAlignmentAnnotation();
     if (alignmentAnnotation != null)
     {
-      for (AlignmentAnnotation a : alignmentAnnotation)
-      {
-        if (a.getCalcId() == calcId
-                || (a.getCalcId() != null && calcId != null && a
-                        .getCalcId().equals(calcId)))
-        {
-          aa.add(a);
-        }
-      }
+      return AlignmentAnnotation.findAnnotation(
+              Arrays.asList(getAlignmentAnnotation()), calcId);
     }
-    return aa;
+    return Arrays.asList(new AlignmentAnnotation[] {});
   }
 
   @Override
   public Iterable<AlignmentAnnotation> findAnnotations(SequenceI seq,
           String calcId, String label)
   {
-    ArrayList<AlignmentAnnotation> aa = new ArrayList<>();
-    for (AlignmentAnnotation ann : getAlignmentAnnotation())
-    {
-      if ((calcId == null || (ann.getCalcId() != null && ann.getCalcId()
-              .equals(calcId)))
-              && (seq == null || (ann.sequenceRef != null && ann.sequenceRef == seq))
-              && (label == null || (ann.label != null && ann.label
-                      .equals(label))))
-      {
-        aa.add(ann);
-      }
-    }
-    return aa;
+    return AlignmentAnnotation.findAnnotations(
+            Arrays.asList(getAlignmentAnnotation()), seq, calcId, label);
   }
 
   @Override
index 1594f2b..f7bf4d8 100755 (executable)
@@ -24,6 +24,7 @@ import jalview.analysis.Rna;
 import jalview.analysis.SecStrConsensus.SimpleBP;
 import jalview.analysis.WUSSParseException;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -96,14 +97,13 @@ public class AlignmentAnnotation
    * Updates the _rnasecstr field Determines the positions that base pair and
    * the positions of helices based on secondary structure from a Stockholm file
    * 
-   * @param RNAannot
+   * @param rnaAnnotation
    */
-  private void _updateRnaSecStr(CharSequence RNAannot)
+  private void _updateRnaSecStr(CharSequence rnaAnnotation)
   {
     try
     {
-      bps = Rna.getModeleBP(RNAannot);
-      _rnasecstr = Rna.getBasePairs(bps);
+      _rnasecstr = Rna.getHelixMap(rnaAnnotation);
       invalidrnastruc = -1;
     } catch (WUSSParseException px)
     {
@@ -114,8 +114,6 @@ public class AlignmentAnnotation
     {
       return;
     }
-    Rna.HelixMap(_rnasecstr);
-    // setRNAStruc(RNAannot);
 
     if (_rnasecstr != null && _rnasecstr.length > 0)
     {
@@ -244,19 +242,6 @@ public class AlignmentAnnotation
 
   private boolean isrna;
 
-  /*
-   * (non-Javadoc)
-   * 
-   * @see java.lang.Object#finalize()
-   */
-  @Override
-  protected void finalize() throws Throwable
-  {
-    sequenceRef = null;
-    groupRef = null;
-    super.finalize();
-  }
-
   public static int getGraphValueFromString(String string)
   {
     if (string.equalsIgnoreCase("BAR_GRAPH"))
@@ -273,12 +258,6 @@ public class AlignmentAnnotation
     }
   }
 
-  // JBPNote: what does this do ?
-  public void ConcenStru(CharSequence RNAannot) throws WUSSParseException
-  {
-    bps = Rna.getModeleBP(RNAannot);
-  }
-
   /**
    * Creates a new AlignmentAnnotation object.
    * 
@@ -379,49 +358,25 @@ public class AlignmentAnnotation
         firstChar = annotations[i].displayCharacter.charAt(0);
         // check to see if it looks like a sequence or is secondary structure
         // labelling.
-        if (annotations[i].secondaryStructure != ' '
-                && !hasIcons
-                &&
-                // Uncomment to only catch case where
-                // displayCharacter==secondary
-                // Structure
-                // to correctly redisplay SS annotation imported from Stockholm,
-                // exported to JalviewXML and read back in again.
-                // &&
-                // annotations[i].displayCharacter.charAt(0)==annotations[i].secondaryStructure
-                firstChar != ' '
-                && firstChar != '$'
-                && firstChar != 0xCE
-                && firstChar != '('
-                && firstChar != '['
-                && firstChar != '>'
-                && firstChar != '{'
-                && firstChar != 'A'
-                && firstChar != 'B'
-                && firstChar != 'C'
-                && firstChar != 'D'
-                && firstChar != 'E'
-                && firstChar != 'F'
-                && firstChar != 'G'
-                && firstChar != 'H'
-                && firstChar != 'I'
-                && firstChar != 'J'
-                && firstChar != 'K'
-                && firstChar != 'L'
-                && firstChar != 'M'
-                && firstChar != 'N'
-                && firstChar != 'O'
-                && firstChar != 'P'
-                && firstChar != 'Q'
-                && firstChar != 'R'
-                && firstChar != 'S'
-                && firstChar != 'T'
-                && firstChar != 'U'
-                && firstChar != 'V'
-                && firstChar != 'W'
-                && firstChar != 'X'
-                && firstChar != 'Y'
-                && firstChar != 'Z'
+        if (annotations[i].secondaryStructure != ' ' && !hasIcons &&
+        // Uncomment to only catch case where
+        // displayCharacter==secondary
+        // Structure
+        // to correctly redisplay SS annotation imported from Stockholm,
+        // exported to JalviewXML and read back in again.
+        // &&
+        // annotations[i].displayCharacter.charAt(0)==annotations[i].secondaryStructure
+                firstChar != ' ' && firstChar != '$' && firstChar != 0xCE
+                && firstChar != '(' && firstChar != '[' && firstChar != '>'
+                && firstChar != '{' && firstChar != 'A' && firstChar != 'B'
+                && firstChar != 'C' && firstChar != 'D' && firstChar != 'E'
+                && firstChar != 'F' && firstChar != 'G' && firstChar != 'H'
+                && firstChar != 'I' && firstChar != 'J' && firstChar != 'K'
+                && firstChar != 'L' && firstChar != 'M' && firstChar != 'N'
+                && firstChar != 'O' && firstChar != 'P' && firstChar != 'Q'
+                && firstChar != 'R' && firstChar != 'S' && firstChar != 'T'
+                && firstChar != 'U' && firstChar != 'V' && firstChar != 'W'
+                && firstChar != 'X' && firstChar != 'Y' && firstChar != 'Z'
                 && firstChar != '-'
                 && firstChar < jalview.schemes.ResidueProperties.aaIndex.length)
         {
@@ -512,12 +467,17 @@ public class AlignmentAnnotation
     {
       return ((index + offset < 0) || (index + offset) >= max
               || annotations[index + offset] == null
-              || (annotations[index + offset].secondaryStructure <= ' ') ? ' '
-              : annotations[index + offset].displayCharacter == null
-                      || annotations[index + offset].displayCharacter
-                              .length() == 0 ? annotations[index + offset].secondaryStructure
-                      : annotations[index + offset].displayCharacter
-                              .charAt(0));
+              || (annotations[index + offset].secondaryStructure <= ' ')
+                      ? ' '
+                      : annotations[index + offset].displayCharacter == null
+                              || annotations[index
+                                      + offset].displayCharacter
+                                              .length() == 0
+                                                      ? annotations[index
+                                                              + offset].secondaryStructure
+                                                      : annotations[index
+                                                              + offset].displayCharacter
+                                                                      .charAt(0));
     }
 
     @Override
@@ -528,10 +488,15 @@ public class AlignmentAnnotation
 
       for (int i = offset; i < mx; i++)
       {
-        string[i] = (annotations[i] == null || (annotations[i].secondaryStructure <= 32)) ? ' '
-                : (annotations[i].displayCharacter == null
-                        || annotations[i].displayCharacter.length() == 0 ? annotations[i].secondaryStructure
-                        : annotations[i].displayCharacter.charAt(0));
+        string[i] = (annotations[i] == null
+                || (annotations[i].secondaryStructure <= 32))
+                        ? ' '
+                        : (annotations[i].displayCharacter == null
+                                || annotations[i].displayCharacter
+                                        .length() == 0
+                                                ? annotations[i].secondaryStructure
+                                                : annotations[i].displayCharacter
+                                                        .charAt(0));
       }
       return new String(string);
     }
@@ -807,8 +772,8 @@ public class AlignmentAnnotation
     Annotation[] temp = new Annotation[endRes - startRes + 1];
     if (startRes < annotations.length)
     {
-      System.arraycopy(annotations, startRes, temp, 0, endRes - startRes
-              + 1);
+      System.arraycopy(annotations, startRes, temp, 0,
+              endRes - startRes + 1);
     }
     if (sequenceRef != null)
     {
@@ -1028,8 +993,8 @@ public class AlignmentAnnotation
       {
         if (i + 1 < iSize)
         {
-          System.arraycopy(annotations, i + 1, annotations, i, iSize - i
-                  - 1);
+          System.arraycopy(annotations, i + 1, annotations, i,
+                  iSize - i - 1);
         }
         iSize--;
       }
@@ -1061,14 +1026,16 @@ public class AlignmentAnnotation
     {
       if (sequenceRef != null)
       {
-        boolean rIsDs = sequenceRef.getDatasetSequence() == null, tIsDs = sequenceI
-                .getDatasetSequence() == null;
+        boolean rIsDs = sequenceRef.getDatasetSequence() == null,
+                tIsDs = sequenceI.getDatasetSequence() == null;
         if (sequenceRef != sequenceI
-                && (rIsDs && !tIsDs && sequenceRef != sequenceI
-                        .getDatasetSequence())
-                && (!rIsDs && tIsDs && sequenceRef.getDatasetSequence() != sequenceI)
-                && (!rIsDs && !tIsDs && sequenceRef.getDatasetSequence() != sequenceI
-                        .getDatasetSequence())
+                && (rIsDs && !tIsDs
+                        && sequenceRef != sequenceI.getDatasetSequence())
+                && (!rIsDs && tIsDs
+                        && sequenceRef.getDatasetSequence() != sequenceI)
+                && (!rIsDs && !tIsDs
+                        && sequenceRef.getDatasetSequence() != sequenceI
+                                .getDatasetSequence())
                 && !sequenceRef.equals(sequenceI))
         {
           // if sequenceRef isn't intersecting with sequenceI
@@ -1263,8 +1230,10 @@ public class AlignmentAnnotation
       throw new Error(
               "liftOver currently not implemented for transfer of annotation between different types of seqeunce");
     }
-    boolean mapIsTo = (sp2sq != null) ? (sp2sq.getTo() == sq || sp2sq
-            .getTo() == sq.getDatasetSequence()) : false;
+    boolean mapIsTo = (sp2sq != null)
+            ? (sp2sq.getTo() == sq
+                    || sp2sq.getTo() == sq.getDatasetSequence())
+            : false;
 
     // TODO build a better annotation element map and get rid of annotations[]
     Map<Integer, Annotation> mapForsq = new HashMap<Integer, Annotation>();
@@ -1274,9 +1243,9 @@ public class AlignmentAnnotation
       {
         for (Entry<Integer, Annotation> ie : sequenceMapping.entrySet())
         {
-          Integer mpos = Integer.valueOf(mapIsTo ? sp2sq
-                  .getMappedPosition(ie.getKey()) : sp2sq.getPosition(ie
-                  .getKey()));
+          Integer mpos = Integer
+                  .valueOf(mapIsTo ? sp2sq.getMappedPosition(ie.getKey())
+                          : sp2sq.getPosition(ie.getKey()));
           if (mpos >= sq.getStart() && mpos <= sq.getEnd())
           {
             mapForsq.put(mpos, ie.getValue());
@@ -1463,8 +1432,8 @@ public class AlignmentAnnotation
        * up to and excluding the target column; if the count is less
        * than 1, the opening bracket is unmatched, so return its match
        */
-      String closer = String.valueOf(Rna
-              .getMatchingClosingParenthesis(symbol));
+      String closer = String
+              .valueOf(Rna.getMatchingClosingParenthesis(symbol));
       String opener = String.valueOf(symbol);
       int count = 0;
       for (int j = col + 1; j < column; j++)
@@ -1503,4 +1472,71 @@ public class AlignmentAnnotation
   {
     return graphMin < graphMax;
   }
+
+  public static Iterable<AlignmentAnnotation> findAnnotations(
+          Iterable<AlignmentAnnotation> list, SequenceI seq, String calcId,
+          String label)
+  {
+
+    ArrayList<AlignmentAnnotation> aa = new ArrayList<>();
+    for (AlignmentAnnotation ann : list)
+    {
+      if ((calcId == null || (ann.getCalcId() != null
+              && ann.getCalcId().equals(calcId)))
+              && (seq == null || (ann.sequenceRef != null
+                      && ann.sequenceRef == seq))
+              && (label == null
+                      || (ann.label != null && ann.label.equals(label))))
+      {
+        aa.add(ann);
+      }
+    }
+    return aa;
+  }
+
+  /**
+   * Answer true if any annotation matches the calcId passed in (if not null).
+   * 
+   * @param list
+   *          annotation to search
+   * @param calcId
+   * @return
+   */
+  public static boolean hasAnnotation(List<AlignmentAnnotation> list,
+          String calcId)
+  {
+
+    if (calcId != null && !"".equals(calcId))
+    {
+      for (AlignmentAnnotation a : list)
+      {
+        if (a.getCalcId() == calcId)
+        {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  public static Iterable<AlignmentAnnotation> findAnnotation(
+          List<AlignmentAnnotation> list, String calcId)
+  {
+
+    List<AlignmentAnnotation> aa = new ArrayList<>();
+    if (calcId == null)
+    {
+      return aa;
+    }
+    for (AlignmentAnnotation a : list)
+    {
+
+      if (a.getCalcId() == calcId || (a.getCalcId() != null
+              && calcId != null && a.getCalcId().equals(calcId)))
+      {
+        aa.add(a);
+      }
+    }
+    return aa;
+  }
 }
index 1b5207f..084b80e 100755 (executable)
@@ -5,16 +5,16 @@
  * This file is part of Jalview.
  * 
  * Jalview is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General License 
+ * modify it under the terms of the GNU General Public License 
  * as published by the Free Software Foundation, either version 3
  * of the License, or (at your option) any later version.
  *  
  * Jalview is distributed in the hope that it will be useful, but 
  * WITHOUT ANY WARRANTY; without even the implied warranty 
  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
- * PURPOSE.  See the GNU General License for more details.
+ * PURPOSE.  See the GNU General Public License for more details.
  * 
- * You should have received a copy of the GNU General License
+ * You should have received a copy of the GNU General Public License
  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
index ccc9bfa..6d09145 100755 (executable)
@@ -218,7 +218,8 @@ public class AlignmentOrder
       {
         if (!identity)
         {
-          throw new Error("Weak sequenceI equivalence not yet implemented.");
+          throw new Error(
+                  "Weak sequenceI equivalence not yet implemented.");
         }
         else
         {
@@ -285,7 +286,8 @@ public class AlignmentOrder
         }
         if (!identity)
         {
-          throw new Error("Weak sequenceI equivalence not yet implemented.");
+          throw new Error(
+                  "Weak sequenceI equivalence not yet implemented.");
         }
         else
         {
index 9ca70f2..d3d1b2b 100644 (file)
@@ -140,18 +140,17 @@ public class AlignmentView
    *          - when set, any groups on the given alignment will be marked on
    *          the view
    */
-  public AlignmentView(AlignmentI alignment,
- HiddenColumns hidden,
-          SequenceGroup selection,
-          boolean hasHiddenColumns, boolean selectedRegionOnly,
-          boolean recordGroups)
+  public AlignmentView(AlignmentI alignment, HiddenColumns hidden,
+          SequenceGroup selection, boolean hasHiddenColumns,
+          boolean selectedRegionOnly, boolean recordGroups)
   {
     // refactored from AlignViewport.getAlignmentView(selectedOnly);
     this(new jalview.datamodel.CigarArray(alignment,
             (hasHiddenColumns ? hidden : null),
             (selectedRegionOnly ? selection : null)),
-            (selectedRegionOnly && selection != null) ? selection
-                    .getStartRes() : 0);
+            (selectedRegionOnly && selection != null)
+                    ? selection.getStartRes()
+                    : 0);
     isNa = alignment.isNucleotide();
     // walk down SeqCigar array and Alignment Array - optionally restricted by
     // selected region.
@@ -163,8 +162,8 @@ public class AlignmentView
     {
       List<SequenceI> sel = selection.getSequences(null);
       this.selected = new ScGroup();
-      selseqs = selection
-              .getSequencesInOrder(alignment, selectedRegionOnly);
+      selseqs = selection.getSequencesInOrder(alignment,
+              selectedRegionOnly);
     }
     else
     {
@@ -335,9 +334,9 @@ public class AlignmentView
   {
     HiddenColumns hidden = new HiddenColumns();
 
-    return new Object[] {
-        SeqCigar.createAlignmentSequences(sequences, gapCharacter, hidden,
-                contigs), hidden };
+    return new Object[] { SeqCigar.createAlignmentSequences(sequences,
+            gapCharacter, hidden, contigs),
+        hidden };
   }
 
   /**
@@ -370,8 +369,8 @@ public class AlignmentView
    *          - true if vcal is alignment of the visible regions of the view
    *          (e.g. as returned from getVisibleAlignment)
    */
-  private void addPrunedGroupsInOrder(AlignmentI vcal, int gstart,
-          int gend, boolean viscontigs)
+  private void addPrunedGroupsInOrder(AlignmentI vcal, int gstart, int gend,
+          boolean viscontigs)
   {
     boolean r = false;
     if (gstart > -1 && gstart <= gend)
@@ -441,8 +440,8 @@ public class AlignmentView
               for (int h = 0; h < contigs.length; h += 3)
               {
                 {
-                  prune.addShift(p + contigs[h + 1], contigs[h + 2]
-                          - contigs[h + 1]);
+                  prune.addShift(p + contigs[h + 1],
+                          contigs[h + 2] - contigs[h + 1]);
                 }
                 p = contigs[h + 1] + contigs[h + 2];
               }
@@ -652,8 +651,8 @@ public class AlignmentView
           SequenceI mseq[] = new SequenceI[sequences.length];
           for (int s = 0; s < mseq.length; s++)
           {
-            mseq[s] = sequences[s].getSeq(gapCharacter).getSubSequence(
-                    start, contigs[contig + 1]);
+            mseq[s] = sequences[s].getSeq(gapCharacter)
+                    .getSubSequence(start, contigs[contig + 1]);
           }
           smsa[j] = mseq;
           j++;
@@ -699,9 +698,8 @@ public class AlignmentView
   {
     if (sequences == null || width <= 0)
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.empty_view_cannot_be_updated"));
+      throw new Error(MessageManager
+              .getString("error.empty_view_cannot_be_updated"));
     }
     if (nvismsa == null)
     {
@@ -732,17 +730,13 @@ public class AlignmentView
               j++;
               if (mseq.length != sequences.length)
               {
-                throw new Error(
-                        MessageManager
-                                .formatMessage(
-                                        "error.mismatch_between_number_of_sequences_in_block",
-                                        new String[] {
-                                            Integer.valueOf(j).toString(),
-                                            Integer.valueOf(mseq.length)
-                                                    .toString(),
-                                            Integer.valueOf(
-                                                    sequences.length)
-                                                    .toString() }));
+                throw new Error(MessageManager.formatMessage(
+                        "error.mismatch_between_number_of_sequences_in_block",
+                        new String[]
+                        { Integer.valueOf(j).toString(),
+                            Integer.valueOf(mseq.length).toString(),
+                            Integer.valueOf(sequences.length)
+                                    .toString() }));
               }
               swidth = mseq[0].getLength(); // JBPNote: could ensure padded
               // here.
@@ -754,9 +748,9 @@ public class AlignmentView
                 }
                 else
                 {
-                  alignment[s].setSequence(alignment[s]
-                          .getSequenceAsString()
-                          + mseq[s].getSequenceAsString());
+                  alignment[s]
+                          .setSequence(alignment[s].getSequenceAsString()
+                                  + mseq[s].getSequenceAsString());
                   if (mseq[s].getStart() <= mseq[s].getEnd())
                   {
                     alignment[s].setEnd(mseq[s].getEnd());
@@ -788,9 +782,9 @@ public class AlignmentView
                   }
                   else
                   {
-                    alignment[s].setSequence(alignment[s]
-                            .getSequenceAsString()
-                            + oseq.getSequenceAsString());
+                    alignment[s]
+                            .setSequence(alignment[s].getSequenceAsString()
+                                    + oseq.getSequenceAsString());
                     if (oseq.getEnd() >= oseq.getStart())
                     {
                       alignment[s].setEnd(oseq.getEnd());
@@ -825,8 +819,7 @@ public class AlignmentView
             }
           }
           // mark hidden segment as hidden in the new alignment
-          hidden.hideColumns(nwidth, nwidth + contigs[contig + 2]
-                  - 1);
+          hidden.hideColumns(nwidth, nwidth + contigs[contig + 2] - 1);
           nwidth += contigs[contig + 2];
         }
         // Do final segment - if it exists
@@ -881,9 +874,9 @@ public class AlignmentView
                   }
                   else
                   {
-                    alignment[s].setSequence(alignment[s]
-                            .getSequenceAsString()
-                            + oseq.getSequenceAsString());
+                    alignment[s]
+                            .setSequence(alignment[s].getSequenceAsString()
+                                    + oseq.getSequenceAsString());
                     if (oseq.getEnd() >= oseq.getStart())
                     {
                       alignment[s].setEnd(oseq.getEnd());
@@ -895,9 +888,8 @@ public class AlignmentView
               else
               {
                 // place gaps.
-                throw new Error(
-                        MessageManager
-                                .getString("error.padding_not_yet_implemented"));
+                throw new Error(MessageManager
+                        .getString("error.padding_not_yet_implemented"));
               }
             }
           }
@@ -909,12 +901,10 @@ public class AlignmentView
     {
       if (nvismsa.length != 1)
       {
-        throw new Error(
-                MessageManager
-                        .formatMessage(
-                                "error.mismatch_between_visible_blocks_to_update_and_number_of_contigs_in_view",
-                                new String[] { Integer.valueOf(
-                                        nvismsa.length).toString() }));
+        throw new Error(MessageManager.formatMessage(
+                "error.mismatch_between_visible_blocks_to_update_and_number_of_contigs_in_view",
+                new String[]
+                { Integer.valueOf(nvismsa.length).toString() }));
       }
       if (nvismsa[0] != null)
       {
@@ -1143,8 +1133,8 @@ public class AlignmentView
     AlignmentView view = null;
     try
     {
-      System.out
-              .println("View with no hidden columns, no limit to selection, no groups to be collected:");
+      System.out.println(
+              "View with no hidden columns, no limit to selection, no groups to be collected:");
       view = new AlignmentView(alignment, hidden, selection, false, false,
               false);
       summariseAlignmentView(view, System.out);
@@ -1152,99 +1142,99 @@ public class AlignmentView
     } catch (Exception e)
     {
       e.printStackTrace();
-      System.err
-              .println("Failed to generate alignment with selection but no groups marked.");
+      System.err.println(
+              "Failed to generate alignment with selection but no groups marked.");
     }
     try
     {
-      System.out
-              .println("View with no hidden columns, no limit to selection, and all groups to be collected:");
+      System.out.println(
+              "View with no hidden columns, no limit to selection, and all groups to be collected:");
       view = new AlignmentView(alignment, hidden, selection, false, false,
               true);
       summariseAlignmentView(view, System.out);
     } catch (Exception e)
     {
       e.printStackTrace();
-      System.err
-              .println("Failed to generate alignment with selection marked but no groups marked.");
+      System.err.println(
+              "Failed to generate alignment with selection marked but no groups marked.");
     }
     try
     {
-      System.out
-              .println("View with no hidden columns, limited to selection and no groups to be collected:");
+      System.out.println(
+              "View with no hidden columns, limited to selection and no groups to be collected:");
       view = new AlignmentView(alignment, hidden, selection, false, true,
               false);
       summariseAlignmentView(view, System.out);
     } catch (Exception e)
     {
       e.printStackTrace();
-      System.err
-              .println("Failed to generate alignment with selection restricted but no groups marked.");
+      System.err.println(
+              "Failed to generate alignment with selection restricted but no groups marked.");
     }
     try
     {
-      System.out
-              .println("View with no hidden columns, limited to selection, and all groups to be collected:");
+      System.out.println(
+              "View with no hidden columns, limited to selection, and all groups to be collected:");
       view = new AlignmentView(alignment, hidden, selection, false, true,
               true);
       summariseAlignmentView(view, System.out);
     } catch (Exception e)
     {
       e.printStackTrace();
-      System.err
-              .println("Failed to generate alignment with selection restricted and groups marked.");
+      System.err.println(
+              "Failed to generate alignment with selection restricted and groups marked.");
     }
     try
     {
-      System.out
-              .println("View *with* hidden columns, no limit to selection, no groups to be collected:");
+      System.out.println(
+              "View *with* hidden columns, no limit to selection, no groups to be collected:");
       view = new AlignmentView(alignment, hidden, selection, true, false,
               false);
       summariseAlignmentView(view, System.out);
     } catch (Exception e)
     {
       e.printStackTrace();
-      System.err
-              .println("Failed to generate alignment with selection but no groups marked.");
+      System.err.println(
+              "Failed to generate alignment with selection but no groups marked.");
     }
     try
     {
-      System.out
-              .println("View *with* hidden columns, no limit to selection, and all groups to be collected:");
+      System.out.println(
+              "View *with* hidden columns, no limit to selection, and all groups to be collected:");
       view = new AlignmentView(alignment, hidden, selection, true, false,
               true);
       summariseAlignmentView(view, System.out);
     } catch (Exception e)
     {
       e.printStackTrace();
-      System.err
-              .println("Failed to generate alignment with selection marked but no groups marked.");
+      System.err.println(
+              "Failed to generate alignment with selection marked but no groups marked.");
     }
     try
     {
-      System.out
-              .println("View *with* hidden columns, limited to selection and no groups to be collected:");
+      System.out.println(
+              "View *with* hidden columns, limited to selection and no groups to be collected:");
       view = new AlignmentView(alignment, hidden, selection, true, true,
               false);
       summariseAlignmentView(view, System.out);
     } catch (Exception e)
     {
       e.printStackTrace();
-      System.err
-              .println("Failed to generate alignment with selection restricted but no groups marked.");
+      System.err.println(
+              "Failed to generate alignment with selection restricted but no groups marked.");
     }
     try
     {
-      System.out
-              .println("View *with* hidden columns, limited to selection, and all groups to be collected:");
+      System.out.println(
+              "View *with* hidden columns, limited to selection, and all groups to be collected:");
       view = new AlignmentView(alignment, hidden, selection, true, true,
               true);
       summariseAlignmentView(view, System.out);
     } catch (Exception e)
     {
       e.printStackTrace();
-      System.err
-              .println("Failed to generate alignment with selection restricted and groups marked.");
+      System.err.println(
+              "Failed to generate alignment with selection restricted and groups marked.");
     }
 
   }
index f84ba95..e216c46 100644 (file)
@@ -27,21 +27,22 @@ import java.util.Iterator;
 public class AllColsCollection implements AlignmentColsCollectionI
 {
   int start;
+
   int end;
 
   HiddenColumns hidden;
-  
+
   public AllColsCollection(int s, int e, AlignmentI al)
   {
     start = s;
     end = e;
     hidden = al.getHiddenColumns();
   }
-  
+
   @Override
   public Iterator<Integer> iterator()
   {
-    return new AllColsIterator(start,end,hidden);
+    return new AllColsIterator(start, end, hidden);
   }
 
   @Override
@@ -49,4 +50,10 @@ public class AllColsCollection implements AlignmentColsCollectionI
   {
     return !hidden.isVisible(c);
   }
+
+  @Override
+  public boolean hasHidden()
+  {
+    return hidden.hasHiddenColumns();
+  }
 }
index c1296d5..1ff6a66 100644 (file)
@@ -38,7 +38,8 @@ public class AllColsIterator implements Iterator<Integer>
 
   private int current;
 
-  public AllColsIterator(int firstcol, int lastcol, HiddenColumns hiddenCols)
+  public AllColsIterator(int firstcol, int lastcol,
+          HiddenColumns hiddenCols)
   {
     last = lastcol;
     next = firstcol;
@@ -70,4 +71,3 @@ public class AllColsIterator implements Iterator<Integer>
     throw new UnsupportedOperationException();
   }
 }
-
index 502ace4..10c47f0 100644 (file)
@@ -59,5 +59,10 @@ public class AllRowsCollection implements AlignmentRowsCollectionI
   {
     return alignment.getSequenceAtAbsoluteIndex(seq);
   }
-}
 
+  @Override
+  public boolean hasHidden()
+  {
+    return (hidden.getSize() > 0);
+  }
+}
index b6d45f8..ae397af 100644 (file)
@@ -73,5 +73,3 @@ public class AllRowsIterator implements Iterator<Integer>
     throw new UnsupportedOperationException();
   }
 }
-
-
index 8de8eb2..ae29417 100755 (executable)
@@ -51,7 +51,9 @@ public class Annotation
    */
   public char secondaryStructure = ' ';
 
-  /** Score for the position - used in histograms, line graphs and for shading */
+  /**
+   * Score for the position - used in histograms, line graphs and for shading
+   */
   public float value;
 
   /** Colour for position */
@@ -206,10 +208,10 @@ public class Annotation
   public boolean isWhitespace()
   {
     return ((value == 0f)
-            && ((description == null) || (description.trim()
-                    .length() == 0))
-            && ((displayCharacter == null) || (displayCharacter
-                    .trim().length() == 0))
-            && (secondaryStructure == '\0' || (secondaryStructure == ' ')) && colour == null);
+            && ((description == null) || (description.trim().length() == 0))
+            && ((displayCharacter == null)
+                    || (displayCharacter.trim().length() == 0))
+            && (secondaryStructure == '\0' || (secondaryStructure == ' '))
+            && colour == null);
   }
 }
index a13b492..c0ff0e4 100755 (executable)
@@ -263,7 +263,8 @@ public class BinaryNode
    * 
    * set the display name
    * 
-   * @param new name
+   * @param new
+   *          name
    */
   public void setName(String name)
   {
index b7e15a6..c33abb3 100755 (executable)
@@ -70,7 +70,7 @@ public class BinarySequence extends Sequence
     int nores = (isNa) ? ResidueProperties.maxNucleotideIndex
             : ResidueProperties.maxProteinIndex;
 
-    dbinary = new double[getSequence().length * nores];
+    dbinary = new double[getLength() * nores];
 
     return nores;
   }
@@ -88,7 +88,7 @@ public class BinarySequence extends Sequence
   {
     int nores = initMatrixGetNoRes();
     final int[] sindex = getSymbolmatrix();
-    for (int i = 0; i < getSequence().length; i++)
+    for (int i = 0; i < getLength(); i++)
     {
       int aanum = nores - 1;
 
@@ -119,10 +119,10 @@ public class BinarySequence extends Sequence
   {
     if (isNa != smtrx.isDNA())
     {
-      throw new InvalidSequenceTypeException("matrix "
-              + smtrx.getClass().getCanonicalName()
-              + " is not a valid matrix for "
-              + (isNa ? "nucleotide" : "protein") + "sequences");
+      throw new InvalidSequenceTypeException(
+              "matrix " + smtrx.getClass().getCanonicalName()
+                      + " is not a valid matrix for "
+                      + (isNa ? "nucleotide" : "protein") + "sequences");
     }
     matrixEncode(smtrx.isDNA() ? ResidueProperties.nucleotideIndex
             : ResidueProperties.aaIndex, smtrx.getMatrix());
@@ -132,7 +132,7 @@ public class BinarySequence extends Sequence
   {
     int nores = initMatrixGetNoRes();
 
-    for (int i = 0, iSize = getSequence().length; i < iSize; i++)
+    for (int i = 0, iSize = getLength(); i < iSize; i++)
     {
       int aanum = nores - 1;
 
index febf6b4..1723f1d 100644 (file)
@@ -68,7 +68,8 @@ public class CigarArray extends CigarBase
       for (int c = 0; c < cigars.length; c++)
       {
         refCigars[c] = cigars[c];
-        if (!((cigars[c] instanceof SeqCigar) || cigars[c] instanceof CigarCigar))
+        if (!((cigars[c] instanceof SeqCigar)
+                || cigars[c] instanceof CigarCigar))
         {
           seqcigararray = false;
         }
@@ -90,8 +91,8 @@ public class CigarArray extends CigarBase
   {
     this(constructSeqCigarArray(alignment, selectionGroup));
     constructFromAlignment(alignment,
-            hidden != null ? hidden.getHiddenColumnsCopy()
-                    : null, selectionGroup);
+            hidden != null ? hidden.getHiddenColumnsCopy() : null,
+            selectionGroup);
   }
 
   private static int[] _calcStartEndBounds(AlignmentI alignment,
@@ -169,32 +170,30 @@ public class CigarArray extends CigarBase
         hideStart = region[0];
         hideEnd = region[1];
         // edit hidden regions to selection range
-        if (hideStart < last)
+
+        // just move on if hideEnd is before last
+        if (hideEnd < last)
         {
-          if (hideEnd > last)
-          {
-            hideStart = last;
-          }
-          else
-          {
-            continue;
-          }
+          continue;
         }
-
+        // exit if next region is after end
         if (hideStart > end)
         {
           break;
         }
 
-        if (hideEnd > end)
+        // truncate region at start if last falls in region
+        if ((hideStart < last) && (hideEnd >= last))
         {
-          hideEnd = end;
+          hideStart = last;
         }
 
-        if (hideStart > hideEnd)
+        // truncate region at end if end falls in region
+        if (hideEnd > end) // already checked that hideStart<=end
         {
-          break;
+          hideEnd = end;
         }
+
         /**
          * form operations...
          */
@@ -206,7 +205,7 @@ public class CigarArray extends CigarBase
         last = hideEnd + 1;
       }
       // Final match if necessary.
-      if (last < end)
+      if (last <= end)
       {
         addOperation(CigarArray.M, end - last + 1);
       }
index 5fb507a..4e7e03f 100644 (file)
@@ -83,7 +83,8 @@ public abstract class CigarBase
     int[][] deletions = new int[length][];
     int[][] trunc_deletions = null;
     StringBuffer sq = new StringBuffer();
-    int cursor = 0, alcursor = 0, start = 0, startpos = 0, end = 0, endpos = 0, delcount = -1;
+    int cursor = 0, alcursor = 0, start = 0, startpos = 0, end = 0,
+            endpos = 0, delcount = -1;
     boolean consecutive_del = false;
     if (length == 0)
     {
@@ -146,8 +147,8 @@ public abstract class CigarBase
         break;
       default:
         throw new Error(MessageManager.formatMessage(
-                "error.unknown_seq_cigar_operation",
-                new String[] { new StringBuffer(operation[i]).toString() }));
+                "error.unknown_seq_cigar_operation", new String[]
+                { new StringBuffer(operation[i]).toString() }));
       }
     }
     if (++delcount > 0)
@@ -157,7 +158,8 @@ public abstract class CigarBase
     }
     deletions = null;
     return new Object[] { ((reference != null) ? sq.toString() : null),
-        new int[] { start, startpos, end, endpos }, trunc_deletions };
+        new int[]
+        { start, startpos, end, endpos }, trunc_deletions };
   }
 
   protected void compact_operations()
@@ -225,9 +227,8 @@ public abstract class CigarBase
       } while (c >= '0' && c <= '9' && j < l);
       if (j >= l && c >= '0' && c <= '9')
       {
-        throw new Exception(
-                MessageManager
-                        .getString("exception.unterminated_cigar_string"));
+        throw new Exception(MessageManager
+                .getString("exception.unterminated_cigar_string"));
       }
       try
       {
@@ -236,9 +237,8 @@ public abstract class CigarBase
         i = j;
       } catch (Exception e)
       {
-        throw new Error(
-                MessageManager
-                        .getString("error.implementation_bug_parse_cigar_string"));
+        throw new Error(MessageManager
+                .getString("error.implementation_bug_parse_cigar_string"));
       }
       if (c >= 'a' && c <= 'z')
       {
@@ -252,7 +252,8 @@ public abstract class CigarBase
       {
         throw new Exception(MessageManager.formatMessage(
                 "exception.unexpected_operation_cigar_string_pos",
-                new String[] { new StringBuffer(c).toString(),
+                new String[]
+                { new StringBuffer(c).toString(),
                     Integer.valueOf(i).toString(), cigarString }));
       }
     }
@@ -275,9 +276,8 @@ public abstract class CigarBase
     }
     if (op != M && op != D && op != I)
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_error_invalid_operation_string"));
+      throw new Error(MessageManager.getString(
+              "error.implementation_error_invalid_operation_string"));
     }
     if (range == 0)
     {
@@ -345,14 +345,14 @@ public abstract class CigarBase
    *          int public void addOperationAt(int pos, char op, int range) { int
    *          cursor = -1; // mark the position for the current operation being
    *          edited. int o = 0; boolean last_d = false; // previous op was a
-   *          deletion. if (pos < -1) throw new
-   *          Error("pos<-1 is not supported."); while (o<length) { if
-   *          (operation[o] != D) { if ( (cursor + this.range[o]) < pos) {
-   *          cursor += this.range[o]; o++; last_d=false; } else { break; } }
-   *          else { last_d=true; o++; } } if (o==length) { // must insert more
-   *          operations before pos if (pos-cursor>0) addInsertion(pos-cursor);
-   *          // then just add the new operation. Regardless of what it is.
-   *          addOperation(op, range); } else { int diff = pos - cursor;
+   *          deletion. if (pos < -1) throw new Error("pos<-1 is not
+   *          supported."); while (o<length) { if (operation[o] != D) { if (
+   *          (cursor + this.range[o]) < pos) { cursor += this.range[o]; o++;
+   *          last_d=false; } else { break; } } else { last_d=true; o++; } } if
+   *          (o==length) { // must insert more operations before pos if
+   *          (pos-cursor>0) addInsertion(pos-cursor); // then just add the new
+   *          operation. Regardless of what it is. addOperation(op, range); }
+   *          else { int diff = pos - cursor;
    * 
    *          int e_length = length-o; // new edit operation array length. //
    *          diff<0 - can only happen before first insertion or match. -
@@ -398,9 +398,8 @@ public abstract class CigarBase
     }
     if (start < 0 || start > end)
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_error_delete_range_out_of_bounds"));
+      throw new Error(MessageManager.getString(
+              "error.implementation_error_delete_range_out_of_bounds"));
     }
     // find beginning
     int cursor = 0; // mark the position for the current operation being edited.
@@ -478,7 +477,8 @@ public abstract class CigarBase
         default:
           throw new Error(MessageManager.formatMessage(
                   "error.implementation_error_unknown_operation",
-                  new String[] { new StringBuffer(oldops[o]).toString() }));
+                  new String[]
+                  { new StringBuffer(oldops[o]).toString() }));
         }
         rlength -= remain;
         remain = oldrange[++o]; // number of op characters left to edit
index e2da220..9643d9d 100644 (file)
@@ -52,8 +52,8 @@ public class CigarCigar extends CigarSimple
     String refString = refCigar.getSequenceString(GapChar);
     if (refString != null)
     {
-      return (length == 0) ? "" : (String) getSequenceAndDeletions(
-              refString, GapChar)[0];
+      return (length == 0) ? ""
+              : (String) getSequenceAndDeletions(refString, GapChar)[0];
     }
     else
     {
index 4cdd7af..6d620b4 100644 (file)
@@ -401,7 +401,6 @@ public class ColumnSelection
 
   }
 
-
   /**
    * Hides the specified column and any adjacent selected columns
    * 
@@ -444,10 +443,6 @@ public class ColumnSelection
     hidden.hideColumns(min, max);
   }
 
-
-
-
-
   /**
    * Copy constructor
    * 
@@ -468,11 +463,6 @@ public class ColumnSelection
   {
   }
 
-
-
-
-
-
   /**
    * Invert the column selection from first to end-1. leaves hiddenColumns
    * untouched (and unselected)
@@ -534,7 +524,6 @@ public class ColumnSelection
     }
   }
 
-
   /**
    * 
    * @return true if there are columns marked
@@ -544,8 +533,6 @@ public class ColumnSelection
     return (selection != null && selection.size() > 0);
   }
 
-
-
   public boolean filterAnnotations(Annotation[] annotations,
           AnnotationFilterParameter filterParams)
   {
@@ -560,13 +547,15 @@ public class ColumnSelection
 
         boolean itemMatched = false;
 
-        if (filterParams.getThresholdType() == AnnotationFilterParameter.ThresholdType.ABOVE_THRESHOLD
+        if (filterParams
+                .getThresholdType() == AnnotationFilterParameter.ThresholdType.ABOVE_THRESHOLD
                 && annotations[count].value >= filterParams
                         .getThresholdValue())
         {
           itemMatched = true;
         }
-        if (filterParams.getThresholdType() == AnnotationFilterParameter.ThresholdType.BELOW_THRESHOLD
+        if (filterParams
+                .getThresholdType() == AnnotationFilterParameter.ThresholdType.BELOW_THRESHOLD
                 && annotations[count].value <= filterParams
                         .getThresholdValue())
         {
@@ -691,8 +680,8 @@ public class ColumnSelection
    * 
    * @return
    */
-  public boolean markColumns(BitSet markedColumns, int startCol,
-          int endCol, boolean invert, boolean extendCurrent, boolean toggle)
+  public boolean markColumns(BitSet markedColumns, int startCol, int endCol,
+          boolean invert, boolean extendCurrent, boolean toggle)
   {
     boolean changed = false;
     if (!extendCurrent && !toggle)
diff --git a/src/jalview/datamodel/ContiguousI.java b/src/jalview/datamodel/ContiguousI.java
new file mode 100644 (file)
index 0000000..a9b1372
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+public interface ContiguousI
+{
+  int getBegin(); // todo want long for genomic positions?
+
+  int getEnd();
+}
index ec6dcf8..f7837f7 100755 (executable)
@@ -68,10 +68,10 @@ public class DBRefEntry implements DBRefEntryI
   public DBRefEntry(DBRefEntryI entry)
   {
     this((entry.getSource() == null ? "" : new String(entry.getSource())),
-            (entry.getVersion() == null ? "" : new String(
-                    entry.getVersion())),
-            (entry.getAccessionId() == null ? "" : new String(
-                    entry.getAccessionId())),
+            (entry.getVersion() == null ? ""
+                    : new String(entry.getVersion())),
+            (entry.getAccessionId() == null ? ""
+                    : new String(entry.getAccessionId())),
             (entry.getMap() == null ? null : new Mapping(entry.getMap())));
   }
 
@@ -89,9 +89,8 @@ public class DBRefEntry implements DBRefEntryI
     {
       return true;
     }
-    if (equalRef(entry)
-            && ((map == null && entry.map == null) || (map != null
-                    && entry.map != null && map.equals(entry.map))))
+    if (equalRef(entry) && ((map == null && entry.map == null)
+            || (map != null && entry.map != null && map.equals(entry.map))))
     {
       return true;
     }
@@ -104,7 +103,8 @@ public class DBRefEntry implements DBRefEntryI
    * <ul>
    * <li>source and accession are identical (ignoring case)</li>
    * <li>version is identical (ignoring case), or this version is of the format
-   * "someSource:0", in which case the version for the other entry replaces it</li>
+   * "someSource:0", in which case the version for the other entry replaces
+   * it</li>
    * <li>mappings are not compared but if this entry has no mapping, replace
    * with that for the other entry</li>
    * </ul>
@@ -141,8 +141,8 @@ public class DBRefEntry implements DBRefEntryI
     String otherAccession = other.getAccessionId();
     if ((accessionId == null && otherAccession != null)
             || (accessionId != null && otherAccession == null)
-            || (accessionId != null && !accessionId
-                    .equalsIgnoreCase(otherAccession)))
+            || (accessionId != null
+                    && !accessionId.equalsIgnoreCase(otherAccession)))
     {
       return false;
     }
@@ -160,9 +160,8 @@ public class DBRefEntry implements DBRefEntryI
     }
     else
     {
-      if (version != null
-              && (otherVersion == null || !version
-                      .equalsIgnoreCase(otherVersion)))
+      if (version != null && (otherVersion == null
+              || !version.equalsIgnoreCase(otherVersion)))
       {
         return false;
       }
@@ -197,12 +196,12 @@ public class DBRefEntry implements DBRefEntryI
       return true;
     }
     if (entry != null
-            && (source != null && entry.getSource() != null && source
-                    .equalsIgnoreCase(entry.getSource()))
-            && (accessionId != null && entry.getAccessionId() != null && accessionId
-                    .equalsIgnoreCase(entry.getAccessionId()))
-            && (version != null && entry.getVersion() != null && version
-                    .equalsIgnoreCase(entry.getVersion())))
+            && (source != null && entry.getSource() != null
+                    && source.equalsIgnoreCase(entry.getSource()))
+            && (accessionId != null && entry.getAccessionId() != null
+                    && accessionId.equalsIgnoreCase(entry.getAccessionId()))
+            && (version != null && entry.getVersion() != null
+                    && version.equalsIgnoreCase(entry.getVersion())))
     {
       return true;
     }
index 2306bec..f495624 100644 (file)
@@ -47,8 +47,8 @@ public class FeatureProperties
     if (type.equalsIgnoreCase(EMBL_CODING_FEATURE))
     {
       return (dbrefsource == null
-              || dbrefsource.equalsIgnoreCase(DBRefSource.EMBL) || dbrefsource
-                .equalsIgnoreCase(DBRefSource.EMBLCDS));
+              || dbrefsource.equalsIgnoreCase(DBRefSource.EMBL)
+              || dbrefsource.equalsIgnoreCase(DBRefSource.EMBLCDS));
     }
     return false;
   }
index df2f866..38a5061 100755 (executable)
@@ -61,12 +61,14 @@ public class GraphLine
     if (obj != null && obj instanceof GraphLine)
     {
       GraphLine other = (GraphLine) obj;
-      return displayed == other.displayed
-              && value == other.value
-              && (colour != null ? (other.colour != null && other.colour
-                      .equals(colour)) : other.colour == null)
-              && (label != null ? (other.label != null && other.label
-                      .equals(label)) : other.label == null);
+      return displayed == other.displayed && value == other.value
+              && (colour != null
+                      ? (other.colour != null
+                              && other.colour.equals(colour))
+                      : other.colour == null)
+              && (label != null
+                      ? (other.label != null && other.label.equals(label))
+                      : other.label == null);
     }
     return false;
   }
index 169b0a4..c0a43ee 100644 (file)
@@ -33,7 +33,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
 public class HiddenColumns
 {
   private static final ReentrantReadWriteLock LOCK = new ReentrantReadWriteLock();
-  
+
   /*
    * list of hidden column [start, end] ranges; the list is maintained in
    * ascending start column order
@@ -135,8 +135,7 @@ public class HiddenColumns
         }
       }
       return size;
-    }
-    finally
+    } finally
     {
       LOCK.readLock().unlock();
     }
@@ -290,47 +289,47 @@ public class HiddenColumns
     {
 
       LOCK.readLock().lock();
-    int distance = visibleDistance;
+      int distance = visibleDistance;
 
-    // in case startColumn is in a hidden region, move it to the left
-    int start = adjustForHiddenColumns(findColumnPosition(startColumn));
+      // in case startColumn is in a hidden region, move it to the left
+      int start = adjustForHiddenColumns(findColumnPosition(startColumn));
 
-    // get index of hidden region to left of start
-    int index = getHiddenIndexLeft(start);
-    if (index == -1)
-    {
-      // no hidden regions to left of startColumn
-      return start - distance;
-    }
+      // get index of hidden region to left of start
+      int index = getHiddenIndexLeft(start);
+      if (index == -1)
+      {
+        // no hidden regions to left of startColumn
+        return start - distance;
+      }
 
-    // walk backwards through the alignment subtracting the counts of visible
-    // columns from distance
-    int[] region;
-    int gap = 0;
-    int nextstart = start;
+      // walk backwards through the alignment subtracting the counts of visible
+      // columns from distance
+      int[] region;
+      int gap = 0;
+      int nextstart = start;
 
-    while ((index > -1) && (distance - gap > 0))
-    {
-      // subtract the gap to right of region from distance
-      distance -= gap;
-      start = nextstart;
+      while ((index > -1) && (distance - gap > 0))
+      {
+        // subtract the gap to right of region from distance
+        distance -= gap;
+        start = nextstart;
 
-      // calculate the next gap
-      region = hiddenColumns.get(index);
-      gap = start - region[1];
+        // calculate the next gap
+        region = hiddenColumns.get(index);
+        gap = start - region[1];
 
-      // set start to just to left of current region
-      nextstart = region[0] - 1;
-      index--;
-    }
+        // set start to just to left of current region
+        nextstart = region[0] - 1;
+        index--;
+      }
 
-    if (distance - gap > 0)
-    {
-      // fell out of loop because there are no more hidden regions
-      distance -= gap;
-      return nextstart - distance;
-    }
-    return start - distance;
+      if (distance - gap > 0)
+      {
+        // fell out of loop because there are no more hidden regions
+        distance -= gap;
+        return nextstart - distance;
+      }
+      return start - distance;
     } finally
     {
       LOCK.readLock().unlock();
@@ -382,8 +381,7 @@ public class HiddenColumns
       }
 
       return positions;
-    }
-    finally
+    } finally
     {
       LOCK.readLock().unlock();
     }
@@ -437,22 +435,22 @@ public class HiddenColumns
     {
       LOCK.readLock().lock();
 
-    if (hiddenColumns != null)
-    {
-      int index = hiddenColumns.size() - 1;
-      do
+      if (hiddenColumns != null)
       {
-          int[] region = hiddenColumns.get(index);
-        if (alPos > region[1])
+        int index = hiddenColumns.size() - 1;
+        do
         {
-          return region[1];
-        }
+          int[] region = hiddenColumns.get(index);
+          if (alPos > region[1])
+          {
+            return region[1];
+          }
 
-        index--;
-      } while (index > -1);
-    }
+          index--;
+        } while (index > -1);
+      }
 
-    return alPos;
+      return alPos;
     } finally
     {
       LOCK.readLock().unlock();
@@ -473,22 +471,22 @@ public class HiddenColumns
     {
 
       LOCK.readLock().lock();
-    if (hiddenColumns != null)
-    {
-      int index = hiddenColumns.size() - 1;
-      do
+      if (hiddenColumns != null)
       {
-          int[] region = hiddenColumns.get(index);
-        if (pos > region[1])
+        int index = hiddenColumns.size() - 1;
+        do
         {
-          return index;
-        }
+          int[] region = hiddenColumns.get(index);
+          if (pos > region[1])
+          {
+            return index;
+          }
 
-        index--;
-      } while (index > -1);
-    }
+          index--;
+        } while (index > -1);
+      }
 
-    return -1;
+      return -1;
     } finally
     {
       LOCK.readLock().unlock();
@@ -578,11 +576,11 @@ public class HiddenColumns
           }
           return;
         }
-    }
+      }
 
-    /*
-     * remaining case is that the new range follows everything else
-     */
+      /*
+       * remaining case is that the new range follows everything else
+       */
       hiddenColumns.add(new int[] { start, end });
     } finally
     {
@@ -599,18 +597,18 @@ public class HiddenColumns
     {
       LOCK.readLock().lock();
 
-    if (hiddenColumns != null)
-    {
-      for (int[] region : hiddenColumns)
+      if (hiddenColumns != null)
       {
-        if (column >= region[0] && column <= region[1])
+        for (int[] region : hiddenColumns)
         {
-          return false;
+          if (column >= region[0] && column <= region[1])
+          {
+            return false;
+          }
         }
       }
-    }
 
-    return true;
+      return true;
     } finally
     {
       LOCK.readLock().unlock();
@@ -641,7 +639,7 @@ public class HiddenColumns
 
     return copy;
   }
-  
+
   /**
    * Returns a copy of the vector of hidden regions, as an ArrayList. Before
    * using this method please consider if you really need access to the hidden
@@ -760,8 +758,7 @@ public class HiddenColumns
           }
         }
       }
-    }
-    finally
+    } finally
     {
       LOCK.writeLock().unlock();
     }
@@ -828,8 +825,7 @@ public class HiddenColumns
       {
         return new int[] { start, end - 1 };
       }
-    }
-    finally
+    } finally
     {
       LOCK.readLock().unlock();
     }
@@ -898,8 +894,7 @@ public class HiddenColumns
       }
 
       return selections;
-    }
-    finally
+    } finally
     {
       LOCK.readLock().unlock();
     }
@@ -992,8 +987,7 @@ public class HiddenColumns
       }
       // otherwise, sequence was completely hidden
       return new int[] { visPrev, visNext, 0, 0, firstP, lastP };
-    }
-    finally
+    } finally
     {
       LOCK.readLock().unlock();
     }
@@ -1114,8 +1108,7 @@ public class HiddenColumns
       {
         alignmentAnnotation.restrict(start, end);
       }
-    }
-    finally
+    } finally
     {
       LOCK.readLock().unlock();
     }
@@ -1196,8 +1189,7 @@ public class HiddenColumns
       }
 
       hiddenColumns = null;
-    }
-    finally
+    } finally
     {
       LOCK.writeLock().unlock();
     }
@@ -1232,8 +1224,7 @@ public class HiddenColumns
       {
         hiddenColumns = null;
       }
-    }
-    finally
+    } finally
     {
       LOCK.writeLock().unlock();
     }
@@ -1357,8 +1348,7 @@ public class HiddenColumns
           hiddenColumns = null;
         }
       }
-    }
-    finally
+    } finally
     {
       LOCK.writeLock().unlock();
     }
@@ -1456,9 +1446,8 @@ public class HiddenColumns
             }
             else
             {
-              al.getSequenceAt(s).setSequence(
-                      sq.substring(0, spos + offset) + sb.toString()
-                              + sq.substring(spos + offset));
+              al.getSequenceAt(s).setSequence(sq.substring(0, spos + offset)
+                      + sb.toString() + sq.substring(spos + offset));
             }
           }
         }
@@ -1470,7 +1459,8 @@ public class HiddenColumns
     {
       // pad the final region with gaps.
       StringBuffer sb = new StringBuffer();
-      for (int s = 0, ns = profileseq.getLength() - spos - offset; s < ns; s++)
+      for (int s = 0, ns = profileseq.getLength() - spos
+              - offset; s < ns; s++)
       {
         sb.append(gc);
       }
@@ -1572,8 +1562,7 @@ public class HiddenColumns
         }
       }
       return hashCode;
-    }
-    finally
+    } finally
     {
       LOCK.readLock().unlock();
     }
@@ -1621,8 +1610,7 @@ public class HiddenColumns
       {
         inserts.set(range[0], range[1] + 1);
       }
-    }
-    finally
+    } finally
     {
       LOCK.readLock().unlock();
     }
index 32443d8..c9dce08 100755 (executable)
@@ -239,8 +239,8 @@ public class HiddenSequences
           }
           else
           {
-            System.out.println(seq.getName()
-                    + " has been deleted whilst hidden");
+            System.out.println(
+                    seq.getName() + " has been deleted whilst hidden");
           }
         }
       }
index 1c196be..b5184fb 100644 (file)
@@ -46,7 +46,7 @@ public class Mapping
     /*
      * The characters of the aligned sequence e.g. "-cGT-ACgTG-"
      */
-    private final char[] alignedSeq;
+    private final SequenceI alignedSeq;
 
     /*
      * the sequence start residue
@@ -102,7 +102,7 @@ public class Mapping
      */
     public AlignedCodonIterator(SequenceI seq, char gapChar)
     {
-      this.alignedSeq = seq.getSequence();
+      this.alignedSeq = seq;
       this.start = seq.getStart();
       this.gap = gapChar;
       fromRanges = map.getFromRanges().iterator();
@@ -176,14 +176,14 @@ public class Mapping
       if (toPosition <= currentToRange[1])
       {
         SequenceI seq = Mapping.this.to;
-        char pep = seq.getSequence()[toPosition - seq.getStart()];
+        char pep = seq.getCharAt(toPosition - seq.getStart());
         toPosition++;
         return String.valueOf(pep);
       }
       if (!toRanges.hasNext())
       {
-        throw new NoSuchElementException("Ran out of peptide at position "
-                + toPosition);
+        throw new NoSuchElementException(
+                "Ran out of peptide at position " + toPosition);
       }
       currentToRange = toRanges.next();
       toPosition = currentToRange[0];
@@ -257,9 +257,10 @@ public class Mapping
        * allow for offset e.g. treat pos 8 as 2 if sequence starts at 7
        */
       int truePos = sequencePos - (start - 1);
-      while (alignedBases < truePos && alignedColumn < alignedSeq.length)
+      int length = alignedSeq.getLength();
+      while (alignedBases < truePos && alignedColumn < length)
       {
-        char c = alignedSeq[alignedColumn++];
+        char c = alignedSeq.getCharAt(alignedColumn++);
         if (c != gap && !Comparison.isGap(c))
         {
           alignedBases++;
@@ -530,9 +531,8 @@ public class Mapping
         SequenceFeature[] vf = new SequenceFeature[frange.length / 2];
         for (int i = 0, v = 0; i < frange.length; i += 2, v++)
         {
-          vf[v] = new SequenceFeature(f);
-          vf[v].setBegin(frange[i]);
-          vf[v].setEnd(frange[i + 1]);
+          vf[v] = new SequenceFeature(f, frange[i], frange[i + 1],
+                  f.getFeatureGroup(), f.getScore());
           if (frange.length > 2)
           {
             vf[v].setDescription(f.getDescription() + "\nPart " + (v + 1));
@@ -541,27 +541,7 @@ public class Mapping
         return vf;
       }
     }
-    if (false) // else
-    {
-      int[] word = getWord(f.getBegin());
-      if (word[0] < word[1])
-      {
-        f.setBegin(word[0]);
-      }
-      else
-      {
-        f.setBegin(word[1]);
-      }
-      word = getWord(f.getEnd());
-      if (word[0] > word[1])
-      {
-        f.setEnd(word[0]);
-      }
-      else
-      {
-        f.setEnd(word[1]);
-      }
-    }
+
     // give up and just return the feature.
     return new SequenceFeature[] { f };
   }
@@ -687,8 +667,8 @@ public class Mapping
         to[f * 2] = r[0];
         to[f * 2 + 1] = r[1];
       }
-      copy.setMap(new MapList(from, to, map.getFromRatio(), map
-              .getToRatio()));
+      copy.setMap(
+              new MapList(from, to, map.getFromRatio(), map.getToRatio()));
     }
     return copy;
   }
@@ -713,19 +693,6 @@ public class Mapping
     to = tto;
   }
 
-  /*
-   * (non-Javadoc)
-   * 
-   * @see java.lang.Object#finalize()
-   */
-  @Override
-  protected void finalize() throws Throwable
-  {
-    map = null;
-    to = null;
-    super.finalize();
-  }
-
   /**
    * Returns an iterator which can serve up the aligned codon column positions
    * and their corresponding peptide products
@@ -735,7 +702,8 @@ public class Mapping
    * @param gapChar
    * @return
    */
-  public Iterator<AlignedCodon> getCodonIterator(SequenceI seq, char gapChar)
+  public Iterator<AlignedCodon> getCodonIterator(SequenceI seq,
+          char gapChar)
   {
     return new AlignedCodonIterator(seq, gapChar);
   }
@@ -746,8 +714,8 @@ public class Mapping
   @Override
   public String toString()
   {
-    return String.format("%s %s", this.map.toString(), this.to == null ? ""
-            : this.to.getName());
+    return String.format("%s %s", this.map.toString(),
+            this.to == null ? "" : this.to.getName());
   }
 
   /**
index 8debacf..c1dc77c 100755 (executable)
@@ -73,6 +73,7 @@ public class PDBEntry
     {
       return format;
     }
+
     public String getExtension()
     {
       return ext;
@@ -151,7 +152,6 @@ public class PDBEntry
   {
   }
 
-
   public PDBEntry(String pdbId, String chain, PDBEntry.Type type,
           String filePath)
   {
@@ -164,7 +164,8 @@ public class PDBEntry
    * @param entryType
    * @param filePath
    */
-  void init(String pdbId, String chain, PDBEntry.Type entryType, String filePath)
+  void init(String pdbId, String chain, PDBEntry.Type entryType,
+          String filePath)
   {
     this.id = pdbId;
     this.type = entryType == null ? null : entryType.toString();
@@ -199,8 +200,8 @@ public class PDBEntry
   {
     if (!DBRefSource.PDB.equals(dbr.getSource()))
     {
-      throw new IllegalArgumentException("Invalid source: "
-              + dbr.getSource());
+      throw new IllegalArgumentException(
+              "Invalid source: " + dbr.getSource());
     }
 
     String pdbId = dbr.getAccessionId();
index 1501808..8638896 100644 (file)
@@ -20,7 +20,6 @@
  */
 package jalview.datamodel;
 
-
 /**
  * A profile for one column of an alignment
  * 
index f65830a..14eae51 100644 (file)
@@ -38,7 +38,8 @@ public class Profiles implements ProfilesI
   @Override
   public ProfileI get(int col)
   {
-    return profiles != null && col >= 0 && col < profiles.length ? profiles[col]
+    return profiles != null && col >= 0 && col < profiles.length
+            ? profiles[col]
             : null;
   }
 
diff --git a/src/jalview/datamodel/Range.java b/src/jalview/datamodel/Range.java
new file mode 100644 (file)
index 0000000..8b6f617
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+/**
+ * An immutable data bean that models a start-end range
+ */
+public class Range implements ContiguousI
+{
+  public final int start;
+
+  public final int end;
+
+  @Override
+  public int getBegin()
+  {
+    return start;
+  }
+
+  @Override
+  public int getEnd()
+  {
+    return end;
+  }
+
+  public Range(int i, int j)
+  {
+    start = i;
+    end = j;
+  }
+
+  @Override
+  public String toString()
+  {
+    return String.valueOf(start) + "-" + String.valueOf(end);
+  }
+
+  @Override
+  public int hashCode()
+  {
+    return start * 31 + end;
+  }
+
+  @Override
+  public boolean equals(Object obj)
+  {
+    if (obj instanceof Range)
+    {
+      Range r = (Range) obj;
+      return (start == r.start && end == r.end);
+    }
+    return false;
+  }
+}
index 3e3a966..74eb887 100644 (file)
@@ -28,6 +28,7 @@ import jalview.util.SparseCount;
 /**
  * A class to count occurrences of residues in a profile, optimised for speed
  * and memory footprint.
+ * 
  * @author gmcarstairs
  *
  */
@@ -447,8 +448,8 @@ public class ResidueCount
       {
         if (intCounts[i] == count)
         {
-          modal.append(isNucleotide ? NUCS.charAt(i - 1) : AAS
-                  .charAt(i - 1));
+          modal.append(
+                  isNucleotide ? NUCS.charAt(i - 1) : AAS.charAt(i - 1));
         }
       }
     }
@@ -458,8 +459,8 @@ public class ResidueCount
       {
         if (counts[i] == count)
         {
-          modal.append(isNucleotide ? NUCS.charAt(i - 1) : AAS
-                  .charAt(i - 1));
+          modal.append(
+                  isNucleotide ? NUCS.charAt(i - 1) : AAS.charAt(i - 1));
         }
       }
     }
@@ -492,7 +493,8 @@ public class ResidueCount
    * 
    * @return
    */
-  public int size() {
+  public int size()
+  {
     int size = 0;
     if (useIntCounts)
     {
@@ -546,8 +548,8 @@ public class ResidueCount
       {
         if (intCounts[i] > 0)
         {
-          char symbol = isNucleotide ? NUCS.charAt(i - 1) : AAS
-                  .charAt(i - 1);
+          char symbol = isNucleotide ? NUCS.charAt(i - 1)
+                  : AAS.charAt(i - 1);
           symbols[j] = symbol;
           values[j] = intCounts[i];
           j++;
@@ -560,8 +562,8 @@ public class ResidueCount
       {
         if (counts[i] > 0)
         {
-          char symbol = isNucleotide ? NUCS.charAt(i - 1) : AAS
-                  .charAt(i - 1);
+          char symbol = isNucleotide ? NUCS.charAt(i - 1)
+                  : AAS.charAt(i - 1);
           symbols[j] = symbol;
           values[j] = counts[i];
           j++;
index 1bf5475..cde50e5 100755 (executable)
@@ -34,7 +34,7 @@ import java.util.List;
 public class SearchResults implements SearchResultsI
 {
 
-  private List<SearchResultMatchI> matches = new ArrayList<SearchResultMatchI>();
+  private List<SearchResultMatchI> matches = new ArrayList<>();
 
   /**
    * One match consists of a sequence reference, start and end positions.
@@ -42,17 +42,17 @@ public class SearchResults implements SearchResultsI
    */
   public class Match implements SearchResultMatchI
   {
-    SequenceI sequence;
+    final SequenceI sequence;
 
     /**
      * Start position of match in sequence (base 1)
      */
-    int start;
+    final int start;
 
     /**
      * End position (inclusive) (base 1)
      */
-    int end;
+    final int end;
 
     /**
      * create a Match on a range of sequence. Match always holds region in
@@ -133,11 +133,6 @@ public class SearchResults implements SearchResultsI
       return sb.toString();
     }
 
-    public void setSequence(SequenceI seq)
-    {
-      this.sequence = seq;
-    }
-
     /**
      * Hashcode is the hashcode of the matched sequence plus a hash of start and
      * end positions. Match objects that pass the test for equals are guaranteed
@@ -164,8 +159,8 @@ public class SearchResults implements SearchResultsI
         return false;
       }
       SearchResultMatchI m = (SearchResultMatchI) obj;
-      return (sequence == m.getSequence() && start == m.getStart() && end == m
-              .getEnd());
+      return (sequence == m.getSequence() && start == m.getStart()
+              && end == m.getEnd());
     }
   }
 
@@ -219,20 +214,15 @@ public class SearchResults implements SearchResultsI
       m = (Match) _m;
 
       mfound = false;
-      if (m.sequence == sequence)
-      {
-        mfound = true;
-        // locate aligned position
-        matchStart = sequence.findIndex(m.start) - 1;
-        matchEnd = sequence.findIndex(m.end) - 1;
-      }
-      else if (m.sequence == sequence.getDatasetSequence())
+      if (m.sequence == sequence
+              || m.sequence == sequence.getDatasetSequence())
       {
         mfound = true;
-        // locate region in local context
         matchStart = sequence.findIndex(m.start) - 1;
-        matchEnd = sequence.findIndex(m.end) - 1;
+        matchEnd = m.start == m.end ? matchStart : sequence
+                .findIndex(m.end) - 1;
       }
+
       if (mfound)
       {
         if (matchStart <= end && matchEnd >= start)
@@ -264,7 +254,7 @@ public class SearchResults implements SearchResultsI
         else
         {
           // debug
-          // System.err.println("Outwith bounds!" + matchStart+">"+end +"  or "
+          // System.err.println("Outwith bounds!" + matchStart+">"+end +" or "
           // + matchEnd+"<"+start);
         }
       }
@@ -363,4 +353,10 @@ public class SearchResults implements SearchResultsI
     SearchResultsI sr = (SearchResultsI) obj;
     return matches.equals(sr.getResults());
   }
+
+  @Override
+  public void addSearchResults(SearchResultsI toAdd)
+  {
+    matches.addAll(toAdd.getResults());
+  }
 }
index 52a0467..c3dc0e8 100644 (file)
@@ -44,6 +44,13 @@ public interface SearchResultsI
   SearchResultMatchI addResult(SequenceI seq, int start, int end);
 
   /**
+   * adds all match results in the argument to this set
+   * 
+   * @param toAdd
+   */
+  void addSearchResults(SearchResultsI toAdd);
+
+  /**
    * Answers true if the search results include the given sequence (or its
    * dataset sequence), else false
    * 
index 9cc7b4a..c2a6a9c 100644 (file)
@@ -113,8 +113,9 @@ public class SeqCigar extends CigarSimple
   @Override
   public String getSequenceString(char GapChar)
   {
-    return (length == 0) ? "" : (String) getSequenceAndDeletions(
-            refseq.getSequenceAsString(start, end), GapChar)[0];
+    return (length == 0) ? ""
+            : (String) getSequenceAndDeletions(
+                    refseq.getSequenceAsString(start, end), GapChar)[0];
   }
 
   /**
@@ -134,14 +135,13 @@ public class SeqCigar extends CigarSimple
             refseq.getSequenceAsString(start, end), GapChar);
     if (edit_result == null)
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_error_unexpected_null_from_get_sequence_and_deletions"));
+      throw new Error(MessageManager.getString(
+              "error.implementation_error_unexpected_null_from_get_sequence_and_deletions"));
     }
     int bounds[] = (int[]) edit_result[1];
     seq = new Sequence(refseq.getName(), (String) edit_result[0],
-            refseq.getStart() + start + bounds[0], refseq.getStart()
-                    + start + ((bounds[2] == 0) ? -1 : bounds[2]));
+            refseq.getStart() + start + bounds[0], refseq.getStart() + start
+                    + ((bounds[2] == 0) ? -1 : bounds[2]));
     seq.setDescription(refseq.getDescription());
     int sstart = seq.getStart(), send = seq.getEnd();
     // seq.checkValidRange(); probably not needed
@@ -184,15 +184,14 @@ public class SeqCigar extends CigarSimple
     boolean hasgaps = false;
     if (seq == null)
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_error_set_seq_null"));
+      throw new Error(MessageManager
+              .getString("error.implementation_error_set_seq_null"));
     }
     if (_s < 0)
     {
-      throw new Error(MessageManager.formatMessage(
-              "error.implementation_error_s", new String[] { Integer
-                      .valueOf(_s).toString() }));
+      throw new Error(MessageManager
+              .formatMessage("error.implementation_error_s", new String[]
+              { Integer.valueOf(_s).toString() }));
     }
     String seq_string = seq.getSequenceAsString();
     if (_e == 0 || _e < _s || _e > seq_string.length())
@@ -258,9 +257,8 @@ public class SeqCigar extends CigarSimple
     // Check offsets
     if (end > ds.getLength())
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_error_seqcigar_possible"));
+      throw new Error(MessageManager
+              .getString("error.implementation_error_seqcigar_possible"));
       // end = ds.getLength();
     }
 
@@ -289,9 +287,8 @@ public class SeqCigar extends CigarSimple
     }
     if (operation.length != range.length)
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_bug_cigar_operation_list_range_list"));
+      throw new Error(MessageManager.getString(
+              "error.implementation_bug_cigar_operation_list_range_list"));
     }
 
     if (operation != null)
@@ -301,9 +298,8 @@ public class SeqCigar extends CigarSimple
 
       if (_setSeq(seq, false, 0, 0))
       {
-        throw new Error(
-                MessageManager
-                        .getString("error.not_yet_implemented_cigar_object_from_cigar_string"));
+        throw new Error(MessageManager.getString(
+                "error.not_yet_implemented_cigar_object_from_cigar_string"));
       }
       for (int i = this.length, j = 0; j < operation.length; i++, j++)
       {
@@ -311,8 +307,8 @@ public class SeqCigar extends CigarSimple
         if (op != M && op != I && op != D)
         {
           throw new Error(MessageManager.formatMessage(
-                  "error.implementation_bug_cigar_operation", new String[] {
-                      Integer.valueOf(j).toString(),
+                  "error.implementation_bug_cigar_operation", new String[]
+                  { Integer.valueOf(j).toString(),
                       Integer.valueOf(op).toString(),
                       Integer.valueOf(M).toString(),
                       Integer.valueOf(I).toString(),
@@ -330,9 +326,8 @@ public class SeqCigar extends CigarSimple
       this.length = 0;
       if (_setSeq(seq, false, 0, 0))
       {
-        throw new Error(
-                MessageManager
-                        .getString("error.not_yet_implemented_cigar_object_from_cigar_string"));
+        throw new Error(MessageManager.getString(
+                "error.not_yet_implemented_cigar_object_from_cigar_string"));
       }
     }
   }
@@ -378,8 +373,9 @@ public class SeqCigar extends CigarSimple
 
     while (p <= endpos)
     {
-      boolean isGap = (p < res) ? jalview.util.Comparison.isGap(seq
-              .getCharAt(p)) : true;
+      boolean isGap = (p < res)
+              ? jalview.util.Comparison.isGap(seq.getCharAt(p))
+              : true;
       if ((startpos <= p) && (p <= endpos))
       {
         if (isGap)
@@ -439,9 +435,8 @@ public class SeqCigar extends CigarSimple
     super();
     if (seq == null)
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_error_for_new_cigar"));
+      throw new Error(MessageManager
+              .getString("error.implementation_error_for_new_cigar"));
     }
     _setSeq(seq, false, 0, 0);
     // there is still work to do
@@ -463,9 +458,8 @@ public class SeqCigar extends CigarSimple
     super();
     if (seq == null)
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_error_for_new_cigar"));
+      throw new Error(MessageManager
+              .getString("error.implementation_error_for_new_cigar"));
     }
     _setSeq(seq, false, start, end + 1);
     // there is still work to do
@@ -513,8 +507,8 @@ public class SeqCigar extends CigarSimple
     Object[] gs_regions = new Object[alseqs.length];
     for (int i = 0; i < alseqs.length; i++)
     {
-      alseqs_string[i] = alseqs[i].getRefSeq().getSequenceAsString(
-              alseqs[i].start, alseqs[i].end);
+      alseqs_string[i] = alseqs[i].getRefSeq()
+              .getSequenceAsString(alseqs[i].start, alseqs[i].end);
       gs_regions[i] = alseqs[i].getSequenceAndDeletions(alseqs_string[i],
               gapCharacter); // gapped sequence, {start, start col, end.
       // endcol}, hidden regions {{start, end, col}})
@@ -522,7 +516,8 @@ public class SeqCigar extends CigarSimple
       {
         throw new Error(MessageManager.formatMessage(
                 "error.implementation_error_cigar_seq_no_operations",
-                new String[] { Integer.valueOf(i).toString() }));
+                new String[]
+                { Integer.valueOf(i).toString() }));
       }
       g_seqs[i] = new StringBuffer((String) ((Object[]) gs_regions[i])[0]); // the
       // visible
@@ -587,8 +582,9 @@ public class SeqCigar extends CigarSimple
       int[] bounds = ((int[]) ((Object[]) gs_regions[i])[1]);
       SequenceI ref = alseqs[i].getRefSeq();
       seqs[i] = new Sequence(ref.getName(), g_seqs[i].toString(),
-              ref.getStart() + alseqs[i].start + bounds[0], ref.getStart()
-                      + alseqs[i].start + (bounds[2] == 0 ? -1 : bounds[2]));
+              ref.getStart() + alseqs[i].start + bounds[0],
+              ref.getStart() + alseqs[i].start
+                      + (bounds[2] == 0 ? -1 : bounds[2]));
       seqs[i].setDatasetSequence(ref);
       seqs[i].setDescription(ref.getDescription());
     }
@@ -598,8 +594,8 @@ public class SeqCigar extends CigarSimple
       {
         // int start=shifts.shift(segments[i]-1)+1;
         // int end=shifts.shift(segments[i]+segments[i+1]-1)-1;
-        hidden.hideColumns(segments[i + 1], segments[i + 1]
-                + segments[i + 2] - 1);
+        hidden.hideColumns(segments[i + 1],
+                segments[i + 1] + segments[i + 2] - 1);
       }
     }
     return seqs;
index 8176221..15d1378 100755 (executable)
@@ -22,6 +22,8 @@ package jalview.datamodel;
 
 import jalview.analysis.AlignSeq;
 import jalview.api.DBRefEntryI;
+import jalview.datamodel.features.SequenceFeatures;
+import jalview.datamodel.features.SequenceFeaturesI;
 import jalview.util.Comparison;
 import jalview.util.DBRefUtils;
 import jalview.util.MapList;
@@ -33,6 +35,7 @@ import java.util.BitSet;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.List;
+import java.util.ListIterator;
 import java.util.Vector;
 
 import fr.orsay.lri.varna.models.rna.RNA;
@@ -74,13 +77,22 @@ public class Sequence extends ASequence implements SequenceI
    */
   Vector<AlignmentAnnotation> annotation;
 
-  /**
-   * The index of the sequence in a MSA
+  private SequenceFeaturesI sequenceFeatureStore;
+
+  /*
+   * A cursor holding the approximate current view position to the sequence,
+   * as determined by findIndex or findPosition or findPositions.
+   * Using a cursor as a hint allows these methods to be more performant for
+   * large sequences.
    */
-  int index = -1;
+  private SequenceCursor cursor;
 
-  /** array of sequence features - may not be null for a valid sequence object */
-  public SequenceFeature[] sequenceFeatures;
+  /*
+   * A number that should be incremented whenever the sequence is edited.
+   * If the value matches the cursor token, then we can trust the cursor,
+   * if not then it should be recomputed. 
+   */
+  private int changeCount;
 
   /**
    * Creates a new Sequence object.
@@ -97,11 +109,13 @@ public class Sequence extends ASequence implements SequenceI
    */
   public Sequence(String name, String sequence, int start, int end)
   {
+    this();
     initSeqAndName(name, sequence.toCharArray(), start, end);
   }
 
   public Sequence(String name, char[] sequence, int start, int end)
   {
+    this();
     initSeqAndName(name, sequence, start, end);
   }
 
@@ -125,30 +139,49 @@ public class Sequence extends ASequence implements SequenceI
     checkValidRange();
   }
 
-  com.stevesoft.pat.Regex limitrx = new com.stevesoft.pat.Regex(
-          "[/][0-9]{1,}[-][0-9]{1,}$");
-
-  com.stevesoft.pat.Regex endrx = new com.stevesoft.pat.Regex("[0-9]{1,}$");
-
+  /**
+   * If 'name' ends in /i-j, where i >= j > 0 are integers, extracts i and j as
+   * start and end respectively and removes the suffix from the name
+   */
   void parseId()
   {
     if (name == null)
     {
-      System.err
-              .println("POSSIBLE IMPLEMENTATION ERROR: null sequence name passed to constructor.");
+      System.err.println(
+              "POSSIBLE IMPLEMENTATION ERROR: null sequence name passed to constructor.");
       name = "";
     }
-    // Does sequence have the /start-end signature?
-    if (limitrx.search(name))
+    int slashPos = name.lastIndexOf('/');
+    if (slashPos > -1 && slashPos < name.length() - 1)
     {
-      name = limitrx.left();
-      endrx.search(limitrx.stringMatched());
-      setStart(Integer.parseInt(limitrx.stringMatched().substring(1,
-              endrx.matchedFrom() - 1)));
-      setEnd(Integer.parseInt(endrx.stringMatched()));
+      String suffix = name.substring(slashPos + 1);
+      String[] range = suffix.split("-");
+      if (range.length == 2)
+      {
+        try
+        {
+          int from = Integer.valueOf(range[0]);
+          int to = Integer.valueOf(range[1]);
+          if (from > 0 && to >= from)
+          {
+            name = name.substring(0, slashPos);
+            setStart(from);
+            setEnd(to);
+            checkValidRange();
+          }
+        } catch (NumberFormatException e)
+        {
+          // leave name unchanged if suffix is invalid
+        }
+      }
     }
   }
 
+  /**
+   * Ensures that 'end' is not before the end of the sequence, that is,
+   * (end-start+1) is at least as long as the count of ungapped positions. Note
+   * that end is permitted to be beyond the end of the sequence data.
+   */
   void checkValidRange()
   {
     // Note: JAL-774 :
@@ -157,7 +190,7 @@ public class Sequence extends ASequence implements SequenceI
       int endRes = 0;
       for (int j = 0; j < sequence.length; j++)
       {
-        if (!jalview.util.Comparison.isGap(sequence[j]))
+        if (!Comparison.isGap(sequence[j]))
         {
           endRes++;
         }
@@ -176,6 +209,14 @@ public class Sequence extends ASequence implements SequenceI
   }
 
   /**
+   * default constructor
+   */
+  private Sequence()
+  {
+    sequenceFeatureStore = new SequenceFeatures();
+  }
+
+  /**
    * Creates a new Sequence object.
    * 
    * @param name
@@ -214,8 +255,8 @@ public class Sequence extends ASequence implements SequenceI
    */
   public Sequence(SequenceI seq, AlignmentAnnotation[] alAnnotation)
   {
+    this();
     initSeqFrom(seq, alAnnotation);
-
   }
 
   /**
@@ -231,33 +272,38 @@ public class Sequence extends ASequence implements SequenceI
   protected void initSeqFrom(SequenceI seq,
           AlignmentAnnotation[] alAnnotation)
   {
-    {
-      char[] oseq = seq.getSequence();
-      initSeqAndName(seq.getName(), Arrays.copyOf(oseq, oseq.length),
-              seq.getStart(), seq.getEnd());
-    }
+    char[] oseq = seq.getSequence(); // returns a copy of the array
+    initSeqAndName(seq.getName(), oseq, seq.getStart(), seq.getEnd());
+
     description = seq.getDescription();
     if (seq != datasetSequence)
     {
       setDatasetSequence(seq.getDatasetSequence());
     }
-    if (datasetSequence == null && seq.getDBRefs() != null)
+    
+    /*
+     * only copy DBRefs and seqfeatures if we really are a dataset sequence
+     */
+    if (datasetSequence == null)
     {
-      // only copy DBRefs and seqfeatures if we really are a dataset sequence
-      DBRefEntry[] dbr = seq.getDBRefs();
-      for (int i = 0; i < dbr.length; i++)
-      {
-        addDBRef(new DBRefEntry(dbr[i]));
-      }
-      if (seq.getSequenceFeatures() != null)
+      if (seq.getDBRefs() != null)
       {
-        SequenceFeature[] sf = seq.getSequenceFeatures();
-        for (int i = 0; i < sf.length; i++)
+        DBRefEntry[] dbr = seq.getDBRefs();
+        for (int i = 0; i < dbr.length; i++)
         {
-          addSequenceFeature(new SequenceFeature(sf[i]));
+          addDBRef(new DBRefEntry(dbr[i]));
         }
       }
+
+      /*
+       * make copies of any sequence features
+       */
+      for (SequenceFeature sf : seq.getSequenceFeatures())
+      {
+        addSequenceFeature(new SequenceFeature(sf));
+      }
     }
+
     if (seq.getAnnotation() != null)
     {
       AlignmentAnnotation[] sqann = seq.getAnnotation();
@@ -294,122 +340,67 @@ public class Sequence extends ASequence implements SequenceI
   }
 
   @Override
-  public void setSequenceFeatures(SequenceFeature[] features)
+  public void setSequenceFeatures(List<SequenceFeature> features)
   {
-    if (datasetSequence == null)
-    {
-      sequenceFeatures = features;
-    }
-    else
+    if (datasetSequence != null)
     {
-      if (datasetSequence.getSequenceFeatures() != features
-              && datasetSequence.getSequenceFeatures() != null
-              && datasetSequence.getSequenceFeatures().length > 0)
-      {
-        new Exception(
-                "Warning: JAL-2046 side effect ? Possible implementation error: overwriting dataset sequence features by setting sequence features on alignment")
-                .printStackTrace();
-      }
       datasetSequence.setSequenceFeatures(features);
+      return;
     }
+    sequenceFeatureStore = new SequenceFeatures(features);
   }
 
   @Override
   public synchronized boolean addSequenceFeature(SequenceFeature sf)
   {
-    if (sequenceFeatures == null && datasetSequence != null)
-    {
-      return datasetSequence.addSequenceFeature(sf);
-    }
-    if (sequenceFeatures == null)
+    if (sf.getType() == null)
     {
-      sequenceFeatures = new SequenceFeature[0];
+      System.err.println("SequenceFeature type may not be null: "
+              + sf.toString());
+      return false;
     }
 
-    for (int i = 0; i < sequenceFeatures.length; i++)
+    if (datasetSequence != null)
     {
-      if (sequenceFeatures[i].equals(sf))
-      {
-        return false;
-      }
+      return datasetSequence.addSequenceFeature(sf);
     }
 
-    SequenceFeature[] temp = new SequenceFeature[sequenceFeatures.length + 1];
-    System.arraycopy(sequenceFeatures, 0, temp, 0, sequenceFeatures.length);
-    temp[sequenceFeatures.length] = sf;
-
-    sequenceFeatures = temp;
-    return true;
+    return sequenceFeatureStore.add(sf);
   }
 
   @Override
   public void deleteFeature(SequenceFeature sf)
   {
-    if (sequenceFeatures == null)
-    {
-      if (datasetSequence != null)
-      {
-        datasetSequence.deleteFeature(sf);
-      }
-      return;
-    }
-
-    int index = 0;
-    for (index = 0; index < sequenceFeatures.length; index++)
-    {
-      if (sequenceFeatures[index].equals(sf))
-      {
-        break;
-      }
-    }
-
-    if (index == sequenceFeatures.length)
-    {
-      return;
-    }
-
-    int sfLength = sequenceFeatures.length;
-    if (sfLength < 2)
+    if (datasetSequence != null)
     {
-      sequenceFeatures = null;
+      datasetSequence.deleteFeature(sf);
     }
     else
     {
-      SequenceFeature[] temp = new SequenceFeature[sfLength - 1];
-      System.arraycopy(sequenceFeatures, 0, temp, 0, index);
-
-      if (index < sfLength)
-      {
-        System.arraycopy(sequenceFeatures, index + 1, temp, index,
-                sequenceFeatures.length - index - 1);
-      }
-
-      sequenceFeatures = temp;
+      sequenceFeatureStore.delete(sf);
     }
   }
 
   /**
-   * Returns the sequence features (if any), looking first on the sequence, then
-   * on its dataset sequence, and so on until a non-null value is found (or
-   * none). This supports retrieval of sequence features stored on the sequence
-   * (as in the applet) or on the dataset sequence (as in the Desktop version).
+   * {@inheritDoc}
    * 
    * @return
    */
   @Override
-  public SequenceFeature[] getSequenceFeatures()
+  public List<SequenceFeature> getSequenceFeatures()
   {
-    SequenceFeature[] features = sequenceFeatures;
-
-    SequenceI seq = this;
-    int count = 0; // failsafe against loop in sequence.datasetsequence...
-    while (features == null && seq.getDatasetSequence() != null
-            && count++ < 10)
+    if (datasetSequence != null)
     {
-      seq = seq.getDatasetSequence();
-      features = ((Sequence) seq).sequenceFeatures;
+      return datasetSequence.getSequenceFeatures();
     }
-    return features;
+    return sequenceFeatureStore.getAllFeatures();
+  }
+
+  @Override
+  public SequenceFeaturesI getFeatures()
+  {
+    return datasetSequence != null ? datasetSequence.getFeatures()
+            : sequenceFeatureStore;
   }
 
   @Override
@@ -474,15 +465,15 @@ public class Sequence extends ASequence implements SequenceI
   }
 
   /**
-   * DOCUMENT ME!
+   * Sets the sequence name. If the name ends in /start-end, then the start-end
+   * values are parsed out and set, and the suffix is removed from the name.
    * 
-   * @param name
-   *          DOCUMENT ME!
+   * @param theName
    */
   @Override
-  public void setName(String name)
+  public void setName(String theName)
   {
-    this.name = name;
+    this.name = theName;
     this.parseId();
   }
 
@@ -565,6 +556,7 @@ public class Sequence extends ASequence implements SequenceI
   {
     this.sequence = seq.toCharArray();
     checkValidRange();
+    sequenceChanged();
   }
 
   @Override
@@ -582,7 +574,9 @@ public class Sequence extends ASequence implements SequenceI
   @Override
   public char[] getSequence()
   {
-    return sequence;
+    // return sequence;
+    return sequence == null ? null : Arrays.copyOf(sequence,
+            sequence.length);
   }
 
   /*
@@ -685,58 +679,370 @@ public class Sequence extends ASequence implements SequenceI
     return this.description;
   }
 
-  /*
-   * (non-Javadoc)
-   * 
-   * @see jalview.datamodel.SequenceI#findIndex(int)
+  /**
+   * {@inheritDoc}
    */
   @Override
   public int findIndex(int pos)
   {
-    // returns the alignment position for a residue
+    /*
+     * use a valid, hopefully nearby, cursor if available
+     */
+    if (isValidCursor(cursor))
+    {
+      return findIndex(pos, cursor);
+    }
+
     int j = start;
     int i = 0;
-    // Rely on end being at least as long as the length of the sequence.
+    int startColumn = 0;
+
+    /*
+     * traverse sequence from the start counting gaps; make a note of
+     * the column of the first residue to save in the cursor
+     */
     while ((i < sequence.length) && (j <= end) && (j <= pos))
     {
-      if (!jalview.util.Comparison.isGap(sequence[i]))
+      if (!Comparison.isGap(sequence[i]))
       {
+        if (j == start)
+        {
+          startColumn = i;
+        }
         j++;
       }
-
       i++;
     }
 
-    if ((j == end) && (j < pos))
+    if (j == end && j < pos)
     {
       return end + 1;
     }
-    else
+
+    updateCursor(pos, i, startColumn);
+    return i;
+  }
+
+  /**
+   * Updates the cursor to the latest found residue and column position
+   * 
+   * @param residuePos
+   *          (start..)
+   * @param column
+   *          (1..)
+   * @param startColumn
+   *          column position of the first sequence residue
+   */
+  protected void updateCursor(int residuePos, int column, int startColumn)
+  {
+    /*
+     * preserve end residue column provided cursor was valid
+     */
+    int endColumn = isValidCursor(cursor) ? cursor.lastColumnPosition : 0;
+    if (residuePos == this.end)
     {
-      return i;
+      endColumn = column;
     }
+
+    cursor = new SequenceCursor(this, residuePos, column, startColumn,
+            endColumn, this.changeCount);
   }
 
+  /**
+   * Answers the aligned column position (1..) for the given residue position
+   * (start..) given a 'hint' of a residue/column location in the neighbourhood.
+   * The hint may be left of, at, or to the right of the required position.
+   * 
+   * @param pos
+   * @param curs
+   * @return
+   */
+  protected int findIndex(int pos, SequenceCursor curs)
+  {
+    if (!isValidCursor(curs))
+    {
+      /*
+       * wrong or invalidated cursor, compute de novo
+       */
+      return findIndex(pos);
+    }
+
+    if (curs.residuePosition == pos)
+    {
+      return curs.columnPosition;
+    }
+
+    /*
+     * move left or right to find pos from hint.position
+     */
+    int col = curs.columnPosition - 1; // convert from base 1 to 0-based array
+                                       // index
+    int newPos = curs.residuePosition;
+    int delta = newPos > pos ? -1 : 1;
+
+    while (newPos != pos)
+    {
+      col += delta; // shift one column left or right
+      if (col < 0 || col == sequence.length)
+      {
+        break;
+      }
+      if (!Comparison.isGap(sequence[col]))
+      {
+        newPos += delta;
+      }
+    }
+
+    col++; // convert back to base 1
+    updateCursor(pos, col, curs.firstColumnPosition);
+
+    return col;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
   @Override
-  public int findPosition(int i)
+  public int findPosition(final int column)
   {
+    /*
+     * use a valid, hopefully nearby, cursor if available
+     */
+    if (isValidCursor(cursor))
+    {
+      return findPosition(column + 1, cursor);
+    }
+    
+    // TODO recode this more naturally i.e. count residues only
+    // as they are found, not 'in anticipation'
+
+    /*
+     * traverse the sequence counting gaps; note the column position
+     * of the first residue, to save in the cursor
+     */
+    int firstResidueColumn = 0;
+    int lastPosFound = 0;
+    int lastPosFoundColumn = 0;
+    int seqlen = sequence.length;
+
+    if (seqlen > 0 && !Comparison.isGap(sequence[0]))
+    {
+      lastPosFound = start;
+      lastPosFoundColumn = 0;
+    }
+
     int j = 0;
     int pos = start;
-    int seqlen = sequence.length;
-    while ((j < i) && (j < seqlen))
+
+    while (j < column && j < seqlen)
     {
-      if (!jalview.util.Comparison.isGap(sequence[j]))
+      if (!Comparison.isGap(sequence[j]))
       {
+        lastPosFound = pos;
+        lastPosFoundColumn = j;
+        if (pos == this.start)
+        {
+          firstResidueColumn = j;
+        }
         pos++;
       }
-
       j++;
     }
+    if (j < seqlen && !Comparison.isGap(sequence[j]))
+    {
+      lastPosFound = pos;
+      lastPosFoundColumn = j;
+      if (pos == this.start)
+      {
+        firstResidueColumn = j;
+      }
+    }
+
+    /*
+     * update the cursor to the last residue position found (if any)
+     * (converting column position to base 1)
+     */
+    if (lastPosFound != 0)
+    {
+      updateCursor(lastPosFound, lastPosFoundColumn + 1,
+              firstResidueColumn + 1);
+    }
 
     return pos;
   }
 
   /**
+   * Answers true if the given cursor is not null, is for this sequence object,
+   * and has a token value that matches this object's changeCount, else false.
+   * This allows us to ignore a cursor as 'stale' if the sequence has been
+   * modified since the cursor was created.
+   * 
+   * @param curs
+   * @return
+   */
+  protected boolean isValidCursor(SequenceCursor curs)
+  {
+    if (curs == null || curs.sequence != this || curs.token != changeCount)
+    {
+      return false;
+    }
+    /*
+     * sanity check against range
+     */
+    if (curs.columnPosition < 0 || curs.columnPosition > sequence.length)
+    {
+      return false;
+    }
+    if (curs.residuePosition < start || curs.residuePosition > end)
+    {
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * Answers the sequence position (start..) for the given aligned column
+   * position (1..), given a hint of a cursor in the neighbourhood. The cursor
+   * may lie left of, at, or to the right of the column position.
+   * 
+   * @param col
+   * @param curs
+   * @return
+   */
+  protected int findPosition(final int col, SequenceCursor curs)
+  {
+    if (!isValidCursor(curs))
+    {
+      /*
+       * wrong or invalidated cursor, compute de novo
+       */
+      return findPosition(col - 1);// ugh back to base 0
+    }
+
+    if (curs.columnPosition == col)
+    {
+      cursor = curs; // in case this method becomes public
+      return curs.residuePosition; // easy case :-)
+    }
+
+    if (curs.lastColumnPosition > 0 && curs.lastColumnPosition < col)
+    {
+      /*
+       * sequence lies entirely to the left of col
+       * - return last residue + 1
+       */
+      return end + 1;
+    }
+
+    if (curs.firstColumnPosition > 0 && curs.firstColumnPosition > col)
+    {
+      /*
+       * sequence lies entirely to the right of col
+       * - return first residue
+       */
+      return start;
+    }
+
+    // todo could choose closest to col out of column,
+    // firstColumnPosition, lastColumnPosition as a start point
+
+    /*
+     * move left or right to find pos from cursor position
+     */
+    int firstResidueColumn = curs.firstColumnPosition;
+    int column = curs.columnPosition - 1; // to base 0
+    int newPos = curs.residuePosition;
+    int delta = curs.columnPosition > col ? -1 : 1;
+    boolean gapped = false;
+    int lastFoundPosition = curs.residuePosition;
+    int lastFoundPositionColumn = curs.columnPosition;
+
+    while (column != col - 1)
+    {
+      column += delta; // shift one column left or right
+      if (column < 0 || column == sequence.length)
+      {
+        break;
+      }
+      gapped = Comparison.isGap(sequence[column]);
+      if (!gapped)
+      {
+        newPos += delta;
+        lastFoundPosition = newPos;
+        lastFoundPositionColumn = column + 1;
+        if (lastFoundPosition == this.start)
+        {
+          firstResidueColumn = column + 1;
+        }
+      }
+    }
+
+    if (cursor == null || lastFoundPosition != cursor.residuePosition)
+    {
+      updateCursor(lastFoundPosition, lastFoundPositionColumn,
+              firstResidueColumn);
+    }
+
+    /*
+     * hack to give position to the right if on a gap
+     * or beyond the length of the sequence (see JAL-2562)
+     */
+    if (delta > 0 && (gapped || column >= sequence.length))
+    {
+      newPos++;
+    }
+
+    return newPos;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Range findPositions(int fromColumn, int toColumn)
+  {
+    if (toColumn < fromColumn || fromColumn < 1)
+    {
+      return null;
+    }
+
+    /*
+     * find the first non-gapped position, if any
+     */
+    int firstPosition = 0;
+    int col = fromColumn - 1;
+    int length = sequence.length;
+    while (col < length && col < toColumn)
+    {
+      if (!Comparison.isGap(sequence[col]))
+      {
+        firstPosition = findPosition(col++);
+        break;
+      }
+      col++;
+    }
+
+    if (firstPosition == 0)
+    {
+      return null;
+    }
+
+    /*
+     * find the last non-gapped position
+     */
+    int lastPosition = firstPosition;
+    while (col < length && col < toColumn)
+    {
+      if (!Comparison.isGap(sequence[col++]))
+      {
+        lastPosition++;
+      }
+    }
+
+    return new Range(firstPosition, lastPosition);
+  }
+
+  /**
    * Returns an int array where indices correspond to each residue in the
    * sequence and the element value gives its position in the alignment
    * 
@@ -854,7 +1160,7 @@ public class Sequence extends ASequence implements SequenceI
   }
 
   @Override
-  public void deleteChars(int i, int j)
+  public void deleteChars(final int i, final int j)
   {
     int newstart = start, newend = end;
     if (i >= sequence.length || i < 0)
@@ -866,66 +1172,80 @@ public class Sequence extends ASequence implements SequenceI
     boolean createNewDs = false;
     // TODO: take a (second look) at the dataset creation validation method for
     // the very large sequence case
-    int eindex = -1, sindex = -1;
-    boolean ecalc = false, scalc = false;
+    int startIndex = findIndex(start) - 1;
+    int endIndex = findIndex(end) - 1;
+    int startDeleteColumn = -1; // for dataset sequence deletions
+    int deleteCount = 0;
+
     for (int s = i; s < j; s++)
     {
-      if (jalview.schemes.ResidueProperties.aaIndex[sequence[s]] != 23)
+      if (Comparison.isGap(sequence[s]))
+      {
+        continue;
+      }
+      deleteCount++;
+      if (startDeleteColumn == -1)
+      {
+        startDeleteColumn = findPosition(s) - start;
+      }
+      if (createNewDs)
+      {
+        newend--;
+      }
+      else
       {
-        if (createNewDs)
+        if (startIndex == s)
         {
-          newend--;
+          /*
+           * deleting characters from start of sequence; new start is the
+           * sequence position of the next column (position to the right
+           * if the column position is gapped)
+           */
+          newstart = findPosition(j);
+          break;
         }
         else
         {
-          if (!scalc)
+          if (endIndex < j)
           {
-            sindex = findIndex(start) - 1;
-            scalc = true;
-          }
-          if (sindex == s)
-          {
-            // delete characters including start of sequence
-            newstart = findPosition(j);
-            break; // don't need to search for any more residue characters.
+            /*
+             * deleting characters at end of sequence; new end is the sequence
+             * position of the column before the deletion; subtract 1 if this is
+             * gapped since findPosition returns the next sequence position
+             */
+            newend = findPosition(i - 1);
+            if (Comparison.isGap(sequence[i - 1]))
+            {
+              newend--;
+            }
+            break;
           }
           else
           {
-            // delete characters after start.
-            if (!ecalc)
-            {
-              eindex = findIndex(end) - 1;
-              ecalc = true;
-            }
-            if (eindex < j)
-            {
-              // delete characters at end of sequence
-              newend = findPosition(i - 1);
-              break; // don't need to search for any more residue characters.
-            }
-            else
-            {
-              createNewDs = true;
-              newend--; // decrease end position by one for the deleted residue
-              // and search further
-            }
+            createNewDs = true;
+            newend--;
           }
         }
       }
     }
-    // deletion occured in the middle of the sequence
+
     if (createNewDs && this.datasetSequence != null)
     {
-      // construct a new sequence
+      /*
+       * if deletion occured in the middle of the sequence,
+       * construct a new dataset sequence and delete the residues
+       * that were deleted from the aligned sequence
+       */
       Sequence ds = new Sequence(datasetSequence);
+      ds.deleteChars(startDeleteColumn, startDeleteColumn + deleteCount);
+      datasetSequence = ds;
       // TODO: remove any non-inheritable properties ?
       // TODO: create a sequence mapping (since there is a relation here ?)
-      ds.deleteChars(i, j);
-      datasetSequence = ds;
     }
     start = newstart;
     end = newend;
     sequence = tmp;
+    sequenceChanged();
   }
 
   @Override
@@ -956,6 +1276,7 @@ public class Sequence extends ASequence implements SequenceI
     }
 
     sequence = tmp;
+    sequenceChanged();
   }
 
   @Override
@@ -1068,8 +1389,9 @@ public class Sequence extends ASequence implements SequenceI
   @Override
   public AlignmentAnnotation[] getAnnotation()
   {
-    return annotation == null ? null : annotation
-            .toArray(new AlignmentAnnotation[annotation.size()]);
+    return annotation == null ? null
+            : annotation
+                    .toArray(new AlignmentAnnotation[annotation.size()]);
   }
 
   @Override
@@ -1150,7 +1472,7 @@ public class Sequence extends ASequence implements SequenceI
 
   private boolean _isNa;
 
-  private long _seqhash = 0;
+  private int _seqhash = 0;
 
   /**
    * Answers false if the sequence is more than 85% nucleotide (ACGTU), else
@@ -1181,16 +1503,17 @@ public class Sequence extends ASequence implements SequenceI
   {
     if (datasetSequence == null)
     {
-      Sequence dsseq = new Sequence(getName(), AlignSeq.extractGaps(
-              jalview.util.Comparison.GapChars, getSequenceAsString()),
+      Sequence dsseq = new Sequence(getName(),
+              AlignSeq.extractGaps(jalview.util.Comparison.GapChars,
+                      getSequenceAsString()),
               getStart(), getEnd());
 
       datasetSequence = dsseq;
 
       dsseq.setDescription(description);
       // move features and database references onto dataset sequence
-      dsseq.sequenceFeatures = sequenceFeatures;
-      sequenceFeatures = null;
+      dsseq.sequenceFeatureStore = sequenceFeatureStore;
+      sequenceFeatureStore = null;
       dsseq.dbrefs = dbrefs;
       dbrefs = null;
       // TODO: search and replace any references to this sequence with
@@ -1249,11 +1572,11 @@ public class Sequence extends ASequence implements SequenceI
       return null;
     }
 
-    Vector subset = new Vector();
-    Enumeration e = annotation.elements();
+    Vector<AlignmentAnnotation> subset = new Vector<AlignmentAnnotation>();
+    Enumeration<AlignmentAnnotation> e = annotation.elements();
     while (e.hasMoreElements())
     {
-      AlignmentAnnotation ann = (AlignmentAnnotation) e.nextElement();
+      AlignmentAnnotation ann = e.nextElement();
       if (ann.label != null && ann.label.equals(label))
       {
         subset.addElement(ann);
@@ -1268,7 +1591,7 @@ public class Sequence extends ASequence implements SequenceI
     e = subset.elements();
     while (e.hasMoreElements())
     {
-      anns[i++] = (AlignmentAnnotation) e.nextElement();
+      anns[i++] = e.nextElement();
     }
     subset.removeAllElements();
     return anns;
@@ -1321,12 +1644,12 @@ public class Sequence extends ASequence implements SequenceI
     if (entry.getSequenceFeatures() != null)
     {
 
-      SequenceFeature[] sfs = entry.getSequenceFeatures();
-      for (int si = 0; si < sfs.length; si++)
+      List<SequenceFeature> sfs = entry.getSequenceFeatures();
+      for (SequenceFeature feature : sfs)
       {
-        SequenceFeature sf[] = (mp != null) ? mp.locateFeature(sfs[si])
-                : new SequenceFeature[] { new SequenceFeature(sfs[si]) };
-        if (sf != null && sf.length > 0)
+       SequenceFeature sf[] = (mp != null) ? mp.locateFeature(feature)
+                : new SequenceFeature[] { new SequenceFeature(feature) };
+        if (sf != null)
         {
           for (int sfi = 0; sfi < sf.length; sfi++)
           {
@@ -1339,10 +1662,10 @@ public class Sequence extends ASequence implements SequenceI
     // transfer PDB entries
     if (entry.getAllPDBEntries() != null)
     {
-      Enumeration e = entry.getAllPDBEntries().elements();
+      Enumeration<PDBEntry> e = entry.getAllPDBEntries().elements();
       while (e.hasMoreElements())
       {
-        PDBEntry pdb = (PDBEntry) e.nextElement();
+        PDBEntry pdb = e.nextElement();
         addPDBId(pdb);
       }
     }
@@ -1367,30 +1690,6 @@ public class Sequence extends ASequence implements SequenceI
     }
   }
 
-  /**
-   * @return The index (zero-based) on this sequence in the MSA. It returns
-   *         {@code -1} if this information is not available.
-   */
-  @Override
-  public int getIndex()
-  {
-    return index;
-  }
-
-  /**
-   * Defines the position of this sequence in the MSA. Use the value {@code -1}
-   * if this information is undefined.
-   * 
-   * @param The
-   *          position for this sequence. This value is zero-based (zero for
-   *          this first sequence)
-   */
-  @Override
-  public void setIndex(int value)
-  {
-    index = value;
-  }
-
   @Override
   public void setRNA(RNA r)
   {
@@ -1481,8 +1780,8 @@ public class Sequence extends ASequence implements SequenceI
           }
         }
         // whilst it looks like it is a primary ref, we also sanity check type
-        if (DBRefUtils.getCanonicalName(DBRefSource.PDB).equals(
-                DBRefUtils.getCanonicalName(ref.getSource())))
+        if (DBRefUtils.getCanonicalName(DBRefSource.PDB)
+                .equals(DBRefUtils.getCanonicalName(ref.getSource())))
         {
           // PDB dbrefs imply there should be a PDBEntry associated
           // TODO: tighten PDB dbrefs
@@ -1510,4 +1809,99 @@ public class Sequence extends ASequence implements SequenceI
     }
   }
 
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public List<SequenceFeature> findFeatures(int fromColumn, int toColumn,
+          String... types)
+  {
+    int startPos = findPosition(fromColumn - 1); // convert base 1 to base 0
+    int endPos = fromColumn == toColumn ? startPos
+            : findPosition(toColumn - 1);
+
+    List<SequenceFeature> result = getFeatures().findFeatures(startPos,
+            endPos, types);
+
+    /*
+     * if end column is gapped, endPos may be to the right, 
+     * and we may have included adjacent or enclosing features;
+     * remove any that are not enclosing, non-contact features
+     */
+    boolean endColumnIsGapped = toColumn > 0 && toColumn <= sequence.length
+            && Comparison.isGap(sequence[toColumn - 1]);
+    if (endPos > this.end || endColumnIsGapped)
+    {
+      ListIterator<SequenceFeature> it = result.listIterator();
+      while (it.hasNext())
+      {
+        SequenceFeature sf = it.next();
+        int sfBegin = sf.getBegin();
+        int sfEnd = sf.getEnd();
+        int featureStartColumn = findIndex(sfBegin);
+        if (featureStartColumn > toColumn)
+        {
+          it.remove();
+        }
+        else if (featureStartColumn < fromColumn)
+        {
+          int featureEndColumn = sfEnd == sfBegin ? featureStartColumn
+                  : findIndex(sfEnd);
+          if (featureEndColumn < fromColumn)
+          {
+            it.remove();
+          }
+          else if (featureEndColumn > toColumn && sf.isContactFeature())
+          {
+            /*
+             * remove an enclosing feature if it is a contact feature
+             */
+            it.remove();
+          }
+        }
+      }
+    }
+
+    return result;
+  }
+
+  /**
+   * Invalidates any stale cursors (forcing recalculation) by incrementing the
+   * token that has to match the one presented by the cursor
+   */
+  @Override
+  public void sequenceChanged()
+  {
+    changeCount++;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public int replace(char c1, char c2)
+  {
+    if (c1 == c2)
+    {
+      return 0;
+    }
+    int count = 0;
+    synchronized (sequence)
+    {
+      for (int c = 0; c < sequence.length; c++)
+      {
+        if (sequence[c] == c1)
+        {
+          sequence[c] = c2;
+          count++;
+        }
+      }
+    }
+    if (count > 0)
+    {
+      sequenceChanged();
+    }
+
+    return count;
+  }
 }
diff --git a/src/jalview/datamodel/SequenceCursor.java b/src/jalview/datamodel/SequenceCursor.java
new file mode 100644 (file)
index 0000000..24752bf
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+/**
+ * An immutable object representing one or more residue and corresponding
+ * alignment column positions for a sequence
+ */
+public class SequenceCursor
+{
+  /**
+   * the aligned sequence this cursor applies to
+   */
+  public final SequenceI sequence;
+
+  /**
+   * residue position in sequence (start...), 0 if undefined
+   */
+  public final int residuePosition;
+
+  /**
+   * column position (1...) corresponding to residuePosition, or 0 if undefined
+   */
+  public final int columnPosition;
+
+  /**
+   * column position (1...) of first residue in the sequence, or 0 if undefined
+   */
+  public final int firstColumnPosition;
+
+  /**
+   * column position (1...) of last residue in the sequence, or 0 if undefined
+   */
+  public final int lastColumnPosition;
+
+  /**
+   * a token which may be used to check whether this cursor is still valid for
+   * its sequence (allowing it to be ignored if the sequence has changed)
+   */
+  public final int token;
+
+  /**
+   * Constructor
+   * 
+   * @param seq
+   *          sequence this cursor applies to
+   * @param resPos
+   *          residue position in sequence (start..)
+   * @param column
+   *          column position in alignment (1..)
+   * @param tok
+   *          a token that may be validated by the sequence to check the cursor
+   *          is not stale
+   */
+  public SequenceCursor(SequenceI seq, int resPos, int column, int tok)
+  {
+    this(seq, resPos, column, 0, 0, tok);
+  }
+
+  /**
+   * Constructor
+   * 
+   * @param seq
+   *          sequence this cursor applies to
+   * @param resPos
+   *          residue position in sequence (start..)
+   * @param column
+   *          column position in alignment (1..)
+   * @param firstResCol
+   *          column position of the first residue in the sequence (1..), or 0
+   *          if not known
+   * @param lastResCol
+   *          column position of the last residue in the sequence (1..), or 0 if
+   *          not known
+   * @param tok
+   *          a token that may be validated by the sequence to check the cursor
+   *          is not stale
+   */
+  public SequenceCursor(SequenceI seq, int resPos, int column, int firstResCol,
+          int lastResCol, int tok)
+  {
+    sequence = seq;
+    residuePosition = resPos;
+    columnPosition = column;
+    firstColumnPosition = firstResCol;
+    lastColumnPosition = lastResCol;
+    token = tok;
+  }
+
+  @Override
+  public int hashCode()
+  {
+    int hash = 31 * residuePosition;
+    hash = 31 * hash + columnPosition;
+    hash = 31 * hash + token;
+    if (sequence != null)
+    {
+      hash += sequence.hashCode();
+    }
+    return hash;
+  }
+
+  /**
+   * Two cursors are equal if they refer to the same sequence object and have
+   * the same residue position, column position and token value
+   */
+  @Override
+  public boolean equals(Object obj)
+  {
+    if (!(obj instanceof SequenceCursor))
+    {
+      return false;
+    }
+    SequenceCursor sc = (SequenceCursor) obj;
+    return sequence == sc.sequence && residuePosition == sc.residuePosition
+            && columnPosition == sc.columnPosition && token == sc.token;
+  }
+
+  @Override
+  public String toString()
+  {
+    String name = sequence == null ? "" : sequence.getName();
+    return String.format("%s:Pos%d:Col%d:startCol%d:endCol%d:tok%d", name,
+            residuePosition, columnPosition, firstColumnPosition,
+            lastColumnPosition, token);
+  }
+}
index 15f54b9..9c4087e 100755 (executable)
  */
 package jalview.datamodel;
 
+import jalview.datamodel.features.FeatureLocationI;
+
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Vector;
 
 /**
@@ -30,8 +33,14 @@ import java.util.Vector;
  * @author $author$
  * @version $Revision$
  */
-public class SequenceFeature
+public class SequenceFeature implements FeatureLocationI
 {
+  /*
+   * score value if none is set; preferably Float.Nan, but see
+   * JAL-2060 and JAL-2554 for a couple of blockers to that
+   */
+  private static final float NO_SCORE = 0f;
+
   private static final String STATUS = "status";
 
   private static final String STRAND = "STRAND";
@@ -48,13 +57,22 @@ public class SequenceFeature
    */
   private static final String ATTRIBUTES = "ATTRIBUTES";
 
-  public int begin;
+  /*
+   * type, begin, end, featureGroup, score and contactFeature are final 
+   * to ensure that the integrity of SequenceFeatures data store 
+   * can't be broken by direct update of these fields
+   */
+  public final String type;
 
-  public int end;
+  public final int begin;
 
-  public float score;
+  public final int end;
 
-  public String type;
+  public final String featureGroup;
+
+  public final float score;
+
+  private final boolean contactFeature;
 
   public String description;
 
@@ -66,14 +84,6 @@ public class SequenceFeature
 
   public Vector<String> links;
 
-  // Feature group can be set from a features file
-  // as a group of features between STARTGROUP and ENDGROUP markers
-  public String featureGroup;
-
-  public SequenceFeature()
-  {
-  }
-
   /**
    * Constructs a duplicate feature. Note: Uses makes a shallow copy of the
    * otherDetails map, so the new and original SequenceFeature may reference the
@@ -83,96 +93,99 @@ public class SequenceFeature
    */
   public SequenceFeature(SequenceFeature cpy)
   {
-    if (cpy != null)
-    {
-      begin = cpy.begin;
-      end = cpy.end;
-      score = cpy.score;
-      if (cpy.type != null)
-      {
-        type = new String(cpy.type);
-      }
-      if (cpy.description != null)
-      {
-        description = new String(cpy.description);
-      }
-      if (cpy.featureGroup != null)
-      {
-        featureGroup = new String(cpy.featureGroup);
-      }
-      if (cpy.otherDetails != null)
-      {
-        try
-        {
-          otherDetails = (Map<String, Object>) ((HashMap<String, Object>) cpy.otherDetails)
-                  .clone();
-        } catch (Exception e)
-        {
-          // ignore
-        }
-      }
-      if (cpy.links != null && cpy.links.size() > 0)
-      {
-        links = new Vector<String>();
-        for (int i = 0, iSize = cpy.links.size(); i < iSize; i++)
-        {
-          links.addElement(cpy.links.elementAt(i));
-        }
-      }
-    }
+    this(cpy, cpy.getBegin(), cpy.getEnd(), cpy.getFeatureGroup(), cpy
+            .getScore());
   }
 
   /**
-   * Constructor including a Status value
+   * Constructor
    * 
-   * @param type
-   * @param desc
-   * @param status
-   * @param begin
-   * @param end
-   * @param featureGroup
+   * @param theType
+   * @param theDesc
+   * @param theBegin
+   * @param theEnd
+   * @param group
    */
-  public SequenceFeature(String type, String desc, String status,
-          int begin, int end, String featureGroup)
+  public SequenceFeature(String theType, String theDesc, int theBegin,
+          int theEnd, String group)
   {
-    this(type, desc, begin, end, featureGroup);
-    setStatus(status);
+    this(theType, theDesc, theBegin, theEnd, NO_SCORE, group);
   }
 
   /**
-   * Constructor
+   * Constructor including a score value
    * 
-   * @param type
-   * @param desc
-   * @param begin
-   * @param end
-   * @param featureGroup
+   * @param theType
+   * @param theDesc
+   * @param theBegin
+   * @param theEnd
+   * @param theScore
+   * @param group
    */
-  SequenceFeature(String type, String desc, int begin, int end,
-          String featureGroup)
+  public SequenceFeature(String theType, String theDesc, int theBegin,
+          int theEnd, float theScore, String group)
   {
-    this.type = type;
-    this.description = desc;
-    this.begin = begin;
-    this.end = end;
-    this.featureGroup = featureGroup;
+    this.type = theType;
+    this.description = theDesc;
+    this.begin = theBegin;
+    this.end = theEnd;
+    this.featureGroup = group;
+    this.score = theScore;
+
+    /*
+     * for now, only "Disulfide/disulphide bond" is treated as a contact feature
+     */
+    this.contactFeature = "disulfide bond".equalsIgnoreCase(type)
+            || "disulphide bond".equalsIgnoreCase(type);
   }
 
   /**
-   * Constructor including a score value
+   * A copy constructor that allows the value of final fields to be 'modified'
+   * 
+   * @param sf
+   * @param newType
+   * @param newBegin
+   * @param newEnd
+   * @param newGroup
+   * @param newScore
+   */
+  public SequenceFeature(SequenceFeature sf, String newType, int newBegin,
+          int newEnd, String newGroup, float newScore)
+  {
+    this(newType, sf.getDescription(), newBegin, newEnd, newScore,
+            newGroup);
+
+    if (sf.otherDetails != null)
+    {
+      otherDetails = new HashMap<String, Object>();
+      for (Entry<String, Object> entry : sf.otherDetails.entrySet())
+      {
+        otherDetails.put(entry.getKey(), entry.getValue());
+      }
+    }
+    if (sf.links != null && sf.links.size() > 0)
+    {
+      links = new Vector<String>();
+      for (int i = 0, iSize = sf.links.size(); i < iSize; i++)
+      {
+        links.addElement(sf.links.elementAt(i));
+      }
+    }
+  }
+
+  /**
+   * A copy constructor that allows the value of final fields to be 'modified'
    * 
-   * @param type
-   * @param desc
-   * @param begin
-   * @param end
-   * @param score
-   * @param featureGroup
+   * @param sf
+   * @param newBegin
+   * @param newEnd
+   * @param newGroup
+   * @param newScore
    */
-  public SequenceFeature(String type, String desc, int begin, int end,
-          float score, String featureGroup)
+  public SequenceFeature(SequenceFeature sf, int newBegin, int newEnd,
+          String newGroup, float newScore)
   {
-    this(type, desc, begin, end, featureGroup);
-    this.score = score;
+    this(sf, sf.getType(), newBegin, newEnd, newGroup, newScore);
   }
 
   /**
@@ -220,8 +233,8 @@ public class SequenceFeature
       return false;
     }
 
-    if (!(type + description + featureGroup + getPhase()).equals(sf.type
-            + sf.description + sf.featureGroup + sf.getPhase()))
+    if (!(type + description + featureGroup + getPhase()).equals(
+            sf.type + sf.description + sf.featureGroup + sf.getPhase()))
     {
       return false;
     }
@@ -268,31 +281,23 @@ public class SequenceFeature
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public int getBegin()
   {
     return begin;
   }
 
-  public void setBegin(int start)
-  {
-    this.begin = start;
-  }
-
   /**
    * DOCUMENT ME!
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public int getEnd()
   {
     return end;
   }
 
-  public void setEnd(int end)
-  {
-    this.end = end;
-  }
-
   /**
    * DOCUMENT ME!
    * 
@@ -303,11 +308,6 @@ public class SequenceFeature
     return type;
   }
 
-  public void setType(String type)
-  {
-    this.type = type;
-  }
-
   /**
    * DOCUMENT ME!
    * 
@@ -328,11 +328,6 @@ public class SequenceFeature
     return featureGroup;
   }
 
-  public void setFeatureGroup(String featureGroup)
-  {
-    this.featureGroup = featureGroup;
-  }
-
   public void addLink(String labelLink)
   {
     if (links == null)
@@ -340,7 +335,10 @@ public class SequenceFeature
       links = new Vector<String>();
     }
 
-    links.insertElementAt(labelLink, 0);
+    if (!links.contains(labelLink))
+    {
+      links.insertElementAt(labelLink, 0);
+    }
   }
 
   public float getScore()
@@ -348,11 +346,6 @@ public class SequenceFeature
     return score;
   }
 
-  public void setScore(float value)
-  {
-    score = value;
-  }
-
   /**
    * Used for getting values which are not in the basic set. eg STRAND, PHASE
    * for GFF file
@@ -432,17 +425,6 @@ public class SequenceFeature
     return (String) getValue(ATTRIBUTES);
   }
 
-  public void setPosition(int pos)
-  {
-    begin = pos;
-    end = pos;
-  }
-
-  public int getPosition()
-  {
-    return begin;
-  }
-
   /**
    * Return 1 for forward strand ('+' in GFF), -1 for reverse strand ('-' in
    * GFF), and 0 for unknown or not (validly) specified
@@ -538,14 +520,19 @@ public class SequenceFeature
    * positions, rather than ends of a range. Such features may be visualised or
    * reported differently to features on a range.
    */
+  @Override
   public boolean isContactFeature()
   {
-    // TODO abstract one day to a FeatureType class
-    if ("disulfide bond".equalsIgnoreCase(type)
-            || "disulphide bond".equalsIgnoreCase(type))
-    {
-      return true;
-    }
-    return false;
+    return contactFeature;
+  }
+
+  /**
+   * Answers true if the sequence has zero start and end position
+   * 
+   * @return
+   */
+  public boolean isNonPositional()
+  {
+    return begin == 0 && end == 0;
   }
 }
index 46c802f..6b797d7 100755 (executable)
@@ -27,7 +27,10 @@ import jalview.renderer.ResidueShaderI;
 import jalview.schemes.ColourSchemeI;
 
 import java.awt.Color;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
@@ -39,6 +42,26 @@ import java.util.Map;
  */
 public class SequenceGroup implements AnnotatedCollectionI
 {
+  // TODO ideally this event notification functionality should be separated into
+  // a
+  // subclass of ViewportProperties similarly to ViewportRanges. Done here as
+  // quick fix for JAL-2665
+  public static final String SEQ_GROUP_CHANGED = "Sequence group changed";
+
+  protected PropertyChangeSupport changeSupport = new PropertyChangeSupport(
+          this);
+
+  public void addPropertyChangeListener(PropertyChangeListener listener)
+  {
+    changeSupport.addPropertyChangeListener(listener);
+  }
+
+  public void removePropertyChangeListener(PropertyChangeListener listener)
+  {
+    changeSupport.removePropertyChangeListener(listener);
+  }
+  // end of event notification functionality initialisation
+
   String groupName;
 
   String description;
@@ -496,6 +519,8 @@ public class SequenceGroup implements AnnotatedCollectionI
       if (s != null && !sequences.contains(s))
       {
         sequences.add(s);
+        changeSupport.firePropertyChange(SEQ_GROUP_CHANGED,
+                sequences.size() - 1, sequences.size());
       }
 
       if (recalc)
@@ -620,8 +645,10 @@ public class SequenceGroup implements AnnotatedCollectionI
     conservation.description = "Conservation for group " + getName()
             + " less than " + consPercGaps + "% gaps";
     // preserve width if already set
-    int aWidth = (conservation.annotations != null) ? (endRes < conservation.annotations.length ? conservation.annotations.length
-            : endRes + 1)
+    int aWidth = (conservation.annotations != null)
+            ? (endRes < conservation.annotations.length
+                    ? conservation.annotations.length
+                    : endRes + 1)
             : endRes + 1;
     conservation.annotations = null;
     conservation.annotations = new Annotation[aWidth]; // should be alignment
@@ -641,8 +668,10 @@ public class SequenceGroup implements AnnotatedCollectionI
     consensus.description = "Percent Identity";
     consensusData = cnsns;
     // preserve width if already set
-    int aWidth = (consensus.annotations != null) ? (endRes < consensus.annotations.length ? consensus.annotations.length
-            : endRes + 1)
+    int aWidth = (consensus.annotations != null)
+            ? (endRes < consensus.annotations.length
+                    ? consensus.annotations.length
+                    : endRes + 1)
             : endRes + 1;
     consensus.annotations = null;
     consensus.annotations = new Annotation[aWidth]; // should be alignment width
@@ -689,6 +718,8 @@ public class SequenceGroup implements AnnotatedCollectionI
     synchronized (sequences)
     {
       sequences.remove(s);
+      changeSupport.firePropertyChange(SEQ_GROUP_CHANGED,
+              sequences.size() + 1, sequences.size());
 
       if (recalc)
       {
@@ -725,7 +756,9 @@ public class SequenceGroup implements AnnotatedCollectionI
    */
   public void setStartRes(int i)
   {
+    int before = startRes;
     startRes = i;
+    changeSupport.firePropertyChange(SEQ_GROUP_CHANGED, before, startRes);
   }
 
   /**
@@ -735,7 +768,9 @@ public class SequenceGroup implements AnnotatedCollectionI
    */
   public void setEndRes(int i)
   {
+    int before = endRes;
     endRes = i;
+    changeSupport.firePropertyChange(SEQ_GROUP_CHANGED, before, endRes);
   }
 
   /**
@@ -1282,38 +1317,16 @@ public class SequenceGroup implements AnnotatedCollectionI
   @Override
   public Iterable<AlignmentAnnotation> findAnnotation(String calcId)
   {
-    List<AlignmentAnnotation> aa = new ArrayList<>();
-    if (calcId == null)
-    {
-      return aa;
-    }
-    for (AlignmentAnnotation a : getAlignmentAnnotation())
-    {
-      if (calcId.equals(a.getCalcId()))
-      {
-        aa.add(a);
-      }
-    }
-    return aa;
+    return AlignmentAnnotation.findAnnotation(
+            Arrays.asList(getAlignmentAnnotation()), calcId);
   }
 
   @Override
   public Iterable<AlignmentAnnotation> findAnnotations(SequenceI seq,
           String calcId, String label)
   {
-    ArrayList<AlignmentAnnotation> aa = new ArrayList<>();
-    for (AlignmentAnnotation ann : getAlignmentAnnotation())
-    {
-      if ((calcId == null || (ann.getCalcId() != null && ann.getCalcId()
-              .equals(calcId)))
-              && (seq == null || (ann.sequenceRef != null && ann.sequenceRef == seq))
-              && (label == null || (ann.label != null && ann.label
-                      .equals(label))))
-      {
-        aa.add(ann);
-      }
-    }
-    return aa;
+    return AlignmentAnnotation.findAnnotations(
+            Arrays.asList(getAlignmentAnnotation()), seq, calcId, label);
   }
 
   /**
@@ -1324,17 +1337,8 @@ public class SequenceGroup implements AnnotatedCollectionI
    */
   public boolean hasAnnotation(String calcId)
   {
-    if (calcId != null && !"".equals(calcId))
-    {
-      for (AlignmentAnnotation a : getAlignmentAnnotation())
-      {
-        if (a.getCalcId() == calcId)
-        {
-          return true;
-        }
-      }
-    }
-    return false;
+    return AlignmentAnnotation
+            .hasAnnotation(Arrays.asList(getAlignmentAnnotation()), calcId);
   }
 
   /**
@@ -1344,7 +1348,10 @@ public class SequenceGroup implements AnnotatedCollectionI
   {
     synchronized (sequences)
     {
+      int before = sequences.size();
       sequences.clear();
+      changeSupport.firePropertyChange(SEQ_GROUP_CHANGED, before,
+              sequences.size());
     }
   }
 
@@ -1432,7 +1439,8 @@ public class SequenceGroup implements AnnotatedCollectionI
   @Override
   public boolean isNucleotide()
   {
-    if (context != null) {
+    if (context != null)
+    {
       return context.isNucleotide();
     }
     return false;
index 12ddf60..2f3e925 100755 (executable)
@@ -20,6 +20,8 @@
  */
 package jalview.datamodel;
 
+import jalview.datamodel.features.SequenceFeaturesI;
+
 import java.util.BitSet;
 import java.util.List;
 import java.util.Vector;
@@ -117,9 +119,9 @@ public interface SequenceI extends ASequenceI
   public String getSequenceAsString(int start, int end);
 
   /**
-   * Get the sequence as a character array
+   * Answers a copy of the sequence as a character array
    * 
-   * @return seqeunce and any gaps
+   * @return
    */
   public char[] getSequence();
 
@@ -175,7 +177,7 @@ public interface SequenceI extends ASequenceI
   public String getDescription();
 
   /**
-   * Return the alignment column for a sequence position
+   * Return the alignment column (from 1..) for a sequence position
    * 
    * @param pos
    *          lying from start to end
@@ -190,17 +192,28 @@ public interface SequenceI extends ASequenceI
   public int findIndex(int pos);
 
   /**
-   * Returns the sequence position for an alignment position.
+   * Returns the sequence position for an alignment (column) position. If at a
+   * gap, returns the position of the next residue to the right. If beyond the
+   * end of the sequence, returns 1 more than the last residue position.
    * 
    * @param i
    *          column index in alignment (from 0..<length)
    * 
-   * @return TODO: JAL-2562 - residue number for residue (left of and) nearest
-   *         ith column
+   * @return
    */
   public int findPosition(int i);
 
   /**
+   * Returns the from-to sequence positions (start..) for the given column
+   * positions (1..), or null if no residues are included in the range
+   * 
+   * @param fromColum
+   * @param toColumn
+   * @return
+   */
+  public Range findPositions(int fromColum, int toColumn);
+
+  /**
    * Returns an int array where indices correspond to each residue in the
    * sequence and the element value gives its position in the alignment
    * 
@@ -261,22 +274,28 @@ public interface SequenceI extends ASequenceI
   public void insertCharAt(int position, int count, char ch);
 
   /**
-   * Gets array holding sequence features associated with this sequence. The
-   * array may be held by the sequence's dataset sequence if that is defined.
+   * Answers a list of all sequence features associated with this sequence. The
+   * list may be held by the sequence's dataset sequence if that is defined.
    * 
-   * @return hard reference to array
+   * @return
+   */
+  public List<SequenceFeature> getSequenceFeatures();
+
+  /**
+   * Answers the object holding features for the sequence
+   * 
+   * @return
    */
-  public SequenceFeature[] getSequenceFeatures();
+  SequenceFeaturesI getFeatures();
 
   /**
-   * Replaces the array of sequence features associated with this sequence with
-   * a new array reference. If this sequence has a dataset sequence, then this
-   * method will update the dataset sequence's feature array
+   * Replaces the sequence features associated with this sequence with the given
+   * features. If this sequence has a dataset sequence, then this method will
+   * update the dataset sequence's features instead.
    * 
    * @param features
-   *          New array of sequence features
    */
-  public void setSequenceFeatures(SequenceFeature[] features);
+  public void setSequenceFeatures(List<SequenceFeature> features);
 
   /**
    * DOCUMENT ME!
@@ -341,7 +360,7 @@ public interface SequenceI extends ASequenceI
 
   /**
    * Adds the given sequence feature and returns true, or returns false if it is
-   * already present on the sequence
+   * already present on the sequence, or if the feature type is null.
    * 
    * @param sf
    * @return
@@ -431,17 +450,6 @@ public interface SequenceI extends ASequenceI
   public void transferAnnotation(SequenceI entry, Mapping mp);
 
   /**
-   * @param index
-   *          The sequence index in the MSA
-   */
-  public void setIndex(int index);
-
-  /**
-   * @return The index of the sequence in the alignment
-   */
-  public int getIndex();
-
-  /**
    * @return The RNA of the sequence in the alignment
    */
 
@@ -479,9 +487,41 @@ public interface SequenceI extends ASequenceI
   public List<DBRefEntry> getPrimaryDBRefs();
 
   /**
+   * Returns a (possibly empty) list of sequence features that overlap the given
+   * alignment column range, optionally restricted to one or more specified
+   * feature types. If the range is all gaps, then features which enclose it are
+   * included (but not contact features).
+   * 
+   * @param fromCol
+   *          start column of range inclusive (1..)
+   * @param toCol
+   *          end column of range inclusive (1..)
+   * @param types
+   *          optional feature types to restrict results to
+   * @return
+   */
+  List<SequenceFeature> findFeatures(int fromCol, int toCol, String... types);
+
+  /**
+   * Method to call to indicate that the sequence (characters or alignment/gaps)
+   * has been modified. Provided to allow any cursors on residue/column
+   * positions to be invalidated.
+   */
+  void sequenceChanged();
+  
+  /**
    * 
    * @return BitSet corresponding to index [0,length) where Comparison.isGap()
    *         returns true.
    */
   BitSet getInsertionsAsBits();
+
+  /**
+   * Replaces every occurrence of c1 in the sequence with c2 and returns the
+   * number of characters changed
+   * 
+   * @param c1
+   * @param c2
+   */
+  public int replace(char c1, char c2);
 }
index 86233ab..e9437a7 100644 (file)
@@ -27,6 +27,7 @@ import java.util.Iterator;
 public class VisibleColsCollection implements AlignmentColsCollectionI
 {
   int start;
+
   int end;
 
   HiddenColumns hidden;
@@ -50,4 +51,10 @@ public class VisibleColsCollection implements AlignmentColsCollectionI
     return false;
   }
 
+  @Override
+  public boolean hasHidden()
+  {
+    return false;
+  }
+
 }
index a82de93..9de468d 100644 (file)
@@ -128,4 +128,3 @@ public class VisibleColsIterator implements Iterator<Integer>
     throw new UnsupportedOperationException();
   }
 }
-
index ce8e8da..fd7cf47 100644 (file)
@@ -56,5 +56,10 @@ public class VisibleRowsCollection implements AlignmentRowsCollectionI
   {
     return alignment.getSequenceAtAbsoluteIndex(seq);
   }
-}
 
+  @Override
+  public boolean hasHidden()
+  {
+    return false;
+  }
+}
index a9c782d..e2fdff6 100644 (file)
@@ -51,7 +51,8 @@ public class VisibleRowsIterator implements Iterator<Integer>
    * @param alignment
    *          alignment to work with
    */
-  public VisibleRowsIterator(int firstrow, int lastrow, AlignmentI alignment)
+  public VisibleRowsIterator(int firstrow, int lastrow,
+          AlignmentI alignment)
   {
     al = alignment;
     current = firstrow;
@@ -96,4 +97,3 @@ public class VisibleRowsIterator implements Iterator<Integer>
     throw new UnsupportedOperationException();
   }
 }
-
similarity index 66%
rename from src/jalview/io/MatrixFile.java
rename to src/jalview/datamodel/features/FeatureLocationI.java
index 418eea2..378b8db 100644 (file)
  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
-package jalview.io;
+package jalview.datamodel.features;
+
+import jalview.datamodel.ContiguousI;
 
 /**
- * IO for asymmetric matrix with arbitrary dimension with labels, as displayed
- * by PCA viewer. Form is: tab separated entity defs header line TITLE\ttitle
- * DESC\tdesc PROPERTY\t<id or empty for whole matrix>\tname\ttype\tvalue
- * ROW\tRow i label (ID)/tPrinciple text/tprinciple description/t...
- * COLUMN\t(similar, optional).. .. <float>\t<float>...(column-wise data for row
- * i)
+ * An extension of ContiguousI that allows start/end values to be interpreted
+ * instead as two contact positions
  */
-
-public class MatrixFile extends FileParse
+public interface FeatureLocationI extends ContiguousI
 {
-
+  boolean isContactFeature();
 }
diff --git a/src/jalview/datamodel/features/FeatureStore.java b/src/jalview/datamodel/features/FeatureStore.java
new file mode 100644 (file)
index 0000000..02ce1c5
--- /dev/null
@@ -0,0 +1,1084 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel.features;
+
+import jalview.datamodel.ContiguousI;
+import jalview.datamodel.SequenceFeature;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A data store for a set of sequence features that supports efficient lookup of
+ * features overlapping a given range. Intended for (but not limited to) storage
+ * of features for one sequence and feature type.
+ * 
+ * @author gmcarstairs
+ *
+ */
+public class FeatureStore
+{
+  /**
+   * a class providing criteria for performing a binary search of a list
+   */
+  abstract static class SearchCriterion
+  {
+    /**
+     * Answers true if the entry passes the search criterion test
+     * 
+     * @param entry
+     * @return
+     */
+    abstract boolean compare(SequenceFeature entry);
+
+    /**
+     * serves a search condition for finding the first feature whose start
+     * position follows a given target location
+     * 
+     * @param target
+     * @return
+     */
+    static SearchCriterion byStart(final long target)
+    {
+      return new SearchCriterion() {
+
+        @Override
+        boolean compare(SequenceFeature entry)
+        {
+          return entry.getBegin() >= target;
+        }
+      };
+    }
+
+    /**
+     * serves a search condition for finding the first feature whose end
+     * position is at or follows a given target location
+     * 
+     * @param target
+     * @return
+     */
+    static SearchCriterion byEnd(final long target)
+    {
+      return new SearchCriterion()
+      {
+
+        @Override
+        boolean compare(SequenceFeature entry)
+        {
+          return entry.getEnd() >= target;
+        }
+      };
+    }
+
+    /**
+     * serves a search condition for finding the first feature which follows the
+     * given range as determined by a supplied comparator
+     * 
+     * @param target
+     * @return
+     */
+    static SearchCriterion byFeature(final ContiguousI to,
+            final Comparator<ContiguousI> rc)
+    {
+      return new SearchCriterion()
+      {
+
+        @Override
+        boolean compare(SequenceFeature entry)
+        {
+          return rc.compare(entry, to) >= 0;
+        }
+      };
+    }
+  }
+
+  /*
+   * Non-positional features have no (zero) start/end position.
+   * Kept as a separate list in case this criterion changes in future.
+   */
+  List<SequenceFeature> nonPositionalFeatures;
+
+  /*
+   * An ordered list of features, with the promise that no feature in the list 
+   * properly contains any other. This constraint allows bounded linear search
+   * of the list for features overlapping a region.
+   * Contact features are not included in this list.
+   */
+  List<SequenceFeature> nonNestedFeatures;
+
+  /*
+   * contact features ordered by first contact position
+   */
+  List<SequenceFeature> contactFeatureStarts;
+
+  /*
+   * contact features ordered by second contact position
+   */
+  List<SequenceFeature> contactFeatureEnds;
+
+  /*
+   * Nested Containment List is used to hold any features that are nested 
+   * within (properly contained by) any other feature. This is a recursive tree
+   * which supports depth-first scan for features overlapping a range.
+   * It is used here as a 'catch-all' fallback for features that cannot be put
+   * into a simple ordered list without invalidating the search methods.
+   */
+  NCList<SequenceFeature> nestedFeatures;
+
+  /*
+   * Feature groups represented in stored positional features 
+   * (possibly including null)
+   */
+  Set<String> positionalFeatureGroups;
+
+  /*
+   * Feature groups represented in stored non-positional features 
+   * (possibly including null)
+   */
+  Set<String> nonPositionalFeatureGroups;
+
+  /*
+   * the total length of all positional features; contact features count 1 to
+   * the total and 1 to size(), consistent with an average 'feature length' of 1
+   */
+  int totalExtent;
+
+  float positionalMinScore;
+
+  float positionalMaxScore;
+
+  float nonPositionalMinScore;
+
+  float nonPositionalMaxScore;
+
+  /**
+   * Constructor
+   */
+  public FeatureStore()
+  {
+    nonNestedFeatures = new ArrayList<SequenceFeature>();
+    positionalFeatureGroups = new HashSet<String>();
+    nonPositionalFeatureGroups = new HashSet<String>();
+    positionalMinScore = Float.NaN;
+    positionalMaxScore = Float.NaN;
+    nonPositionalMinScore = Float.NaN;
+    nonPositionalMaxScore = Float.NaN;
+
+    // we only construct nonPositionalFeatures, contactFeatures
+    // or the NCList if we need to
+  }
+
+  /**
+   * Adds one sequence feature to the store, and returns true, unless the
+   * feature is already contained in the store, in which case this method
+   * returns false. Containment is determined by SequenceFeature.equals()
+   * comparison.
+   * 
+   * @param feature
+   */
+  public boolean addFeature(SequenceFeature feature)
+  {
+    if (contains(feature))
+    {
+      return false;
+    }
+
+    /*
+     * keep a record of feature groups
+     */
+    if (!feature.isNonPositional())
+    {
+      positionalFeatureGroups.add(feature.getFeatureGroup());
+    }
+
+    boolean added = false;
+
+    if (feature.isContactFeature())
+    {
+      added = addContactFeature(feature);
+    }
+    else if (feature.isNonPositional())
+    {
+      added = addNonPositionalFeature(feature);
+    }
+    else
+    {
+      added = addNonNestedFeature(feature);
+      if (!added)
+      {
+        /*
+         * detected a nested feature - put it in the NCList structure
+         */
+        added = addNestedFeature(feature);
+      }
+    }
+
+    if (added)
+    {
+      /*
+       * record the total extent of positional features, to make
+       * getTotalFeatureLength possible; we count the length of a 
+       * contact feature as 1
+       */
+      totalExtent += getFeatureLength(feature);
+
+      /*
+       * record the minimum and maximum score for positional
+       * and non-positional features
+       */
+      float score = feature.getScore();
+      if (!Float.isNaN(score))
+      {
+        if (feature.isNonPositional())
+        {
+          nonPositionalMinScore = min(nonPositionalMinScore, score);
+          nonPositionalMaxScore = max(nonPositionalMaxScore, score);
+        }
+        else
+        {
+          positionalMinScore = min(positionalMinScore, score);
+          positionalMaxScore = max(positionalMaxScore, score);
+        }
+      }
+    }
+
+    return added;
+  }
+
+  /**
+   * Answers true if this store contains the given feature (testing by
+   * SequenceFeature.equals), else false
+   * 
+   * @param feature
+   * @return
+   */
+  public boolean contains(SequenceFeature feature)
+  {
+    if (feature.isNonPositional())
+    {
+      return nonPositionalFeatures == null ? false : nonPositionalFeatures
+              .contains(feature);
+    }
+
+    if (feature.isContactFeature())
+    {
+      return contactFeatureStarts == null ? false : listContains(
+              contactFeatureStarts, feature);
+    }
+
+    if (listContains(nonNestedFeatures, feature))
+    {
+      return true;
+    }
+
+    return nestedFeatures == null ? false : nestedFeatures
+            .contains(feature);
+  }
+
+  /**
+   * Answers the 'length' of the feature, counting 0 for non-positional features
+   * and 1 for contact features
+   * 
+   * @param feature
+   * @return
+   */
+  protected static int getFeatureLength(SequenceFeature feature)
+  {
+    if (feature.isNonPositional())
+    {
+      return 0;
+    }
+    if (feature.isContactFeature())
+    {
+      return 1;
+    }
+    return 1 + feature.getEnd() - feature.getBegin();
+  }
+
+  /**
+   * Adds the feature to the list of non-positional features (with lazy
+   * instantiation of the list if it is null), and returns true. The feature
+   * group is added to the set of distinct feature groups for non-positional
+   * features. This method allows duplicate features, so test before calling to
+   * prevent this.
+   * 
+   * @param feature
+   */
+  protected boolean addNonPositionalFeature(SequenceFeature feature)
+  {
+    if (nonPositionalFeatures == null)
+    {
+      nonPositionalFeatures = new ArrayList<SequenceFeature>();
+    }
+
+    nonPositionalFeatures.add(feature);
+
+    nonPositionalFeatureGroups.add(feature.getFeatureGroup());
+
+    return true;
+  }
+
+  /**
+   * Adds one feature to the NCList that can manage nested features (creating
+   * the NCList if necessary), and returns true. If the feature is already
+   * stored in the NCList (by equality test), then it is not added, and this
+   * method returns false.
+   */
+  protected synchronized boolean addNestedFeature(SequenceFeature feature)
+  {
+    if (nestedFeatures == null)
+    {
+      nestedFeatures = new NCList<>(feature);
+      return true;
+    }
+    return nestedFeatures.add(feature, false);
+  }
+
+  /**
+   * Add a feature to the list of non-nested features, maintaining the ordering
+   * of the list. A check is made for whether the feature is nested in (properly
+   * contained by) an existing feature. If there is no nesting, the feature is
+   * added to the list and the method returns true. If nesting is found, the
+   * feature is not added and the method returns false.
+   * 
+   * @param feature
+   * @return
+   */
+  protected boolean addNonNestedFeature(SequenceFeature feature)
+  {
+    synchronized (nonNestedFeatures)
+    {
+      /*
+       * find the first stored feature which doesn't precede the new one
+       */
+      int insertPosition = binarySearch(nonNestedFeatures,
+              SearchCriterion.byFeature(feature, RangeComparator.BY_START_POSITION));
+
+      /*
+       * fail if we detect feature enclosure - of the new feature by
+       * the one preceding it, or of the next feature by the new one
+       */
+      if (insertPosition > 0)
+      {
+        if (encloses(nonNestedFeatures.get(insertPosition - 1), feature))
+        {
+          return false;
+        }
+      }
+      if (insertPosition < nonNestedFeatures.size())
+      {
+        if (encloses(feature, nonNestedFeatures.get(insertPosition)))
+        {
+          return false;
+        }
+      }
+
+      /*
+       * checks passed - add the feature
+       */
+      nonNestedFeatures.add(insertPosition, feature);
+
+      return true;
+    }
+  }
+
+  /**
+   * Answers true if range1 properly encloses range2, else false
+   * 
+   * @param range1
+   * @param range2
+   * @return
+   */
+  protected boolean encloses(ContiguousI range1, ContiguousI range2)
+  {
+    int begin1 = range1.getBegin();
+    int begin2 = range2.getBegin();
+    int end1 = range1.getEnd();
+    int end2 = range2.getEnd();
+    if (begin1 == begin2 && end1 > end2)
+    {
+      return true;
+    }
+    if (begin1 < begin2 && end1 >= end2)
+    {
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * Add a contact feature to the lists that hold them ordered by start (first
+   * contact) and by end (second contact) position, ensuring the lists remain
+   * ordered, and returns true. This method allows duplicate features to be
+   * added, so test before calling to avoid this.
+   * 
+   * @param feature
+   * @return
+   */
+  protected synchronized boolean addContactFeature(SequenceFeature feature)
+  {
+    if (contactFeatureStarts == null)
+    {
+      contactFeatureStarts = new ArrayList<SequenceFeature>();
+    }
+    if (contactFeatureEnds == null)
+    {
+      contactFeatureEnds = new ArrayList<SequenceFeature>();
+    }
+
+    /*
+     * binary search the sorted list to find the insertion point
+     */
+    int insertPosition = binarySearch(contactFeatureStarts,
+            SearchCriterion.byFeature(feature,
+                    RangeComparator.BY_START_POSITION));
+    contactFeatureStarts.add(insertPosition, feature);
+    // and resort to mak siccar...just in case insertion point not quite right
+    Collections.sort(contactFeatureStarts, RangeComparator.BY_START_POSITION);
+
+    insertPosition = binarySearch(contactFeatureStarts,
+            SearchCriterion.byFeature(feature,
+                    RangeComparator.BY_END_POSITION));
+    contactFeatureEnds.add(feature);
+    Collections.sort(contactFeatureEnds, RangeComparator.BY_END_POSITION);
+
+    return true;
+  }
+
+  /**
+   * Answers true if the list contains the feature, else false. This method is
+   * optimised for the condition that the list is sorted on feature start
+   * position ascending, and will give unreliable results if this does not hold.
+   * 
+   * @param features
+   * @param feature
+   * @return
+   */
+  protected static boolean listContains(List<SequenceFeature> features,
+          SequenceFeature feature)
+  {
+    if (features == null || feature == null)
+    {
+      return false;
+    }
+
+    /*
+     * locate the first entry in the list which does not precede the feature
+     */
+    int pos = binarySearch(features,
+            SearchCriterion.byFeature(feature, RangeComparator.BY_START_POSITION));
+    int len = features.size();
+    while (pos < len)
+    {
+      SequenceFeature sf = features.get(pos);
+      if (sf.getBegin() > feature.getBegin())
+      {
+        return false; // no match found
+      }
+      if (sf.equals(feature))
+      {
+        return true;
+      }
+      pos++;
+    }
+    return false;
+  }
+
+  /**
+   * Returns a (possibly empty) list of features whose extent overlaps the given
+   * range. The returned list is not ordered. Contact features are included if
+   * either of the contact points lies within the range.
+   * 
+   * @param start
+   *          start position of overlap range (inclusive)
+   * @param end
+   *          end position of overlap range (inclusive)
+   * @return
+   */
+  public List<SequenceFeature> findOverlappingFeatures(long start, long end)
+  {
+    List<SequenceFeature> result = new ArrayList<>();
+
+    findNonNestedFeatures(start, end, result);
+
+    findContactFeatures(start, end, result);
+
+    if (nestedFeatures != null)
+    {
+      result.addAll(nestedFeatures.findOverlaps(start, end));
+    }
+
+    return result;
+  }
+
+  /**
+   * Adds contact features to the result list where either the second or the
+   * first contact position lies within the target range
+   * 
+   * @param from
+   * @param to
+   * @param result
+   */
+  protected void findContactFeatures(long from, long to,
+          List<SequenceFeature> result)
+  {
+    if (contactFeatureStarts != null)
+    {
+      findContactStartFeatures(from, to, result);
+    }
+    if (contactFeatureEnds != null)
+    {
+      findContactEndFeatures(from, to, result);
+    }
+  }
+
+  /**
+   * Adds to the result list any contact features whose end (second contact
+   * point), but not start (first contact point), lies in the query from-to
+   * range
+   * 
+   * @param from
+   * @param to
+   * @param result
+   */
+  protected void findContactEndFeatures(long from, long to,
+          List<SequenceFeature> result)
+  {
+    /*
+     * find the first contact feature (if any) that does not lie 
+     * entirely before the target range
+     */
+    int startPosition = binarySearch(contactFeatureEnds,
+            SearchCriterion.byEnd(from));
+    for (; startPosition < contactFeatureEnds.size(); startPosition++)
+    {
+      SequenceFeature sf = contactFeatureEnds.get(startPosition);
+      if (!sf.isContactFeature())
+      {
+        System.err.println("Error! non-contact feature type "
+                + sf.getType() + " in contact features list");
+        continue;
+      }
+
+      int begin = sf.getBegin();
+      if (begin >= from && begin <= to)
+      {
+        /*
+         * this feature's first contact position lies in the search range
+         * so we don't include it in results a second time
+         */
+        continue;
+      }
+
+      int end = sf.getEnd();
+      if (end >= from && end <= to)
+      {
+        result.add(sf);
+      }
+      if (end > to)
+      {
+        break;
+      }
+    }
+  }
+
+  /**
+   * Adds non-nested features to the result list that lie within the target
+   * range. Non-positional features (start=end=0), contact features and nested
+   * features are excluded.
+   * 
+   * @param from
+   * @param to
+   * @param result
+   */
+  protected void findNonNestedFeatures(long from, long to,
+          List<SequenceFeature> result)
+  {
+    /*
+     * find the first feature whose end position is
+     * after the target range start
+     */
+    int startIndex = binarySearch(nonNestedFeatures,
+            SearchCriterion.byEnd(from));
+
+    final int startIndex1 = startIndex;
+    int i = startIndex1;
+    while (i < nonNestedFeatures.size())
+    {
+      SequenceFeature sf = nonNestedFeatures.get(i);
+      if (sf.getBegin() > to)
+      {
+        break;
+      }
+      if (sf.getBegin() <= to && sf.getEnd() >= from)
+      {
+        result.add(sf);
+      }
+      i++;
+    }
+  }
+
+  /**
+   * Adds contact features whose start position lies in the from-to range to the
+   * result list
+   * 
+   * @param from
+   * @param to
+   * @param result
+   */
+  protected void findContactStartFeatures(long from, long to,
+          List<SequenceFeature> result)
+  {
+    int startPosition = binarySearch(contactFeatureStarts,
+            SearchCriterion.byStart(from));
+
+    for (; startPosition < contactFeatureStarts.size(); startPosition++)
+    {
+      SequenceFeature sf = contactFeatureStarts.get(startPosition);
+      if (!sf.isContactFeature())
+      {
+        System.err.println("Error! non-contact feature type "
+                + sf.getType() + " in contact features list");
+        continue;
+      }
+      int begin = sf.getBegin();
+      if (begin >= from && begin <= to)
+      {
+        result.add(sf);
+      }
+    }
+  }
+
+  /**
+   * Answers a list of all positional features stored, in no guaranteed order
+   * 
+   * @return
+   */
+  public List<SequenceFeature> getPositionalFeatures()
+  {
+    /*
+     * add non-nested features (may be all features for many cases)
+     */
+    List<SequenceFeature> result = new ArrayList<>();
+    result.addAll(nonNestedFeatures);
+
+    /*
+     * add any contact features - from the list by start position
+     */
+    if (contactFeatureStarts != null)
+    {
+      result.addAll(contactFeatureStarts);
+    }
+
+    /*
+     * add any nested features
+     */
+    if (nestedFeatures != null)
+    {
+      result.addAll(nestedFeatures.getEntries());
+    }
+
+    return result;
+  }
+
+  /**
+   * Answers a list of all contact features. If there are none, returns an
+   * immutable empty list.
+   * 
+   * @return
+   */
+  public List<SequenceFeature> getContactFeatures()
+  {
+    if (contactFeatureStarts == null)
+    {
+      return Collections.emptyList();
+    }
+    return new ArrayList<>(contactFeatureStarts);
+  }
+
+  /**
+   * Answers a list of all non-positional features. If there are none, returns
+   * an immutable empty list.
+   * 
+   * @return
+   */
+  public List<SequenceFeature> getNonPositionalFeatures()
+  {
+    if (nonPositionalFeatures == null)
+    {
+      return Collections.emptyList();
+    }
+    return new ArrayList<>(nonPositionalFeatures);
+  }
+
+  /**
+   * Deletes the given feature from the store, returning true if it was found
+   * (and deleted), else false. This method makes no assumption that the feature
+   * is in the 'expected' place in the store, in case it has been modified since
+   * it was added.
+   * 
+   * @param sf
+   */
+  public synchronized boolean delete(SequenceFeature sf)
+  {
+    /*
+     * try the non-nested positional features first
+     */
+    boolean removed = nonNestedFeatures.remove(sf);
+
+    /*
+     * if not found, try contact positions (and if found, delete
+     * from both lists of contact positions)
+     */
+    if (!removed && contactFeatureStarts != null)
+    {
+      removed = contactFeatureStarts.remove(sf);
+      if (removed)
+      {
+        contactFeatureEnds.remove(sf);
+      }
+    }
+
+    boolean removedNonPositional = false;
+
+    /*
+     * if not found, try non-positional features
+     */
+    if (!removed && nonPositionalFeatures != null)
+    {
+      removedNonPositional = nonPositionalFeatures.remove(sf);
+      removed = removedNonPositional;
+    }
+
+    /*
+     * if not found, try nested features
+     */
+    if (!removed && nestedFeatures != null)
+    {
+      removed = nestedFeatures.delete(sf);
+    }
+
+    if (removed)
+    {
+      rescanAfterDelete();
+    }
+
+    return removed;
+  }
+
+  /**
+   * Rescan all features to recompute any cached values after an entry has been
+   * deleted. This is expected to be an infrequent event, so performance here is
+   * not critical.
+   */
+  protected synchronized void rescanAfterDelete()
+  {
+    positionalFeatureGroups.clear();
+    nonPositionalFeatureGroups.clear();
+    totalExtent = 0;
+    positionalMinScore = Float.NaN;
+    positionalMaxScore = Float.NaN;
+    nonPositionalMinScore = Float.NaN;
+    nonPositionalMaxScore = Float.NaN;
+
+    /*
+     * scan non-positional features for groups and scores
+     */
+    for (SequenceFeature sf : getNonPositionalFeatures())
+    {
+      nonPositionalFeatureGroups.add(sf.getFeatureGroup());
+      float score = sf.getScore();
+      nonPositionalMinScore = min(nonPositionalMinScore, score);
+      nonPositionalMaxScore = max(nonPositionalMaxScore, score);
+    }
+
+    /*
+     * scan positional features for groups, scores and extents
+     */
+    for (SequenceFeature sf : getPositionalFeatures())
+    {
+      positionalFeatureGroups.add(sf.getFeatureGroup());
+      float score = sf.getScore();
+      positionalMinScore = min(positionalMinScore, score);
+      positionalMaxScore = max(positionalMaxScore, score);
+      totalExtent += getFeatureLength(sf);
+    }
+  }
+
+  /**
+   * A helper method to return the minimum of two floats, where a non-NaN value
+   * is treated as 'less than' a NaN value (unlike Math.min which does the
+   * opposite)
+   * 
+   * @param f1
+   * @param f2
+   */
+  protected static float min(float f1, float f2)
+  {
+    if (Float.isNaN(f1))
+    {
+      return Float.isNaN(f2) ? f1 : f2;
+    }
+    else
+    {
+      return Float.isNaN(f2) ? f1 : Math.min(f1, f2);
+    }
+  }
+
+  /**
+   * A helper method to return the maximum of two floats, where a non-NaN value
+   * is treated as 'greater than' a NaN value (unlike Math.max which does the
+   * opposite)
+   * 
+   * @param f1
+   * @param f2
+   */
+  protected static float max(float f1, float f2)
+  {
+    if (Float.isNaN(f1))
+    {
+      return Float.isNaN(f2) ? f1 : f2;
+    }
+    else
+    {
+      return Float.isNaN(f2) ? f1 : Math.max(f1, f2);
+    }
+  }
+
+  /**
+   * Answers true if this store has no features, else false
+   * 
+   * @return
+   */
+  public boolean isEmpty()
+  {
+    boolean hasFeatures = !nonNestedFeatures.isEmpty()
+            || (contactFeatureStarts != null && !contactFeatureStarts
+                    .isEmpty())
+            || (nonPositionalFeatures != null && !nonPositionalFeatures
+                    .isEmpty())
+            || (nestedFeatures != null && nestedFeatures.size() > 0);
+
+    return !hasFeatures;
+  }
+
+  /**
+   * Answers the set of distinct feature groups stored, possibly including null,
+   * as an unmodifiable view of the set. The parameter determines whether the
+   * groups for positional or for non-positional features are returned.
+   * 
+   * @param positionalFeatures
+   * @return
+   */
+  public Set<String> getFeatureGroups(boolean positionalFeatures)
+  {
+    if (positionalFeatures)
+    {
+      return Collections.unmodifiableSet(positionalFeatureGroups);
+    }
+    else
+    {
+      return nonPositionalFeatureGroups == null ? Collections
+              .<String> emptySet() : Collections
+              .unmodifiableSet(nonPositionalFeatureGroups);
+    }
+  }
+
+  /**
+   * Performs a binary search of the (sorted) list to find the index of the
+   * first entry which returns true for the given comparator function. Returns
+   * the length of the list if there is no such entry.
+   * 
+   * @param features
+   * @param sc
+   * @return
+   */
+  protected static int binarySearch(List<SequenceFeature> features,
+          SearchCriterion sc)
+  {
+    int start = 0;
+    int end = features.size() - 1;
+    int matched = features.size();
+
+    while (start <= end)
+    {
+      int mid = (start + end) / 2;
+      SequenceFeature entry = features.get(mid);
+      boolean compare = sc.compare(entry);
+      if (compare)
+      {
+        matched = mid;
+        end = mid - 1;
+      }
+      else
+      {
+        start = mid + 1;
+      }
+    }
+
+    return matched;
+  }
+
+  /**
+   * Answers the number of positional (or non-positional) features stored.
+   * Contact features count as 1.
+   * 
+   * @param positional
+   * @return
+   */
+  public int getFeatureCount(boolean positional)
+  {
+    if (!positional)
+    {
+      return nonPositionalFeatures == null ? 0 : nonPositionalFeatures
+              .size();
+    }
+
+    int size = nonNestedFeatures.size();
+
+    if (contactFeatureStarts != null)
+    {
+      // note a contact feature (start/end) counts as one
+      size += contactFeatureStarts.size();
+    }
+
+    if (nestedFeatures != null)
+    {
+      size += nestedFeatures.size();
+    }
+
+    return size;
+  }
+
+  /**
+   * Answers the total length of positional features (or zero if there are
+   * none). Contact features contribute a value of 1 to the total.
+   * 
+   * @return
+   */
+  public int getTotalFeatureLength()
+  {
+    return totalExtent;
+  }
+
+  /**
+   * Answers the minimum score held for positional or non-positional features.
+   * This may be Float.NaN if there are no features, are none has a non-NaN
+   * score.
+   * 
+   * @param positional
+   * @return
+   */
+  public float getMinimumScore(boolean positional)
+  {
+    return positional ? positionalMinScore : nonPositionalMinScore;
+  }
+
+  /**
+   * Answers the maximum score held for positional or non-positional features.
+   * This may be Float.NaN if there are no features, are none has a non-NaN
+   * score.
+   * 
+   * @param positional
+   * @return
+   */
+  public float getMaximumScore(boolean positional)
+  {
+    return positional ? positionalMaxScore : nonPositionalMaxScore;
+  }
+
+  /**
+   * Answers a list of all either positional or non-positional features whose
+   * feature group matches the given group (which may be null)
+   * 
+   * @param positional
+   * @param group
+   * @return
+   */
+  public List<SequenceFeature> getFeaturesForGroup(boolean positional,
+          String group)
+  {
+    List<SequenceFeature> result = new ArrayList<>();
+
+    /*
+     * if we know features don't include the target group, no need
+     * to inspect them for matches
+     */
+    if (positional && !positionalFeatureGroups.contains(group)
+            || !positional && !nonPositionalFeatureGroups.contains(group))
+    {
+      return result;
+    }
+
+    List<SequenceFeature> sfs = positional ? getPositionalFeatures()
+            : getNonPositionalFeatures();
+    for (SequenceFeature sf : sfs)
+    {
+      String featureGroup = sf.getFeatureGroup();
+      if (group == null && featureGroup == null || group != null
+              && group.equals(featureGroup))
+      {
+        result.add(sf);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Adds the shift value to the start and end of all positional features.
+   * Returns true if at least one feature was updated, else false.
+   * 
+   * @param shift
+   * @return
+   */
+  public synchronized boolean shiftFeatures(int shift)
+  {
+    /*
+     * Because begin and end are final fields (to ensure the data store's
+     * integrity), we have to delete each feature and re-add it as amended.
+     * (Although a simple shift of all values would preserve data integrity!)
+     */
+    boolean modified = false;
+    for (SequenceFeature sf : getPositionalFeatures())
+    {
+      modified = true;
+      int newBegin = sf.getBegin() + shift;
+      int newEnd = sf.getEnd() + shift;
+
+      /*
+       * sanity check: don't shift left of the first residue
+       */
+      if (newEnd > 0)
+      {
+        newBegin = Math.max(1, newBegin);
+        SequenceFeature sf2 = new SequenceFeature(sf, newBegin, newEnd,
+                sf.getFeatureGroup(), sf.getScore());
+        addFeature(sf2);
+      }
+      delete(sf);
+    }
+    return modified;
+  }
+}
diff --git a/src/jalview/datamodel/features/NCList.java b/src/jalview/datamodel/features/NCList.java
new file mode 100644 (file)
index 0000000..ae58a69
--- /dev/null
@@ -0,0 +1,646 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel.features;
+
+import jalview.datamodel.ContiguousI;
+import jalview.datamodel.Range;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * An adapted implementation of NCList as described in the paper
+ * 
+ * <pre>
+ * Nested Containment List (NCList): a new algorithm for accelerating
+ * interval query of genome alignment and interval databases
+ * - Alexander V. Alekseyenko, Christopher J. Lee
+ * https://doi.org/10.1093/bioinformatics/btl647
+ * </pre>
+ */
+public class NCList<T extends ContiguousI>
+{
+  /*
+   * the number of ranges represented
+   */
+  private int size;
+
+  /*
+   * a list, in start position order, of sublists of ranges ordered so 
+   * that each contains (or is the same as) the one that follows it
+   */
+  private List<NCNode<T>> subranges;
+
+  /**
+   * Constructor given a list of things that are each located on a contiguous
+   * interval. Note that the constructor may reorder the list.
+   * <p>
+   * We assume here that for each range, start &lt;= end. Behaviour for reverse
+   * ordered ranges is undefined.
+   * 
+   * @param ranges
+   */
+  public NCList(List<T> ranges)
+  {
+    this();
+    build(ranges);
+  }
+
+  /**
+   * Sort and group ranges into sublists where each sublist represents a region
+   * and its contained subregions
+   * 
+   * @param ranges
+   */
+  protected void build(List<T> ranges)
+  {
+    /*
+     * sort by start ascending so that contained intervals 
+     * follow their containing interval
+     */
+    Collections.sort(ranges, RangeComparator.BY_START_POSITION);
+
+    List<Range> sublists = buildSubranges(ranges);
+
+    /*
+     * convert each subrange to an NCNode consisting of a range and
+     * (possibly) its contained NCList
+     */
+    for (Range sublist : sublists)
+    {
+      subranges.add(new NCNode<T>(ranges.subList(sublist.start,
+              sublist.end + 1)));
+    }
+
+    size = ranges.size();
+  }
+
+  public NCList(T entry)
+  {
+    this();
+    subranges.add(new NCNode<>(entry));
+    size = 1;
+  }
+
+  public NCList()
+  {
+    subranges = new ArrayList<NCNode<T>>();
+  }
+
+  /**
+   * Traverses the sorted ranges to identify sublists, within which each
+   * interval contains the one that follows it
+   * 
+   * @param ranges
+   * @return
+   */
+  protected List<Range> buildSubranges(List<T> ranges)
+  {
+    List<Range> sublists = new ArrayList<>();
+    
+    if (ranges.isEmpty())
+    {
+      return sublists;
+    }
+
+    int listStartIndex = 0;
+    long lastEndPos = Long.MAX_VALUE;
+
+    for (int i = 0; i < ranges.size(); i++)
+    {
+      ContiguousI nextInterval = ranges.get(i);
+      long nextStart = nextInterval.getBegin();
+      long nextEnd = nextInterval.getEnd();
+      if (nextStart > lastEndPos || nextEnd > lastEndPos)
+      {
+        /*
+         * this interval is not contained in the preceding one 
+         * close off the last sublist
+         */
+        sublists.add(new Range(listStartIndex, i - 1));
+        listStartIndex = i;
+      }
+      lastEndPos = nextEnd;
+    }
+
+    sublists.add(new Range(listStartIndex, ranges.size() - 1));
+    return sublists;
+  }
+
+  /**
+   * Adds one entry to the stored set (with duplicates allowed)
+   * 
+   * @param entry
+   */
+  public void add(T entry)
+  {
+    add(entry, true);
+  }
+
+  /**
+   * Adds one entry to the stored set, and returns true, unless allowDuplicates
+   * is set to false and it is already contained (by object equality test), in
+   * which case it is not added and this method returns false.
+   * 
+   * @param entry
+   * @param allowDuplicates
+   * @return
+   */
+  public synchronized boolean add(T entry, boolean allowDuplicates)
+  {
+    if (!allowDuplicates && contains(entry))
+    {
+      return false;
+    }
+
+    size++;
+    long start = entry.getBegin();
+    long end = entry.getEnd();
+
+    /*
+     * cases:
+     * - precedes all subranges: add as NCNode on front of list
+     * - follows all subranges: add as NCNode on end of list
+     * - enclosed by a subrange - add recursively to subrange
+     * - encloses one or more subranges - push them inside it
+     * - none of the above - add as a new node and resort nodes list (?)
+     */
+
+    /*
+     * find the first subrange whose end does not precede entry's start
+     */
+    int candidateIndex = findFirstOverlap(start);
+    if (candidateIndex == -1)
+    {
+      /*
+       * all subranges precede this one - add it on the end
+       */
+      subranges.add(new NCNode<>(entry));
+      return true;
+    }
+
+    /*
+     * search for maximal span of subranges i-k that the new entry
+     * encloses; or a subrange that encloses the new entry
+     */
+    boolean enclosing = false;
+    int firstEnclosed = 0;
+    int lastEnclosed = 0;
+    boolean overlapping = false;
+
+    for (int j = candidateIndex; j < subranges.size(); j++)
+    {
+      NCNode<T> subrange = subranges.get(j);
+
+      if (end < subrange.getBegin() && !overlapping && !enclosing)
+      {
+        /*
+         * new entry lies between subranges j-1 j
+         */
+        subranges.add(j, new NCNode<>(entry));
+        return true;
+      }
+
+      if (subrange.getBegin() <= start && subrange.getEnd() >= end)
+      {
+        /*
+         * push new entry inside this subrange as it encloses it
+         */
+        subrange.add(entry);
+        return true;
+      }
+      
+      if (start <= subrange.getBegin())
+      {
+        if (end >= subrange.getEnd())
+        {
+          /*
+           * new entry encloses this subrange (and possibly preceding ones);
+           * continue to find the maximal list it encloses
+           */
+          if (!enclosing)
+          {
+            firstEnclosed = j;
+          }
+          lastEnclosed = j;
+          enclosing = true;
+          continue;
+        }
+        else
+        {
+          /*
+           * entry spans from before this subrange to inside it
+           */
+          if (enclosing)
+          {
+            /*
+             * entry encloses one or more preceding subranges
+             */
+            addEnclosingRange(entry, firstEnclosed, lastEnclosed);
+            return true;
+          }
+          else
+          {
+            /*
+             * entry spans two subranges but doesn't enclose any
+             * so just add it 
+             */
+            subranges.add(j, new NCNode<>(entry));
+            return true;
+          }
+        }
+      }
+      else
+      {
+        overlapping = true;
+      }
+    }
+
+    /*
+     * drops through to here if new range encloses all others
+     * or overlaps the last one
+     */
+    if (enclosing)
+    {
+      addEnclosingRange(entry, firstEnclosed, lastEnclosed);
+    }
+    else
+    {
+      subranges.add(new NCNode<>(entry));
+    }
+
+    return true;
+  }
+  
+  /**
+   * Answers true if this NCList contains the given entry (by object equality
+   * test), else false
+   * 
+   * @param entry
+   * @return
+   */
+  public boolean contains(T entry)
+  {
+    /*
+     * find the first sublist that might overlap, i.e. 
+     * the first whose end position is >= from
+     */
+    int candidateIndex = findFirstOverlap(entry.getBegin());
+
+    if (candidateIndex == -1)
+    {
+      return false;
+    }
+
+    int to = entry.getEnd();
+
+    for (int i = candidateIndex; i < subranges.size(); i++)
+    {
+      NCNode<T> candidate = subranges.get(i);
+      if (candidate.getBegin() > to)
+      {
+        /*
+         * we are past the end of our target range
+         */
+        break;
+      }
+      if (candidate.contains(entry))
+      {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Update the tree so that the range of the new entry encloses subranges i to
+   * j (inclusive). That is, replace subranges i-j (inclusive) with a new
+   * subrange that contains them.
+   * 
+   * @param entry
+   * @param i
+   * @param j
+   */
+  protected synchronized void addEnclosingRange(T entry, final int i,
+          final int j)
+  {
+    NCList<T> newNCList = new NCList<>();
+    newNCList.addNodes(subranges.subList(i, j + 1));
+    NCNode<T> newNode = new NCNode<>(entry, newNCList);
+    for (int k = j; k >= i; k--)
+    {
+      subranges.remove(k);
+    }
+    subranges.add(i, newNode);
+  }
+
+  protected void addNodes(List<NCNode<T>> nodes)
+  {
+    for (NCNode<T> node : nodes)
+    {
+      subranges.add(node);
+      size += node.size();
+    }
+  }
+
+  /**
+   * Returns a (possibly empty) list of items whose extent overlaps the given
+   * range
+   * 
+   * @param from
+   *          start of overlap range (inclusive)
+   * @param to
+   *          end of overlap range (inclusive)
+   * @return
+   */
+  public List<T> findOverlaps(long from, long to)
+  {
+    List<T> result = new ArrayList<>();
+
+    findOverlaps(from, to, result);
+    
+    return result;
+  }
+
+  /**
+   * Recursively searches the NCList adding any items that overlap the from-to
+   * range to the result list
+   * 
+   * @param from
+   * @param to
+   * @param result
+   */
+  protected void findOverlaps(long from, long to, List<T> result)
+  {
+    /*
+     * find the first sublist that might overlap, i.e. 
+     * the first whose end position is >= from
+     */
+    int candidateIndex = findFirstOverlap(from);
+
+    if (candidateIndex == -1)
+    {
+      return;
+    }
+
+    for (int i = candidateIndex; i < subranges.size(); i++)
+    {
+      NCNode<T> candidate = subranges.get(i);
+      if (candidate.getBegin() > to)
+      {
+        /*
+         * we are past the end of our target range
+         */
+        break;
+      }
+      candidate.findOverlaps(from, to, result);
+    }
+
+  }
+
+  /**
+   * Search subranges for the first one whose end position is not before the
+   * target range's start position, i.e. the first one that may overlap the
+   * target range. Returns the index in the list of the first such range found,
+   * or -1 if none found.
+   * 
+   * @param from
+   * @return
+   */
+  protected int findFirstOverlap(long from)
+  {
+    /*
+     * The NCList paper describes binary search for this step,
+     * but this not implemented here as (a) I haven't understood it yet
+     * and (b) it seems to imply complications for adding to an NCList
+     */
+
+    int i = 0;
+    if (subranges != null)
+    {
+      for (NCNode<T> subrange : subranges)
+      {
+        if (subrange.getEnd() >= from)
+        {
+          return i;
+        }
+        i++;
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * Formats the tree as a bracketed list e.g.
+   * 
+   * <pre>
+   * [1-100 [10-30 [10-20]], 15-30 [20-20]]
+   * </pre>
+   */
+  @Override
+  public String toString()
+  {
+    return subranges.toString();
+  }
+
+  /**
+   * Returns a string representation of the data where containment is shown by
+   * indentation on new lines
+   * 
+   * @return
+   */
+  public String prettyPrint()
+  {
+    StringBuilder sb = new StringBuilder(512);
+    int offset = 0;
+    int indent = 2;
+    prettyPrint(sb, offset, indent);
+    sb.append(System.lineSeparator());
+    return sb.toString();
+  }
+
+  /**
+   * @param sb
+   * @param offset
+   * @param indent
+   */
+  void prettyPrint(StringBuilder sb, int offset, int indent)
+  {
+    boolean first = true;
+    for (NCNode<T> subrange : subranges)
+    {
+      if (!first)
+      {
+        sb.append(System.lineSeparator());
+      }
+      first = false;
+      subrange.prettyPrint(sb, offset, indent);
+    }
+  }
+
+  /**
+   * Answers true if the data held satisfy the rules of construction of an
+   * NCList, else false.
+   * 
+   * @return
+   */
+  public boolean isValid()
+  {
+    return isValid(Integer.MIN_VALUE, Integer.MAX_VALUE);
+  }
+
+  /**
+   * Answers true if the data held satisfy the rules of construction of an
+   * NCList bounded within the given start-end range, else false.
+   * <p>
+   * Each subrange must lie within start-end (inclusive). Subranges must be
+   * ordered by start position ascending.
+   * <p>
+   * 
+   * @param start
+   * @param end
+   * @return
+   */
+  boolean isValid(final int start, final int end)
+  {
+    int lastStart = start;
+    for (NCNode<T> subrange : subranges)
+    {
+      if (subrange.getBegin() < lastStart)
+      {
+        System.err.println("error in NCList: range " + subrange.toString()
+                + " starts before " + lastStart);
+        return false;
+      }
+      if (subrange.getEnd() > end)
+      {
+        System.err.println("error in NCList: range " + subrange.toString()
+                + " ends after " + end);
+        return false;
+      }
+      lastStart = subrange.getBegin();
+
+      if (!subrange.isValid())
+      {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Answers the lowest start position enclosed by the ranges
+   * 
+   * @return
+   */
+  public int getStart()
+  {
+    return subranges.isEmpty() ? 0 : subranges.get(0).getBegin();
+  }
+
+  /**
+   * Returns the number of ranges held (deep count)
+   * 
+   * @return
+   */
+  public int size()
+  {
+    return size;
+  }
+
+  /**
+   * Returns a list of all entries stored
+   * 
+   * @return
+   */
+  public List<T> getEntries()
+  {
+    List<T> result = new ArrayList<>();
+    getEntries(result);
+    return result;
+  }
+
+  /**
+   * Adds all contained entries to the given list
+   * 
+   * @param result
+   */
+  void getEntries(List<T> result)
+  {
+    for (NCNode<T> subrange : subranges)
+    {
+      subrange.getEntries(result);
+    }
+  }
+
+  /**
+   * Deletes the given entry from the store, returning true if it was found (and
+   * deleted), else false. This method makes no assumption that the entry is in
+   * the 'expected' place in the store, in case it has been modified since it
+   * was added. Only the first 'same object' match is deleted, not 'equal' or
+   * multiple objects.
+   * 
+   * @param entry
+   */
+  public synchronized boolean delete(T entry)
+  {
+    if (entry == null)
+    {
+      return false;
+    }
+    for (int i = 0; i < subranges.size(); i++)
+    {
+      NCNode<T> subrange = subranges.get(i);
+      NCList<T> subRegions = subrange.getSubRegions();
+
+      if (subrange.getRegion() == entry)
+      {
+        /*
+         * if the subrange is rooted on this entry, promote its
+         * subregions (if any) to replace the subrange here;
+         * NB have to resort subranges after doing this since e.g.
+         * [10-30 [12-20 [16-18], 13-19]]
+         * after deleting 12-20, 16-18 is promoted to sibling of 13-19
+         * but should follow it in the list of subranges of 10-30 
+         */
+        subranges.remove(i);
+        if (subRegions != null)
+        {
+          subranges.addAll(subRegions.subranges);
+          Collections.sort(subranges, RangeComparator.BY_START_POSITION);
+        }
+        size--;
+        return true;
+      }
+      else
+      {
+        if (subRegions != null && subRegions.delete(entry))
+        {
+          size--;
+          subrange.deleteSubRegionsIfEmpty();
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+}
diff --git a/src/jalview/datamodel/features/NCNode.java b/src/jalview/datamodel/features/NCNode.java
new file mode 100644 (file)
index 0000000..b991750
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel.features;
+
+import jalview.datamodel.ContiguousI;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Each node of the NCList tree consists of a range, and (optionally) the NCList
+ * of ranges it encloses
+ *
+ * @param <V>
+ */
+class NCNode<V extends ContiguousI> implements ContiguousI
+{
+  /*
+   * deep size (number of ranges included)
+   */
+  private int size;
+
+  private V region;
+
+  /*
+   * null, or an object holding contained subregions of this nodes region
+   */
+  private NCList<V> subregions;
+
+  /**
+   * Constructor given a list of ranges
+   * 
+   * @param ranges
+   */
+  NCNode(List<V> ranges)
+  {
+    build(ranges);
+  }
+
+  /**
+   * Constructor given a single range
+   * 
+   * @param range
+   */
+  NCNode(V range)
+  {
+    List<V> ranges = new ArrayList<>();
+    ranges.add(range);
+    build(ranges);
+  }
+
+  NCNode(V entry, NCList<V> newNCList)
+  {
+    region = entry;
+    subregions = newNCList;
+    size = 1 + newNCList.size();
+  }
+
+  /**
+   * @param ranges
+   */
+  protected void build(List<V> ranges)
+  {
+    size = ranges.size();
+
+    if (!ranges.isEmpty())
+    {
+      region = ranges.get(0);
+    }
+    if (ranges.size() > 1)
+    {
+      subregions = new NCList<V>(ranges.subList(1, ranges.size()));
+    }
+  }
+
+  @Override
+  public int getBegin()
+  {
+    return region.getBegin();
+  }
+
+  @Override
+  public int getEnd()
+  {
+    return region.getEnd();
+  }
+
+  /**
+   * Formats the node as a bracketed list e.g.
+   * 
+   * <pre>
+   * [1-100 [10-30 [10-20]], 15-30 [20-20]]
+   * </pre>
+   */
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder(10 * size);
+    sb.append(region.getBegin()).append("-").append(region.getEnd());
+    if (subregions != null)
+    {
+      sb.append(" ").append(subregions.toString());
+    }
+    return sb.toString();
+  }
+
+  void prettyPrint(StringBuilder sb, int offset, int indent) {
+    for (int i = 0 ; i < offset ; i++) {
+      sb.append(" ");
+    }
+    sb.append(region.getBegin()).append("-").append(region.getEnd());
+    if (subregions != null)
+    {
+      sb.append(System.lineSeparator());
+      subregions.prettyPrint(sb, offset + 2, indent);
+    }
+  }
+  /**
+   * Add any ranges that overlap the from-to range to the result list
+   * 
+   * @param from
+   * @param to
+   * @param result
+   */
+  void findOverlaps(long from, long to, List<V> result)
+  {
+    if (region.getBegin() <= to && region.getEnd() >= from)
+    {
+      result.add(region);
+    }
+    if (subregions != null)
+    {
+      subregions.findOverlaps(from, to, result);
+    }
+  }
+
+  /**
+   * Add one range to this subrange
+   * 
+   * @param entry
+   */
+  synchronized void add(V entry)
+  {
+    if (entry.getBegin() < region.getBegin() || entry.getEnd() > region.getEnd()) {
+      throw new IllegalArgumentException(String.format(
+              "adding improper subrange %d-%d to range %d-%d",
+              entry.getBegin(), entry.getEnd(), region.getBegin(),
+              region.getEnd()));
+    }
+    if (subregions == null)
+    {
+      subregions = new NCList<V>(entry);
+    }
+    else
+    {
+      subregions.add(entry);
+    }
+    size++;
+  }
+
+  /**
+   * Answers true if the data held satisfy the rules of construction of an
+   * NCList, else false.
+   * 
+   * @return
+   */
+  boolean isValid()
+  {
+    /*
+     * we don't handle reverse ranges
+     */
+    if (region != null && region.getBegin() > region.getEnd())
+    {
+      return false;
+    }
+    if (subregions == null)
+    {
+      return true;
+    }
+    return subregions.isValid(getBegin(), getEnd());
+  }
+
+  /**
+   * Adds all contained entries to the given list
+   * 
+   * @param entries
+   */
+  void getEntries(List<V> entries)
+  {
+    entries.add(region);
+    if (subregions != null)
+    {
+      subregions.getEntries(entries);
+    }
+  }
+
+  /**
+   * Answers true if this object contains the given entry (by object equals
+   * test), else false
+   * 
+   * @param entry
+   * @return
+   */
+  boolean contains(V entry)
+  {
+    if (entry == null)
+    {
+      return false;
+    }
+    if (entry.equals(region))
+    {
+      return true;
+    }
+    return subregions == null ? false : subregions.contains(entry);
+  }
+
+  /**
+   * Answers the 'root' region modelled by this object
+   * 
+   * @return
+   */
+  V getRegion()
+  {
+    return region;
+  }
+
+  /**
+   * Answers the (possibly null) contained regions within this object
+   * 
+   * @return
+   */
+  NCList<V> getSubRegions()
+  {
+    return subregions;
+  }
+
+  /**
+   * Nulls the subregion reference if it is empty (after a delete entry
+   * operation)
+   */
+  void deleteSubRegionsIfEmpty()
+  {
+    if (subregions != null && subregions.size() == 0)
+    {
+      subregions = null;
+    }
+  }
+
+  /**
+   * Answers the (deep) size of this node i.e. the number of ranges it models
+   * 
+   * @return
+   */
+  int size()
+  {
+    return size;
+  }
+}
diff --git a/src/jalview/datamodel/features/RangeComparator.java b/src/jalview/datamodel/features/RangeComparator.java
new file mode 100644 (file)
index 0000000..b7d702d
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel.features;
+
+import jalview.datamodel.ContiguousI;
+
+import java.util.Comparator;
+
+/**
+ * A comparator that orders ranges by either start position or end position
+ * ascending. If the position matches, ordering is resolved by end position (or
+ * start position).
+ * 
+ * @author gmcarstairs
+ *
+ */
+public class RangeComparator implements Comparator<ContiguousI>
+{
+  public static final Comparator<ContiguousI> BY_START_POSITION = new RangeComparator(
+          true);
+
+  public static final Comparator<ContiguousI> BY_END_POSITION = new RangeComparator(
+          false);
+
+  boolean byStart;
+
+  /**
+   * Constructor
+   * 
+   * @param byStartPosition
+   *          if true, order based on start position, if false by end position
+   */
+  RangeComparator(boolean byStartPosition)
+  {
+    byStart = byStartPosition;
+  }
+
+  @Override
+  public int compare(ContiguousI o1, ContiguousI o2)
+  {
+    int len1 = o1.getEnd() - o1.getBegin();
+    int len2 = o2.getEnd() - o2.getBegin();
+
+    if (byStart)
+    {
+      return compare(o1.getBegin(), o2.getBegin(), len1, len2);
+    }
+    else
+    {
+      return compare(o1.getEnd(), o2.getEnd(), len1, len2);
+    }
+  }
+
+  /**
+   * Compares two ranges for ordering
+   * 
+   * @param pos1
+   *          first range positional ordering criterion
+   * @param pos2
+   *          second range positional ordering criterion
+   * @param len1
+   *          first range length ordering criterion
+   * @param len2
+   *          second range length ordering criterion
+   * @return
+   */
+  public int compare(long pos1, long pos2, int len1, int len2)
+  {
+    int order = Long.compare(pos1, pos2);
+    if (order == 0)
+    {
+      /*
+       * if tied on position order, longer length sorts to left
+       * i.e. the negation of normal ordering by length
+       */
+      order = -Integer.compare(len1, len2);
+    }
+    return order;
+  }
+}
diff --git a/src/jalview/datamodel/features/SequenceFeatures.java b/src/jalview/datamodel/features/SequenceFeatures.java
new file mode 100644 (file)
index 0000000..fcf1b53
--- /dev/null
@@ -0,0 +1,483 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel.features;
+
+import jalview.datamodel.ContiguousI;
+import jalview.datamodel.SequenceFeature;
+import jalview.io.gff.SequenceOntologyFactory;
+import jalview.io.gff.SequenceOntologyI;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+
+/**
+ * A class that stores sequence features in a way that supports efficient
+ * querying by type and location (overlap). Intended for (but not limited to)
+ * storage of features for one sequence.
+ * 
+ * @author gmcarstairs
+ *
+ */
+public class SequenceFeatures implements SequenceFeaturesI
+{
+  /**
+   * a comparator for sorting features by start position ascending
+   */
+  private static Comparator<ContiguousI> FORWARD_STRAND = new Comparator<ContiguousI>()
+  {
+    @Override
+    public int compare(ContiguousI o1, ContiguousI o2)
+    {
+      return Integer.compare(o1.getBegin(), o2.getBegin());
+    }
+  };
+
+  /**
+   * a comparator for sorting features by end position descending
+   */
+  private static Comparator<ContiguousI> REVERSE_STRAND = new Comparator<ContiguousI>()
+  {
+    @Override
+    public int compare(ContiguousI o1, ContiguousI o2)
+    {
+      return Integer.compare(o2.getEnd(), o1.getEnd());
+    }
+  };
+
+  /*
+   * map from feature type to structured store of features for that type
+   * null types are permitted (but not a good idea!)
+   */
+  private Map<String, FeatureStore> featureStore;
+
+  /**
+   * Constructor
+   */
+  public SequenceFeatures()
+  {
+    /*
+     * use a TreeMap so that features are returned in alphabetical order of type
+     * ? wrap as a synchronized map for add and delete operations
+     */
+    // featureStore = Collections
+    // .synchronizedSortedMap(new TreeMap<String, FeatureStore>());
+    featureStore = new TreeMap<String, FeatureStore>();
+  }
+
+  /**
+   * Constructor given a list of features
+   */
+  public SequenceFeatures(List<SequenceFeature> features)
+  {
+    this();
+    if (features != null)
+    {
+      for (SequenceFeature feature : features)
+      {
+        add(feature);
+      }
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean add(SequenceFeature sf)
+  {
+    String type = sf.getType();
+    if (type == null)
+    {
+      System.err.println("Feature type may not be null: " + sf.toString());
+      return false;
+    }
+
+    if (featureStore.get(type) == null)
+    {
+      featureStore.put(type, new FeatureStore());
+    }
+    return featureStore.get(type).addFeature(sf);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public List<SequenceFeature> findFeatures(int from, int to,
+          String... type)
+  {
+    List<SequenceFeature> result = new ArrayList<>();
+
+    for (FeatureStore featureSet : varargToTypes(type))
+    {
+      result.addAll(featureSet.findOverlappingFeatures(from, to));
+    }
+
+    return result;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public List<SequenceFeature> getAllFeatures(String... type)
+  {
+    List<SequenceFeature> result = new ArrayList<>();
+
+    result.addAll(getPositionalFeatures(type));
+
+    result.addAll(getNonPositionalFeatures());
+
+    return result;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public List<SequenceFeature> getFeaturesByOntology(String... ontologyTerm)
+  {
+    if (ontologyTerm == null || ontologyTerm.length == 0)
+    {
+      return new ArrayList<>();
+    }
+
+    Set<String> featureTypes = getFeatureTypes(ontologyTerm);
+    if (featureTypes.isEmpty())
+    {
+      /*
+       * no features of the specified type or any sub-type
+       */
+      return new ArrayList<>();
+    }
+
+    return getAllFeatures(featureTypes.toArray(new String[featureTypes
+            .size()]));
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public int getFeatureCount(boolean positional, String... type)
+  {
+    int result = 0;
+
+    for (FeatureStore featureSet : varargToTypes(type))
+    {
+      result += featureSet.getFeatureCount(positional);
+    }
+    return result;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public int getTotalFeatureLength(String... type)
+  {
+    int result = 0;
+
+    for (FeatureStore featureSet : varargToTypes(type))
+    {
+      result += featureSet.getTotalFeatureLength();
+    }
+    return result;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public List<SequenceFeature> getPositionalFeatures(String... type)
+  {
+    List<SequenceFeature> result = new ArrayList<>();
+
+    for (FeatureStore featureSet : varargToTypes(type))
+    {
+      result.addAll(featureSet.getPositionalFeatures());
+    }
+    return result;
+  }
+
+  /**
+   * A convenience method that converts a vararg for feature types to an
+   * Iterable over matched feature sets in key order
+   * 
+   * @param type
+   * @return
+   */
+  protected Iterable<FeatureStore> varargToTypes(String... type)
+  {
+    if (type == null || type.length == 0)
+    {
+      /*
+       * no vararg parameter supplied - return all
+       */
+      return featureStore.values();
+    }
+
+    List<FeatureStore> types = new ArrayList<>();
+    List<String> args = Arrays.asList(type);
+    for (Entry<String, FeatureStore> featureType : featureStore.entrySet())
+    {
+      if (args.contains(featureType.getKey()))
+      {
+        types.add(featureType.getValue());
+      }
+    }
+    return types;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public List<SequenceFeature> getContactFeatures(String... type)
+  {
+    List<SequenceFeature> result = new ArrayList<>();
+
+    for (FeatureStore featureSet : varargToTypes(type))
+    {
+      result.addAll(featureSet.getContactFeatures());
+    }
+    return result;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public List<SequenceFeature> getNonPositionalFeatures(String... type)
+  {
+    List<SequenceFeature> result = new ArrayList<>();
+
+    for (FeatureStore featureSet : varargToTypes(type))
+    {
+      result.addAll(featureSet.getNonPositionalFeatures());
+    }
+    return result;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean delete(SequenceFeature sf)
+  {
+    for (FeatureStore featureSet : featureStore.values())
+    {
+      if (featureSet.delete(sf))
+      {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean hasFeatures()
+  {
+    for (FeatureStore featureSet : featureStore.values())
+    {
+      if (!featureSet.isEmpty())
+      {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<String> getFeatureGroups(boolean positionalFeatures,
+          String... type)
+  {
+    Set<String> groups = new HashSet<>();
+
+    for (FeatureStore featureSet : varargToTypes(type))
+    {
+      groups.addAll(featureSet.getFeatureGroups(positionalFeatures));
+    }
+
+    return groups;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<String> getFeatureTypesForGroups(boolean positionalFeatures,
+          String... groups)
+  {
+    Set<String> result = new HashSet<>();
+
+    for (Entry<String, FeatureStore> featureType : featureStore.entrySet())
+    {
+      Set<String> featureGroups = featureType.getValue().getFeatureGroups(
+              positionalFeatures);
+      for (String group : groups)
+      {
+        if (featureGroups.contains(group))
+        {
+          /*
+           * yes this feature type includes one of the query groups
+           */
+          result.add(featureType.getKey());
+          break;
+        }
+      }
+    }
+
+    return result;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<String> getFeatureTypes(String... soTerm)
+  {
+    Set<String> types = new HashSet<>();
+    for (Entry<String, FeatureStore> entry : featureStore.entrySet())
+    {
+      String type = entry.getKey();
+      if (!entry.getValue().isEmpty() && isOntologyTerm(type, soTerm))
+      {
+        types.add(type);
+      }
+    }
+    return types;
+  }
+
+  /**
+   * Answers true if the given type is one of the specified sequence ontology
+   * terms (or a sub-type of one), or if no terms are supplied. Answers false if
+   * filter terms are specified and the given term does not match any of them.
+   * 
+   * @param type
+   * @param soTerm
+   * @return
+   */
+  protected boolean isOntologyTerm(String type, String... soTerm)
+  {
+    if (soTerm == null || soTerm.length == 0)
+    {
+      return true;
+    }
+    SequenceOntologyI so = SequenceOntologyFactory.getInstance();
+    for (String term : soTerm)
+    {
+      if (so.isA(type, term))
+      {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public float getMinimumScore(String type, boolean positional)
+  {
+    return featureStore.containsKey(type) ? featureStore.get(type)
+            .getMinimumScore(positional) : Float.NaN;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public float getMaximumScore(String type, boolean positional)
+  {
+    return featureStore.containsKey(type) ? featureStore.get(type)
+            .getMaximumScore(positional) : Float.NaN;
+  }
+
+  /**
+   * A convenience method to sort features by start position ascending (if on
+   * forward strand), or end position descending (if on reverse strand)
+   * 
+   * @param features
+   * @param forwardStrand
+   */
+  public static void sortFeatures(List<SequenceFeature> features,
+          final boolean forwardStrand)
+  {
+    Collections.sort(features, forwardStrand ? FORWARD_STRAND
+            : REVERSE_STRAND);
+  }
+
+  /**
+   * {@inheritDoc} This method is 'semi-optimised': it only inspects features
+   * for types that include the specified group, but has to inspect every
+   * feature of those types for matching feature group. This is efficient unless
+   * a sequence has features that share the same type but are in different
+   * groups - an unlikely case.
+   * <p>
+   * For example, if RESNUM feature is created with group = PDBID, then features
+   * would only be retrieved for those sequences associated with the target
+   * PDBID (group).
+   */
+  @Override
+  public List<SequenceFeature> getFeaturesForGroup(boolean positional,
+          String group, String... type)
+  {
+    List<SequenceFeature> result = new ArrayList<>();
+    for (FeatureStore featureSet : varargToTypes(type))
+    {
+      if (featureSet.getFeatureGroups(positional).contains(group))
+      {
+        result.addAll(featureSet.getFeaturesForGroup(positional, group));
+      }
+    }
+    return result;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean shiftFeatures(int shift)
+  {
+    boolean modified = false;
+    for (FeatureStore fs : featureStore.values())
+    {
+      modified |= fs.shiftFeatures(shift);
+    }
+    return modified;
+  }
+}
\ No newline at end of file
diff --git a/src/jalview/datamodel/features/SequenceFeaturesI.java b/src/jalview/datamodel/features/SequenceFeaturesI.java
new file mode 100644 (file)
index 0000000..80c4f9a
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel.features;
+
+import jalview.datamodel.SequenceFeature;
+
+import java.util.List;
+import java.util.Set;
+
+public interface SequenceFeaturesI
+{
+
+  /**
+   * Adds one sequence feature to the store, and returns true, unless the
+   * feature is already contained in the store, in which case this method
+   * returns false. Containment is determined by SequenceFeature.equals()
+   * comparison. Answers false, and does not add the feature, if feature type is
+   * null.
+   * 
+   * @param sf
+   */
+  boolean add(SequenceFeature sf);
+
+  /**
+   * Returns a (possibly empty) list of features, optionally restricted to
+   * specified types, which overlap the given (inclusive) sequence position
+   * range
+   * 
+   * @param from
+   * @param to
+   * @param type
+   * @return
+   */
+  List<SequenceFeature> findFeatures(int from, int to,
+          String... type);
+
+  /**
+   * Answers a list of all features stored, in no particular guaranteed order.
+   * Positional features may optionally be restricted to specified types, but
+   * all non-positional features (if any) are always returned.
+   * <p>
+   * To filter non-positional features by type, use
+   * getNonPositionalFeatures(type).
+   * 
+   * @param type
+   * @return
+   */
+  List<SequenceFeature> getAllFeatures(String... type);
+
+  /**
+   * Answers a list of all positional (or non-positional) features which are in
+   * the specified feature group, optionally restricted to features of specified
+   * types.
+   * 
+   * @param positional
+   *          if true returns positional features, else non-positional features
+   * @param group
+   *          the feature group to be matched (which may be null)
+   * @param type
+   *          optional feature types to filter by
+   * @return
+   */
+  List<SequenceFeature> getFeaturesForGroup(boolean positional,
+          String group, String... type);
+
+  /**
+   * Answers a list of all features stored, whose type either matches one of the
+   * given ontology terms, or is a specialisation of a term in the Sequence
+   * Ontology. Results are returned in no particular guaranteed order.
+   * 
+   * @param ontologyTerm
+   * @return
+   */
+  List<SequenceFeature> getFeaturesByOntology(String... ontologyTerm);
+
+  /**
+   * Answers the number of (positional or non-positional) features, optionally
+   * restricted to specified feature types. Contact features are counted as 1.
+   * 
+   * @param positional
+   * @param type
+   * @return
+   */
+  int getFeatureCount(boolean positional, String... type);
+
+  /**
+   * Answers the total length of positional features, optionally restricted to
+   * specified feature types. Contact features are counted as length 1.
+   * 
+   * @param type
+   * @return
+   */
+  int getTotalFeatureLength(String... type);
+
+  /**
+   * Answers a list of all positional features, optionally restricted to
+   * specified types, in no particular guaranteed order
+   * 
+   * @param type
+   * @return
+   */
+  List<SequenceFeature> getPositionalFeatures(
+          String... type);
+
+  /**
+   * Answers a list of all contact features, optionally restricted to specified
+   * types, in no particular guaranteed order
+   * 
+   * @return
+   */
+  List<SequenceFeature> getContactFeatures(String... type);
+
+  /**
+   * Answers a list of all non-positional features, optionally restricted to
+   * specified types, in no particular guaranteed order
+   * 
+   * @param type
+   *          if no type is specified, all are returned
+   * @return
+   */
+  List<SequenceFeature> getNonPositionalFeatures(
+          String... type);
+
+  /**
+   * Deletes the given feature from the store, returning true if it was found
+   * (and deleted), else false. This method makes no assumption that the feature
+   * is in the 'expected' place in the store, in case it has been modified since
+   * it was added.
+   * 
+   * @param sf
+   */
+  boolean delete(SequenceFeature sf);
+
+  /**
+   * Answers true if this store contains at least one feature, else false
+   * 
+   * @return
+   */
+  boolean hasFeatures();
+
+  /**
+   * Returns a set of the distinct feature groups present in the collection. The
+   * set may include null. The boolean parameter determines whether the groups
+   * for positional or for non-positional features are returned. The optional
+   * type parameter may be used to restrict to groups for specified feature
+   * types.
+   * 
+   * @param positionalFeatures
+   * @param type
+   * @return
+   */
+  Set<String> getFeatureGroups(boolean positionalFeatures,
+          String... type);
+
+  /**
+   * Answers the set of distinct feature types for which there is at least one
+   * feature with one of the given feature group(s). The boolean parameter
+   * determines whether the groups for positional or for non-positional features
+   * are returned.
+   * 
+   * @param positionalFeatures
+   * @param groups
+   * @return
+   */
+  Set<String> getFeatureTypesForGroups(
+          boolean positionalFeatures, String... groups);
+
+  /**
+   * Answers a set of the distinct feature types for which a feature is stored.
+   * The types may optionally be restricted to those which match, or are a
+   * subtype of, given sequence ontology terms
+   * 
+   * @return
+   */
+  Set<String> getFeatureTypes(String... soTerm);
+
+  /**
+   * Answers the minimum score held for positional or non-positional features
+   * for the specified type. This may be Float.NaN if there are no features, or
+   * none has a non-NaN score.
+   * 
+   * @param type
+   * @param positional
+   * @return
+   */
+  float getMinimumScore(String type, boolean positional);
+
+  /**
+   * Answers the maximum score held for positional or non-positional features
+   * for the specified type. This may be Float.NaN if there are no features, or
+   * none has a non-NaN score.
+   * 
+   * @param type
+   * @param positional
+   * @return
+   */
+  float getMaximumScore(String type, boolean positional);
+
+  /**
+   * Adds the shift amount to the start and end of all positional features,
+   * returning true if at least one feature was shifted, else false
+   * 
+   * @param shift
+   */
+  abstract boolean shiftFeatures(int shift);
+}
\ No newline at end of file
index 4d09bdc..bbe6a20 100644 (file)
@@ -191,13 +191,15 @@ public class EmblEntry
       return null;
     }
     dna.setDescription(description);
-    DBRefEntry retrievedref = new DBRefEntry(sourceDb,
-            getSequenceVersion(), accession);
+    DBRefEntry retrievedref = new DBRefEntry(sourceDb, getSequenceVersion(),
+            accession);
     dna.addDBRef(retrievedref);
     // add map to indicate the sequence is a valid coordinate frame for the
     // dbref
-    retrievedref.setMap(new Mapping(null, new int[] { 1, dna.getLength() },
-            new int[] { 1, dna.getLength() }, 1, 1));
+    retrievedref
+            .setMap(new Mapping(null, new int[]
+            { 1, dna.getLength() }, new int[] { 1, dna.getLength() }, 1,
+                    1));
 
     /*
      * transform EMBL Database refs to canonical form
@@ -242,8 +244,8 @@ public class EmblEntry
   {
     if (sequence == null)
     {
-      System.err.println("No sequence was returned for ENA accession "
-              + accession);
+      System.err.println(
+              "No sequence was returned for ENA accession " + accession);
       return null;
     }
     SequenceI dna = new Sequence(sourceDb + "|" + accession,
@@ -267,7 +269,8 @@ public class EmblEntry
    *          helper to match xrefs in already retrieved sequences
    */
   void parseCodingFeature(EmblFeature feature, String sourceDb,
-          SequenceI dna, List<SequenceI> peptides, SequenceIdMatcher matcher)
+          SequenceI dna, List<SequenceI> peptides,
+          SequenceIdMatcher matcher)
   {
     boolean isEmblCdna = sourceDb.equals(DBRefSource.EMBLCDS);
 
@@ -276,7 +279,7 @@ public class EmblEntry
     String translation = null;
     String proteinName = "";
     String proteinId = null;
-    Map<String, String> vals = new Hashtable<String, String>();
+    Map<String, String> vals = new Hashtable<>();
 
     /*
      * codon_start 1/2/3 in EMBL corresponds to phase 0/1/2 in CDS
@@ -296,8 +299,8 @@ public class EmblEntry
         if (qname.equals("translation"))
         {
           // remove all spaces (precompiled String.replaceAll(" ", ""))
-          translation = SPACE_PATTERN.matcher(q.getValues()[0]).replaceAll(
-                  "");
+          translation = SPACE_PATTERN.matcher(q.getValues()[0])
+                  .replaceAll("");
         }
         else if (qname.equals("protein_id"))
         {
@@ -310,8 +313,8 @@ public class EmblEntry
             codonStart = Integer.parseInt(q.getValues()[0].trim());
           } catch (NumberFormatException e)
           {
-            System.err.println("Invalid codon_start in XML for "
-                    + accession + ": " + e.getMessage());
+            System.err.println("Invalid codon_start in XML for " + accession
+                    + ": " + e.getMessage());
           }
         }
         else if (qname.equals("product"))
@@ -348,9 +351,10 @@ public class EmblEntry
       product = matcher.findIdMatch(proteinId);
       if (product == null)
       {
-        product = new Sequence(proteinId, translation, 1, translationLength);
-        product.setDescription(((proteinName.length() == 0) ? "Protein Product from "
-                + sourceDb
+        product = new Sequence(proteinId, translation, 1,
+                translationLength);
+        product.setDescription(((proteinName.length() == 0)
+                ? "Protein Product from " + sourceDb
                 : proteinName));
         peptides.add(product);
         matcher.add(product);
@@ -364,28 +368,30 @@ public class EmblEntry
          * workaround until we handle dna location for CDS sequence
          * e.g. location="X53828.1:60..1058" correctly
          */
-        System.err
-                .println("Implementation Notice: EMBLCDS records not properly supported yet - Making up the CDNA region of this sequence... may be incorrect ("
+        System.err.println(
+                "Implementation Notice: EMBLCDS records not properly supported yet - Making up the CDNA region of this sequence... may be incorrect ("
                         + sourceDb + ":" + getAccession() + ")");
-        if (translationLength * 3 == (1 - codonStart + dna.getSequence().length))
+        int dnaLength = dna.getLength();
+        if (translationLength * 3 == (1 - codonStart + dnaLength))
         {
-          System.err
-                  .println("Not allowing for additional stop codon at end of cDNA fragment... !");
+          System.err.println(
+                  "Not allowing for additional stop codon at end of cDNA fragment... !");
           // this might occur for CDS sequences where no features are marked
           exons = new int[] { dna.getStart() + (codonStart - 1),
               dna.getEnd() };
-          dnaToProteinMapping = new Mapping(product, exons, new int[] { 1,
-              translationLength }, 3, 1);
+          dnaToProteinMapping = new Mapping(product, exons,
+                  new int[]
+                  { 1, translationLength }, 3, 1);
         }
-        if ((translationLength + 1) * 3 == (1 - codonStart + dna
-                .getSequence().length))
+        if ((translationLength + 1) * 3 == (1 - codonStart + dnaLength))
         {
-          System.err
-                  .println("Allowing for additional stop codon at end of cDNA fragment... will probably cause an error in VAMSAs!");
+          System.err.println(
+                  "Allowing for additional stop codon at end of cDNA fragment... will probably cause an error in VAMSAs!");
           exons = new int[] { dna.getStart() + (codonStart - 1),
               dna.getEnd() - 3 };
-          dnaToProteinMapping = new Mapping(product, exons, new int[] { 1,
-              translationLength }, 3, 1);
+          dnaToProteinMapping = new Mapping(product, exons,
+                  new int[]
+                  { 1, translationLength }, 3, 1);
         }
       }
       else
@@ -404,26 +410,32 @@ public class EmblEntry
         else
         {
           // final product length truncation check
-          int[] cdsRanges = adjustForProteinLength(translationLength, exons);
-          dnaToProteinMapping = new Mapping(product, cdsRanges, new int[] {
-              1, translationLength }, 3, 1);
+          int[] cdsRanges = adjustForProteinLength(translationLength,
+                  exons);
+          dnaToProteinMapping = new Mapping(product, cdsRanges,
+                  new int[]
+                  { 1, translationLength }, 3, 1);
           if (product != null)
           {
             /*
              * make xref with mapping from protein to EMBL dna
              */
             DBRefEntry proteinToEmblRef = new DBRefEntry(DBRefSource.EMBL,
-                    getSequenceVersion(), proteinId, new Mapping(
-                            dnaToProteinMapping.getMap().getInverse()));
+                    getSequenceVersion(), proteinId,
+                    new Mapping(dnaToProteinMapping.getMap().getInverse()));
             product.addDBRef(proteinToEmblRef);
 
             /*
              * make xref from protein to EMBLCDS; we assume here that the 
              * CDS sequence version is same as dna sequence (?!)
              */
-            MapList proteinToCdsMapList = new MapList(new int[] { 1,
-                translationLength }, new int[] { 1 + (codonStart - 1),
-                (codonStart - 1) + 3 * translationLength }, 1, 3);
+            MapList proteinToCdsMapList = new MapList(
+                    new int[]
+                    { 1, translationLength },
+                    new int[]
+                    { 1 + (codonStart - 1),
+                        (codonStart - 1) + 3 * translationLength },
+                    1, 3);
             DBRefEntry proteinToEmblCdsRef = new DBRefEntry(
                     DBRefSource.EMBLCDS, getSequenceVersion(), proteinId,
                     new Mapping(proteinToCdsMapList));
@@ -443,13 +455,27 @@ public class EmblEntry
       /*
        * add cds features to dna sequence
        */
-      for (int xint = 0; exons != null && xint < exons.length; xint += 2)
+      String cds = feature.getName(); // "CDS"
+      for (int xint = 0; exons != null && xint < exons.length - 1; xint += 2)
       {
-        SequenceFeature sf = makeCdsFeature(exons, xint, proteinName,
-                proteinId, vals, codonStart);
-        sf.setType(feature.getName()); // "CDS"
+        int exonStart = exons[xint];
+        int exonEnd = exons[xint + 1];
+        int begin = Math.min(exonStart, exonEnd);
+        int end = Math.max(exonStart, exonEnd);
+        int exonNumber = xint / 2 + 1;
+        String desc = String.format("Exon %d for protein '%s' EMBLCDS:%s",
+                exonNumber, proteinName, proteinId);
+
+        SequenceFeature sf = makeCdsFeature(cds, desc, begin, end,
+                sourceDb, vals);
+
         sf.setEnaLocation(feature.getLocation());
-        sf.setFeatureGroup(sourceDb);
+        boolean forwardStrand = exonStart <= exonEnd;
+        sf.setStrand(forwardStrand ? "+" : "-");
+        sf.setPhase(String.valueOf(codonStart - 1));
+        sf.setValue(FeatureProperties.EXONPOS, exonNumber);
+        sf.setValue(FeatureProperties.EXONPRODUCT, proteinName);
+
         dna.addSequenceFeature(sf);
       }
     }
@@ -518,8 +544,8 @@ public class EmblEntry
           // Add converse mapping reference
           if (dnaToProteinMapping != null)
           {
-            Mapping pmap = new Mapping(dna, dnaToProteinMapping.getMap()
-                    .getInverse());
+            Mapping pmap = new Mapping(dna,
+                    dnaToProteinMapping.getMap().getInverse());
             pref = new DBRefEntry(sourceDb, getSequenceVersion(),
                     this.getAccession());
             pref.setMap(pmap);
@@ -543,8 +569,8 @@ public class EmblEntry
       if (proteinToEmblProteinRef == null)
       {
         // assuming CDSPROTEIN sequence version = dna version (?!)
-        proteinToEmblProteinRef = new DBRefEntry(
-                DBRefSource.EMBLCDSProduct, getSequenceVersion(), proteinId);
+        proteinToEmblProteinRef = new DBRefEntry(DBRefSource.EMBLCDSProduct,
+                getSequenceVersion(), proteinId);
       }
       product.addDBRef(proteinToEmblProteinRef);
 
@@ -552,7 +578,8 @@ public class EmblEntry
               && dnaToProteinMapping.getTo() != null)
       {
         DBRefEntry dnaToEmblProteinRef = new DBRefEntry(
-                DBRefSource.EMBLCDSProduct, getSequenceVersion(), proteinId);
+                DBRefSource.EMBLCDSProduct, getSequenceVersion(),
+                proteinId);
         dnaToEmblProteinRef.setMap(dnaToProteinMapping);
         dnaToProteinMapping.setMappedFromId(proteinId);
         dna.addDBRef(dnaToEmblProteinRef);
@@ -563,33 +590,24 @@ public class EmblEntry
   /**
    * Helper method to construct a SequenceFeature for one cds range
    * 
-   * @param exons
-   *          array of cds [start, end, ...] positions
-   * @param exonStartIndex
-   *          offset into the exons array
-   * @param proteinName
-   * @param proteinAccessionId
+   * @param type
+   *          feature type ("CDS")
+   * @param desc
+   *          description
+   * @param begin
+   *          start position
+   * @param end
+   *          end position
+   * @param group
+   *          feature group
    * @param vals
    *          map of 'miscellaneous values' for feature
-   * @param codonStart
-   *          codon start position for CDS (1/2/3, normally 1)
    * @return
    */
-  protected SequenceFeature makeCdsFeature(int[] exons, int exonStartIndex,
-          String proteinName, String proteinAccessionId,
-          Map<String, String> vals, int codonStart)
-  {
-    int exonNumber = exonStartIndex / 2 + 1;
-    SequenceFeature sf = new SequenceFeature();
-    sf.setBegin(Math.min(exons[exonStartIndex], exons[exonStartIndex + 1]));
-    sf.setEnd(Math.max(exons[exonStartIndex], exons[exonStartIndex + 1]));
-    sf.setDescription(String.format("Exon %d for protein '%s' EMBLCDS:%s",
-            exonNumber, proteinName, proteinAccessionId));
-    sf.setPhase(String.valueOf(codonStart - 1));
-    sf.setStrand(exons[exonStartIndex] <= exons[exonStartIndex + 1] ? "+"
-            : "-");
-    sf.setValue(FeatureProperties.EXONPOS, exonNumber);
-    sf.setValue(FeatureProperties.EXONPRODUCT, proteinName);
+  protected SequenceFeature makeCdsFeature(String type, String desc,
+          int begin, int end, String group, Map<String, String> vals)
+  {
+    SequenceFeature sf = new SequenceFeature(type, desc, begin, end, group);
     if (!vals.isEmpty())
     {
       StringBuilder sb = new StringBuilder();
@@ -629,9 +647,9 @@ public class EmblEntry
       return listToArray(ranges);
     } catch (ParseException e)
     {
-      Cache.log.warn(String.format(
-              "Not parsing inexact CDS location %s in ENA %s",
-              feature.location, this.accession));
+      Cache.log.warn(
+              String.format("Not parsing inexact CDS location %s in ENA %s",
+                      feature.location, this.accession));
       return new int[] {};
     }
   }
index 1dd854a..8a32c13 100644 (file)
@@ -121,8 +121,9 @@ public class EmblFile
       try
       {
         // uncomment to DEBUG EMBLFile reading
-        if (jalview.bin.Cache.getDefault(jalview.bin.Cache.CASTORLOGLEVEL,
-                "debug").equalsIgnoreCase("DEBUG"))
+        if (jalview.bin.Cache
+                .getDefault(jalview.bin.Cache.CASTORLOGLEVEL, "debug")
+                .equalsIgnoreCase("DEBUG"))
         {
           unmar.setDebug(jalview.bin.Cache.log.isDebugEnabled());
         }
similarity index 90%
rename from src/jalview/datamodel/UniprotEntry.java
rename to src/jalview/datamodel/xdb/uniprot/UniprotEntry.java
index 4cf0f13..a3537c9 100755 (executable)
@@ -18,7 +18,9 @@
  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
-package jalview.datamodel;
+package jalview.datamodel.xdb.uniprot;
+
+import jalview.datamodel.PDBEntry;
 
 import java.util.Vector;
 
@@ -36,7 +38,7 @@ public class UniprotEntry
 
   Vector<String> accession;
 
-  Vector<SequenceFeature> feature;
+  Vector<UniprotFeature> feature;
 
   Vector<PDBEntry> dbrefs;
 
@@ -47,12 +49,12 @@ public class UniprotEntry
     accession = items;
   }
 
-  public void setFeature(Vector<SequenceFeature> items)
+  public void setFeature(Vector<UniprotFeature> items)
   {
     feature = items;
   }
 
-  public Vector<SequenceFeature> getFeature()
+  public Vector<UniprotFeature> getFeature()
   {
     return feature;
   }
diff --git a/src/jalview/datamodel/xdb/uniprot/UniprotFeature.java b/src/jalview/datamodel/xdb/uniprot/UniprotFeature.java
new file mode 100644 (file)
index 0000000..b1ed275
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel.xdb.uniprot;
+
+/**
+ * A data model class for binding from Uniprot XML via uniprot_mapping.xml
+ */
+public class UniprotFeature
+{
+  private String type;
+
+  private String description;
+
+  private String status;
+
+  private int begin;
+
+  private int end;
+
+  public String getType()
+  {
+    return type;
+  }
+
+  public void setType(String t)
+  {
+    this.type = t;
+  }
+
+  public String getDescription()
+  {
+    return description;
+  }
+
+  public void setDescription(String d)
+  {
+    this.description = d;
+  }
+
+  public String getStatus()
+  {
+    return status;
+  }
+
+  public void setStatus(String s)
+  {
+    this.status = s;
+  }
+
+  public int getBegin()
+  {
+    return begin;
+  }
+
+  public void setBegin(int b)
+  {
+    this.begin = b;
+  }
+
+  public int getEnd()
+  {
+    return end;
+  }
+
+  public void setEnd(int e)
+  {
+    this.end = e;
+  }
+
+  public int getPosition()
+  {
+    return begin;
+  }
+
+  public void setPosition(int p)
+  {
+    this.begin = p;
+    this.end = p;
+  }
+}
similarity index 96%
rename from src/jalview/datamodel/UniprotFile.java
rename to src/jalview/datamodel/xdb/uniprot/UniprotFile.java
index f0e38d8..9cc0391 100755 (executable)
@@ -18,7 +18,7 @@
  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
-package jalview.datamodel;
+package jalview.datamodel.xdb.uniprot;
 
 import java.util.Vector;
 
@@ -18,7 +18,7 @@
  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
-package jalview.datamodel;
+package jalview.datamodel.xdb.uniprot;
 
 import java.util.Vector;
 
similarity index 97%
rename from src/jalview/datamodel/UniprotSequence.java
rename to src/jalview/datamodel/xdb/uniprot/UniprotSequence.java
index 1150f1e..bdba73f 100755 (executable)
@@ -18,7 +18,7 @@
  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
-package jalview.datamodel;
+package jalview.datamodel.xdb.uniprot;
 
 /**
  * Data model for the sequence returned by a Uniprot query
index dc000c6..6d031b7 100644 (file)
@@ -24,6 +24,9 @@ import jalview.datamodel.SequenceFeature;
 import jalview.io.gff.SequenceOntologyFactory;
 import jalview.io.gff.SequenceOntologyI;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import com.stevesoft.pat.Regex;
 
 /**
@@ -44,6 +47,13 @@ public class EnsemblCdna extends EnsemblSeqProxy
   private static final Regex ACCESSION_REGEX = new Regex(
           "(ENS([A-Z]{3}|)[TG][0-9]{11}$)" + "|" + "(CCDS[0-9.]{3,}$)");
 
+  private static Map<String, String> params = new HashMap<String, String>();
+
+  static
+  {
+    params.put("object_type", "transcript");
+  }
+
   /*
    * fetch exon features on genomic sequence (to identify the cdna regions)
    * and cds and variation features (to retain)
@@ -128,4 +138,14 @@ public class EnsemblCdna extends EnsemblSeqProxy
     return false;
   }
 
+  /**
+   * Parameter object_type=cdna added to ensure cdna and not peptide is returned
+   * (JAL-2529)
+   */
+  @Override
+  protected Map<String, String> getAdditionalParameters()
+  {
+    return params;
+  }
+
 }
index 37c787b..50dfa90 100644 (file)
@@ -26,6 +26,7 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
+import jalview.datamodel.features.SequenceFeatures;
 import jalview.io.gff.SequenceOntologyFactory;
 import jalview.io.gff.SequenceOntologyI;
 import jalview.schemes.FeatureColour;
@@ -109,7 +110,8 @@ public class EnsemblGene extends EnsemblSeqProxy
    * <li>resolves an external identifier by looking up xref-ed gene ids</li>
    * <li>fetches the gene sequence</li>
    * <li>fetches features on the sequence</li>
-   * <li>identifies "transcript" features whose Parent is the requested gene</li>
+   * <li>identifies "transcript" features whose Parent is the requested
+   * gene</li>
    * <li>fetches the transcript sequence for each transcript</li>
    * <li>makes a mapping from the gene to each transcript</li>
    * <li>copies features from gene to transcript sequences</li>
@@ -159,8 +161,9 @@ public class EnsemblGene extends EnsemblSeqProxy
   }
 
   /**
-   * Converts a query, which may contain one or more gene or transcript
-   * identifiers, into a non-redundant list of gene identifiers.
+   * Converts a query, which may contain one or more gene, transcript, or
+   * external (to Ensembl) identifiers, into a non-redundant list of gene
+   * identifiers.
    * 
    * @param accessions
    * @return
@@ -171,54 +174,30 @@ public class EnsemblGene extends EnsemblSeqProxy
 
     for (String acc : accessions.split(getAccessionSeparator()))
     {
-      if (isGeneIdentifier(acc))
-      {
-        if (!geneIds.contains(acc))
-        {
-          geneIds.add(acc);
-        }
-      }
-
       /*
-       * if given a transcript id, look up its gene parent
+       * First try lookup as an Ensembl (gene or transcript) identifier
        */
-      else if (isTranscriptIdentifier(acc))
+      String geneId = new EnsemblLookup(getDomain()).getGeneId(acc);
+      if (geneId != null)
       {
-        String geneId = new EnsemblLookup(getDomain()).getParent(acc);
-        if (geneId != null && !geneIds.contains(geneId))
+        if (!geneIds.contains(geneId))
         {
           geneIds.add(geneId);
         }
       }
-      else if (isProteinIdentifier(acc))
-      {
-        String tscriptId = new EnsemblLookup(getDomain()).getParent(acc);
-        if (tscriptId != null)
-        {
-          String geneId = new EnsemblLookup(getDomain())
-                  .getParent(tscriptId);
-
-          if (geneId != null && !geneIds.contains(geneId))
-          {
-            geneIds.add(geneId);
-          }
-        }
-        // NOTE - acc is lost if it resembles an ENS.+ ID but isn't actually
-        // resolving to one... e.g. ENSMICP00000009241
-      }
-      /*
-       * if given a gene or other external name, lookup and fetch 
-       * the corresponding gene for all model organisms 
-       */
       else
       {
+        /*
+         * if given a gene or other external name, lookup and fetch 
+         * the corresponding gene for all model organisms 
+         */
         List<String> ids = new EnsemblSymbol(getDomain(), getDbSource(),
-                getDbVersion()).getIds(acc);
-        for (String geneId : ids)
+                getDbVersion()).getGeneIds(acc);
+        for (String id : ids)
         {
-          if (!geneIds.contains(geneId))
+          if (!geneIds.contains(id))
           {
-            geneIds.add(geneId);
+            geneIds.add(id);
           }
         }
       }
@@ -227,30 +206,6 @@ public class EnsemblGene extends EnsemblSeqProxy
   }
 
   /**
-   * Attempts to get Ensembl stable identifiers for model organisms for a gene
-   * name by calling the xrefs symbol REST service to resolve the gene name.
-   * 
-   * @param query
-   * @return
-   */
-  protected String getGeneIdentifiersForName(String query)
-  {
-    List<String> ids = new EnsemblSymbol(getDomain(), getDbSource(),
-            getDbVersion()).getIds(query);
-    if (ids != null)
-    {
-      for (String id : ids)
-      {
-        if (isGeneIdentifier(id))
-        {
-          return id;
-        }
-      }
-    }
-    return null;
-  }
-
-  /**
    * Constructs all transcripts for the gene, as identified by "transcript"
    * features whose Parent is the requested gene. The coding transcript
    * sequences (i.e. with introns omitted) are added to the alignment.
@@ -282,22 +237,20 @@ public class EnsemblGene extends EnsemblSeqProxy
    */
   protected void clearGeneFeatures(SequenceI gene)
   {
-    SequenceFeature[] sfs = gene.getSequenceFeatures();
-    if (sfs != null)
+    /*
+     * Note we include NMD_transcript_variant here because it behaves like 
+     * 'transcript' in Ensembl, although strictly speaking it is not 
+     * (it is a sub-type of sequence_variant)    
+     */
+    String[] soTerms = new String[] {
+        SequenceOntologyI.NMD_TRANSCRIPT_VARIANT,
+        SequenceOntologyI.TRANSCRIPT, SequenceOntologyI.EXON,
+        SequenceOntologyI.CDS };
+    List<SequenceFeature> sfs = gene.getFeatures().getFeaturesByOntology(
+            soTerms);
+    for (SequenceFeature sf : sfs)
     {
-      SequenceOntologyI so = SequenceOntologyFactory.getInstance();
-      List<SequenceFeature> filtered = new ArrayList<SequenceFeature>();
-      for (SequenceFeature sf : sfs)
-      {
-        String type = sf.getType();
-        if (!isTranscript(type) && !so.isA(type, SequenceOntologyI.EXON)
-                && !so.isA(type, SequenceOntologyI.CDS))
-        {
-          filtered.add(sf);
-        }
-      }
-      gene.setSequenceFeatures(filtered
-              .toArray(new SequenceFeature[filtered.size()]));
+      gene.deleteFeature(sf);
     }
   }
 
@@ -314,8 +267,8 @@ public class EnsemblGene extends EnsemblSeqProxy
    *          the parent gene sequence, with features
    * @return
    */
-  SequenceI makeTranscript(SequenceFeature transcriptFeature,
-          AlignmentI al, SequenceI gene)
+  SequenceI makeTranscript(SequenceFeature transcriptFeature, AlignmentI al,
+          SequenceI gene)
   {
     String accId = getTranscriptId(transcriptFeature);
     if (accId == null)
@@ -347,6 +300,7 @@ public class EnsemblGene extends EnsemblSeqProxy
     {
       splices = findFeatures(gene, SequenceOntologyI.CDS, parentId);
     }
+    SequenceFeatures.sortFeatures(splices, true);
 
     int transcriptLength = 0;
     final char[] geneChars = gene.getSequence();
@@ -363,7 +317,8 @@ public class EnsemblGene extends EnsemblSeqProxy
       mappedFrom.add(new int[] { sf.getBegin(), sf.getEnd() });
     }
 
-    Sequence transcript = new Sequence(accId, seqChars, 1, transcriptLength);
+    Sequence transcript = new Sequence(accId, seqChars, 1,
+            transcriptLength);
 
     /*
      * Ensembl has gene name as transcript Name
@@ -396,7 +351,7 @@ public class EnsemblGene extends EnsemblSeqProxy
     mapTo.add(new int[] { 1, transcriptLength });
     MapList mapping = new MapList(mappedFrom, mapTo, 1, 1);
     EnsemblCdna cdna = new EnsemblCdna(getDomain());
-    cdna.transferFeatures(gene.getSequenceFeatures(),
+    cdna.transferFeatures(gene.getFeatures().getPositionalFeatures(),
             transcript.getDatasetSequence(), mapping, parentId);
 
     /*
@@ -426,6 +381,12 @@ public class EnsemblGene extends EnsemblSeqProxy
   /**
    * Returns a list of the transcript features on the sequence whose Parent is
    * the gene for the accession id.
+   * <p>
+   * Transcript features are those of type "transcript", or any of its sub-types
+   * in the Sequence Ontology e.g. "mRNA", "processed_transcript". We also
+   * include "NMD_transcript_variant", because this type behaves like a
+   * transcript identifier in Ensembl, although strictly speaking it is not in
+   * the SO.
    * 
    * @param accId
    * @param geneSequence
@@ -437,20 +398,18 @@ public class EnsemblGene extends EnsemblSeqProxy
     List<SequenceFeature> transcriptFeatures = new ArrayList<SequenceFeature>();
 
     String parentIdentifier = GENE_PREFIX + accId;
-    SequenceFeature[] sfs = geneSequence.getSequenceFeatures();
 
-    if (sfs != null)
+    List<SequenceFeature> sfs = geneSequence.getFeatures()
+            .getFeaturesByOntology(SequenceOntologyI.TRANSCRIPT);
+    sfs.addAll(geneSequence.getFeatures().getPositionalFeatures(
+            SequenceOntologyI.NMD_TRANSCRIPT_VARIANT));
+
+    for (SequenceFeature sf : sfs)
     {
-      for (SequenceFeature sf : sfs)
+      String parent = (String) sf.getValue(PARENT);
+      if (parentIdentifier.equals(parent))
       {
-        if (isTranscript(sf.getType()))
-        {
-          String parent = (String) sf.getValue(PARENT);
-          if (parentIdentifier.equals(parent))
-          {
-            transcriptFeatures.add(sf);
-          }
-        }
+        transcriptFeatures.add(sf);
       }
     }
 
@@ -567,8 +526,8 @@ public class EnsemblGene extends EnsemblSeqProxy
       @Override
       public boolean isFeatureDisplayed(String type)
       {
-        return (so.isA(type, SequenceOntologyI.EXON) || so.isA(type,
-                SequenceOntologyI.SEQUENCE_VARIANT));
+        return (so.isA(type, SequenceOntologyI.EXON)
+                || so.isA(type, SequenceOntologyI.SEQUENCE_VARIANT));
       }
 
       @Override
index ef46a5b..bbd1f26 100644 (file)
@@ -39,12 +39,6 @@ public class EnsemblGenomes extends EnsemblGene
   }
 
   @Override
-  public boolean isGeneIdentifier(String query)
-  {
-    return true;
-  }
-
-  @Override
   public String getDbName()
   {
     return "EnsemblGenomes";
@@ -53,7 +47,10 @@ public class EnsemblGenomes extends EnsemblGene
   @Override
   public String getTestQuery()
   {
-    return "DDB_G0283883";
+    /*
+     * Salmonella gene, Uniprot Q8Z9G6, EMBLCDS CAD01290
+     */
+    return "CAD01290";
   }
 
   @Override
index 3108194..7668941 100644 (file)
@@ -70,11 +70,6 @@ class EnsemblInfo
   // flag set to true if REST major version is not the one expected
   boolean restMajorVersionMismatch;
 
-  /*
-   * absolute time to wait till if we overloaded the REST service
-   */
-  long retryAfter;
-
   /**
    * Constructor given expected REST version number e.g 4.5 or 3.4.3
    * 
index eb8f90e..31da9c0 100644 (file)
@@ -43,6 +43,13 @@ import org.json.simple.parser.ParseException;
 public class EnsemblLookup extends EnsemblRestClient
 {
 
+  private static final String OBJECT_TYPE_TRANSLATION = "Translation";
+  private static final String PARENT = "Parent";
+  private static final String OBJECT_TYPE_TRANSCRIPT = "Transcript";
+  private static final String ID = "id";
+  private static final String OBJECT_TYPE_GENE = "Gene";
+  private static final String OBJECT_TYPE = "object_type";
+
   /**
    * Default constructor (to use rest.ensembl.org)
    */
@@ -87,7 +94,7 @@ public class EnsemblLookup extends EnsemblRestClient
   protected URL getUrl(String identifier)
   {
     String url = getDomain() + "/lookup/id/" + identifier
-            + "?content-type=application/json";
+            + CONTENT_TYPE_JSON;
     try
     {
       return new URL(url);
@@ -122,7 +129,7 @@ public class EnsemblLookup extends EnsemblRestClient
    * @param identifier
    * @return
    */
-  public String getParent(String identifier)
+  public String getGeneId(String identifier)
   {
     List<String> ids = Arrays.asList(new String[] { identifier });
 
@@ -134,7 +141,7 @@ public class EnsemblLookup extends EnsemblRestClient
       {
         br = getHttpResponse(url, ids);
       }
-      return (parseResponse(br));
+      return br == null ? null : parseResponse(br);
     } catch (IOException e)
     {
       // ignore
@@ -155,8 +162,10 @@ public class EnsemblLookup extends EnsemblRestClient
   }
 
   /**
-   * Parses "Parent" from the JSON response and returns the value, or null if
-   * not found
+   * Parses the JSON response and returns the gene identifier, or null if not
+   * found. If the returned object_type is Gene, returns the id, if Transcript
+   * returns the Parent. If it is Translation (peptide identifier), then the
+   * Parent is the transcript identifier, so we redo the search with this value.
    * 
    * @param br
    * @return
@@ -164,17 +173,42 @@ public class EnsemblLookup extends EnsemblRestClient
    */
   protected String parseResponse(BufferedReader br) throws IOException
   {
-    String parent = null;
+    String geneId = null;
     JSONParser jp = new JSONParser();
     try
     {
       JSONObject val = (JSONObject) jp.parse(br);
-      parent = val.get("Parent").toString();
+      String type = val.get(OBJECT_TYPE).toString();
+      if (OBJECT_TYPE_GENE.equalsIgnoreCase(type))
+      {
+        geneId = val.get(ID).toString();
+      }
+      else if (OBJECT_TYPE_TRANSCRIPT.equalsIgnoreCase(type))
+      {
+        geneId = val.get(PARENT).toString();
+      }
+      else if (OBJECT_TYPE_TRANSLATION.equalsIgnoreCase(type))
+      {
+        String transcriptId = val.get(PARENT).toString();
+        try
+        {
+          geneId = getGeneId(transcriptId);
+        } catch (StackOverflowError e)
+        {
+          /*
+           * unlikely data condition error!
+           */
+          System.err
+                  .println("** Ensembl lookup "
+                          + getUrl(transcriptId).toString()
+                          + " looping on Parent!");
+        }
+      }
     } catch (ParseException e)
     {
       // ignore
     }
-    return parent;
+    return geneId;
   }
 
 }
index 1554a0b..99006aa 100644 (file)
@@ -23,8 +23,6 @@ package jalview.ext.ensembl;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.SequenceFeature;
 
-import java.util.List;
-
 import com.stevesoft.pat.Regex;
 
 /**
index 2437588..b1bc8e5 100644 (file)
@@ -31,6 +31,7 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.net.HttpURLConnection;
 import java.net.MalformedURLException;
+import java.net.ProtocolException;
 import java.net.URL;
 import java.util.HashMap;
 import java.util.List;
@@ -42,8 +43,6 @@ import org.json.simple.JSONArray;
 import org.json.simple.JSONObject;
 import org.json.simple.parser.JSONParser;
 
-import com.stevesoft.pat.Regex;
-
 /**
  * Base class for Ensembl REST service clients
  * 
@@ -55,15 +54,21 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
 
   private static final int CONNECT_TIMEOUT_MS = 10 * 1000; // 10 seconds
 
+  private static final int MAX_RETRIES = 3;
+
+  private static final int HTTP_OK = 200;
+
+  private static final int HTTP_OVERLOAD = 429;
+
   /*
    * update these constants when Jalview has been checked / updated for
    * changes to Ensembl REST API (ref JAL-2105)
    * @see https://github.com/Ensembl/ensembl-rest/wiki/Change-log
    * @see http://rest.ensembl.org/info/rest?content-type=application/json
    */
-  private static final String LATEST_ENSEMBLGENOMES_REST_VERSION = "5.0";
+  private static final String LATEST_ENSEMBLGENOMES_REST_VERSION = "6.0";
 
-  private static final String LATEST_ENSEMBL_REST_VERSION = "5.0";
+  private static final String LATEST_ENSEMBL_REST_VERSION = "6.1";
 
   private static final String REST_CHANGE_LOG = "https://github.com/Ensembl/ensembl-rest/wiki/Change-log";
 
@@ -76,20 +81,13 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
 
   private final static long VERSION_RETEST_INTERVAL = 1000L * 3600; // 1 hr
 
-  private static final Regex PROTEIN_REGEX = new Regex(
-          "(ENS)([A-Z]{3}|)P[0-9]{11}$");
-
-  private static final Regex TRANSCRIPT_REGEX = new Regex(
-          "(ENS)([A-Z]{3}|)T[0-9]{11}$");
-
-  private static final Regex GENE_REGEX = new Regex(
-          "(ENS)([A-Z]{3}|)G[0-9]{11}$");
+  protected static final String CONTENT_TYPE_JSON = "?content-type=application/json";
 
   static
   {
-    domainData = new HashMap<String, EnsemblInfo>();
-    domainData.put(ENSEMBL_REST, new EnsemblInfo(ENSEMBL_REST,
-            LATEST_ENSEMBL_REST_VERSION));
+    domainData = new HashMap<>();
+    domainData.put(ENSEMBL_REST,
+            new EnsemblInfo(ENSEMBL_REST, LATEST_ENSEMBL_REST_VERSION));
     domainData.put(ENSEMBL_GENOMES_REST, new EnsemblInfo(
             ENSEMBL_GENOMES_REST, LATEST_ENSEMBLGENOMES_REST_VERSION));
   }
@@ -114,42 +112,6 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
     setDomain(d);
   }
 
-  /**
-   * Answers true if the query matches the regular expression pattern for an
-   * Ensembl transcript stable identifier
-   * 
-   * @param query
-   * @return
-   */
-  public boolean isTranscriptIdentifier(String query)
-  {
-    return query == null ? false : TRANSCRIPT_REGEX.search(query);
-  }
-
-  /**
-   * Answers true if the query matches the regular expression pattern for an
-   * Ensembl protein stable identifier
-   * 
-   * @param query
-   * @return
-   */
-  public boolean isProteinIdentifier(String query)
-  {
-    return query == null ? false : PROTEIN_REGEX.search(query);
-  }
-
-  /**
-   * Answers true if the query matches the regular expression pattern for an
-   * Ensembl gene stable identifier
-   * 
-   * @param query
-   * @return
-   */
-  public boolean isGeneIdentifier(String query)
-  {
-    return query == null ? false : GENE_REGEX.search(query);
-  }
-
   @Override
   public boolean queryInProgress()
   {
@@ -204,29 +166,33 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
    * @see http://rest.ensembl.org/documentation/info/ping
    * @return
    */
-  private boolean checkEnsembl()
+  boolean checkEnsembl()
   {
     BufferedReader br = null;
     try
     {
       // note this format works for both ensembl and ensemblgenomes
       // info/ping.json works for ensembl only (March 2016)
-      URL ping = new URL(getDomain()
-              + "/info/ping?content-type=application/json");
+      URL ping = new URL(getDomain() + "/info/ping" + CONTENT_TYPE_JSON);
 
       /*
        * expect {"ping":1} if ok
        * if ping takes more than 2 seconds to respond, treat as if unavailable
        */
       br = getHttpResponse(ping, null, 2 * 1000);
+      if (br == null)
+      {
+        // error reponse status
+        return false;
+      }
       JSONParser jp = new JSONParser();
       JSONObject val = (JSONObject) jp.parse(br);
       String pingString = val.get("ping").toString();
       return pingString != null;
     } catch (Throwable t)
     {
-      System.err.println("Error connecting to " + PING_URL + ": "
-              + t.getMessage());
+      System.err.println(
+              "Error connecting to " + PING_URL + ": " + t.getMessage());
     } finally
     {
       if (br != null)
@@ -250,8 +216,7 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
    * @return
    * @throws IOException
    */
-  protected FileParse getSequenceReader(List<String> ids)
-          throws IOException
+  protected FileParse getSequenceReader(List<String> ids) throws IOException
   {
     URL url = getUrl(ids);
 
@@ -261,7 +226,8 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
       // request failed
       return null;
     }
-    FileParse fp = new FileParse(reader, url.toString(), DataSourceType.URL);
+    FileParse fp = new FileParse(reader, url.toString(),
+            DataSourceType.URL);
     return fp;
   }
 
@@ -281,7 +247,7 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
   }
 
   /**
-   * Writes the HTTP request and gets the response as a reader.
+   * Sends the HTTP request and gets the response as a reader
    * 
    * @param url
    * @param ids
@@ -295,7 +261,56 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
   protected BufferedReader getHttpResponse(URL url, List<String> ids,
           int readTimeout) throws IOException
   {
-    // long now = System.currentTimeMillis();
+    int retriesLeft = MAX_RETRIES;
+    HttpURLConnection connection = null;
+    int responseCode = 0;
+
+    while (retriesLeft > 0)
+    {
+      connection = tryConnection(url, ids, readTimeout);
+      responseCode = connection.getResponseCode();
+      if (responseCode == HTTP_OVERLOAD) // 429
+      {
+        retriesLeft--;
+        checkRetryAfter(connection);
+      }
+      else
+      {
+        retriesLeft = 0;
+      }
+    }
+    if (responseCode != HTTP_OK) // 200
+    {
+      /*
+       * note: a GET request for an invalid id returns an error code e.g. 415
+       * but POST request returns 200 and an empty Fasta response 
+       */
+      System.err.println("Response code " + responseCode + " for " + url);
+      return null;
+    }
+
+    InputStream response = connection.getInputStream();
+
+    // System.out.println(getClass().getName() + " took "
+    // + (System.currentTimeMillis() - now) + "ms to fetch");
+
+    BufferedReader reader = null;
+    reader = new BufferedReader(new InputStreamReader(response, "UTF-8"));
+    return reader;
+  }
+
+  /**
+   * @param url
+   * @param ids
+   * @param readTimeout
+   * @return
+   * @throws IOException
+   * @throws ProtocolException
+   */
+  protected HttpURLConnection tryConnection(URL url, List<String> ids,
+          int readTimeout) throws IOException, ProtocolException
+  {
+    // System.out.println(System.currentTimeMillis() + " " + url);
     HttpURLConnection connection = (HttpURLConnection) url.openConnection();
 
     /*
@@ -303,8 +318,8 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
      * sequence queries, but not for overlap
      */
     boolean multipleIds = ids != null && ids.size() > 1;
-    connection.setRequestMethod(multipleIds ? HttpMethod.POST
-            : HttpMethod.GET);
+    connection.setRequestMethod(
+            multipleIds ? HttpMethod.POST : HttpMethod.GET);
     connection.setRequestProperty("Content-Type",
             getRequestMimeType(multipleIds));
     connection.setRequestProperty("Accept", getResponseMimeType());
@@ -320,77 +335,40 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
     {
       writePostBody(connection, ids);
     }
-
-    int responseCode = connection.getResponseCode();
-
-    if (responseCode != 200)
-    {
-      /*
-       * note: a GET request for an invalid id returns an error code e.g. 415
-       * but POST request returns 200 and an empty Fasta response 
-       */
-      System.err.println("Response code " + responseCode + " for " + url);
-      return null;
-    }
-    // get content
-    InputStream response = connection.getInputStream();
-
-    // System.out.println(getClass().getName() + " took "
-    // + (System.currentTimeMillis() - now) + "ms to fetch");
-
-    checkRateLimits(connection);
-
-    BufferedReader reader = null;
-    reader = new BufferedReader(new InputStreamReader(response, "UTF-8"));
-    return reader;
+    return connection;
   }
 
   /**
-   * Inspect response headers for any sign of server overload and respect any
-   * 'retry-after' directive
+   * Inspects response headers for a 'retry-after' directive, and waits for the
+   * directed period (if less than 10 seconds)
    * 
    * @see https://github.com/Ensembl/ensembl-rest/wiki/Rate-Limits
    * @param connection
    */
-  void checkRateLimits(HttpURLConnection connection)
+  void checkRetryAfter(HttpURLConnection connection)
   {
-    // number of requests allowed per time interval:
-    String limit = connection.getHeaderField("X-RateLimit-Limit");
-    // length of quota time interval in seconds:
-    // String period = connection.getHeaderField("X-RateLimit-Period");
-    // seconds remaining until usage quota is reset:
-    String reset = connection.getHeaderField("X-RateLimit-Reset");
-    // number of requests remaining from quota for current period:
-    String remaining = connection.getHeaderField("X-RateLimit-Remaining");
-    // number of seconds to wait before retrying (if remaining == 0)
     String retryDelay = connection.getHeaderField("Retry-After");
 
     // to test:
     // retryDelay = "5";
 
-    EnsemblInfo info = domainData.get(getDomain());
     if (retryDelay != null)
     {
-      System.err.println("Ensembl REST service rate limit exceeded, wait "
-              + retryDelay + " seconds before retrying");
       try
       {
-        info.retryAfter = System.currentTimeMillis()
-                + (1000 * Integer.valueOf(retryDelay));
-      } catch (NumberFormatException e)
+        int retrySecs = Integer.valueOf(retryDelay);
+        if (retrySecs > 0 && retrySecs < 10)
+        {
+          System.err
+                  .println("Ensembl REST service rate limit exceeded, waiting "
+                          + retryDelay + " seconds before retrying");
+          Thread.sleep(1000 * retrySecs);
+        }
+      } catch (NumberFormatException | InterruptedException e)
       {
-        System.err.println("Unexpected value for Retry-After: "
-                + retryDelay);
+        System.err.println("Error handling Retry-After: " + e.getMessage());
       }
     }
-    else
-    {
-      info.retryAfter = 0;
-      // debug:
-      // System.out.println(String.format(
-      // "%s Ensembl requests remaining of %s (reset in %ss)",
-      // remaining, limit, reset));
-    }
   }
 
   /**
@@ -408,23 +386,10 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
     long now = System.currentTimeMillis();
 
     /*
-     * check if we are waiting for 'Retry-After' to expire
-     */
-    if (info.retryAfter > now)
-    {
-      System.err.println("Still " + (1 + (info.retryAfter - now) / 1000)
-              + " secs to wait before retrying Ensembl");
-      return false;
-    }
-    else
-    {
-      info.retryAfter = 0;
-    }
-
-    /*
      * recheck if Ensembl is up if it was down, or the recheck period has elapsed
      */
-    boolean retestAvailability = (now - info.lastAvailableCheckTime) > AVAILABILITY_RETEST_INTERVAL;
+    boolean retestAvailability = (now
+            - info.lastAvailableCheckTime) > AVAILABILITY_RETEST_INTERVAL;
     if (!info.restAvailable || retestAvailability)
     {
       info.restAvailable = checkEnsembl();
@@ -434,7 +399,8 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
     /*
      * refetch Ensembl versions if the recheck period has elapsed
      */
-    boolean refetchVersion = (now - info.lastVersionCheckTime) > VERSION_RETEST_INTERVAL;
+    boolean refetchVersion = (now
+            - info.lastVersionCheckTime) > VERSION_RETEST_INTERVAL;
     if (refetchVersion)
     {
       checkEnsemblRestVersion();
@@ -475,7 +441,8 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
     byte[] thepostbody = postBody.toString().getBytes();
     connection.setRequestProperty("Content-Length",
             Integer.toString(thepostbody.length));
-    DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
+    DataOutputStream wr = new DataOutputStream(
+            connection.getOutputStream());
     wr.write(thepostbody);
     wr.flush();
     wr.close();
@@ -494,9 +461,12 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
     URL url = null;
     try
     {
-      url = new URL(getDomain()
-              + "/info/rest?content-type=application/json");
+      url = new URL(getDomain() + "/info/rest" + CONTENT_TYPE_JSON);
       BufferedReader br = getHttpResponse(url, null);
+      if (br == null)
+      {
+        return;
+      }
       JSONObject val = (JSONObject) jp.parse(br);
       String version = val.get("release").toString();
       String majorVersion = version.substring(0, version.indexOf("."));
@@ -525,20 +495,19 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
        * if so warn; we don't worry if it is earlier (this indicates Jalview has
        * been tested in advance against the next pending REST version)
        */
-      boolean laterVersion = StringUtils.compareVersions(version, expected) == 1;
+      boolean laterVersion = StringUtils.compareVersions(version,
+              expected) == 1;
       if (laterVersion)
       {
-        System.err
-                .println(String
-                        .format("EnsemblRestClient expected %s REST version %s but found %s, see %s",
-                                getDbSource(), expected, version,
-                                REST_CHANGE_LOG));
+        System.err.println(String.format(
+                "EnsemblRestClient expected %s REST version %s but found %s, see %s",
+                getDbSource(), expected, version, REST_CHANGE_LOG));
       }
       info.restVersion = version;
     } catch (Throwable t)
     {
-      System.err.println("Error checking Ensembl REST version: "
-              + t.getMessage());
+      System.err.println(
+              "Error checking Ensembl REST version: " + t.getMessage());
     }
   }
 
@@ -556,18 +525,35 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
   {
     JSONParser jp = new JSONParser();
     URL url = null;
+    BufferedReader br = null;
+
     try
     {
-      url = new URL(getDomain()
-              + "/info/data?content-type=application/json");
-      BufferedReader br = getHttpResponse(url, null);
-      JSONObject val = (JSONObject) jp.parse(br);
-      JSONArray versions = (JSONArray) val.get("releases");
-      domainData.get(getDomain()).dataVersion = versions.get(0).toString();
+      url = new URL(getDomain() + "/info/data" + CONTENT_TYPE_JSON);
+      br = getHttpResponse(url, null);
+      if (br != null)
+      {
+        JSONObject val = (JSONObject) jp.parse(br);
+        JSONArray versions = (JSONArray) val.get("releases");
+        domainData.get(getDomain()).dataVersion = versions.get(0)
+                .toString();
+      }
     } catch (Throwable t)
     {
-      System.err.println("Error checking Ensembl data version: "
-              + t.getMessage());
+      System.err.println(
+              "Error checking Ensembl data version: " + t.getMessage());
+    } finally
+    {
+      if (br != null)
+      {
+        try
+        {
+          br.close();
+        } catch (IOException e)
+        {
+          // ignore
+        }
+      }
     }
   }
 
index 233707b..577111e 100644 (file)
@@ -30,6 +30,7 @@ import jalview.datamodel.DBRefSource;
 import jalview.datamodel.Mapping;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
+import jalview.datamodel.features.SequenceFeatures;
 import jalview.exceptions.JalviewException;
 import jalview.io.FastaFile;
 import jalview.io.FileParse;
@@ -37,8 +38,8 @@ import jalview.io.gff.SequenceOntologyFactory;
 import jalview.io.gff.SequenceOntologyI;
 import jalview.util.Comparison;
 import jalview.util.DBRefUtils;
+import jalview.util.IntRangeComparator;
 import jalview.util.MapList;
-import jalview.util.RangeComparator;
 
 import java.io.IOException;
 import java.net.MalformedURLException;
@@ -46,8 +47,9 @@ import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 
 /**
  * Base class for Ensembl sequence fetchers
@@ -137,8 +139,8 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
 
     // danger: accession separator used as a regex here, a string elsewhere
     // in this case it is ok (it is just a space), but (e.g.) '\' would not be
-    List<String> allIds = Arrays.asList(query
-            .split(getAccessionSeparator()));
+    List<String> allIds = Arrays
+            .asList(query.split(getAccessionSeparator()));
     AlignmentI alignment = null;
     inProgress = true;
 
@@ -236,8 +238,8 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
       }
     } catch (IOException e)
     {
-      System.err.println("Error transferring Ensembl features: "
-              + e.getMessage());
+      System.err.println(
+              "Error transferring Ensembl features: " + e.getMessage());
     }
   }
 
@@ -275,8 +277,8 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
       proteinSeq.createDatasetSequence();
       querySeq.createDatasetSequence();
 
-      MapList mapList = AlignmentUtils
-              .mapCdsToProtein(querySeq, proteinSeq);
+      MapList mapList = AlignmentUtils.mapCdsToProtein(querySeq,
+              proteinSeq);
       if (mapList != null)
       {
         // clunky: ensure Uniprot xref if we have one is on mapped sequence
@@ -287,9 +289,11 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
                 getEnsemblDataVersion(), proteinSeq.getName(), map);
         querySeq.getDatasetSequence().addDBRef(dbr);
         DBRefEntry[] uprots = DBRefUtils.selectRefs(ds.getDBRefs(),
-                new String[] { DBRefSource.UNIPROT });
+                new String[]
+                { DBRefSource.UNIPROT });
         DBRefEntry[] upxrefs = DBRefUtils.selectRefs(querySeq.getDBRefs(),
-                new String[] { DBRefSource.UNIPROT });
+                new String[]
+                { DBRefSource.UNIPROT });
         if (uprots != null)
         {
           for (DBRefEntry up : uprots)
@@ -304,8 +308,8 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
 
               if (upx.size() > 1)
               {
-                Cache.log
-                        .warn("Implementation issue - multiple uniprot acc on product sequence.");
+                Cache.log.warn(
+                        "Implementation issue - multiple uniprot acc on product sequence.");
               }
             }
             else
@@ -330,8 +334,8 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
          * copy exon features to protein, compute peptide variants from dna 
          * variants and add as features on the protein sequence ta-da
          */
-        AlignmentUtils
-                .computeProteinFeatures(querySeq, proteinSeq, mapList);
+        AlignmentUtils.computeProteinFeatures(querySeq, proteinSeq,
+                mapList);
       }
     } catch (Exception e)
     {
@@ -364,8 +368,8 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
     /*
      * and add a reference to itself
      */
-    DBRefEntry self = new DBRefEntry(getDbSource(),
-            getEnsemblDataVersion(), seq.getName());
+    DBRefEntry self = new DBRefEntry(getDbSource(), getEnsemblDataVersion(),
+            seq.getName());
     seq.addDBRef(self);
   }
 
@@ -379,8 +383,8 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
    * @throws JalviewException
    * @throws IOException
    */
-  protected AlignmentI fetchSequences(List<String> ids, AlignmentI alignment)
-          throws JalviewException, IOException
+  protected AlignmentI fetchSequences(List<String> ids,
+          AlignmentI alignment) throws JalviewException, IOException
   {
     if (!isEnsemblAvailable())
     {
@@ -396,15 +400,15 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
     FastaFile fr = new FastaFile(fp);
     if (fr.hasWarningMessage())
     {
-      System.out.println(String.format(
-              "Warning when retrieving %d ids %s\n%s", ids.size(),
-              ids.toString(), fr.getWarningMessage()));
+      System.out.println(
+              String.format("Warning when retrieving %d ids %s\n%s",
+                      ids.size(), ids.toString(), fr.getWarningMessage()));
     }
     else if (fr.getSeqs().size() != ids.size())
     {
       System.out.println(String.format(
-              "Only retrieved %d sequences for %d query strings", fr
-                      .getSeqs().size(), ids.size()));
+              "Only retrieved %d sequences for %d query strings",
+              fr.getSeqs().size(), ids.size()));
     }
 
     if (fr.getSeqs().size() == 1 && fr.getSeqs().get(0).getLength() == 0)
@@ -468,11 +472,31 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
     urlstring.append("?type=").append(getSourceEnsemblType().getType());
     urlstring.append(("&Accept=text/x-fasta"));
 
+    Map<String, String> params = getAdditionalParameters();
+    if (params != null)
+    {
+      for (Entry<String, String> entry : params.entrySet())
+      {
+        urlstring.append("&").append(entry.getKey()).append("=")
+                .append(entry.getValue());
+      }
+    }
+
     URL url = new URL(urlstring.toString());
     return url;
   }
 
   /**
+   * Override this method to add any additional x=y URL parameters needed
+   * 
+   * @return
+   */
+  protected Map<String, String> getAdditionalParameters()
+  {
+    return null;
+  }
+
+  /**
    * A sequence/id POST request currently allows up to 50 queries
    * 
    * @see http://rest.ensembl.org/documentation/info/sequence_id_post
@@ -536,8 +560,10 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
   protected MapList getGenomicRangesFromFeatures(SequenceI sourceSequence,
           String accId, int start)
   {
-    SequenceFeature[] sfs = sourceSequence.getSequenceFeatures();
-    if (sfs == null)
+    // SequenceFeature[] sfs = sourceSequence.getSequenceFeatures();
+    List<SequenceFeature> sfs = sourceSequence.getFeatures()
+            .getPositionalFeatures();
+    if (sfs.isEmpty())
     {
       return null;
     }
@@ -565,8 +591,8 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
         if (directionSet && strand != direction)
         {
           // abort - mix of forward and backward
-          System.err.println("Error: forward and backward strand for "
-                  + accId);
+          System.err.println(
+                  "Error: forward and backward strand for " + accId);
           return null;
         }
         direction = strand;
@@ -607,10 +633,12 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
      * a final sort is needed since Ensembl returns CDS sorted within source
      * (havana / ensembl_havana)
      */
-    Collections.sort(regions, new RangeComparator(direction == 1));
+    Collections.sort(regions, direction == 1 ? IntRangeComparator.ASCENDING
+            : IntRangeComparator.DESCENDING);
 
-    List<int[]> to = Arrays.asList(new int[] { start,
-        start + mappedLength - 1 });
+    List<int[]> to = Arrays
+            .asList(new int[]
+            { start, start + mappedLength - 1 });
 
     return new MapList(regions, to, 1, 1);
   }
@@ -658,22 +686,23 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
 
     if (mappedRange != null)
     {
-      SequenceFeature copy = new SequenceFeature(sf);
-      copy.setBegin(Math.min(mappedRange[0], mappedRange[1]));
-      copy.setEnd(Math.max(mappedRange[0], mappedRange[1]));
-      if (".".equals(copy.getFeatureGroup()))
+      String group = sf.getFeatureGroup();
+      if (".".equals(group))
       {
-        copy.setFeatureGroup(getDbSource());
+        group = getDbSource();
       }
+      int newBegin = Math.min(mappedRange[0], mappedRange[1]);
+      int newEnd = Math.max(mappedRange[0], mappedRange[1]);
+      SequenceFeature copy = new SequenceFeature(sf, newBegin, newEnd,
+              group, sf.getScore());
       targetSequence.addSequenceFeature(copy);
 
       /*
        * for sequence_variant on reverse strand, have to convert the allele
        * values to their complements
        */
-      if (!forwardStrand
-              && SequenceOntologyFactory.getInstance().isA(sf.getType(),
-                      SequenceOntologyI.SEQUENCE_VARIANT))
+      if (!forwardStrand && SequenceOntologyFactory.getInstance()
+              .isA(sf.getType(), SequenceOntologyI.SEQUENCE_VARIANT))
       {
         reverseComplementAlleles(copy);
       }
@@ -763,8 +792,9 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
       return false;
     }
 
-    // long start = System.currentTimeMillis();
-    SequenceFeature[] sfs = sourceSequence.getSequenceFeatures();
+//    long start = System.currentTimeMillis();
+    List<SequenceFeature> sfs = sourceSequence.getFeatures()
+            .getPositionalFeatures();
     MapList mapping = getGenomicRangesFromFeatures(sourceSequence,
             accessionId, targetSequence.getStart());
     if (mapping == null)
@@ -774,10 +804,10 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
 
     boolean result = transferFeatures(sfs, targetSequence, mapping,
             accessionId);
-    // System.out.println("transferFeatures (" + (sfs.length) + " --> "
-    // + targetSequence.getSequenceFeatures().length + ") to "
-    // + targetSequence.getName()
-    // + " took " + (System.currentTimeMillis() - start) + "ms");
+//    System.out.println("transferFeatures (" + (sfs.size()) + " --> "
+//            + targetSequence.getFeatures().getFeatureCount(true) + ") to "
+//            + targetSequence.getName() + " took "
+//            + (System.currentTimeMillis() - start) + "ms");
     return result;
   }
 
@@ -786,13 +816,13 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
    * converted using the mapping. Features which do not overlap are ignored.
    * Features whose parent is not the specified identifier are also ignored.
    * 
-   * @param features
+   * @param sfs
    * @param targetSequence
    * @param mapping
    * @param parentId
    * @return
    */
-  protected boolean transferFeatures(SequenceFeature[] features,
+  protected boolean transferFeatures(List<SequenceFeature> sfs,
           SequenceI targetSequence, MapList mapping, String parentId)
   {
     final boolean forwardStrand = mapping.isFromForwardStrand();
@@ -802,10 +832,10 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
      * position descending if reverse strand) so as to add them in
      * 'forwards' order to the target sequence
      */
-    sortFeatures(features, forwardStrand);
+    SequenceFeatures.sortFeatures(sfs, forwardStrand);
 
     boolean transferred = false;
-    for (SequenceFeature sf : features)
+    for (SequenceFeature sf : sfs)
     {
       if (retainFeature(sf, parentId))
       {
@@ -817,33 +847,6 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
   }
 
   /**
-   * Sort features by start position ascending (if on forward strand), or end
-   * position descending (if on reverse strand)
-   * 
-   * @param features
-   * @param forwardStrand
-   */
-  protected static void sortFeatures(SequenceFeature[] features,
-          final boolean forwardStrand)
-  {
-    Arrays.sort(features, new Comparator<SequenceFeature>()
-    {
-      @Override
-      public int compare(SequenceFeature o1, SequenceFeature o2)
-      {
-        if (forwardStrand)
-        {
-          return Integer.compare(o1.getBegin(), o2.getBegin());
-        }
-        else
-        {
-          return Integer.compare(o2.getEnd(), o1.getEnd());
-        }
-      }
-    });
-  }
-
-  /**
    * Answers true if the feature type is one we want to keep for the sequence.
    * Some features are only retrieved in order to identify the sequence range,
    * and may then be discarded as redundant information (e.g. "CDS" feature for
@@ -885,35 +888,30 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
 
   /**
    * Returns a (possibly empty) list of features on the sequence which have the
-   * specified sequence ontology type (or a sub-type of it), and the given
+   * specified sequence ontology term (or a sub-type of it), and the given
    * identifier as parent
    * 
    * @param sequence
-   * @param type
+   * @param term
    * @param parentId
    * @return
    */
   protected List<SequenceFeature> findFeatures(SequenceI sequence,
-          String type, String parentId)
+          String term, String parentId)
   {
     List<SequenceFeature> result = new ArrayList<SequenceFeature>();
 
-    SequenceFeature[] sfs = sequence.getSequenceFeatures();
-    if (sfs != null)
+    List<SequenceFeature> sfs = sequence.getFeatures()
+            .getFeaturesByOntology(term);
+    for (SequenceFeature sf : sfs)
     {
-      SequenceOntologyI so = SequenceOntologyFactory.getInstance();
-      for (SequenceFeature sf : sfs)
+      String parent = (String) sf.getValue(PARENT);
+      if (parent != null && parent.equals(parentId))
       {
-        if (so.isA(sf.getType(), type))
-        {
-          String parent = (String) sf.getValue(PARENT);
-          if (parent.equals(parentId))
-          {
-            result.add(sf);
-          }
-        }
+        result.add(sf);
       }
     }
+
     return result;
   }
 
index bd6335a..598dba1 100644 (file)
@@ -38,7 +38,8 @@ abstract class EnsemblSequenceFetcher extends DbSourceProxyImpl
    * or CCDSnnnnn.nn with at least 3 digits
    */
   private static final Regex ACCESSION_REGEX = new Regex(
-          "(ENS([A-Z]{3}|)[GTEP]{1}[0-9]{11}$)" + "|" + "(CCDS[0-9.]{3,}$)");
+          "(ENS([A-Z]{3}|)[GTEP]{1}[0-9]{11}$)" + "|"
+                  + "(CCDS[0-9.]{3,}$)");
 
   protected static final String ENSEMBL_GENOMES_REST = "http://rest.ensemblgenomes.org";
 
index 0d79864..75598a0 100644 (file)
@@ -42,6 +42,10 @@ import org.json.simple.parser.ParseException;
  */
 public class EnsemblSymbol extends EnsemblXref
 {
+  private static final String GENE = "gene";
+  private static final String TYPE = "type";
+  private static final String ID = "id";
+
   /**
    * Constructor given the target domain to fetch data from
    * 
@@ -62,8 +66,7 @@ public class EnsemblSymbol extends EnsemblXref
    * @return
    * @throws IOException
    */
-  protected String parseSymbolResponse(BufferedReader br)
-          throws IOException
+  protected String parseSymbolResponse(BufferedReader br) throws IOException
   {
     JSONParser jp = new JSONParser();
     String result = null;
@@ -74,8 +77,9 @@ public class EnsemblSymbol extends EnsemblXref
       while (rvals.hasNext())
       {
         JSONObject val = (JSONObject) rvals.next();
-        String id = val.get("id").toString();
-        if (id != null && isGeneIdentifier(id))
+        String id = val.get(ID).toString();
+        String type = val.get(TYPE).toString();
+        if (id != null && GENE.equals(type))
         {
           result = id;
           break;
@@ -88,12 +92,31 @@ public class EnsemblSymbol extends EnsemblXref
     return result;
   }
 
-  protected URL getUrl(String id, Species species)
+  /**
+   * Constructs the URL for the REST symbol endpoint
+   * 
+   * @param id
+   *          the accession id (Ensembl or external)
+   * @param species
+   *          a species name recognisable by Ensembl
+   * @param type
+   *          an optional type to filter the response (gene, transcript,
+   *          translation)
+   * @return
+   */
+  protected URL getUrl(String id, Species species, String... type)
   {
-    String url = getDomain() + "/xrefs/symbol/" + species.toString() + "/"
-            + id + "?content-type=application/json";
+    StringBuilder sb = new StringBuilder();
+    sb.append(getDomain()).append("/xrefs/symbol/")
+            .append(species.toString()).append("/").append(id)
+            .append(CONTENT_TYPE_JSON);
+    for (String t : type)
+    {
+      sb.append("&object_type=").append(t);
+    }
     try
     {
+      String url = sb.toString();
       return new URL(url);
     } catch (MalformedURLException e)
     {
@@ -108,7 +131,7 @@ public class EnsemblSymbol extends EnsemblXref
    * @param identifier
    * @return
    */
-  public List<String> getIds(String identifier)
+  public List<String> getGeneIds(String identifier)
   {
     List<String> result = new ArrayList<String>();
     List<String> ids = new ArrayList<String>();
@@ -120,19 +143,20 @@ public class EnsemblSymbol extends EnsemblXref
     {
       for (String query : queries)
       {
-        for (Species taxon : Species.values())
+        for (Species taxon : Species.getModelOrganisms())
         {
-          if (taxon.isModelOrganism())
+          URL url = getUrl(query, taxon, GENE);
+          if (url != null)
           {
-            URL url = getUrl(query, taxon);
-            if (url != null)
-            {
-              br = getHttpResponse(url, ids);
-            }
-            String geneId = parseSymbolResponse(br);
-            if (geneId != null)
+            br = getHttpResponse(url, ids);
+            if (br != null)
             {
-              result.add(geneId);
+              String geneId = parseSymbolResponse(br);
+              System.out.println(url + " returned " + geneId);
+              if (geneId != null && !result.contains(geneId))
+              {
+                result.add(geneId);
+              }
             }
           }
         }
index c0b00b1..27c448e 100644 (file)
@@ -124,8 +124,11 @@ class EnsemblXref extends EnsemblRestClient
       if (url != null)
       {
         br = getHttpResponse(url, ids);
+        if (br != null)
+        {
+          result = parseResponse(br);
+        }
       }
-      return (parseResponse(br));
     } catch (IOException e)
     {
       // ignore
@@ -168,16 +171,13 @@ class EnsemblXref extends EnsemblRestClient
       while (rvals.hasNext())
       {
         JSONObject val = (JSONObject) rvals.next();
-        String dbName = val.get("dbname").toString();
-        if (dbName.equals(GO_GENE_ONTOLOGY))
-        {
-          continue;
-        }
+        String db = val.get("dbname").toString();
         String id = val.get("primary_id").toString();
-        if (dbName != null && id != null)
+        if (db != null && id != null
+                && !GO_GENE_ONTOLOGY.equals(db))
         {
-          dbName = DBRefUtils.getCanonicalName(dbName);
-          DBRefEntry dbref = new DBRefEntry(dbName, getXRefVersion(), id);
+          db = DBRefUtils.getCanonicalName(db);
+          DBRefEntry dbref = new DBRefEntry(db, getXRefVersion(), id);
           result.add(dbref);
         }
       }
@@ -211,7 +211,7 @@ class EnsemblXref extends EnsemblRestClient
   protected URL getUrl(String identifier)
   {
     String url = getDomain() + "/xrefs/id/" + identifier
-            + "?content-type=application/json&all_levels=1";
+            + CONTENT_TYPE_JSON + "&all_levels=1";
     try
     {
       return new URL(url);
index 350d0d5..cc5465e 100644 (file)
@@ -20,6 +20,9 @@
  */
 package jalview.ext.ensembl;
 
+import java.util.HashSet;
+import java.util.Set;
+
 /**
  * Selected species identifiers used by Ensembl
  * 
@@ -34,10 +37,22 @@ enum Species
    */
   human(true), mouse(true), s_cerevisiae(true), cow(false), pig(false),
   rat(true), celegans(true), sheep(false), horse(false), gorilla(false),
-  rabbit(false), gibbon(false), dog(false), orangutan(false),
-  xenopus(true), chimpanzee(false), cat(false), zebrafish(true), chicken(
-          true), dmelanogaster(true);
+  rabbit(false), gibbon(false), dog(false), orangutan(false), xenopus(true),
+  chimpanzee(false), cat(false), zebrafish(true), chicken(true),
+  dmelanogaster(true);
+
+  static Set<Species> modelOrganisms = new HashSet<>();
 
+  static
+  {
+    for (Species s : values())
+    {
+      if (s.isModelOrganism())
+      {
+        modelOrganisms.add(s);
+      }
+    }
+  }
   boolean modelOrganism;
 
   private Species(boolean model)
@@ -49,4 +64,9 @@ enum Species
   {
     return modelOrganism;
   }
+
+  public static Set<Species> getModelOrganisms()
+  {
+    return modelOrganisms;
+  }
 }
index 4357abd..37ce625 100644 (file)
@@ -70,8 +70,8 @@ public class HtsContigDb
       return;
     }
 
-    refFile = ReferenceSequenceFileFactory.getReferenceSequenceFile(
-            dbLocation, true);
+    refFile = ReferenceSequenceFileFactory
+            .getReferenceSequenceFile(dbLocation, true);
     if (refFile == null || refFile.getSequenceDictionary() == null)
     {
       // refFile = initSequenceDictionaryFor(dbLocation);
@@ -144,7 +144,8 @@ public class HtsContigDb
     ReferenceSequence refSeq;
     List<SAMSequenceRecord> ret = new ArrayList<SAMSequenceRecord>();
     Set<String> sequenceNames = new HashSet<String>();
-    for (int numSequences = 0; (refSeq = refSeqFile.nextSequence()) != null; ++numSequences)
+    for (int numSequences = 0; (refSeq = refSeqFile
+            .nextSequence()) != null; ++numSequences)
     {
       if (sequenceNames.contains(refSeq.getName()))
       {
index 5de554b..41bc116 100644 (file)
@@ -27,6 +27,7 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SequenceI;
+import jalview.gui.IProgressIndicator;
 import jalview.io.DataSourceType;
 import jalview.io.StructureFile;
 import jalview.schemes.ColourSchemeI;
@@ -72,7 +73,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
    */
   private boolean associateNewStructs = false;
 
-  Vector<String> atomsPicked = new Vector<String>();
+  Vector<String> atomsPicked = new Vector<>();
 
   private List<String> chainNames;
 
@@ -225,8 +226,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
           HiddenColumns hiddenCols)
   {
     superposeStructures(new AlignmentI[] { alignment },
-            new int[] { refStructure },
- new HiddenColumns[] { hiddenCols });
+            new int[]
+            { refStructure }, new HiddenColumns[] { hiddenCols });
   }
 
   /**
@@ -279,18 +280,16 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
       int refStructure = _refStructure[a];
       AlignmentI alignment = _alignment[a];
       HiddenColumns hiddenCols = _hiddenCols[a];
-      if (a > 0
-              && selectioncom.length() > 0
-              && !selectioncom.substring(selectioncom.length() - 1).equals(
-                      "|"))
+      if (a > 0 && selectioncom.length() > 0 && !selectioncom
+              .substring(selectioncom.length() - 1).equals("|"))
       {
         selectioncom.append("|");
       }
       // process this alignment
       if (refStructure >= files.length)
       {
-        System.err.println("Invalid reference structure value "
-                + refStructure);
+        System.err.println(
+                "Invalid reference structure value " + refStructure);
         refStructure = -1;
       }
 
@@ -332,8 +331,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
       int nmatched = matched.cardinality();
       if (nmatched < 4)
       {
-        return (MessageManager.formatMessage(
-"label.insufficient_residues",
+        return (MessageManager.formatMessage("label.insufficient_residues",
                 nmatched));
       }
 
@@ -429,7 +427,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
         command.append(".1} {");
         command.append(Integer.toString(1 + refStructure));
         // conformation=1 excludes alternate locations for CA (JAL-1757)
-        command.append(".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
+        command.append(
+                ".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
 
         // for (int s = 0; s < 2; s++)
         // {
@@ -461,7 +460,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
       // System.out.println("Select regions:\n" + selectioncom.toString());
       evalStateCommand("select *; cartoons off; backbone; select ("
               + selectioncom.toString() + "); cartoons; ");
-      // evalStateCommand("select *; backbone; select "+selcom.toString()+"; cartoons; center "+selcom.toString());
+      // evalStateCommand("select *; backbone; select "+selcom.toString()+";
+      // cartoons; center "+selcom.toString());
     }
 
     return null;
@@ -549,7 +549,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
   }
 
   @Override
-  public float[][][] functionXYZ(String functionName, int nx, int ny, int nz)
+  public float[][][] functionXYZ(String functionName, int nx, int ny,
+          int nz)
   {
     // TODO Auto-generated method stub
     return null;
@@ -610,7 +611,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     }
     if (modelFileNames == null)
     {
-      List<String> mset = new ArrayList<String>();
+      List<String> mset = new ArrayList<>();
       _modelFileNameMap = new int[viewer.ms.mc];
       String m = viewer.ms.getModelFileName(0);
       if (m != null)
@@ -622,9 +623,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
         } catch (AccessControlException x)
         {
           // usually not allowed to do this in applet
-          System.err
-                  .println("jmolBinding: Using local file string from Jmol: "
-                          + m);
+          System.err.println(
+                  "jmolBinding: Using local file string from Jmol: " + m);
         }
         if (filePath.indexOf("/file:") != -1)
         {
@@ -647,7 +647,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
           } catch (AccessControlException x)
           {
             // usually not allowed to do this in applet, so keep raw handle
-            // System.err.println("jmolBinding: Using local file string from Jmol: "+m);
+            // System.err.println("jmolBinding: Using local file string from
+            // Jmol: "+m);
           }
         }
 
@@ -670,7 +671,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
   @Override
   public synchronized String[] getStructureFiles()
   {
-    List<String> mset = new ArrayList<String>();
+    List<String> mset = new ArrayList<>();
     if (viewer == null)
     {
       return new String[0];
@@ -693,6 +694,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
 
     return modelFileNames;
   }
+
   /**
    * map from string to applet
    */
@@ -703,8 +705,6 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     return null;
   }
 
-  
-
   // ///////////////////////////////
   // JmolStatusListener
 
@@ -827,14 +827,14 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     // handle insertion codes
     if (alocsep != -1)
     {
-      pdbResNum = Integer.parseInt(strInfo.substring(
-              strInfo.indexOf("]") + 1, alocsep));
+      pdbResNum = Integer.parseInt(
+              strInfo.substring(strInfo.indexOf("]") + 1, alocsep));
 
     }
     else
     {
-      pdbResNum = Integer.parseInt(strInfo.substring(
-              strInfo.indexOf("]") + 1, chainSeparator));
+      pdbResNum = Integer.parseInt(
+              strInfo.substring(strInfo.indexOf("]") + 1, chainSeparator));
     }
     String chainId;
 
@@ -856,13 +856,14 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
       {
         chainSeparator1 = strInfo.indexOf(".", mdlSep);
       }
-      String mdlId = (chainSeparator1 > -1) ? strInfo.substring(mdlSep + 1,
-              chainSeparator1) : strInfo.substring(mdlSep + 1);
+      String mdlId = (chainSeparator1 > -1)
+              ? strInfo.substring(mdlSep + 1, chainSeparator1)
+              : strInfo.substring(mdlSep + 1);
       try
       {
         // recover PDB filename for the model hovered over.
-        int _mp = _modelFileNameMap.length - 1, mnumber = new Integer(mdlId)
-                .intValue() - 1;
+        int _mp = _modelFileNameMap.length - 1,
+                mnumber = new Integer(mdlId).intValue() - 1;
         while (mnumber < _modelFileNameMap[_mp])
         {
           _mp--;
@@ -903,7 +904,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
    * } }
    */
 
-  public void notifyAtomPicked(int atomIndex, String strInfo, String strData)
+  public void notifyAtomPicked(int atomIndex, String strInfo,
+          String strData)
   {
     /**
      * this implements the toggle label behaviour copied from the original
@@ -974,6 +976,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
         notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
                 (String) data[0]);
         // also highlight in alignment
+        // deliberate fall through
       case HOVER:
         notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
                 (String) data[0]);
@@ -986,8 +989,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
         sendConsoleEcho((String) data[1]);
         break;
       case MESSAGE:
-        sendConsoleMessage((data == null) ? ((String) null)
-                : (String) data[1]);
+        sendConsoleMessage(
+                (data == null) ? ((String) null) : (String) data[1]);
         break;
       case ERROR:
         // System.err.println("Ignoring error callback.");
@@ -1000,8 +1003,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
 
       case CLICK:
       default:
-        System.err.println("Unhandled callback " + type + " "
-                + data[1].toString());
+        System.err.println(
+                "Unhandled callback " + type + " " + data[1].toString());
         break;
       }
     } catch (Exception e)
@@ -1058,8 +1061,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     fileLoadingError = null;
     String[] oldmodels = modelFileNames;
     modelFileNames = null;
-    chainNames = new ArrayList<String>();
-    chainFile = new Hashtable<String, String>();
+    chainNames = new ArrayList<>();
+    chainFile = new Hashtable<>();
     boolean notifyLoaded = false;
     String[] modelfilenames = getStructureFiles();
     // first check if we've lost any structures
@@ -1110,8 +1113,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
         // calculate essential attributes for the pdb data imported inline.
         // prolly need to resolve modelnumber properly - for now just use our
         // 'best guess'
-        pdbfile = viewer.getData("" + (1 + _modelFileNameMap[modelnum])
-                + ".0", "PDB");
+        pdbfile = viewer.getData(
+                "" + (1 + _modelFileNameMap[modelnum]) + ".0", "PDB");
       }
       // search pdbentries and sequences to find correct pdbentry for this
       // model
@@ -1125,7 +1128,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
           // see JAL-623 - need method of matching pasted data up
           {
             pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
-                    pdbfile, DataSourceType.PASTE);
+                    pdbfile, DataSourceType.PASTE,
+                    getIProgressIndicator());
             getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
             matches = true;
             foundEntry = true;
@@ -1157,7 +1161,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
             }
             // Explicitly map to the filename used by Jmol ;
             pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
-                    fileName, protocol);
+                    fileName, protocol, getIProgressIndicator());
             // pdbentry[pe].getFile(), protocol);
 
           }
@@ -1167,8 +1171,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
           // add an entry for every chain in the model
           for (int i = 0; i < pdb.getChains().size(); i++)
           {
-            String chid = new String(pdb.getId() + ":"
-                    + pdb.getChains().elementAt(i).id);
+            String chid = new String(
+                    pdb.getId() + ":" + pdb.getChains().elementAt(i).id);
             chainFile.put(chid, fileName);
             chainNames.add(chid);
           }
@@ -1200,7 +1204,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     // }
     if (!isLoadingFromArchive())
     {
-      viewer.evalStringQuiet("model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
+      viewer.evalStringQuiet(
+              "model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
     }
     // register ourselves as a listener and notify the gui that it needs to
     // update itself.
@@ -1224,6 +1229,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     return chainNames;
   }
 
+  protected abstract IProgressIndicator getIProgressIndicator();
+
   public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
   {
     notifyAtomPicked(iatom, strMeasure, null);
@@ -1280,8 +1287,9 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
             false);
     for (String resName : residueSet)
     {
-      char res = resName.length() == 3 ? ResidueProperties
-              .getSingleCharacterCode(resName) : resName.charAt(0);
+      char res = resName.length() == 3
+              ? ResidueProperties.getSingleCharacterCode(resName)
+              : resName.charAt(0);
       Color col = cs.findColour(res, 0, null, null, 0f);
       command.append("select " + resName + ";color[" + col.getRed() + ","
               + col.getGreen() + "," + col.getBlue() + "];");
@@ -1360,8 +1368,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
       commandOptions = "";
     }
     viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
-            (jmolfileio ? new SmarterJmolAdapter() : null), htmlName
-                    + ((Object) this).toString(), documentBase, codeBase,
+            (jmolfileio ? new SmarterJmolAdapter() : null),
+            htmlName + ((Object) this).toString(), documentBase, codeBase,
             commandOptions, this);
 
     viewer.setJmolStatusListener(this); // extends JmolCallbackListener
index 3e7ca59..6bf7010 100644 (file)
@@ -113,21 +113,14 @@ public class JmolCommands
                 col = Color.GRAY;
               }
 
-              String newSelcom = (mapping[m].getChain() != " " ? ":"
-                      + mapping[m].getChain() : "")
-                      + "/"
-                      + (pdbfnum + 1)
-                      + ".1"
-                      + ";color["
-                      + col.getRed()
-                      + ","
-                      + col.getGreen()
-                      + ","
+              String newSelcom = (mapping[m].getChain() != " "
+                      ? ":" + mapping[m].getChain()
+                      : "") + "/" + (pdbfnum + 1) + ".1" + ";color["
+                      + col.getRed() + "," + col.getGreen() + ","
                       + col.getBlue() + "]";
-              if (command.length() > newSelcom.length()
-                      && command.substring(
-                              command.length() - newSelcom.length())
-                              .equals(newSelcom))
+              if (command.length() > newSelcom.length() && command
+                      .substring(command.length() - newSelcom.length())
+                      .equals(newSelcom))
               {
                 command = JmolCommands.condenseCommand(command, pos);
                 continue;
index f08e40e..dc3d0ee 100644 (file)
@@ -105,8 +105,9 @@ public class JmolParser extends StructureFile implements JmolStatusListener
       // }
       // ;
       // instead, we distinguish .cif from non-.cif by filename
-      setStructureFileType(getDataName().toLowerCase().endsWith(".cif") ? PDBEntry.Type.MMCIF
-              .toString() : "PDB");
+      setStructureFileType(getDataName().toLowerCase().endsWith(".cif")
+              ? PDBEntry.Type.MMCIF.toString()
+              : "PDB");
 
       transformJmolModelToJalview(jmolModel.ms);
     }
@@ -135,7 +136,8 @@ public class JmolParser extends StructureFile implements JmolStatusListener
       {
         throw new Error(MessageManager.formatMessage(
                 "error.jmol_version_not_compatible_with_jalview_version",
-                new String[] { JmolViewer.getJmolVersion() }), x);
+                new String[]
+                { JmolViewer.getJmolVersion() }), x);
       }
     }
     return viewer;
@@ -205,11 +207,10 @@ public class JmolParser extends StructureFile implements JmolStatusListener
       }
     } catch (OutOfMemoryError er)
     {
-      System.out
-              .println("OUT OF MEMORY LOADING TRANSFORMING JMOL MODEL TO JALVIEW MODEL");
-      throw new IOException(
-              MessageManager
-                      .getString("exception.outofmemory_loading_mmcif_file"));
+      System.out.println(
+              "OUT OF MEMORY LOADING TRANSFORMING JMOL MODEL TO JALVIEW MODEL");
+      throw new IOException(MessageManager
+              .getString("exception.outofmemory_loading_mmcif_file"));
     }
   }
 
@@ -236,8 +237,9 @@ public class JmolParser extends StructureFile implements JmolStatusListener
         curAtom.number = atom.getAtomNumber();
         curAtom.resName = atom.getGroup3(true);
         curAtom.resNumber = atom.getResno();
-        curAtom.occupancy = ms.occupancies != null ? ms.occupancies[atom
-                .getIndex()] : Float.valueOf(atom.getOccupancy100());
+        curAtom.occupancy = ms.occupancies != null
+                ? ms.occupancies[atom.getIndex()]
+                : Float.valueOf(atom.getOccupancy100());
         String fmt = new Format("%4i").form(curAtom.resNumber);
         curAtom.resNumIns = (fmt + curAtom.insCode);
         curAtom.tfactor = atom.getBfactor100() / 100f;
@@ -259,7 +261,7 @@ public class JmolParser extends StructureFile implements JmolStatusListener
           HashMap<String, org.jmol.modelset.Atom> chainTerMap)
   {
     // System.out.println("Atom: " + curAtom.getAtomNumber()
-    // + "   Last atom index " + curAtom.group.lastAtomIndex);
+    // + " Last atom index " + curAtom.group.lastAtomIndex);
     if (chainTerMap == null || prevAtom == null)
     {
       return true;
@@ -282,7 +284,8 @@ public class JmolParser extends StructureFile implements JmolStatusListener
         {
           return false;
         }
-        if ((curAtom.getResno() - chainTerMap.get(curAtomChId).getResno()) < 5)
+        if ((curAtom.getResno()
+                - chainTerMap.get(curAtomChId).getResno()) < 5)
         {
           chainTerMap.put(curAtomChId, curAtom);
           return true;
@@ -297,7 +300,8 @@ public class JmolParser extends StructureFile implements JmolStatusListener
       {
         return false;
       }
-      if ((curAtom.getResno() - chainTerMap.get(curAtomChId).getResno()) < 5)
+      if ((curAtom.getResno()
+              - chainTerMap.get(curAtomChId).getResno()) < 5)
       {
         chainTerMap.put(curAtomChId, curAtom);
         return true;
@@ -305,8 +309,8 @@ public class JmolParser extends StructureFile implements JmolStatusListener
       return false;
     }
     // HETATM with resNum jump > 2
-    return !(curAtom.isHetero() && ((curAtom.getResno() - prevAtom
-            .getResno()) > 2));
+    return !(curAtom.isHetero()
+            && ((curAtom.getResno() - prevAtom.getResno()) > 2));
   }
 
   private void createAnnotation(SequenceI sequence, PDBChain chain,
@@ -351,10 +355,10 @@ public class JmolParser extends StructureFile implements JmolStatusListener
           SequenceI sq, char[] secstr, char[] secstrcode, String chainId,
           int firstResNum)
   {
-    char[] seq = sq.getSequence();
+    int length = sq.getLength();
     boolean ssFound = false;
-    Annotation asecstr[] = new Annotation[seq.length + firstResNum - 1];
-    for (int p = 0; p < seq.length; p++)
+    Annotation asecstr[] = new Annotation[length + firstResNum - 1];
+    for (int p = 0; p < length; p++)
     {
       if (secstr[p] >= 'A' && secstr[p] <= 'z')
       {
@@ -411,8 +415,8 @@ public class JmolParser extends StructureFile implements JmolStatusListener
    * @param secstr
    * @param secstrcode
    */
-  protected void setSecondaryStructure(STR proteinStructureSubType,
-          int pos, char[] secstr, char[] secstrcode)
+  protected void setSecondaryStructure(STR proteinStructureSubType, int pos,
+          char[] secstr, char[] secstrcode)
   {
     switch (proteinStructureSubType)
     {
@@ -489,8 +493,8 @@ public class JmolParser extends StructureFile implements JmolStatusListener
   @Override
   public void notifyCallback(CBK cbType, Object[] data)
   {
-    String strInfo = (data == null || data[1] == null ? null : data[1]
-            .toString());
+    String strInfo = (data == null || data[1] == null ? null
+            : data[1].toString());
     switch (cbType)
     {
     case ECHO:
@@ -590,7 +594,8 @@ public class JmolParser extends StructureFile implements JmolStatusListener
    * Not implemented - returns null
    */
   @Override
-  public float[][][] functionXYZ(String functionName, int nx, int ny, int nz)
+  public float[][][] functionXYZ(String functionName, int nx, int ny,
+          int nz)
   {
     return null;
   }
@@ -642,7 +647,8 @@ public class JmolParser extends StructureFile implements JmolStatusListener
     return predictSecondaryStructure;
   }
 
-  public void setPredictSecondaryStructure(boolean predictSecondaryStructure)
+  public void setPredictSecondaryStructure(
+          boolean predictSecondaryStructure)
   {
     this.predictSecondaryStructure = predictSecondaryStructure;
   }
index 5b75206..d50ad87 100644 (file)
@@ -94,8 +94,8 @@ public class Annotate3D
       }
 
       @Override
-      public boolean startObjectEntry(String key) throws ParseException,
-              IOException
+      public boolean startObjectEntry(String key)
+              throws ParseException, IOException
       {
         // TODO Auto-generated method stub
         return false;
@@ -123,8 +123,8 @@ public class Annotate3D
       }
 
       @Override
-      public boolean primitive(Object value) throws ParseException,
-              IOException
+      public boolean primitive(Object value)
+              throws ParseException, IOException
       {
         // TODO Auto-generated method stub
         return false;
@@ -144,8 +144,8 @@ public class Annotate3D
     // return processJsonResponseFor(HttpClientUtils.doHttpUrlPost(twoDtoolsURL,
     // vals));
     ArrayList<Reader> readers = new ArrayList<Reader>();
-    final BufferedReader postResponse = HttpClientUtils.doHttpUrlPost(
-            twoDtoolsURL, vals, 0, 0);
+    final BufferedReader postResponse = HttpClientUtils
+            .doHttpUrlPost(twoDtoolsURL, vals, 0, 0);
     readers.add(postResponse);
     return readers.iterator();
 
@@ -183,15 +183,15 @@ public class Annotate3D
           ;
           if (sval == null)
           {
-            System.err
-                    .println("DEVELOPER WARNING: Annotate3d didn't return a '2D' tag in its response. Consider checking output of server. Response was :"
+            System.err.println(
+                    "DEVELOPER WARNING: Annotate3d didn't return a '2D' tag in its response. Consider checking output of server. Response was :"
                             + val.toString());
 
             sval = "";
           }
-          return new StringReader(
-                  (sval instanceof JSONObject) ? ((JSONObject) sval)
-                          .toString() : sval.toString());
+          return new StringReader((sval instanceof JSONObject)
+                  ? ((JSONObject) sval).toString()
+                  : sval.toString());
 
         }
 
@@ -228,9 +228,8 @@ public class Annotate3D
       };
     } catch (Exception foo)
     {
-      throw new Exception(
-              MessageManager
-                      .getString("exception.couldnt_parse_responde_from_annotated3d_server"),
+      throw new Exception(MessageManager.getString(
+              "exception.couldnt_parse_responde_from_annotated3d_server"),
               foo);
     }
 
index d62cc3c..39d6704 100644 (file)
@@ -1,6 +1,26 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.ext.rbvi.chimera;
 
-import jalview.util.RangeComparator;
+import jalview.util.IntRangeComparator;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -26,7 +46,7 @@ import java.util.TreeMap;
  * </ul>
  * 
  * <pre>
- * @see http://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/midas/frameatom_spec.html
+ * &#64;see http://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/midas/frameatom_spec.html
  * </pre>
  */
 public class AtomSpecModel
@@ -100,14 +120,14 @@ public class AtomSpecModel
 
       for (String chain : modelData.keySet())
       {
-        chain = chain.trim();
+        chain = " ".equals(chain) ? chain : chain.trim();
 
         List<int[]> rangeList = modelData.get(chain);
 
         /*
          * sort ranges into ascending start position order
          */
-        Collections.sort(rangeList, new RangeComparator(true));
+        Collections.sort(rangeList, IntRangeComparator.ASCENDING);
 
         int start = rangeList.isEmpty() ? 0 : rangeList.get(0)[0];
         int end = rangeList.isEmpty() ? 0 : rangeList.get(0)[1];
@@ -172,9 +192,10 @@ public class AtomSpecModel
     {
       sb.append(start).append("-").append(end);
     }
-    if (chain.length() > 0)
-    {
-      sb.append(".").append(chain);
+
+    sb.append(".");
+    if (!" ".equals(chain)) {
+      sb.append(chain);
     }
   }
 }
index 62aaa1c..dad8511 100644 (file)
@@ -269,8 +269,8 @@ public class ChimeraCommands
             // final colour range
             if (lastColour != null)
             {
-              addColourRange(colourMap, lastColour, pdbfnum, startPos, lastPos,
-                      lastChain);
+              addColourRange(colourMap, lastColour, pdbfnum, startPos,
+                      lastPos, lastChain);
             }
             // break;
           }
@@ -318,8 +318,8 @@ public class ChimeraCommands
    * @return
    */
   public static StructureMappingcommandSet getSetAttributeCommandsForFeatures(
-          StructureSelectionManager ssm, String[] files,
-          SequenceI[][] seqs, AlignmentViewPanel viewPanel)
+          StructureSelectionManager ssm, String[] files, SequenceI[][] seqs,
+          AlignmentViewPanel viewPanel)
   {
     Map<String, Map<Object, AtomSpecModel>> featureMap = buildFeaturesMap(
             ssm, files, seqs, viewPanel);
@@ -346,8 +346,8 @@ public class ChimeraCommands
    * @return
    */
   protected static Map<String, Map<Object, AtomSpecModel>> buildFeaturesMap(
-          StructureSelectionManager ssm, String[] files,
-          SequenceI[][] seqs, AlignmentViewPanel viewPanel)
+          StructureSelectionManager ssm, String[] files, SequenceI[][] seqs,
+          AlignmentViewPanel viewPanel)
   {
     Map<String, Map<Object, AtomSpecModel>> theMap = new LinkedHashMap<String, Map<Object, AtomSpecModel>>();
 
@@ -411,12 +411,8 @@ public class ChimeraCommands
           StructureMapping mapping, SequenceI seq,
           Map<String, Map<Object, AtomSpecModel>> theMap, int modelNumber)
   {
-    SequenceFeature[] sfs = seq.getSequenceFeatures();
-    if (sfs == null)
-    {
-      return;
-    }
-
+    List<SequenceFeature> sfs = seq.getFeatures().getPositionalFeatures(
+            visibleFeatures.toArray(new String[visibleFeatures.size()]));
     for (SequenceFeature sf : sfs)
     {
       String type = sf.getType();
@@ -427,7 +423,7 @@ public class ChimeraCommands
        */
       boolean isFromViewer = JalviewChimeraBinding.CHIMERA_FEATURE_GROUP
               .equals(sf.getFeatureGroup());
-      if (isFromViewer || !visibleFeatures.contains(type))
+      if (isFromViewer)
       {
         continue;
       }
@@ -454,8 +450,8 @@ public class ChimeraCommands
         }
         for (int[] range : mappedRanges)
         {
-          addColourRange(featureValues, value, modelNumber, range[0], range[1],
-                  mapping.getChain());
+          addColourRange(featureValues, value, modelNumber, range[0],
+                  range[1], mapping.getChain());
         }
       }
     }
@@ -517,9 +513,11 @@ public class ChimeraCommands
    * to an underscore.
    * 
    * @param featureType
-   * @return <pre>
-   * @see https://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/midas/setattr.html
-   * </pre>
+   * @return
+   * 
+   *         <pre>
+   * &#64;see https://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/midas/setattr.html
+   *         </pre>
    */
   protected static String makeAttributeName(String featureType)
   {
index 507ddbc..a0d74bc 100644 (file)
@@ -39,7 +39,8 @@ import javax.servlet.http.HttpServletResponse;
  * <li>Start the ChimeraListener, get the URL it is listening on</li>
  * <li>The first listener started will start the singleton HttpServer</li>
  * <li>Send a 'listen' command to Chimera with the URL of the listener</li>
- * <li>When Jalview's Chimera window is closed, shut down the ChimeraListener</li>
+ * <li>When Jalview's Chimera window is closed, shut down the
+ * ChimeraListener</li>
  * <li>Multiple linked Chimera instances will each have a separate listener (but
  * share one Http server)</li>
  * </ul>
@@ -47,8 +48,8 @@ import javax.servlet.http.HttpServletResponse;
  * @author gmcarstairs
  *
  */
-public class ChimeraListener extends AbstractRequestHandler implements
-        SelectionSource
+public class ChimeraListener extends AbstractRequestHandler
+        implements SelectionSource
 {
   /*
    * Chimera notification parameter name
@@ -96,8 +97,7 @@ public class ChimeraListener extends AbstractRequestHandler implements
    * @throws BindException
    *           if no free port can be assigned
    */
-  public ChimeraListener(JalviewChimeraBinding binding)
-          throws BindException
+  public ChimeraListener(JalviewChimeraBinding binding) throws BindException
   {
     myChimeraId = chimeraId++;
     this.chimeraBinding = binding;
index b954677..00446f2 100644 (file)
@@ -79,7 +79,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
   private List<String> chainNames = new ArrayList<String>();
 
   private Hashtable<String, String> chainFile = new Hashtable<String, String>();
-  
+
   /*
    * Object through which we talk to Chimera
    */
@@ -192,7 +192,8 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
    * @param protocol
    */
   public JalviewChimeraBinding(StructureSelectionManager ssm,
-          PDBEntry[] pdbentry, SequenceI[][] sequenceIs, DataSourceType protocol)
+          PDBEntry[] pdbentry, SequenceI[][] sequenceIs,
+          DataSourceType protocol)
   {
     super(ssm, pdbentry, sequenceIs, protocol);
     viewer = new ChimeraManager(new StructureManager(true));
@@ -241,8 +242,8 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
       viewer.startListening(chimeraListener.getUri());
     } catch (BindException e)
     {
-      System.err.println("Failed to start Chimera listener: "
-              + e.getMessage());
+      System.err.println(
+              "Failed to start Chimera listener: " + e.getMessage());
     }
   }
 
@@ -263,8 +264,8 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
     for (String chain : toshow)
     {
       int modelNumber = getModelNoForChain(chain);
-      String showChainCmd = modelNumber == -1 ? "" : modelNumber + ":."
-              + chain.split(":")[1];
+      String showChainCmd = modelNumber == -1 ? ""
+              : modelNumber + ":." + chain.split(":")[1];
       if (!first)
       {
         cmd.append(",");
@@ -515,8 +516,8 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
         if (debug)
         {
           System.out.println("Select regions:\n" + selectioncom.toString());
-          System.out.println("Superimpose command(s):\n"
-                  + command.toString());
+          System.out.println(
+                  "Superimpose command(s):\n" + command.toString());
         }
         allComs.append("~display all; chain @CA|P; ribbon ")
                 .append(selectioncom.toString())
@@ -596,8 +597,8 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
       return true;
     }
 
-    boolean launched = viewer.launchChimera(StructureManager
-            .getChimeraPaths());
+    boolean launched = viewer
+            .launchChimera(StructureManager.getChimeraPaths());
     if (launched)
     {
       startChimeraProcessMonitor();
@@ -741,7 +742,6 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
    */
   private int _modelFileNameMap[];
 
-
   // ////////////////////////////////
   // /StructureListener
   @Override
@@ -752,8 +752,8 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
       return new String[0];
     }
 
-    return chimeraMaps.keySet().toArray(
-            modelFileNames = new String[chimeraMaps.size()]);
+    return chimeraMaps.keySet()
+            .toArray(modelFileNames = new String[chimeraMaps.size()]);
   }
 
   /**
@@ -837,7 +837,8 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
      * Parse model number, residue and chain for each selected position,
      * formatted as #0:123.A or #1.2:87.B (#model.submodel:residue.chain)
      */
-    List<AtomSpec> atomSpecs = convertStructureResiduesToAlignment(selection);
+    List<AtomSpec> atomSpecs = convertStructureResiduesToAlignment(
+            selection);
 
     /*
      * Broadcast the selection (which may be empty, if the user just cleared all
@@ -932,12 +933,13 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
             false);
     for (String resName : residueSet)
     {
-      char res = resName.length() == 3 ? ResidueProperties
-              .getSingleCharacterCode(resName) : resName.charAt(0);
+      char res = resName.length() == 3
+              ? ResidueProperties.getSingleCharacterCode(resName)
+              : resName.charAt(0);
       Color col = cs.findColour(res, 0, null, null, 0f);
       command.append("color " + col.getRed() / normalise + ","
-              + col.getGreen() / normalise + "," + col.getBlue()
-              / normalise + " ::" + resName + ";");
+              + col.getGreen() / normalise + "," + col.getBlue() / normalise
+              + " ::" + resName + ";");
     }
 
     sendAsynchronousCommand(command.toString(), COLOURING_CHIMERA);
@@ -983,7 +985,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
   /**
    * Send the Chimera 'background solid <color>" command.
    * 
-   * @see https 
+   * @see https
    *      ://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/midas/background
    *      .html
    * @param col
@@ -994,8 +996,8 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
     viewerCommandHistory(false);
     double normalise = 255D;
     final String command = "background solid " + col.getRed() / normalise
-            + "," + col.getGreen() / normalise + "," + col.getBlue()
-            / normalise + ";";
+            + "," + col.getGreen() / normalise + ","
+            + col.getBlue() / normalise + ";";
     viewer.sendChimeraCommand(command, false);
     viewerCommandHistory(true);
   }
@@ -1148,9 +1150,8 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
       sendAsynchronousCommand("open cmd:" + path, null);
     } catch (IOException e)
     {
-      System.err
-              .println("Sending commands to Chimera via file failed with "
-                      + e.getMessage());
+      System.err.println("Sending commands to Chimera via file failed with "
+              + e.getMessage());
     }
   }
 
@@ -1288,7 +1289,6 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
     return CHIMERA_FEATURE_GROUP;
   }
 
-
   public Hashtable<String, String> getChainFile()
   {
     return chainFile;
index a4c195f..0d631e6 100644 (file)
@@ -102,8 +102,8 @@ public class SequenceOntology implements SequenceOntologyI
     try
     {
       String zipFile = ontologyFile + ".zip";
-      InputStream inStream = this.getClass().getResourceAsStream(
-              "/" + zipFile);
+      InputStream inStream = this.getClass()
+              .getResourceAsStream("/" + zipFile);
       zipStream = new ZipInputStream(new BufferedInputStream(inStream));
       ZipEntry entry;
       while ((entry = zipStream.getNextEntry()) != null)
@@ -151,8 +151,8 @@ public class SequenceOntology implements SequenceOntologyI
    * @throws ParseException
    * @throws IOException
    */
-  protected void loadOboFile(InputStream is) throws ParseException,
-          IOException
+  protected void loadOboFile(InputStream is)
+          throws ParseException, IOException
   {
     BufferedReader oboFile = new BufferedReader(new InputStreamReader(is));
     OboParser parser = new OboParser();
index ab479c2..6dd5a86 100644 (file)
@@ -26,8 +26,8 @@ import jalview.structures.models.SequenceStructureBindingModel;
 
 import java.awt.event.ComponentListener;
 
-public abstract class JalviewVarnaBinding extends
-        SequenceStructureBindingModel implements StructureListener,
+public abstract class JalviewVarnaBinding
+        extends SequenceStructureBindingModel implements StructureListener,
         ComponentListener, StructureSelectionManagerProvider
 
 {
index d65f1d5..4dd0648 100644 (file)
@@ -48,8 +48,7 @@ public class VarnaCommands
   public static String[] getColourBySequenceCommand(
           StructureSelectionManager ssm, String[] files,
           SequenceI[][] sequence, SequenceRenderer sr,
-          FeatureColourFinder finder,
-          AlignmentI alignment)
+          FeatureColourFinder finder, AlignmentI alignment)
   {
     ArrayList<String> str = new ArrayList<String>();
     StringBuffer command = new StringBuffer();
@@ -91,21 +90,14 @@ public class VarnaCommands
               Color col = sr.getResidueColour(sequence[pdbfnum][s], r,
                       finder);
 
-              String newSelcom = (mapping[m].getChain() != " " ? ":"
-                      + mapping[m].getChain() : "")
-                      + "/"
-                      + (pdbfnum + 1)
-                      + ".1"
-                      + ";color["
-                      + col.getRed()
-                      + ","
-                      + col.getGreen()
-                      + ","
+              String newSelcom = (mapping[m].getChain() != " "
+                      ? ":" + mapping[m].getChain()
+                      : "") + "/" + (pdbfnum + 1) + ".1" + ";color["
+                      + col.getRed() + "," + col.getGreen() + ","
                       + col.getBlue() + "]";
-              if (command.length() > newSelcom.length()
-                      && command.substring(
-                              command.length() - newSelcom.length())
-                              .equals(newSelcom))
+              if (command.length() > newSelcom.length() && command
+                      .substring(command.length() - newSelcom.length())
+                      .equals(newSelcom))
               {
                 command = VarnaCommands.condenseCommand(command, pos);
                 continue;
index 99c0c51..974cc88 100644 (file)
@@ -145,4 +145,11 @@ public interface GFTSPanelI
    * @return
    */
   public String getCacheKey();
+
+  /**
+   * 
+   * @return user preference name for configuring this FTS search's autosearch
+   *         checkbox
+   */
+  public String getAutosearchPreference();
 }
index a9e303c..8a8e7ab 100644 (file)
@@ -30,8 +30,7 @@ import javax.swing.table.DefaultTableCellRenderer;
 /**
  * The class to handle the formatting of the double values for JTable cells.
  */
-public class DecimalFormatTableCellRenderer extends
-        DefaultTableCellRenderer
+public class DecimalFormatTableCellRenderer extends DefaultTableCellRenderer
 {
   private DecimalFormat formatter;
 
@@ -47,8 +46,8 @@ public class DecimalFormatTableCellRenderer extends
       {
         significantFigureBuilder.append("0");
       }
-      formatter = new DecimalFormat(fractionFormater
-              + significantFigureBuilder.toString());
+      formatter = new DecimalFormat(
+              fractionFormater + significantFigureBuilder.toString());
     }
     else
     {
@@ -63,9 +62,8 @@ public class DecimalFormatTableCellRenderer extends
   }
 
   @Override
-  public Component getTableCellRendererComponent(JTable table,
-          Object value, boolean isSelected, boolean hasFocus, int row,
-          int column)
+  public Component getTableCellRendererComponent(JTable table, Object value,
+          boolean isSelected, boolean hasFocus, int row, int column)
   {
     if (value == null)
     {
index 1a8f398..cb6249e 100644 (file)
@@ -109,9 +109,9 @@ public class FTSDataColumnPreferences extends JScrollPane
       switch (source)
       {
       case SEARCH_SUMMARY:
-        data[x++] = new Object[] {
-            ftsRestClient.getAllDefaultDisplayedFTSDataColumns().contains(
-                    field), field.getName(), field.getGroup() };
+        data[x++] = new Object[] { ftsRestClient
+                .getAllDefaultDisplayedFTSDataColumns().contains(field),
+            field.getName(), field.getGroup() };
         break;
       case STRUCTURE_CHOOSER:
         data[x++] = new Object[] { structSummaryColumns.contains(field),
@@ -119,9 +119,9 @@ public class FTSDataColumnPreferences extends JScrollPane
         break;
       case PREFERENCES:
         data[x++] = new Object[] {
-            field.getName(),
-            ftsRestClient.getAllDefaultDisplayedFTSDataColumns().contains(
-                    field), structSummaryColumns.contains(field) };
+            field.getName(), ftsRestClient
+                    .getAllDefaultDisplayedFTSDataColumns().contains(field),
+            structSummaryColumns.contains(field) };
         break;
       default:
         break;
index 4899e38..076e212 100644 (file)
@@ -82,8 +82,8 @@ public abstract class FTSRestClient implements FTSRestClientI
             {
               primaryKeyColumnCode = lineData[1];
             }
-            if (lineData[0]
-                    .equalsIgnoreCase("_data_column.default_response_page_size"))
+            if (lineData[0].equalsIgnoreCase(
+                    "_data_column.default_response_page_size"))
             {
               defaultResponsePageSize = Integer.valueOf(lineData[1]);
             }
@@ -158,8 +158,9 @@ public abstract class FTSRestClient implements FTSRestClientI
               @Override
               public String getAltCode()
               {
-                return lineData[1].split("\\|").length > 1 ? lineData[1]
-                        .split("\\|")[1] : getCode();
+                return lineData[1].split("\\|").length > 1
+                        ? lineData[1].split("\\|")[1]
+                        : getCode();
               }
 
               @Override
@@ -313,7 +314,8 @@ public abstract class FTSRestClient implements FTSRestClientI
       }
       try
       {
-        this.primaryKeyColumn = getDataColumnByNameOrCode(primaryKeyColumnCode);
+        this.primaryKeyColumn = getDataColumnByNameOrCode(
+                primaryKeyColumnCode);
       } catch (Exception e)
       {
         e.printStackTrace();
@@ -421,8 +423,8 @@ public abstract class FTSRestClient implements FTSRestClientI
         return column;
       }
     }
-    throw new Exception("Couldn't find data column with name : "
-            + nameOrCode);
+    throw new Exception(
+            "Couldn't find data column with name : " + nameOrCode);
   }
 
   @Override
index 2e1c632..2d9eeb6 100644 (file)
@@ -45,8 +45,8 @@ public class FTSRestRequest
 
   private boolean allowEmptySequence;
 
-  private boolean allowUnpublishedEntries = Cache.getDefault(
-          "ALLOW_UNPUBLISHED_PDB_QUERYING", false);
+  private boolean allowUnpublishedEntries = Cache
+          .getDefault("ALLOW_UNPUBLISHED_PDB_QUERYING", false);
 
   private boolean facet;
 
@@ -117,7 +117,8 @@ public class FTSRestRequest
     return fieldToSortBy;
   }
 
-  public void setFieldToSortBy(String fieldToSortBy, boolean isSortAscending)
+  public void setFieldToSortBy(String fieldToSortBy,
+          boolean isSortAscending)
   {
     this.fieldToSortBy = fieldToSortBy;
     this.isSortAscending = isSortAscending;
index 5d8fb96..d9658e4 100644 (file)
@@ -90,8 +90,8 @@ public class FTSRestResponse
   public static DefaultTableModel getTableModel(FTSRestRequest request,
           Collection<FTSData> summariesList)
   {
-    final FTSDataColumnI[] cols = request.getWantedFields().toArray(
-            new FTSDataColumnI[0]);
+    final FTSDataColumnI[] cols = request.getWantedFields()
+            .toArray(new FTSDataColumnI[0]);
     final int colOffset = request.getAssociatedSequence() == null ? 0 : 1;
     DefaultTableModel tableModel = new DefaultTableModel()
     {
@@ -141,15 +141,15 @@ public class FTSRestResponse
     {
       try
       {
-        tbl_summary.getColumn(wantedField.getName()).setMinWidth(
-                wantedField.getMinWidth());
-        tbl_summary.getColumn(wantedField.getName()).setMaxWidth(
-                wantedField.getMaxWidth());
-        int prefedWidth = columnPrefs.get(wantedField.getName()) == null ? wantedField
-                .getPreferredWidth() : columnPrefs.get(wantedField
-                .getName());
-        tbl_summary.getColumn(wantedField.getName()).setPreferredWidth(
-                prefedWidth);
+        tbl_summary.getColumn(wantedField.getName())
+                .setMinWidth(wantedField.getMinWidth());
+        tbl_summary.getColumn(wantedField.getName())
+                .setMaxWidth(wantedField.getMaxWidth());
+        int prefedWidth = columnPrefs.get(wantedField.getName()) == null
+                ? wantedField.getPreferredWidth()
+                : columnPrefs.get(wantedField.getName());
+        tbl_summary.getColumn(wantedField.getName())
+                .setPreferredWidth(prefedWidth);
       } catch (Exception e)
       {
         e.printStackTrace();
@@ -157,15 +157,16 @@ public class FTSRestResponse
       if (wantedField.getDataType().getDataTypeClass() == Double.class)
       {
         DecimalFormatTableCellRenderer dfr = new DecimalFormatTableCellRenderer(
-                wantedField.getDataType().isFormtted(), wantedField
-                        .getDataType().getSignificantFigures());
+                wantedField.getDataType().isFormtted(),
+                wantedField.getDataType().getSignificantFigures());
         tbl_summary.getColumn(wantedField.getName()).setCellRenderer(dfr);
       }
-      else if (wantedField.getDataType().getDataTypeClass() == Integer.class)
+      else if (wantedField.getDataType()
+              .getDataTypeClass() == Integer.class)
       {
         DecimalFormatTableCellRenderer dfr = new DecimalFormatTableCellRenderer(
-                wantedField.getDataType().isFormtted(), wantedField
-                        .getDataType().getSignificantFigures());
+                wantedField.getDataType().isFormtted(),
+                wantedField.getDataType().getSignificantFigures());
         tbl_summary.getColumn(wantedField.getName()).setCellRenderer(dfr);
       }
     }
index f1db383..9802d4b 100644 (file)
@@ -56,6 +56,7 @@ import java.util.List;
 
 import javax.swing.ImageIcon;
 import javax.swing.JButton;
+import javax.swing.JCheckBox;
 import javax.swing.JComboBox;
 import javax.swing.JFrame;
 import javax.swing.JInternalFrame;
@@ -88,6 +89,7 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI
   protected JInternalFrame mainFrame = new JInternalFrame(
           getFTSFrameTitle());
 
+  protected JTabbedPane tabs = new JTabbedPane();
   protected IProgressIndicator progressIndicator;
 
   protected JComboBox<FTSDataColumnI> cmb_searchTarget = new JComboBox<FTSDataColumnI>();
@@ -98,6 +100,8 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI
 
   protected JButton btn_cancel = new JButton();
 
+  protected JCheckBox btn_autosearch = new JCheckBox();
+
   protected JvCacheableInputBox<String> txt_search;
 
   protected SequenceFetcher seqFetcher;
@@ -112,14 +116,14 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI
 
   protected StringBuilder errorWarning = new StringBuilder();
 
-  protected ImageIcon warningImage = new ImageIcon(getClass().getResource(
-          "/images/warning.gif"));
+  protected ImageIcon warningImage = new ImageIcon(
+          getClass().getResource("/images/warning.gif"));
 
-  protected ImageIcon loadingImage = new ImageIcon(getClass().getResource(
-          "/images/loading.gif"));
+  protected ImageIcon loadingImage = new ImageIcon(
+          getClass().getResource("/images/loading.gif"));
 
-  protected ImageIcon balnkPlaceholderImage = new ImageIcon(getClass()
-          .getResource("/images/blank_16x16_placeholder.png"));
+  protected ImageIcon balnkPlaceholderImage = new ImageIcon(
+          getClass().getResource("/images/blank_16x16_placeholder.png"));
 
   protected JLabel lbl_warning = new JLabel(warningImage);
 
@@ -226,8 +230,9 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI
         e.printStackTrace();
       }
       toolTipText = (toolTipText == null ? null
-              : (toolTipText.length() > 500 ? JvSwingUtils.wrapTooltip(
-                      true, toolTipText.subSequence(0, 500) + "...")
+              : (toolTipText.length() > 500
+                      ? JvSwingUtils.wrapTooltip(true,
+                              toolTipText.subSequence(0, 500) + "...")
                       : JvSwingUtils.wrapTooltip(true, toolTipText)));
 
       return toolTipText;
@@ -238,16 +243,38 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI
 
   public GFTSPanel()
   {
+    this(null);
+  }
+
+  public GFTSPanel(SequenceFetcher fetcher)
+  {
     try
     {
+      if (fetcher == null)
+      {
+        tabs = null;
+      }
       jbInit();
+      if (fetcher != null)
+      {
+        tabs.addTab(MessageManager.getString("label.retrieve_ids"),
+                fetcher);
+        fetcher.setDatabaseChooserVisible(false);
+        fetcher.embedWithFTSPanel(this);
+      }
       mainFrame.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
+      final JPanel ftsPanel = this;
       mainFrame.addFocusListener(new FocusAdapter()
       {
         @Override
         public void focusGained(FocusEvent e)
         {
-          txt_search.requestFocusInWindow();
+          // TODO: make selected tab gain focus in correct widget
+          if (tabs != null
+                  && tabs.getSelectedComponent() == ftsPanel)
+          {
+            txt_search.requestFocusInWindow();
+          }
         }
       });
       mainFrame.invalidate();
@@ -330,6 +357,20 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI
       }
     });
 
+    btn_autosearch.setText(MessageManager.getString("option.autosearch"));
+    btn_autosearch.setToolTipText(
+            MessageManager.getString("option.enable_disable_autosearch"));
+    btn_autosearch.setSelected(
+            jalview.bin.Cache.getDefault(getAutosearchPreference(), true));
+    btn_autosearch.addActionListener(new java.awt.event.ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        jalview.bin.Cache.setProperty(getAutosearchPreference(),
+                Boolean.toString(btn_autosearch.isSelected()));
+      }
+    });
     btn_back.setFont(new java.awt.Font("Verdana", 0, 12));
     btn_back.setText(MessageManager.getString("action.back"));
     btn_back.addActionListener(new java.awt.event.ActionListener()
@@ -375,8 +416,8 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI
       }
     });
     btn_next_page.setEnabled(false);
-    btn_next_page.setToolTipText(MessageManager
-            .getString("label.next_page_tooltip"));
+    btn_next_page.setToolTipText(
+            MessageManager.getString("label.next_page_tooltip"));
     btn_next_page.setFont(new java.awt.Font("Verdana", 0, 12));
     btn_next_page.setText(MessageManager.getString("action.next_page"));
     btn_next_page.addActionListener(new java.awt.event.ActionListener()
@@ -400,8 +441,8 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI
     });
 
     btn_prev_page.setEnabled(false);
-    btn_prev_page.setToolTipText(MessageManager
-            .getString("label.prev_page_tooltip"));
+    btn_prev_page.setToolTipText(
+            MessageManager.getString("label.prev_page_tooltip"));
     btn_prev_page.setFont(new java.awt.Font("Verdana", 0, 12));
     btn_prev_page.setText(MessageManager.getString("action.prev_page"));
     btn_prev_page.addActionListener(new java.awt.event.ActionListener()
@@ -467,13 +508,13 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI
         if (e.getStateChange() == ItemEvent.SELECTED)
         {
           String tooltipText;
-          if ("all".equalsIgnoreCase(getCmbSearchTarget().getSelectedItem()
-                  .toString()))
+          if ("all".equalsIgnoreCase(
+                  getCmbSearchTarget().getSelectedItem().toString()))
           {
             tooltipText = MessageManager.getString("label.search_all");
           }
-          else if ("pdb id".equalsIgnoreCase(getCmbSearchTarget()
-                  .getSelectedItem().toString()))
+          else if ("pdb id".equalsIgnoreCase(
+                  getCmbSearchTarget().getSelectedItem().toString()))
           {
             tooltipText = MessageManager
                     .getString("label.separate_multiple_accession_ids");
@@ -481,54 +522,56 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI
           else
           {
             tooltipText = MessageManager.formatMessage(
-                    "label.separate_multiple_query_values",
-                    new Object[] { getCmbSearchTarget().getSelectedItem()
-                            .toString() });
+                    "label.separate_multiple_query_values", new Object[]
+                    { getCmbSearchTarget().getSelectedItem().toString() });
           }
-          txt_search.setToolTipText(JvSwingUtils.wrapTooltip(true,
-                  tooltipText));
+          txt_search.setToolTipText(
+                  JvSwingUtils.wrapTooltip(true, tooltipText));
           searchAction(true);
         }
       }
     });
 
     txt_search.setFont(new java.awt.Font("Verdana", 0, 12));
 
     txt_search.getEditor().getEditorComponent()
             .addKeyListener(new KeyAdapter()
-    {
-      @Override
-      public void keyPressed(KeyEvent e)
-      {
-        if (e.getKeyCode() == KeyEvent.VK_ENTER)
-        {
-          if (getTypedText() == null || getTypedText().isEmpty())
-          {
-            return;
-          }
-          String primaryKeyName = getFTSRestClient().getPrimaryKeyColumn()
-                  .getName();
-          if (primaryKeyName.equalsIgnoreCase(getCmbSearchTarget()
-                  .getSelectedItem().toString()))
-          {
-            transferToSequenceFetcher(getTypedText());
-          }
-        }
-      }
-    });
+            {
+              @Override
+              public void keyPressed(KeyEvent e)
+              {
+                if (e.getKeyCode() == KeyEvent.VK_ENTER)
+                {
+                  if (getTypedText() == null || getTypedText().isEmpty())
+                  {
+                    return;
+                  }
+                  String primaryKeyName = getFTSRestClient()
+                          .getPrimaryKeyColumn().getName();
+                  if (primaryKeyName.equalsIgnoreCase(getCmbSearchTarget()
+                          .getSelectedItem().toString()))
+                  {
+                    // TODO: nicer to show the list in the result set before
+                    // viewing in Jalview perhaps ?
+                    transferToSequenceFetcher(getTypedText());
+                  }
+                  else
+                  {
+                    performSearchAction();
+                  }
+                }
+              }
+            });
     final DeferredTextInputListener listener = new DeferredTextInputListener(
             1500, new ActionListener()
             {
               @Override
               public void actionPerformed(ActionEvent e)
               {
-                String typed = getTypedText();
-                if (!typed.equalsIgnoreCase(lastSearchTerm))
+                if (btn_autosearch.isSelected()
+                        || txt_search.wasEnterPressed())
                 {
-                  searchAction(true);
-                  paginatorCart.clear();
-                  lastSearchTerm = typed;
+                  performSearchAction();
                 }
               }
             }, false);
@@ -550,6 +593,15 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI
       }
     });
 
+    txt_search.addActionListener(new ActionListener()
+    {
+
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        performSearchAction();
+      }
+    });
     final String searchTabTitle = MessageManager
             .getString("label.search_result");
     final String configureCols = MessageManager
@@ -579,8 +631,8 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI
           txt_search.setEnabled(false);
           cmb_searchTarget.setEnabled(false);
           previousWantedFields = getFTSRestClient()
-                  .getAllDefaultDisplayedFTSDataColumns().toArray(
-                          new Object[0]);
+                  .getAllDefaultDisplayedFTSDataColumns()
+                  .toArray(new Object[0]);
         }
         if (sourceTabbedPane.getTitleAt(index).equals(searchTabTitle))
         {
@@ -614,6 +666,7 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI
     pnl_results.add(tabbedPane);
     pnl_inputs.add(cmb_searchTarget);
     pnl_inputs.add(txt_search);
+    pnl_inputs.add(btn_autosearch);
     pnl_inputs.add(lbl_loading);
     pnl_inputs.add(lbl_warning);
     pnl_inputs.add(lbl_blank);
@@ -625,10 +678,20 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI
     this.add(pnl_results, java.awt.BorderLayout.CENTER);
     this.add(pnl_actions, java.awt.BorderLayout.SOUTH);
     mainFrame.setVisible(true);
-    mainFrame.setContentPane(this);
+    if (tabs != null)
+    {
+      tabs.setOpaque(true);
+      tabs.insertTab("Free Text Search", null, this, "", 0);
+      mainFrame.setContentPane(tabs);
+      tabs.setVisible(true);
+    }
+    else
+    {
+      mainFrame.setContentPane(this);
+    }
     mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
-    mainFrame
-            .addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
+    mainFrame.addInternalFrameListener(
+            new javax.swing.event.InternalFrameAdapter()
             {
               @Override
               public void internalFrameClosing(InternalFrameEvent e)
@@ -636,8 +699,6 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI
                 closeAction();
               }
             });
-    mainFrame.setVisible(true);
-    mainFrame.setContentPane(this);
     mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
     Integer x = getTempUserPrefs().get("FTSPanel.x");
     Integer y = getTempUserPrefs().get("FTSPanel.y");
@@ -699,6 +760,18 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI
 
   }
 
+  void performSearchAction()
+  {
+    String typed = getTypedText();
+    if (typed != null && typed.length() > 0
+            && !typed.equalsIgnoreCase(lastSearchTerm))
+    {
+      searchAction(true);
+      paginatorCart.clear();
+      lastSearchTerm = typed;
+    }
+  }
+
   public boolean wantedFieldsUpdated()
   {
     if (previousWantedFields == null)
@@ -769,13 +842,13 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI
     {
       lbl_loading.setVisible(false);
       lbl_blank.setVisible(false);
-      lbl_warning.setToolTipText(JvSwingUtils.wrapTooltip(true,
-              errorWarning.toString()));
+      lbl_warning.setToolTipText(
+              JvSwingUtils.wrapTooltip(true, errorWarning.toString()));
       lbl_warning.setVisible(true);
     }
   }
 
-  protected void btn_back_ActionPerformed()
+  public void btn_back_ActionPerformed()
   {
     closeAction();
     new SequenceFetcher(progressIndicator);
@@ -788,7 +861,7 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI
     btn_cancel.setEnabled(false);
   }
 
-  protected void btn_cancel_ActionPerformed()
+  public void btn_cancel_ActionPerformed()
   {
     closeAction();
   }
@@ -918,8 +991,8 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI
     int totalRows = resultTable.getRowCount();
     try
     {
-      primaryKeyColIndex = getFTSRestClient().getPrimaryKeyColumIndex(
-              wantedFields, false);
+      primaryKeyColIndex = getFTSRestClient()
+              .getPrimaryKeyColumIndex(wantedFields, false);
     } catch (Exception e)
     {
       e.printStackTrace();
@@ -952,8 +1025,8 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI
     int primaryKeyColIndex = 0;
     try
     {
-      primaryKeyColIndex = getFTSRestClient().getPrimaryKeyColumIndex(
-              wantedFields, false);
+      primaryKeyColIndex = getFTSRestClient()
+              .getPrimaryKeyColumIndex(wantedFields, false);
     } catch (Exception e)
     {
       e.printStackTrace();
@@ -993,5 +1066,4 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI
     mainFrame.setTitle(getFTSFrameTitle());
   }
 
-
 }
index b944b9b..053d91b 100644 (file)
@@ -39,18 +39,19 @@ public class PDBFTSPanel extends GFTSPanel
   private static String defaultFTSFrameTitle = MessageManager
           .getString("label.pdb_sequence_fetcher");
 
-
   private static Map<String, Integer> tempUserPrefs = new HashMap<String, Integer>();
 
   private static final String PDB_FTS_CACHE_KEY = "CACHE.PDB_FTS";
 
-  public PDBFTSPanel(SequenceFetcher seqFetcher)
+  private static final String PDB_AUTOSEARCH = "FTS.PDB.AUTOSEARCH";
+
+  public PDBFTSPanel(SequenceFetcher fetcher)
   {
-    super();
+    super(fetcher);
     pageLimit = PDBFTSRestClient.getInstance().getDefaultResponsePageSize();
-    this.seqFetcher = seqFetcher;
-    this.progressIndicator = (seqFetcher == null) ? null : seqFetcher
-            .getProgressIndicator();
+    this.seqFetcher = fetcher;
+    this.progressIndicator = (fetcher == null) ? null
+            : fetcher.getProgressIndicator();
   }
 
   @Override
@@ -87,24 +88,24 @@ public class PDBFTSPanel extends GFTSPanel
           request.setSearchTerm(searchTerm + ")");
           request.setOffSet(offSet);
           request.setWantedFields(wantedFields);
-          FTSRestClientI pdbRestCleint = PDBFTSRestClient.getInstance();
+          FTSRestClientI pdbRestClient = PDBFTSRestClient.getInstance();
           FTSRestResponse resultList;
           try
           {
-            resultList = pdbRestCleint.executeRequest(request);
+            resultList = pdbRestClient.executeRequest(request);
           } catch (Exception e)
           {
             setErrorMessage(e.getMessage());
             checkForErrors();
+            setSearchInProgress(false);
             return;
           }
 
           if (resultList.getSearchSummary() != null
                   && resultList.getSearchSummary().size() > 0)
           {
-            getResultTable().setModel(
-                    FTSRestResponse.getTableModel(request,
-                            resultList.getSearchSummary()));
+            getResultTable().setModel(FTSRestResponse.getTableModel(request,
+                    resultList.getSearchSummary()));
             FTSRestResponse.configureTableColumn(getResultTable(),
                     wantedFields, tempUserPrefs);
             getResultTable().setVisible(true);
@@ -114,15 +115,13 @@ public class PDBFTSPanel extends GFTSPanel
           totalResultSetCount = resultList.getNumberOfItemsFound();
           resultSetCount = resultList.getSearchSummary() == null ? 0
                   : resultList.getSearchSummary().size();
-          String result = (resultSetCount > 0) ? MessageManager
-                  .getString("label.results") : MessageManager
-                  .getString("label.result");
+          String result = (resultSetCount > 0)
+                  ? MessageManager.getString("label.results")
+                  : MessageManager.getString("label.result");
 
           if (isPaginationEnabled() && resultSetCount > 0)
           {
-            updateSearchFrameTitle(defaultFTSFrameTitle
-                    + " - "
-                    + result
+            updateSearchFrameTitle(defaultFTSFrameTitle + " - " + result
                     + " "
                     + totalNumberformatter.format((Number) (offSet + 1))
                     + " to "
@@ -130,8 +129,8 @@ public class PDBFTSPanel extends GFTSPanel
                             .format((Number) (offSet + resultSetCount))
                     + " of "
                     + totalNumberformatter
-                            .format((Number) totalResultSetCount) + " "
-                    + " (" + (endTime - startTime) + " milli secs)");
+                            .format((Number) totalResultSetCount)
+                    + " " + " (" + (endTime - startTime) + " milli secs)");
           }
           else
           {
@@ -174,8 +173,8 @@ public class PDBFTSPanel extends GFTSPanel
       foundSearchTerms = foundSearchTermsBuilder.toString();
       if (foundSearchTerms.contains(" OR "))
       {
-        foundSearchTerms = foundSearchTerms.substring(
-                targetField.length() + 1, endIndex);
+        foundSearchTerms = foundSearchTerms
+                .substring(targetField.length() + 1, endIndex);
       }
     }
     else if (enteredText.contains(":"))
@@ -195,8 +194,8 @@ public class PDBFTSPanel extends GFTSPanel
     int primaryKeyColIndex = 0;
     try
     {
-      primaryKeyColIndex = getFTSRestClient().getPrimaryKeyColumIndex(
-              wantedFields, false);
+      primaryKeyColIndex = getFTSRestClient()
+              .getPrimaryKeyColumIndex(wantedFields, false);
     } catch (Exception e)
     {
       e.printStackTrace();
@@ -205,8 +204,8 @@ public class PDBFTSPanel extends GFTSPanel
     String searchTerm = getTypedText();
     for (int summaryRow : selectedRows)
     {
-      String idStr = getResultTable().getValueAt(summaryRow,
-              primaryKeyColIndex).toString();
+      String idStr = getResultTable()
+              .getValueAt(summaryRow, primaryKeyColIndex).toString();
       selectedIdsSet.add(getPDBIdwithSpecifiedChain(idStr, searchTerm));
     }
 
@@ -278,12 +277,15 @@ public class PDBFTSPanel extends GFTSPanel
     return tempUserPrefs;
   }
 
-
   @Override
   public String getCacheKey()
   {
     return PDB_FTS_CACHE_KEY;
   }
 
-
-}
+  @Override
+  public String getAutosearchPreference()
+  {
+    return PDB_AUTOSEARCH;
+  }
+}
\ No newline at end of file
index 06bf55b..cbeaff1 100644 (file)
@@ -59,7 +59,7 @@ public class PDBFTSRestClient extends FTSRestClient
 
   private static FTSRestClientI instance = null;
 
-  public static final String PDB_SEARCH_ENDPOINT = "http://www.ebi.ac.uk/pdbe/search/pdb/select?";
+  public static final String PDB_SEARCH_ENDPOINT = "https://www.ebi.ac.uk/pdbe/search/pdb/select?";
 
   protected PDBFTSRestClient()
   {
@@ -82,9 +82,10 @@ public class PDBFTSRestClient extends FTSRestClient
       ClientConfig clientConfig = new DefaultClientConfig();
       Client client = Client.create(clientConfig);
 
-      String wantedFields = getDataColumnsFieldsAsCommaDelimitedString(pdbRestRequest
-              .getWantedFields());
-      int responseSize = (pdbRestRequest.getResponseSize() == 0) ? getDefaultResponsePageSize()
+      String wantedFields = getDataColumnsFieldsAsCommaDelimitedString(
+              pdbRestRequest.getWantedFields());
+      int responseSize = (pdbRestRequest.getResponseSize() == 0)
+              ? getDefaultResponsePageSize()
               : pdbRestRequest.getResponseSize();
       int offSet = pdbRestRequest.getOffSet();
       String sortParam = null;
@@ -108,11 +109,11 @@ public class PDBFTSRestClient extends FTSRestClient
         }
       }
 
-      String facetPivot = (pdbRestRequest.getFacetPivot() == null || pdbRestRequest
-              .getFacetPivot().isEmpty()) ? "" : pdbRestRequest
-              .getFacetPivot();
-      String facetPivotMinCount = String.valueOf(pdbRestRequest
-              .getFacetPivotMinCount());
+      String facetPivot = (pdbRestRequest.getFacetPivot() == null
+              || pdbRestRequest.getFacetPivot().isEmpty()) ? ""
+                      : pdbRestRequest.getFacetPivot();
+      String facetPivotMinCount = String
+              .valueOf(pdbRestRequest.getFacetPivotMinCount());
 
       String query = pdbRestRequest.getFieldToSearchBy()
               + pdbRestRequest.getSearchTerm()
@@ -143,8 +144,8 @@ public class PDBFTSRestClient extends FTSRestClient
                 .queryParam("q", query).queryParam("sort", sortParam);
       }
       // Execute the REST request
-      ClientResponse clientResponse = webResource.accept(
-              MediaType.APPLICATION_JSON).get(ClientResponse.class);
+      ClientResponse clientResponse = webResource
+              .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
 
       // Get the JSON string from the response object
       String responseString = clientResponse.getEntity(String.class);
@@ -180,9 +181,8 @@ public class PDBFTSRestClient extends FTSRestClient
       if (exceptionMsg.contains("SocketException"))
       {
         // No internet connection
-        throw new Exception(
-                MessageManager
-                        .getString("exception.unable_to_detect_internet_connection"));
+        throw new Exception(MessageManager.getString(
+                "exception.unable_to_detect_internet_connection"));
       }
       else if (exceptionMsg.contains("UnknownHostException"))
       {
@@ -260,8 +260,8 @@ public class PDBFTSRestClient extends FTSRestClient
               .parse(pdbJsonResponseString);
 
       JSONObject pdbResponse = (JSONObject) jsonObj.get("response");
-      String queryTime = ((JSONObject) jsonObj.get("responseHeader")).get(
-              "QTime").toString();
+      String queryTime = ((JSONObject) jsonObj.get("responseHeader"))
+              .get("QTime").toString();
       int numFound = Integer
               .valueOf(pdbResponse.get("numFound").toString());
       if (numFound > 0)
@@ -298,8 +298,9 @@ public class PDBFTSRestClient extends FTSRestClient
     Collection<FTSDataColumnI> diplayFields = request.getWantedFields();
     SequenceI associatedSeq = request.getAssociatedSequence();
     int colCounter = 0;
-    summaryRowData = new Object[(associatedSeq != null) ? diplayFields
-            .size() + 1 : diplayFields.size()];
+    summaryRowData = new Object[(associatedSeq != null)
+            ? diplayFields.size() + 1
+            : diplayFields.size()];
     if (associatedSeq != null)
     {
       associatedSequence = associatedSeq;
@@ -325,10 +326,12 @@ public class PDBFTSRestClient extends FTSRestClient
         try
         {
           summaryRowData[colCounter++] = (field.getDataType()
-                  .getDataTypeClass() == Integer.class) ? Integer
-                  .valueOf(fieldData) : (field.getDataType()
-                  .getDataTypeClass() == Double.class) ? Double
-                  .valueOf(fieldData) : sanitiseData(fieldData);
+                  .getDataTypeClass() == Integer.class)
+                          ? Integer.valueOf(fieldData)
+                          : (field.getDataType()
+                                  .getDataTypeClass() == Double.class)
+                                          ? Double.valueOf(fieldData)
+                                          : sanitiseData(fieldData);
         } catch (Exception e)
         {
           e.printStackTrace();
@@ -418,8 +421,8 @@ public class PDBFTSRestClient extends FTSRestClient
             || allDefaultDisplayedStructureDataColumns.isEmpty())
     {
       allDefaultDisplayedStructureDataColumns = new ArrayList<FTSDataColumnI>();
-      allDefaultDisplayedStructureDataColumns.addAll(super
-              .getAllDefaultDisplayedFTSDataColumns());
+      allDefaultDisplayedStructureDataColumns
+              .addAll(super.getAllDefaultDisplayedFTSDataColumns());
     }
     return allDefaultDisplayedStructureDataColumns;
   }
index a23df4c..250fba0 100644 (file)
@@ -57,9 +57,10 @@ public class UniProtFTSRestClient extends FTSRestClient
       ClientConfig clientConfig = new DefaultClientConfig();
       Client client = Client.create(clientConfig);
 
-      String wantedFields = getDataColumnsFieldsAsCommaDelimitedString(uniportRestRequest
-              .getWantedFields());
-      int responseSize = (uniportRestRequest.getResponseSize() == 0) ? getDefaultResponsePageSize()
+      String wantedFields = getDataColumnsFieldsAsCommaDelimitedString(
+              uniportRestRequest.getWantedFields());
+      int responseSize = (uniportRestRequest.getResponseSize() == 0)
+              ? getDefaultResponsePageSize()
               : uniportRestRequest.getResponseSize();
 
       int offSet = uniportRestRequest.getOffSet();
@@ -70,11 +71,13 @@ public class UniProtFTSRestClient extends FTSRestClient
       }
       else
       {
-        query = uniportRestRequest.getFieldToSearchBy().equalsIgnoreCase(
-                "Search All") ? uniportRestRequest.getSearchTerm()
-                + " or mnemonic:" + uniportRestRequest.getSearchTerm()
-                : uniportRestRequest.getFieldToSearchBy() + ":"
-                        + uniportRestRequest.getSearchTerm();
+        query = uniportRestRequest.getFieldToSearchBy()
+                .equalsIgnoreCase("Search All")
+                        ? uniportRestRequest.getSearchTerm()
+                                + " or mnemonic:"
+                                + uniportRestRequest.getSearchTerm()
+                        : uniportRestRequest.getFieldToSearchBy() + ":"
+                                + uniportRestRequest.getSearchTerm();
       }
 
       WebResource webResource = null;
@@ -85,8 +88,8 @@ public class UniProtFTSRestClient extends FTSRestClient
               .queryParam("offset", String.valueOf(offSet))
               .queryParam("sort", "score").queryParam("query", query);
       // Execute the REST request
-      ClientResponse clientResponse = webResource.accept(
-              MediaType.TEXT_PLAIN).get(ClientResponse.class);
+      ClientResponse clientResponse = webResource
+              .accept(MediaType.TEXT_PLAIN).get(ClientResponse.class);
       String uniProtTabDelimittedResponseString = clientResponse
               .getEntity(String.class);
       // Make redundant objects eligible for garbage collection to conserve
@@ -100,8 +103,8 @@ public class UniProtFTSRestClient extends FTSRestClient
         throw new Exception(errorMessage);
 
       }
-      int xTotalResults = Integer.valueOf(clientResponse.getHeaders()
-              .get("X-Total-Results").get(0));
+      int xTotalResults = Integer.valueOf(
+              clientResponse.getHeaders().get("X-Total-Results").get(0));
       clientResponse = null;
       client = null;
       return parseUniprotResponse(uniProtTabDelimittedResponseString,
@@ -112,9 +115,8 @@ public class UniProtFTSRestClient extends FTSRestClient
       if (exceptionMsg.contains("SocketException"))
       {
         // No internet connection
-        throw new Exception(
-                MessageManager
-                        .getString("exception.unable_to_detect_internet_connection"));
+        throw new Exception(MessageManager.getString(
+                "exception.unable_to_detect_internet_connection"));
       }
       else if (exceptionMsg.contains("UnknownHostException"))
       {
@@ -239,10 +241,12 @@ public class UniProtFTSRestClient extends FTSRestClient
           try
           {
             summaryRowData[colCounter++] = (field.getDataType()
-                    .getDataTypeClass() == Integer.class) ? Integer
-                    .valueOf(fieldData.replace(",", ""))
-                    : (field.getDataType().getDataTypeClass() == Double.class) ? Double
-                            .valueOf(fieldData) : fieldData;
+                    .getDataTypeClass() == Integer.class)
+                            ? Integer.valueOf(fieldData.replace(",", ""))
+                            : (field.getDataType()
+                                    .getDataTypeClass() == Double.class)
+                                            ? Double.valueOf(fieldData)
+                                            : fieldData;
           } catch (Exception e)
           {
             e.printStackTrace();
index ace3600..df54dea 100644 (file)
@@ -40,19 +40,20 @@ public class UniprotFTSPanel extends GFTSPanel
   private static String defaultFTSFrameTitle = MessageManager
           .getString("label.uniprot_sequence_fetcher");
 
-
-  private static Map<String, Integer> tempUserPrefs = new HashMap<String, Integer>();
+  private static Map<String, Integer> tempUserPrefs = new HashMap<>();
 
   private static final String UNIPROT_FTS_CACHE_KEY = "CACHE.UNIPROT_FTS";
 
-  public UniprotFTSPanel(SequenceFetcher seqFetcher)
+  private static final String UNIPROT_AUTOSEARCH = "FTS.UNIPROT.AUTOSEARCH";
+
+  public UniprotFTSPanel(SequenceFetcher fetcher)
   {
-    super();
+    super(fetcher);
     pageLimit = UniProtFTSRestClient.getInstance()
             .getDefaultResponsePageSize();
-    this.seqFetcher = seqFetcher;
-    this.progressIndicator = (seqFetcher == null) ? null : seqFetcher
-            .getProgressIndicator();
+    this.seqFetcher = fetcher;
+    this.progressIndicator = (fetcher == null) ? null
+            : fetcher.getProgressIndicator();
   }
 
   @Override
@@ -86,26 +87,25 @@ public class UniprotFTSPanel extends GFTSPanel
           request.setSearchTerm(searchTerm);
           request.setOffSet(offSet);
           request.setWantedFields(wantedFields);
-          FTSRestClientI uniProtRestCleint = UniProtFTSRestClient
+          FTSRestClientI uniProtRestClient = UniProtFTSRestClient
                   .getInstance();
           FTSRestResponse resultList;
           try
           {
-            resultList = uniProtRestCleint.executeRequest(request);
+            resultList = uniProtRestClient.executeRequest(request);
           } catch (Exception e)
           {
-            e.printStackTrace();
             setErrorMessage(e.getMessage());
             checkForErrors();
+            setSearchInProgress(false);
             return;
           }
 
           if (resultList.getSearchSummary() != null
                   && resultList.getSearchSummary().size() > 0)
           {
-            getResultTable().setModel(
-                    FTSRestResponse.getTableModel(request,
-                            resultList.getSearchSummary()));
+            getResultTable().setModel(FTSRestResponse.getTableModel(request,
+                    resultList.getSearchSummary()));
             FTSRestResponse.configureTableColumn(getResultTable(),
                     wantedFields, tempUserPrefs);
             getResultTable().setVisible(true);
@@ -115,14 +115,12 @@ public class UniprotFTSPanel extends GFTSPanel
           totalResultSetCount = resultList.getNumberOfItemsFound();
           resultSetCount = resultList.getSearchSummary() == null ? 0
                   : resultList.getSearchSummary().size();
-          String result = (resultSetCount > 0) ? MessageManager
-                  .getString("label.results") : MessageManager
-                  .getString("label.result");
+          String result = (resultSetCount > 0)
+                  ? MessageManager.getString("label.results")
+                  : MessageManager.getString("label.result");
           if (isPaginationEnabled() && resultSetCount > 0)
           {
-            updateSearchFrameTitle(defaultFTSFrameTitle
-                    + " - "
-                    + result
+            updateSearchFrameTitle(defaultFTSFrameTitle + " - " + result
                     + " "
                     + totalNumberformatter.format((Number) (offSet + 1))
                     + " to "
@@ -130,8 +128,8 @@ public class UniprotFTSPanel extends GFTSPanel
                             .format((Number) (offSet + resultSetCount))
                     + " of "
                     + totalNumberformatter
-                            .format((Number) totalResultSetCount) + " "
-                    + " (" + (endTime - startTime) + " milli secs)");
+                            .format((Number) totalResultSetCount)
+                    + " " + " (" + (endTime - startTime) + " milli secs)");
           }
           else
           {
@@ -187,12 +185,12 @@ public class UniprotFTSPanel extends GFTSPanel
   {
     disableActionButtons();
     StringBuilder selectedIds = new StringBuilder();
-    HashSet<String> selectedIdsSet = new HashSet<String>();
+    HashSet<String> selectedIdsSet = new HashSet<>();
     int primaryKeyColIndex = 0;
     try
     {
-      primaryKeyColIndex = getFTSRestClient().getPrimaryKeyColumIndex(
-              wantedFields, false);
+      primaryKeyColIndex = getFTSRestClient()
+              .getPrimaryKeyColumIndex(wantedFields, false);
     } catch (Exception e)
     {
       e.printStackTrace();
@@ -200,8 +198,8 @@ public class UniprotFTSPanel extends GFTSPanel
     int[] selectedRows = getResultTable().getSelectedRows();
     for (int summaryRow : selectedRows)
     {
-      String idStr = getResultTable().getValueAt(summaryRow,
-              primaryKeyColIndex).toString();
+      String idStr = getResultTable()
+              .getValueAt(summaryRow, primaryKeyColIndex).toString();
       selectedIdsSet.add(idStr);
     }
     selectedIdsSet.addAll(paginatorCart);
@@ -241,4 +239,10 @@ public class UniprotFTSPanel extends GFTSPanel
   {
     return UNIPROT_FTS_CACHE_KEY;
   }
+
+  @Override
+  public String getAutosearchPreference()
+  {
+    return UNIPROT_AUTOSEARCH;
+  }
 }
index b9845a4..201570e 100644 (file)
@@ -34,8 +34,8 @@ import javax.swing.JDialog;
 import javax.swing.JOptionPane;
 
 @SuppressWarnings("serial")
-public class AlignExportSettings extends GAlignExportSettings implements
-        AlignExportSettingI
+public class AlignExportSettings extends GAlignExportSettings
+        implements AlignExportSettingI
 {
   boolean cancelled = false;
 
@@ -49,7 +49,8 @@ public class AlignExportSettings extends GAlignExportSettings implements
     {
 
       JOptionPane pane = new JOptionPane(null, JOptionPane.DEFAULT_OPTION,
-              JvOptionPane.DEFAULT_OPTION, null, new Object[] { this });
+              JvOptionPane.DEFAULT_OPTION, null, new Object[]
+              { this });
       dialog = pane.createDialog(Desktop.desktop,
               MessageManager.getString("label.export_settings"));
       dialog.addWindowListener(new WindowAdapter()
index f4dd851..298688b 100644 (file)
@@ -163,8 +163,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
   AlignViewport viewport;
 
-  ViewportRanges vpRanges;
-
   public AlignViewControllerI avc;
 
   List<AlignmentPanel> alignPanels = new ArrayList<>();
@@ -234,8 +232,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    * @param height
    *          height of frame.
    */
-  public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns,
-          int width, int height)
+  public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
+          int height)
   {
     this(al, hiddenColumns, width, height, null);
   }
@@ -251,8 +249,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    * @param sequenceSetId
    *          (may be null)
    */
-  public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns,
-          int width, int height, String sequenceSetId)
+  public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
+          int height, String sequenceSetId)
   {
     this(al, hiddenColumns, width, height, sequenceSetId, null);
   }
@@ -270,8 +268,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    * @param viewId
    *          (may be null)
    */
-  public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns,
-          int width, int height, String sequenceSetId, String viewId)
+  public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
+          int height, String sequenceSetId, String viewId)
   {
     setSize(width, height);
 
@@ -336,7 +334,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       progressBar = new ProgressBar(this.statusPanel, this.statusBar);
     }
 
-    vpRanges = viewport.getRanges();
     avc = new jalview.controller.AlignViewController(this, viewport,
             alignPanel);
     if (viewport.getAlignmentConservationAnnotation() == null)
@@ -510,9 +507,10 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       public void keyPressed(KeyEvent evt)
       {
         if (viewport.cursorMode
-                && ((evt.getKeyCode() >= KeyEvent.VK_0 && evt.getKeyCode() <= KeyEvent.VK_9) || (evt
-                        .getKeyCode() >= KeyEvent.VK_NUMPAD0 && evt
-                        .getKeyCode() <= KeyEvent.VK_NUMPAD9))
+                && ((evt.getKeyCode() >= KeyEvent.VK_0
+                        && evt.getKeyCode() <= KeyEvent.VK_9)
+                        || (evt.getKeyCode() >= KeyEvent.VK_NUMPAD0
+                                && evt.getKeyCode() <= KeyEvent.VK_NUMPAD9))
                 && Character.isDigit(evt.getKeyChar()))
         {
           alignPanel.getSeqPanel().numberPressed(evt.getKeyChar());
@@ -552,7 +550,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
         case KeyEvent.VK_LEFT:
           if (evt.isAltDown() || !viewport.cursorMode)
           {
-            slideSequences(false, alignPanel.getSeqPanel().getKeyboardNo1());
+            slideSequences(false,
+                    alignPanel.getSeqPanel().getKeyboardNo1());
           }
           else
           {
@@ -575,9 +574,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
         case KeyEvent.VK_SPACE:
           if (viewport.cursorMode)
           {
-            alignPanel.getSeqPanel().insertGapAtCursor(
-                    evt.isControlDown() || evt.isShiftDown()
-                            || evt.isAltDown());
+            alignPanel.getSeqPanel().insertGapAtCursor(evt.isControlDown()
+                    || evt.isShiftDown() || evt.isAltDown());
           }
           break;
 
@@ -600,9 +598,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           }
           else
           {
-            alignPanel.getSeqPanel().deleteGapAtCursor(
-                    evt.isControlDown() || evt.isShiftDown()
-                            || evt.isAltDown());
+            alignPanel.getSeqPanel().deleteGapAtCursor(evt.isControlDown()
+                    || evt.isShiftDown() || evt.isAltDown());
           }
 
           break;
@@ -649,14 +646,15 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
         case KeyEvent.VK_F2:
           viewport.cursorMode = !viewport.cursorMode;
-          statusBar.setText(MessageManager.formatMessage(
-                  "label.keyboard_editing_mode",
-                  new String[] { (viewport.cursorMode ? "on" : "off") }));
+          statusBar.setText(MessageManager
+                  .formatMessage("label.keyboard_editing_mode", new String[]
+                  { (viewport.cursorMode ? "on" : "off") }));
           if (viewport.cursorMode)
           {
-            alignPanel.getSeqPanel().seqCanvas.cursorX = vpRanges
+            ViewportRanges ranges = viewport.getRanges();
+            alignPanel.getSeqPanel().seqCanvas.cursorX = ranges
                     .getStartRes();
-            alignPanel.getSeqPanel().seqCanvas.cursorY = vpRanges
+            alignPanel.getSeqPanel().seqCanvas.cursorY = ranges
                     .getStartSeq();
           }
           alignPanel.getSeqPanel().seqCanvas.repaint();
@@ -689,10 +687,10 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           break;
         }
         case KeyEvent.VK_PAGE_UP:
-          vpRanges.pageUp();
+          viewport.getRanges().pageUp();
           break;
         case KeyEvent.VK_PAGE_DOWN:
-          vpRanges.pageDown();
+          viewport.getRanges().pageDown();
           break;
         }
       }
@@ -705,16 +703,16 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
         case KeyEvent.VK_LEFT:
           if (evt.isAltDown() || !viewport.cursorMode)
           {
-            viewport.firePropertyChange("alignment", null, viewport
-                    .getAlignment().getSequences());
+            viewport.firePropertyChange("alignment", null,
+                    viewport.getAlignment().getSequences());
           }
           break;
 
         case KeyEvent.VK_RIGHT:
           if (evt.isAltDown() || !viewport.cursorMode)
           {
-            viewport.firePropertyChange("alignment", null, viewport
-                    .getAlignment().getSequences());
+            viewport.firePropertyChange("alignment", null,
+                    viewport.getAlignment().getSequences());
           }
           break;
         }
@@ -800,8 +798,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                     @Override
                     public void run()
                     {
-                      System.err
-                              .println("Rebuild WS Menu for service change");
+                      System.err.println(
+                              "Rebuild WS Menu for service change");
                       BuildWebServiceMenu();
                     }
 
@@ -845,13 +843,13 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     showReverse.setVisible(nucleotide);
     showReverseComplement.setVisible(nucleotide);
     conservationMenuItem.setEnabled(!nucleotide);
-    modifyConservation.setEnabled(!nucleotide
-            && conservationMenuItem.isSelected());
+    modifyConservation
+            .setEnabled(!nucleotide && conservationMenuItem.isSelected());
     showGroupConservation.setEnabled(!nucleotide);
 
-    showComplementMenuItem.setText(nucleotide ? MessageManager
-            .getString("label.protein") : MessageManager
-            .getString("label.nucleotide"));
+    showComplementMenuItem
+            .setText(nucleotide ? MessageManager.getString("label.protein")
+                    : MessageManager.getString("label.nucleotide"));
   }
 
   /**
@@ -1025,7 +1023,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
         Desktop.instance.closeAssociatedWindows();
 
         FileLoader loader = new FileLoader();
-        DataSourceType protocol = fileName.startsWith("http:") ? DataSourceType.URL
+        DataSourceType protocol = fileName.startsWith("http:")
+                ? DataSourceType.URL
                 : DataSourceType.FILE;
         loader.LoadFile(viewport, fileName, protocol, currentFileFormat);
       }
@@ -1034,7 +1033,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
         Rectangle bounds = this.getBounds();
 
         FileLoader loader = new FileLoader();
-        DataSourceType protocol = fileName.startsWith("http:") ? DataSourceType.URL
+        DataSourceType protocol = fileName.startsWith("http:")
+                ? DataSourceType.URL
                 : DataSourceType.FILE;
         AlignFrame newframe = loader.LoadFileWaitTillLoaded(fileName,
                 protocol, currentFileFormat);
@@ -1066,8 +1066,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   public void addFromText_actionPerformed(ActionEvent e)
   {
-    Desktop.instance.inputTextboxMenuItem_actionPerformed(viewport
-            .getAlignPanel());
+    Desktop.instance
+            .inputTextboxMenuItem_actionPerformed(viewport.getAlignPanel());
   }
 
   @Override
@@ -1099,14 +1099,14 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   public void saveAs_actionPerformed(ActionEvent e)
   {
-    String format = currentFileFormat == null ? null : currentFileFormat
-            .getName();
-    JalviewFileChooser chooser = JalviewFileChooser.forWrite(
-            Cache.getProperty("LAST_DIRECTORY"), format);
+    String format = currentFileFormat == null ? null
+            : currentFileFormat.getName();
+    JalviewFileChooser chooser = JalviewFileChooser
+            .forWrite(Cache.getProperty("LAST_DIRECTORY"), format);
 
     chooser.setFileView(new JalviewFileView());
-    chooser.setDialogTitle(MessageManager
-            .getString("label.save_alignment_to_file"));
+    chooser.setDialogTitle(
+            MessageManager.getString("label.save_alignment_to_file"));
     chooser.setToolTipText(MessageManager.getString("action.save"));
 
     int value = chooser.showSaveDialog(this);
@@ -1116,14 +1116,11 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       currentFileFormat = chooser.getSelectedFormat();
       while (currentFileFormat == null)
       {
-        JvOptionPane
-                .showInternalMessageDialog(
-                        Desktop.desktop,
-                        MessageManager
-                                .getString("label.select_file_format_before_saving"),
-                        MessageManager
-                                .getString("label.file_format_not_specified"),
-                        JvOptionPane.WARNING_MESSAGE);
+        JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                MessageManager.getString(
+                        "label.select_file_format_before_saving"),
+                MessageManager.getString("label.file_format_not_specified"),
+                JvOptionPane.WARNING_MESSAGE);
         currentFileFormat = chooser.getSelectedFormat();
         value = chooser.showSaveDialog(this);
         if (value != JalviewFileChooser.APPROVE_OPTION)
@@ -1151,15 +1148,15 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
       if (shortName.indexOf(java.io.File.separatorChar) > -1)
       {
-        shortName = shortName.substring(shortName
-                .lastIndexOf(java.io.File.separatorChar) + 1);
+        shortName = shortName.substring(
+                shortName.lastIndexOf(java.io.File.separatorChar) + 1);
       }
 
       success = new Jalview2XML().saveAlignment(this, file, shortName);
 
       statusBar.setText(MessageManager.formatMessage(
-              "label.successfully_saved_to_file_in_format", new Object[] {
-                  fileName, format }));
+              "label.successfully_saved_to_file_in_format", new Object[]
+              { fileName, format }));
 
     }
     else
@@ -1172,13 +1169,14 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       }
       FormatAdapter f = new FormatAdapter(alignPanel,
               exportData.getSettings());
-      String output = f.formatSequences(
-              format,
-              exportData.getAlignment(), // class cast exceptions will
+      String output = f.formatSequences(format, exportData.getAlignment(), // class
+                                                                           // cast
+                                                                           // exceptions
+                                                                           // will
               // occur in the distant future
               exportData.getOmitHidden(), exportData.getStartEndPostions(),
-              f.getCacheSuffixDefault(format), viewport.getAlignment()
-                      .getHiddenColumns());
+              f.getCacheSuffixDefault(format),
+              viewport.getAlignment().getHiddenColumns());
 
       if (output == null)
       {
@@ -1194,8 +1192,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           out.close();
           this.setTitle(file);
           statusBar.setText(MessageManager.formatMessage(
-                  "label.successfully_saved_to_file_in_format",
-                  new Object[] { fileName, format.getName() }));
+                  "label.successfully_saved_to_file_in_format", new Object[]
+                  { fileName, format.getName() }));
         } catch (Exception ex)
         {
           success = false;
@@ -1207,9 +1205,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     if (!success)
     {
       JvOptionPane.showInternalMessageDialog(this, MessageManager
-              .formatMessage("label.couldnt_save_file",
-                      new Object[] { fileName }), MessageManager
-              .getString("label.error_saving_file"),
+              .formatMessage("label.couldnt_save_file", new Object[]
+              { fileName }),
+              MessageManager.getString("label.error_saving_file"),
               JvOptionPane.WARNING_MESSAGE);
     }
 
@@ -1240,8 +1238,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   protected void outputText_actionPerformed(ActionEvent e)
   {
-    FileFormatI fileFormat = FileFormats.getInstance().forName(
-            e.getActionCommand());
+    FileFormatI fileFormat = FileFormats.getInstance()
+            .forName(e.getActionCommand());
     AlignmentExportData exportData = getAlignmentForExport(fileFormat,
             viewport, null);
     if (exportData.getSettings().isCancelled())
@@ -1256,15 +1254,15 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       cap.setText(new FormatAdapter(alignPanel, exportData.getSettings())
               .formatSequences(format, exportData.getAlignment(),
                       exportData.getOmitHidden(),
- exportData
-                              .getStartEndPostions(), viewport
-                              .getAlignment().getHiddenColumns()));
-      Desktop.addInternalFrame(cap, MessageManager.formatMessage(
-              "label.alignment_output_command",
-              new Object[] { e.getActionCommand() }), 600, 500);
+                      exportData.getStartEndPostions(),
+                      viewport.getAlignment().getHiddenColumns()));
+      Desktop.addInternalFrame(cap, MessageManager
+              .formatMessage("label.alignment_output_command", new Object[]
+              { e.getActionCommand() }), 600, 500);
     } catch (OutOfMemoryError oom)
     {
-      new OOMWarning("Outputting alignment as " + e.getActionCommand(), oom);
+      new OOMWarning("Outputting alignment as " + e.getActionCommand(),
+              oom);
       cap.dispose();
     }
 
@@ -1408,10 +1406,10 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     JalviewFileChooser chooser = new JalviewFileChooser(
             jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
     chooser.setFileView(new JalviewFileView());
-    chooser.setDialogTitle(MessageManager
-            .getString("label.load_jalview_annotations"));
-    chooser.setToolTipText(MessageManager
-            .getString("label.load_jalview_annotations"));
+    chooser.setDialogTitle(
+            MessageManager.getString("label.load_jalview_annotations"));
+    chooser.setToolTipText(
+            MessageManager.getString("label.load_jalview_annotations"));
 
     int value = chooser.showOpenDialog(null);
 
@@ -1510,9 +1508,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     {
       undoMenuItem.setEnabled(true);
       CommandI command = viewport.getHistoryList().peek();
-      undoMenuItem.setText(MessageManager.formatMessage(
-              "label.undo_command",
-              new Object[] { command.getDescription() }));
+      undoMenuItem.setText(MessageManager
+              .formatMessage("label.undo_command", new Object[]
+              { command.getDescription() }));
     }
     else
     {
@@ -1525,9 +1523,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       redoMenuItem.setEnabled(true);
 
       CommandI command = viewport.getRedoList().peek();
-      redoMenuItem.setText(MessageManager.formatMessage(
-              "label.redo_command",
-              new Object[] { command.getDescription() }));
+      redoMenuItem.setText(MessageManager
+              .formatMessage("label.redo_command", new Object[]
+              { command.getDescription() }));
     }
     else
     {
@@ -1599,8 +1597,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     {
       if (originalSource != viewport)
       {
-        Cache.log
-                .warn("Implementation worry: mismatch of viewport origin for undo");
+        Cache.log.warn(
+                "Implementation worry: mismatch of viewport origin for undo");
       }
       originalSource.updateHiddenColumns();
       // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
@@ -1608,8 +1606,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       // && viewport.getColumnSelection().getHiddenColumns() != null &&
       // viewport.getColumnSelection()
       // .getHiddenColumns().size() > 0);
-      originalSource.firePropertyChange("alignment", null, originalSource
-              .getAlignment().getSequences());
+      originalSource.firePropertyChange("alignment", null,
+              originalSource.getAlignment().getSequences());
     }
   }
 
@@ -1639,8 +1637,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
       if (originalSource != viewport)
       {
-        Cache.log
-                .warn("Implementation worry: mismatch of viewport origin for redo");
+        Cache.log.warn(
+                "Implementation worry: mismatch of viewport origin for redo");
       }
       originalSource.updateHiddenColumns();
       // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
@@ -1648,8 +1646,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       // && viewport.getColumnSelection().getHiddenColumns() != null &&
       // viewport.getColumnSelection()
       // .getHiddenColumns().size() > 0);
-      originalSource.firePropertyChange("alignment", null, originalSource
-              .getAlignment().getSequences());
+      originalSource.firePropertyChange("alignment", null,
+              originalSource.getAlignment().getSequences());
     }
   }
 
@@ -1664,8 +1662,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     {
       EditCommand editCommand = (EditCommand) command;
       al = editCommand.getAlignment();
-      List<Component> comps = PaintRefresher.components.get(viewport
-              .getSequenceSetId());
+      List<Component> comps = PaintRefresher.components
+              .get(viewport.getSequenceSetId());
 
       for (Component comp : comps)
       {
@@ -1711,7 +1709,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
     viewport.getAlignment().moveSelectedSequencesByOne(sg,
             viewport.getHiddenRepSequences(), up);
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, false);
   }
 
   synchronized void slideSequences(boolean right, int size)
@@ -1719,15 +1717,15 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     List<SequenceI> sg = new ArrayList<>();
     if (viewport.cursorMode)
     {
-      sg.add(viewport.getAlignment().getSequenceAt(
-              alignPanel.getSeqPanel().seqCanvas.cursorY));
+      sg.add(viewport.getAlignment()
+              .getSequenceAt(alignPanel.getSeqPanel().seqCanvas.cursorY));
     }
     else if (viewport.getSelectionGroup() != null
             && viewport.getSelectionGroup().getSize() != viewport
                     .getAlignment().getHeight())
     {
-      sg = viewport.getSelectionGroup().getSequences(
-              viewport.getHiddenRepSequences());
+      sg = viewport.getSelectionGroup()
+              .getSequences(viewport.getHiddenRepSequences());
     }
 
     if (sg.size() < 1)
@@ -1756,13 +1754,13 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     SlideSequencesCommand ssc;
     if (right)
     {
-      ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1,
-              size, viewport.getGapCharacter());
+      ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1, size,
+              viewport.getGapCharacter());
     }
     else
     {
-      ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2,
-              size, viewport.getGapCharacter());
+      ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2, size,
+              viewport.getGapCharacter());
     }
 
     int groupAdjustment = 0;
@@ -1807,9 +1805,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     if (!inSplitFrame && historyList != null && historyList.size() > 0
             && historyList.peek() instanceof SlideSequencesCommand)
     {
-      appendHistoryItem = ssc
-              .appendSlideCommand((SlideSequencesCommand) historyList
-                      .peek());
+      appendHistoryItem = ssc.appendSlideCommand(
+              (SlideSequencesCommand) historyList.peek());
     }
 
     if (!appendHistoryItem)
@@ -1857,8 +1854,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       Toolkit.getDefaultToolkit().getSystemClipboard()
               .setContents(new StringSelection(""), null);
 
-      Toolkit.getDefaultToolkit().getSystemClipboard()
-              .setContents(ss, Desktop.instance);
+      Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss,
+              Desktop.instance);
     } catch (OutOfMemoryError er)
     {
       new OOMWarning("copying region", er);
@@ -1877,8 +1874,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       {
         if (region[0] >= hiddenOffset && region[1] <= hiddenCutoff)
         {
-          hiddenColumns.add(new int[] { region[0] - hiddenOffset,
-              region[1] - hiddenOffset });
+          hiddenColumns
+                  .add(new int[]
+                  { region[0] - hiddenOffset, region[1] - hiddenOffset });
         }
       }
     }
@@ -1886,8 +1884,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     Desktop.jalviewClipboard = new Object[] { seqs,
         viewport.getAlignment().getDataset(), hiddenColumns };
     statusBar.setText(MessageManager.formatMessage(
-            "label.copied_sequences_to_clipboard", new Object[] { Integer
-                    .valueOf(seqs.length).toString() }));
+            "label.copied_sequences_to_clipboard", new Object[]
+            { Integer.valueOf(seqs.length).toString() }));
   }
 
   /**
@@ -2037,8 +2035,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           {
             // copy and derive new dataset sequence
             sequences[i] = sequences[i].deriveSequence();
-            alignment.getDataset().addSequence(
-                    sequences[i].getDatasetSequence());
+            alignment.getDataset()
+                    .addSequence(sequences[i].getDatasetSequence());
             // TODO: avoid creation of duplicate dataset sequences with a
             // 'contains' method using SequenceI.equals()/SequenceI.contains()
           }
@@ -2068,18 +2066,20 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
             annotationAdded = true;
             if (alann[i].sequenceRef == null && !alann[i].autoCalculated)
             {
-              AlignmentAnnotation newann = new AlignmentAnnotation(alann[i]);
+              AlignmentAnnotation newann = new AlignmentAnnotation(
+                      alann[i]);
               if (newann.graphGroup > -1)
               {
                 if (newGraphGroups.size() <= newann.graphGroup
                         || newGraphGroups.get(newann.graphGroup) == null)
                 {
-                  for (int q = newGraphGroups.size(); q <= newann.graphGroup; q++)
+                  for (int q = newGraphGroups
+                          .size(); q <= newann.graphGroup; q++)
                   {
                     newGraphGroups.add(q, null);
                   }
-                  newGraphGroups.set(newann.graphGroup, new Integer(
-                          ++fgroup));
+                  newGraphGroups.set(newann.graphGroup,
+                          new Integer(++fgroup));
                 }
                 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
                         .intValue();
@@ -2098,7 +2098,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
         //
         addHistoryItem(new EditCommand(
                 MessageManager.getString("label.add_sequences"),
-                Action.PASTE, sequences, 0, alignment.getWidth(), alignment));
+                Action.PASTE, sequences, 0, alignment.getWidth(),
+                alignment));
       }
       // Add any annotations attached to sequences
       for (int i = 0; i < sequences.length; i++)
@@ -2119,12 +2120,13 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                 if (newGraphGroups.size() <= newann.graphGroup
                         || newGraphGroups.get(newann.graphGroup) == null)
                 {
-                  for (int q = newGraphGroups.size(); q <= newann.graphGroup; q++)
+                  for (int q = newGraphGroups
+                          .size(); q <= newann.graphGroup; q++)
                   {
                     newGraphGroups.add(q, null);
                   }
-                  newGraphGroups.set(newann.graphGroup, new Integer(
-                          ++fgroup));
+                  newGraphGroups.set(newann.graphGroup,
+                          new Integer(++fgroup));
                 }
                 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
                         .intValue();
@@ -2134,8 +2136,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
             // was
             // duplicated
             // earlier
-            alignment
-                    .setAnnotationIndex(sequences[i].getAnnotation()[a], a);
+            alignment.setAnnotationIndex(sequences[i].getAnnotation()[a],
+                    a);
           }
         }
       }
@@ -2143,7 +2145,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       {
 
         // propagate alignment changed.
-        vpRanges.setEndSeq(alignment.getHeight());
+        viewport.getRanges().setEndSeq(alignment.getHeight());
         if (annotationAdded)
         {
           // Duplicate sequence annotation in all views.
@@ -2215,9 +2217,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
         // >>>This is a fix for the moment, until a better solution is
         // found!!<<<
         af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
-                .transferSettings(
-                        alignPanel.getSeqPanel().seqCanvas
-                                .getFeatureRenderer());
+                .transferSettings(alignPanel.getSeqPanel().seqCanvas
+                        .getFeatureRenderer());
 
         // TODO: maintain provenance of an alignment, rather than just make the
         // title a concatenation of operations.
@@ -2256,8 +2257,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   {
     try
     {
-      AlignmentI alignment = AlignmentUtils.expandContext(getViewport()
-              .getAlignment(), -1);
+      AlignmentI alignment = AlignmentUtils
+              .expandContext(getViewport().getAlignment(), -1);
       AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
               DEFAULT_HEIGHT);
       String newtitle = new String("Flanking alignment");
@@ -2275,9 +2276,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       // >>>This is a fix for the moment, until a better solution is
       // found!!<<<
       af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
-              .transferSettings(
-                      alignPanel.getSeqPanel().seqCanvas
-                              .getFeatureRenderer());
+              .transferSettings(alignPanel.getSeqPanel().seqCanvas
+                      .getFeatureRenderer());
 
       // TODO: maintain provenance of an alignment, rather than just make the
       // title a concatenation of operations.
@@ -2339,8 +2339,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
      */
     if (sg.getSize() == viewport.getAlignment().getHeight())
     {
-      boolean isEntireAlignWidth = (((sg.getEndRes() - sg.getStartRes()) + 1) == viewport
-              .getAlignment().getWidth()) ? true : false;
+      boolean isEntireAlignWidth = (((sg.getEndRes() - sg.getStartRes())
+              + 1) == viewport.getAlignment().getWidth()) ? true : false;
       if (isEntireAlignWidth)
       {
         int confirm = JvOptionPane.showConfirmDialog(this,
@@ -2369,8 +2369,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     viewport.sendSelection();
     viewport.getAlignment().deleteGroup(sg);
 
-    viewport.firePropertyChange("alignment", null, viewport.getAlignment()
-            .getSequences());
+    viewport.firePropertyChange("alignment", null,
+            viewport.getAlignment().getSequences());
     if (viewport.getAlignment().getHeight() < 1)
     {
       try
@@ -2395,7 +2395,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     {
       PaintRefresher.Refresh(this, viewport.getSequenceSetId());
       alignPanel.updateAnnotation();
-      alignPanel.paintAlignment(true);
+      alignPanel.paintAlignment(true, true);
     }
   }
 
@@ -2421,7 +2421,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     // JAL-2034 - should delegate to
     // alignPanel to decide if overview needs
     // updating.
-    alignPanel.paintAlignment(false);
+    alignPanel.paintAlignment(false, false);
     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
   }
 
@@ -2442,12 +2442,11 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     viewport.setSelectionGroup(null);
     viewport.getColumnSelection().clear();
     viewport.setSelectionGroup(null);
-    alignPanel.getSeqPanel().seqCanvas.highlightSearchResults(null);
     alignPanel.getIdPanel().getIdCanvas().searchResults = null;
     // JAL-2034 - should delegate to
     // alignPanel to decide if overview needs
     // updating.
-    alignPanel.paintAlignment(false);
+    alignPanel.paintAlignment(false, false);
     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
     viewport.sendSelection();
   }
@@ -2478,7 +2477,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     // alignPanel to decide if overview needs
     // updating.
 
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, false);
     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
     viewport.sendSelection();
   }
@@ -2487,7 +2486,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   public void invertColSel_actionPerformed(ActionEvent e)
   {
     viewport.invertColumnSelection();
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, false);
     viewport.sendSelection();
   }
 
@@ -2534,8 +2533,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       SequenceI[] seqs;
       if (viewport.getSelectionGroup() != null)
       {
-        seqs = viewport.getSelectionGroup().getSequencesAsArray(
-                viewport.getHiddenRepSequences());
+        seqs = viewport.getSelectionGroup()
+                .getSequencesAsArray(viewport.getHiddenRepSequences());
       }
       else
       {
@@ -2547,7 +2546,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       {
         trimRegion = new TrimRegionCommand("Remove Left", true, seqs,
                 column, viewport.getAlignment());
-        vpRanges.setStartRes(0);
+        viewport.getRanges().setStartRes(0);
       }
       else
       {
@@ -2555,10 +2554,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                 column, viewport.getAlignment());
       }
 
-      statusBar.setText(MessageManager.formatMessage(
-              "label.removed_columns",
-              new String[] { Integer.valueOf(trimRegion.getSize())
-                      .toString() }));
+      statusBar.setText(MessageManager
+              .formatMessage("label.removed_columns", new String[]
+              { Integer.valueOf(trimRegion.getSize()).toString() }));
 
       addHistoryItem(trimRegion);
 
@@ -2571,8 +2569,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
         }
       }
 
-      viewport.firePropertyChange("alignment", null, viewport
-              .getAlignment().getSequences());
+      viewport.firePropertyChange("alignment", null,
+              viewport.getAlignment().getSequences());
     }
   }
 
@@ -2590,8 +2588,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     SequenceI[] seqs;
     if (viewport.getSelectionGroup() != null)
     {
-      seqs = viewport.getSelectionGroup().getSequencesAsArray(
-              viewport.getHiddenRepSequences());
+      seqs = viewport.getSelectionGroup()
+              .getSequencesAsArray(viewport.getHiddenRepSequences());
       start = viewport.getSelectionGroup().getStartRes();
       end = viewport.getSelectionGroup().getEndRes();
     }
@@ -2606,23 +2604,23 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
     addHistoryItem(removeGapCols);
 
-    statusBar.setText(MessageManager.formatMessage(
-            "label.removed_empty_columns",
-            new Object[] { Integer.valueOf(removeGapCols.getSize())
-                    .toString() }));
+    statusBar.setText(MessageManager
+            .formatMessage("label.removed_empty_columns", new Object[]
+            { Integer.valueOf(removeGapCols.getSize()).toString() }));
 
     // This is to maintain viewport position on first residue
     // of first sequence
     SequenceI seq = viewport.getAlignment().getSequenceAt(0);
-    int startRes = seq.findPosition(vpRanges.getStartRes());
+    ViewportRanges ranges = viewport.getRanges();
+    int startRes = seq.findPosition(ranges.getStartRes());
     // ShiftList shifts;
     // viewport.getAlignment().removeGaps(shifts=new ShiftList());
     // edit.alColumnChanges=shifts.getInverse();
     // if (viewport.hasHiddenColumns)
     // viewport.getColumnSelection().compensateForEdits(shifts);
-    vpRanges.setStartRes(seq.findIndex(startRes) - 1);
-    viewport.firePropertyChange("alignment", null, viewport.getAlignment()
-            .getSequences());
+    ranges.setStartRes(seq.findIndex(startRes) - 1);
+    viewport.firePropertyChange("alignment", null,
+            viewport.getAlignment().getSequences());
 
   }
 
@@ -2640,8 +2638,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     SequenceI[] seqs;
     if (viewport.getSelectionGroup() != null)
     {
-      seqs = viewport.getSelectionGroup().getSequencesAsArray(
-              viewport.getHiddenRepSequences());
+      seqs = viewport.getSelectionGroup()
+              .getSequencesAsArray(viewport.getHiddenRepSequences());
       start = viewport.getSelectionGroup().getStartRes();
       end = viewport.getSelectionGroup().getEndRes();
     }
@@ -2653,15 +2651,15 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     // This is to maintain viewport position on first residue
     // of first sequence
     SequenceI seq = viewport.getAlignment().getSequenceAt(0);
-    int startRes = seq.findPosition(vpRanges.getStartRes());
+    int startRes = seq.findPosition(viewport.getRanges().getStartRes());
 
     addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,
             viewport.getAlignment()));
 
-    vpRanges.setStartRes(seq.findIndex(startRes) - 1);
+    viewport.getRanges().setStartRes(seq.findIndex(startRes) - 1);
 
-    viewport.firePropertyChange("alignment", null, viewport.getAlignment()
-            .getSequences());
+    viewport.firePropertyChange("alignment", null,
+            viewport.getAlignment().getSequences());
 
   }
 
@@ -2675,8 +2673,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   public void padGapsMenuitem_actionPerformed(ActionEvent e)
   {
     viewport.setPadGaps(padGapsMenuitem.isSelected());
-    viewport.firePropertyChange("alignment", null, viewport.getAlignment()
-            .getSequences());
+    viewport.firePropertyChange("alignment", null,
+            viewport.getAlignment().getSequences());
   }
 
   /**
@@ -2714,8 +2712,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     /*
      * Create a new AlignmentPanel (with its own, new Viewport)
      */
-    AlignmentPanel newap = new Jalview2XML().copyAlignPanel(alignPanel,
-            true);
+    AlignmentPanel newap = new Jalview2XML().copyAlignPanel(alignPanel);
     if (!copyAnnotation)
     {
       /*
@@ -2790,8 +2787,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
     String newViewName = viewTitle + ((addFirstIndex) ? " " + index : "");
 
-    List<Component> comps = PaintRefresher.components.get(viewport
-            .getSequenceSetId());
+    List<Component> comps = PaintRefresher.components
+            .get(viewport.getSequenceSetId());
 
     List<String> existingNames = getExistingViewNames(comps);
 
@@ -2869,21 +2866,21 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
     alignPanel.getIdPanel().getIdCanvas()
             .setPreferredSize(alignPanel.calculateIdWidth());
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, false);
   }
 
   @Override
   public void idRightAlign_actionPerformed(ActionEvent e)
   {
     viewport.setRightAlignIds(idRightAlign.isSelected());
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(false, false);
   }
 
   @Override
   public void centreColumnLabels_actionPerformed(ActionEvent e)
   {
     viewport.setCentreColumnLabels(centreColumnLabelsMenuItem.getState());
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(false, false);
   }
 
   /*
@@ -2916,7 +2913,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   protected void colourTextMenuItem_actionPerformed(ActionEvent e)
   {
     viewport.setColourText(colourTextMenuItem.isSelected());
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(false, false);
   }
 
   /**
@@ -2945,7 +2942,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   public void showAllColumns_actionPerformed(ActionEvent e)
   {
     viewport.showAllHiddenColumns();
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, true);
     viewport.sendSelection();
   }
 
@@ -2971,9 +2968,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       // Hide everything by the current selection - this is a hack - we do the
       // invert and then hide
       // first check that there will be visible columns after the invert.
-      if (viewport.hasSelectedColumns()
-              || (sg != null && sg.getSize() > 0 && sg.getStartRes() <= sg
-                      .getEndRes()))
+      if (viewport.hasSelectedColumns() || (sg != null && sg.getSize() > 0
+              && sg.getStartRes() <= sg.getEndRes()))
       {
         // now invert the sequence set, if required - empty selection implies
         // that no hiding is required.
@@ -3050,7 +3046,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     viewport.expandColSelection(sg, false);
     viewport.hideAllSelectedSeqs();
     viewport.hideSelectedColumns();
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, true);
     viewport.sendSelection();
   }
 
@@ -3066,7 +3062,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   {
     viewport.showAllHiddenColumns();
     viewport.showAllHiddenSeqs();
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, true);
     viewport.sendSelection();
   }
 
@@ -3074,7 +3070,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   public void hideSelColumns_actionPerformed(ActionEvent e)
   {
     viewport.hideSelectedColumns();
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, true);
     viewport.sendSelection();
   }
 
@@ -3095,7 +3091,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   protected void scaleAbove_actionPerformed(ActionEvent e)
   {
     viewport.setScaleAboveWrapped(scaleAbove.isSelected());
-    alignPanel.paintAlignment(true);
+    // TODO: do we actually need to update overview for scale above change ?
+    alignPanel.paintAlignment(true, false);
   }
 
   /**
@@ -3108,7 +3105,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   protected void scaleLeft_actionPerformed(ActionEvent e)
   {
     viewport.setScaleLeftWrapped(scaleLeft.isSelected());
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, false);
   }
 
   /**
@@ -3121,7 +3118,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   protected void scaleRight_actionPerformed(ActionEvent e)
   {
     viewport.setScaleRightWrapped(scaleRight.isSelected());
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, false);
   }
 
   /**
@@ -3134,7 +3131,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
   {
     viewport.setShowBoxes(viewBoxesMenuItem.isSelected());
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(false, false);
   }
 
   /**
@@ -3147,7 +3144,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   public void viewTextMenuItem_actionPerformed(ActionEvent e)
   {
     viewport.setShowText(viewTextMenuItem.isSelected());
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(false, false);
   }
 
   /**
@@ -3160,7 +3157,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
   {
     viewport.setRenderGaps(renderGapsMenuItem.isSelected());
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(false, false);
   }
 
   public FeatureSettings featureSettings;
@@ -3198,7 +3195,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   public void showSeqFeatures_actionPerformed(ActionEvent evt)
   {
     viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, true);
   }
 
   /**
@@ -3229,14 +3226,15 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     editPane.setEditable(false);
     StringBuffer contents = new AlignmentProperties(viewport.getAlignment())
             .formatAsHtml();
-    editPane.setText(MessageManager.formatMessage("label.html_content",
-            new Object[] { contents.toString() }));
+    editPane.setText(
+            MessageManager.formatMessage("label.html_content", new Object[]
+            { contents.toString() }));
     JInternalFrame frame = new JInternalFrame();
     frame.getContentPane().add(new JScrollPane(editPane));
 
-    Desktop.addInternalFrame(frame, MessageManager.formatMessage(
-            "label.alignment_properties", new Object[] { getTitle() }),
-            500, 400);
+    Desktop.addInternalFrame(frame, MessageManager
+            .formatMessage("label.alignment_properties", new Object[]
+            { getTitle() }), 500, 400);
   }
 
   /**
@@ -3256,21 +3254,23 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     JInternalFrame frame = new JInternalFrame();
     final OverviewPanel overview = new OverviewPanel(alignPanel);
     frame.setContentPane(overview);
-    Desktop.addInternalFrame(frame, MessageManager.formatMessage(
-            "label.overview_params", new Object[] { this.getTitle() }),
-            true, frame.getWidth(), frame.getHeight(), true, true);
+    Desktop.addInternalFrame(frame, MessageManager
+            .formatMessage("label.overview_params", new Object[]
+            { this.getTitle() }), true, frame.getWidth(), frame.getHeight(),
+            true, true);
     frame.pack();
     frame.setLayer(JLayeredPane.PALETTE_LAYER);
-    frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
-    {
-      @Override
-      public void internalFrameClosed(
-              javax.swing.event.InternalFrameEvent evt)
-      {
-        overview.dispose();
-        alignPanel.setOverviewPanel(null);
-      };
-    });
+    frame.addInternalFrameListener(
+            new javax.swing.event.InternalFrameAdapter()
+            {
+              @Override
+              public void internalFrameClosed(
+                      javax.swing.event.InternalFrameEvent evt)
+              {
+                overview.dispose();
+                alignPanel.setOverviewPanel(null);
+              };
+            });
 
     alignPanel.setOverviewPanel(overview);
   }
@@ -3352,7 +3352,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
     viewport.setGlobalColourScheme(cs);
 
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, true);
   }
 
   /**
@@ -3361,8 +3361,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   protected void modifyPID_actionPerformed()
   {
-    SliderPanel.setPIDSliderSource(alignPanel,
-            viewport.getResidueShading(), alignPanel.getViewName());
+    SliderPanel.setPIDSliderSource(alignPanel, viewport.getResidueShading(),
+            alignPanel.getViewName());
     SliderPanel.showPIDSlider();
   }
 
@@ -3433,11 +3433,11 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
   {
     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
-    AlignmentSorter.sortByPID(viewport.getAlignment(), viewport
-            .getAlignment().getSequenceAt(0));
+    AlignmentSorter.sortByPID(viewport.getAlignment(),
+            viewport.getAlignment().getSequenceAt(0));
     addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
             viewport.getAlignment()));
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, false);
   }
 
   /**
@@ -3451,9 +3451,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   {
     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
     AlignmentSorter.sortByID(viewport.getAlignment());
-    addHistoryItem(new OrderCommand("ID Sort", oldOrder,
-            viewport.getAlignment()));
-    alignPanel.paintAlignment(true);
+    addHistoryItem(
+            new OrderCommand("ID Sort", oldOrder, viewport.getAlignment()));
+    alignPanel.paintAlignment(true, false);
   }
 
   /**
@@ -3469,7 +3469,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     AlignmentSorter.sortByLength(viewport.getAlignment());
     addHistoryItem(new OrderCommand("Length Sort", oldOrder,
             viewport.getAlignment()));
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, false);
   }
 
   /**
@@ -3486,7 +3486,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     addHistoryItem(new OrderCommand("Group Sort", oldOrder,
             viewport.getAlignment()));
 
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, false);
   }
 
   /**
@@ -3513,8 +3513,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     if ((viewport.getSelectionGroup() == null)
             || (viewport.getSelectionGroup().getSize() < 2))
     {
-      JvOptionPane.showInternalMessageDialog(this, MessageManager
-              .getString("label.you_must_select_least_two_sequences"),
+      JvOptionPane.showInternalMessageDialog(this,
+              MessageManager.getString(
+                      "label.you_must_select_least_two_sequences"),
               MessageManager.getString("label.invalid_selection"),
               JvOptionPane.WARNING_MESSAGE);
     }
@@ -3534,8 +3535,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     viewport.autoCalculateConsensus = autoCalculate.isSelected();
     if (viewport.autoCalculateConsensus)
     {
-      viewport.firePropertyChange("alignment", null, viewport
-              .getAlignment().getSequences());
+      viewport.firePropertyChange("alignment", null,
+              viewport.getAlignment().getSequences());
     }
   }
 
@@ -3561,7 +3562,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    * @param options
    *          parameters for the distance or similarity calculation
    */
-  void newTreePanel(String type, String modelName, SimilarityParamsI options)
+  void newTreePanel(String type, String modelName,
+          SimilarityParamsI options)
   {
     String frameTitle = "";
     TreePanel tp;
@@ -3577,14 +3579,12 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       {
         if (_s.getLength() < sg.getEndRes())
         {
-          JvOptionPane
-                  .showMessageDialog(
-                          Desktop.desktop,
-                          MessageManager
-                                  .getString("label.selected_region_to_tree_may_only_contain_residues_or_gaps"),
-                          MessageManager
-                                  .getString("label.sequences_selection_not_aligned"),
-                          JvOptionPane.WARNING_MESSAGE);
+          JvOptionPane.showMessageDialog(Desktop.desktop,
+                  MessageManager.getString(
+                          "label.selected_region_to_tree_may_only_contain_residues_or_gaps"),
+                  MessageManager.getString(
+                          "label.sequences_selection_not_aligned"),
+                  JvOptionPane.WARNING_MESSAGE);
 
           return;
         }
@@ -3625,8 +3625,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   public void addSortByOrderMenuItem(String title,
           final AlignmentOrder order)
   {
-    final JMenuItem item = new JMenuItem(MessageManager.formatMessage(
-            "action.by_title_param", new Object[] { title }));
+    final JMenuItem item = new JMenuItem(MessageManager
+            .formatMessage("action.by_title_param", new Object[]
+            { title }));
     sort.add(item);
     item.addActionListener(new java.awt.event.ActionListener()
     {
@@ -3639,10 +3640,10 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
         // pointers
         AlignmentSorter.sortBy(viewport.getAlignment(), order);
 
-        addHistoryItem(new OrderCommand(order.getName(), oldOrder, viewport
-                .getAlignment()));
+        addHistoryItem(new OrderCommand(order.getName(), oldOrder,
+                viewport.getAlignment()));
 
-        alignPanel.paintAlignment(true);
+        alignPanel.paintAlignment(true, false);
       }
     });
   }
@@ -3671,7 +3672,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                 viewport.getAlignment());// ,viewport.getSelectionGroup());
         addHistoryItem(new OrderCommand("Sort by " + scoreLabel, oldOrder,
                 viewport.getAlignment()));
-        alignPanel.paintAlignment(true);
+        alignPanel.paintAlignment(true, false);
       }
     });
   }
@@ -3696,7 +3697,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       return;
     }
 
-    if (viewport.getAlignment().getAlignmentAnnotation().hashCode() != _annotationScoreVectorHash)
+    if (viewport.getAlignment().getAlignmentAnnotation()
+            .hashCode() != _annotationScoreVectorHash)
     {
       sortByAnnotScore.removeAll();
       // almost certainly a quicker way to do this - but we keep it simple
@@ -3739,8 +3741,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   {
     sortByTreeMenu.removeAll();
 
-    List<Component> comps = PaintRefresher.components.get(viewport
-            .getSequenceSetId());
+    List<Component> comps = PaintRefresher.components
+            .get(viewport.getSequenceSetId());
     List<TreePanel> treePanels = new ArrayList<>();
     for (Component comp : comps)
     {
@@ -3785,7 +3787,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       addHistoryItem(new OrderCommand(undoname, oldOrder,
               viewport.getAlignment()));
     }
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, false);
     return true;
   }
 
@@ -3879,9 +3881,10 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     JalviewFileChooser chooser = new JalviewFileChooser(
             jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
     chooser.setFileView(new JalviewFileView());
-    chooser.setDialogTitle(MessageManager
-            .getString("label.select_newick_like_tree_file"));
-    chooser.setToolTipText(MessageManager.getString("label.load_tree_file"));
+    chooser.setDialogTitle(
+            MessageManager.getString("label.select_newick_like_tree_file"));
+    chooser.setToolTipText(
+            MessageManager.getString("label.load_tree_file"));
 
     int value = chooser.showOpenDialog(null);
 
@@ -3896,20 +3899,17 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
         viewport.setCurrentTree(showNewickTree(fin, filePath).getTree());
       } catch (Exception ex)
       {
-        JvOptionPane
-                .showMessageDialog(
-                        Desktop.desktop,
-                        ex.getMessage(),
-                        MessageManager
-                                .getString("label.problem_reading_tree_file"),
-                        JvOptionPane.WARNING_MESSAGE);
+        JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(),
+                MessageManager.getString("label.problem_reading_tree_file"),
+                JvOptionPane.WARNING_MESSAGE);
         ex.printStackTrace();
       }
       if (fin != null && fin.hasWarningMessage())
       {
-        JvOptionPane.showMessageDialog(Desktop.desktop, fin
-                .getWarningMessage(), MessageManager
-                .getString("label.possible_problem_with_tree_file"),
+        JvOptionPane.showMessageDialog(Desktop.desktop,
+                fin.getWarningMessage(),
+                MessageManager
+                        .getString("label.possible_problem_with_tree_file"),
                 JvOptionPane.WARNING_MESSAGE);
       }
     }
@@ -4139,9 +4139,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                 }
               } catch (Exception e)
               {
-                Cache.log
-                        .debug("Exception during web service menu building process.",
-                                e);
+                Cache.log.debug(
+                        "Exception during web service menu building process.",
+                        e);
               }
             }
           });
@@ -4226,7 +4226,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           @Override
           public void actionPerformed(ActionEvent e)
           {
-            showProductsFor(af.viewport.getSequenceSelection(), dna, source);
+            showProductsFor(af.viewport.getSequenceSelection(), dna,
+                    source);
           }
         });
         showProducts.add(xtype);
@@ -4235,9 +4236,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       showProducts.setEnabled(showp);
     } catch (Exception e)
     {
-      Cache.log
-              .warn("canShowProducts threw an exception - please report to help@jalview.org",
-                      e);
+      Cache.log.warn(
+              "canShowProducts threw an exception - please report to help@jalview.org",
+              e);
       return false;
     }
     return showp;
@@ -4254,8 +4255,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    * @param source
    *          the database to show cross-references for
    */
-  protected void showProductsFor(final SequenceI[] sel,
-          final boolean _odna, final String source)
+  protected void showProductsFor(final SequenceI[] sel, final boolean _odna,
+          final String source)
   {
     new Thread(CrossRefAction.showProductsFor(sel, _odna, source, this))
             .start();
@@ -4278,8 +4279,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     {
       jalview.bin.Cache.log.error(
               "Exception during translation. Please report this !", ex);
-      final String msg = MessageManager
-              .getString("label.error_when_translating_sequences_submit_bug_report");
+      final String msg = MessageManager.getString(
+              "label.error_when_translating_sequences_submit_bug_report");
       final String errorTitle = MessageManager
               .getString("label.implementation_error")
               + MessageManager.getString("label.translation_failed");
@@ -4289,8 +4290,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
     if (al == null || al.getHeight() == 0)
     {
-      final String msg = MessageManager
-              .getString("label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation");
+      final String msg = MessageManager.getString(
+              "label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation");
       final String errorTitle = MessageManager
               .getString("label.translation_failed");
       JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
@@ -4300,9 +4301,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     {
       AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
       af.setFileFormat(this.currentFileFormat);
-      final String newTitle = MessageManager.formatMessage(
-              "label.translation_of_params",
-              new Object[] { this.getTitle() });
+      final String newTitle = MessageManager
+              .formatMessage("label.translation_of_params", new Object[]
+              { this.getTitle() });
       af.setTitle(newTitle);
       if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true))
       {
@@ -4384,7 +4385,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     // Java's Transferable for native dnd
     evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
     Transferable t = evt.getTransferable();
-    List<String> files = new ArrayList<>();
+    final AlignFrame thisaf = this;
+    final List<String> files = new ArrayList<>();
     List<DataSourceType> protocols = new ArrayList<>();
 
     try
@@ -4396,145 +4398,146 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
     if (files != null)
     {
-      try
+      new Thread(new Runnable()
       {
-        // check to see if any of these files have names matching sequences in
-        // the alignment
-        SequenceIdMatcher idm = new SequenceIdMatcher(viewport
-                .getAlignment().getSequencesArray());
-        /**
-         * Object[] { String,SequenceI}
-         */
-        ArrayList<Object[]> filesmatched = new ArrayList<>();
-        ArrayList<String> filesnotmatched = new ArrayList<>();
-        for (int i = 0; i < files.size(); i++)
+        @Override
+        public void run()
         {
-          String file = files.get(i).toString();
-          String pdbfn = "";
-          DataSourceType protocol = FormatAdapter.checkProtocol(file);
-          if (protocol == DataSourceType.FILE)
-          {
-            File fl = new File(file);
-            pdbfn = fl.getName();
-          }
-          else if (protocol == DataSourceType.URL)
-          {
-            URL url = new URL(file);
-            pdbfn = url.getFile();
-          }
-          if (pdbfn.length() > 0)
+          try
           {
-            // attempt to find a match in the alignment
-            SequenceI[] mtch = idm.findAllIdMatches(pdbfn);
-            int l = 0, c = pdbfn.indexOf(".");
-            while (mtch == null && c != -1)
+            // check to see if any of these files have names matching sequences
+            // in
+            // the alignment
+            SequenceIdMatcher idm = new SequenceIdMatcher(
+                    viewport.getAlignment().getSequencesArray());
+            /**
+             * Object[] { String,SequenceI}
+             */
+            ArrayList<Object[]> filesmatched = new ArrayList<>();
+            ArrayList<String> filesnotmatched = new ArrayList<>();
+            for (int i = 0; i < files.size(); i++)
             {
-              do
+              String file = files.get(i).toString();
+              String pdbfn = "";
+              DataSourceType protocol = FormatAdapter.checkProtocol(file);
+              if (protocol == DataSourceType.FILE)
               {
-                l = c;
-              } while ((c = pdbfn.indexOf(".", l)) > l);
-              if (l > -1)
-              {
-                pdbfn = pdbfn.substring(0, l);
+                File fl = new File(file);
+                pdbfn = fl.getName();
               }
-              mtch = idm.findAllIdMatches(pdbfn);
-            }
-            if (mtch != null)
-            {
-              FileFormatI type = null;
-              try
-              {
-                type = new IdentifyFile().identify(file, protocol);
-              } catch (Exception ex)
+              else if (protocol == DataSourceType.URL)
               {
-                type = null;
+                URL url = new URL(file);
+                pdbfn = url.getFile();
               }
-              if (type != null && type.isStructureFile())
+              if (pdbfn.length() > 0)
               {
-                filesmatched.add(new Object[] { file, protocol, mtch });
-                continue;
+                // attempt to find a match in the alignment
+                SequenceI[] mtch = idm.findAllIdMatches(pdbfn);
+                int l = 0, c = pdbfn.indexOf(".");
+                while (mtch == null && c != -1)
+                {
+                  do
+                  {
+                    l = c;
+                  } while ((c = pdbfn.indexOf(".", l)) > l);
+                  if (l > -1)
+                  {
+                    pdbfn = pdbfn.substring(0, l);
+                  }
+                  mtch = idm.findAllIdMatches(pdbfn);
+                }
+                if (mtch != null)
+                {
+                  FileFormatI type = null;
+                  try
+                  {
+                    type = new IdentifyFile().identify(file, protocol);
+                  } catch (Exception ex)
+                  {
+                    type = null;
+                  }
+                  if (type != null && type.isStructureFile())
+                  {
+                    filesmatched.add(new Object[] { file, protocol, mtch });
+                    continue;
+                  }
+                }
+                // File wasn't named like one of the sequences or wasn't a PDB
+                // file.
+                filesnotmatched.add(file);
               }
             }
-            // File wasn't named like one of the sequences or wasn't a PDB file.
-            filesnotmatched.add(file);
-          }
-        }
-        int assocfiles = 0;
-        if (filesmatched.size() > 0)
-        {
-          if (Cache.getDefault("AUTOASSOCIATE_PDBANDSEQS", false)
-                  || JvOptionPane
-                          .showConfirmDialog(
-                                  this,
-                                  MessageManager
-                                          .formatMessage(
-                                                  "label.automatically_associate_structure_files_with_sequences_same_name",
-                                                  new Object[] { Integer
-                                                          .valueOf(
-                                                                  filesmatched
-                                                                          .size())
-                                                          .toString() }),
-                                  MessageManager
-                                          .getString("label.automatically_associate_structure_files_by_name"),
-                                  JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION)
-
-          {
-            for (Object[] fm : filesmatched)
+            int assocfiles = 0;
+            if (filesmatched.size() > 0)
             {
-              // try and associate
-              // TODO: may want to set a standard ID naming formalism for
-              // associating PDB files which have no IDs.
-              for (SequenceI toassoc : (SequenceI[]) fm[2])
+              if (Cache.getDefault("AUTOASSOCIATE_PDBANDSEQS", false)
+                      || JvOptionPane.showConfirmDialog(thisaf,
+                              MessageManager.formatMessage(
+                                      "label.automatically_associate_structure_files_with_sequences_same_name",
+                                      new Object[]
+                                      { Integer.valueOf(filesmatched.size())
+                                              .toString() }),
+                              MessageManager.getString(
+                                      "label.automatically_associate_structure_files_by_name"),
+                              JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION)
+
               {
-                PDBEntry pe = new AssociatePdbFileWithSeq()
-                        .associatePdbWithSeq((String) fm[0],
-                                (DataSourceType) fm[1], toassoc, false,
-                                Desktop.instance);
-                if (pe != null)
+                for (Object[] fm : filesmatched)
                 {
-                  System.err.println("Associated file : "
-                          + ((String) fm[0]) + " with "
-                          + toassoc.getDisplayId(true));
-                  assocfiles++;
+                  // try and associate
+                  // TODO: may want to set a standard ID naming formalism for
+                  // associating PDB files which have no IDs.
+                  for (SequenceI toassoc : (SequenceI[]) fm[2])
+                  {
+                    PDBEntry pe = new AssociatePdbFileWithSeq()
+                            .associatePdbWithSeq((String) fm[0],
+                                    (DataSourceType) fm[1], toassoc, false,
+                                    Desktop.instance);
+                    if (pe != null)
+                    {
+                      System.err.println("Associated file : "
+                              + ((String) fm[0]) + " with "
+                              + toassoc.getDisplayId(true));
+                      assocfiles++;
+                    }
+                  }
+                  // TODO: do we need to update overview ? only if features are
+                  // shown I guess
+                  alignPanel.paintAlignment(true, false);
                 }
               }
-              alignPanel.paintAlignment(true);
             }
-          }
-        }
-        if (filesnotmatched.size() > 0)
-        {
-          if (assocfiles > 0
-                  && (Cache.getDefault(
-                          "AUTOASSOCIATE_PDBANDSEQS_IGNOREOTHERS", false) || JvOptionPane
-                          .showConfirmDialog(
-                                  this,
-                                  "<html>"
-                                          + MessageManager
-                                                  .formatMessage(
-                                                          "label.ignore_unmatched_dropped_files_info",
-                                                          new Object[] { Integer
-                                                                  .valueOf(
-                                                                          filesnotmatched
-                                                                                  .size())
-                                                                  .toString() })
-                                          + "</html>",
-                                  MessageManager
-                                          .getString("label.ignore_unmatched_dropped_files"),
-                                  JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION))
-          {
-            return;
-          }
-          for (String fn : filesnotmatched)
+            if (filesnotmatched.size() > 0)
+            {
+              if (assocfiles > 0 && (Cache.getDefault(
+                      "AUTOASSOCIATE_PDBANDSEQS_IGNOREOTHERS", false)
+                      || JvOptionPane.showConfirmDialog(thisaf,
+                              "<html>" + MessageManager.formatMessage(
+                                      "label.ignore_unmatched_dropped_files_info",
+                                      new Object[]
+                                      { Integer.valueOf(
+                                              filesnotmatched.size())
+                                              .toString() })
+                                      + "</html>",
+                              MessageManager.getString(
+                                      "label.ignore_unmatched_dropped_files"),
+                              JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION))
+              {
+                return;
+              }
+              for (String fn : filesnotmatched)
+              {
+                loadJalviewDataFile(fn, null, null, null);
+              }
+
+            }
+          } catch (Exception ex)
           {
-            loadJalviewDataFile(fn, null, null, null);
+            ex.printStackTrace();
           }
-
         }
-      } catch (Exception ex)
-      {
-        ex.printStackTrace();
-      }
+      }).start();
     }
   }
 
@@ -4562,9 +4565,11 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       // if the file isn't identified, or not positively identified as some
       // other filetype (PFAM is default unidentified alignment file type) then
       // try to parse as annotation.
-      boolean isAnnotation = (format == null || FileFormat.Pfam
-              .equals(format)) ? new AnnotationFile()
-              .annotateAlignmentView(viewport, file, sourceType) : false;
+      boolean isAnnotation = (format == null
+              || FileFormat.Pfam.equals(format))
+                      ? new AnnotationFile().annotateAlignmentView(viewport,
+                              file, sourceType)
+                      : false;
 
       if (!isAnnotation)
       {
@@ -4578,25 +4583,24 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
             if (tcf.annotateAlignment(viewport.getAlignment(), true))
             {
               buildColourMenu();
-              changeColour(new TCoffeeColourScheme(viewport.getAlignment()));
+              changeColour(
+                      new TCoffeeColourScheme(viewport.getAlignment()));
               isAnnotation = true;
-              statusBar
-                      .setText(MessageManager
-                              .getString("label.successfully_pasted_tcoffee_scores_to_alignment"));
+              statusBar.setText(MessageManager.getString(
+                      "label.successfully_pasted_tcoffee_scores_to_alignment"));
             }
             else
             {
               // some problem - if no warning its probable that the ID matching
               // process didn't work
-              JvOptionPane
-                      .showMessageDialog(
-                              Desktop.desktop,
-                              tcf.getWarningMessage() == null ? MessageManager
-                                      .getString("label.check_file_matches_sequence_ids_alignment")
-                                      : tcf.getWarningMessage(),
-                              MessageManager
-                                      .getString("label.problem_reading_tcoffee_score_file"),
-                              JvOptionPane.WARNING_MESSAGE);
+              JvOptionPane.showMessageDialog(Desktop.desktop,
+                      tcf.getWarningMessage() == null
+                              ? MessageManager.getString(
+                                      "label.check_file_matches_sequence_ids_alignment")
+                              : tcf.getWarningMessage(),
+                      MessageManager.getString(
+                              "label.problem_reading_tcoffee_score_file"),
+                      JvOptionPane.WARNING_MESSAGE);
             }
           }
           else
@@ -4605,9 +4609,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           }
         } catch (Exception x)
         {
-          Cache.log
-                  .debug("Exception when processing data source as T-COFFEE score file",
-                          x);
+          Cache.log.debug(
+                  "Exception when processing data source as T-COFFEE score file",
+                  x);
           tcf = null;
         }
         if (tcf == null)
@@ -4621,14 +4625,13 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           }
           if (FileFormat.ScoreMatrix == format)
           {
-            ScoreMatrixFile sm = new ScoreMatrixFile(new FileParse(file,
-                    sourceType));
+            ScoreMatrixFile sm = new ScoreMatrixFile(
+                    new FileParse(file, sourceType));
             sm.parse();
             // todo: i18n this message
-            statusBar
-                    .setText(MessageManager.formatMessage(
-                            "label.successfully_loaded_matrix",
-                            sm.getMatrixName()));
+            statusBar.setText(MessageManager.formatMessage(
+                    "label.successfully_loaded_matrix",
+                    sm.getMatrixName()));
           }
           else if (FileFormat.Jnet.equals(format))
           {
@@ -4648,7 +4651,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           {
             if (parseFeaturesFile(file, sourceType))
             {
-              alignPanel.paintAlignment(true);
+              alignPanel.paintAlignment(true, true);
             }
           }
           else
@@ -4663,7 +4666,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
         alignPanel.adjustAnnotationHeight();
         viewport.updateSequenceIdColours();
         buildSortByAnnotationScoresMenu();
-        alignPanel.paintAlignment(true);
+        alignPanel.paintAlignment(true, true);
       }
     } catch (Exception ex)
     {
@@ -4678,11 +4681,16 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       }
       new OOMWarning(
               "loading data "
-                      + (sourceType != null ? (sourceType == DataSourceType.PASTE ? "from clipboard."
-                              : "using " + sourceType + " from " + file)
+                      + (sourceType != null
+                              ? (sourceType == DataSourceType.PASTE
+                                      ? "from clipboard."
+                                      : "using " + sourceType + " from "
+                                              + file)
                               : ".")
-                      + (format != null ? "(parsing as '" + format
-                              + "' file)" : ""), oom, Desktop.desktop);
+                      + (format != null
+                              ? "(parsing as '" + format + "' file)"
+                              : ""),
+              oom, Desktop.desktop);
     }
   }
 
@@ -4733,7 +4741,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     final AlignViewportI peer = viewport.getCodingComplement();
     if (peer != null)
     {
-      AlignFrame linkedAlignFrame = ((AlignViewport) peer).getAlignPanel().alignFrame;
+      AlignFrame linkedAlignFrame = ((AlignViewport) peer)
+              .getAlignPanel().alignFrame;
       if (linkedAlignFrame.tabbedPane.getTabCount() > index)
       {
         linkedAlignFrame.tabbedPane.setSelectedIndex(index);
@@ -4848,14 +4857,14 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     // here
     final JMenu rfetch = new JMenu(
             MessageManager.getString("action.fetch_db_references"));
-    rfetch.setToolTipText(MessageManager
-            .getString("label.retrieve_parse_sequence_database_records_alignment_or_selected_sequences"));
+    rfetch.setToolTipText(MessageManager.getString(
+            "label.retrieve_parse_sequence_database_records_alignment_or_selected_sequences"));
     webService.add(rfetch);
 
     final JCheckBoxMenuItem trimrs = new JCheckBoxMenuItem(
             MessageManager.getString("option.trim_retrieved_seqs"));
-    trimrs.setToolTipText(MessageManager
-            .getString("label.trim_retrieved_sequences"));
+    trimrs.setToolTipText(
+            MessageManager.getString("label.trim_retrieved_sequences"));
     trimrs.setSelected(Cache.getDefault("TRIM_FETCHED_DATASET_SEQS", true));
     trimrs.addActionListener(new ActionListener()
     {
@@ -4870,8 +4879,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     rfetch.add(trimrs);
     JMenuItem fetchr = new JMenuItem(
             MessageManager.getString("label.standard_databases"));
-    fetchr.setToolTipText(MessageManager
-            .getString("label.fetch_embl_uniprot"));
+    fetchr.setToolTipText(
+            MessageManager.getString("label.fetch_embl_uniprot"));
     fetchr.addActionListener(new ActionListener()
     {
 
@@ -4885,8 +4894,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           {
             boolean isNucleotide = alignPanel.alignFrame.getViewport()
                     .getAlignment().isNucleotide();
-            DBRefFetcher dbRefFetcher = new DBRefFetcher(alignPanel.av
-                    .getSequenceSelection(), alignPanel.alignFrame, null,
+            DBRefFetcher dbRefFetcher = new DBRefFetcher(
+                    alignPanel.av.getSequenceSelection(),
+                    alignPanel.alignFrame, null,
                     alignPanel.alignFrame.featureSettings, isNucleotide);
             dbRefFetcher.addListener(new FetchFinishedListenerI()
             {
@@ -4989,8 +4999,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                 });
                 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
                         MessageManager.formatMessage(
-                                "label.fetch_retrieve_from",
-                                new Object[] { src.getDbName() })));
+                                "label.fetch_retrieve_from", new Object[]
+                                { src.getDbName() })));
                 dfetch.add(fetchr);
                 comp++;
               }
@@ -5000,9 +5010,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                         .toArray(new DbSourceProxy[0]);
                 // fetch all entry
                 DbSourceProxy src = otherdb.get(0);
-                fetchr = new JMenuItem(MessageManager.formatMessage(
-                        "label.fetch_all_param",
-                        new Object[] { src.getDbSource() }));
+                fetchr = new JMenuItem(MessageManager
+                        .formatMessage("label.fetch_all_param", new Object[]
+                        { src.getDbSource() }));
                 fetchr.addActionListener(new ActionListener()
                 {
                   @Override
@@ -5040,30 +5050,33 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
                         MessageManager.formatMessage(
                                 "label.fetch_retrieve_from_all_sources",
-                                new Object[] {
-                                    Integer.valueOf(otherdb.size())
-                                            .toString(), src.getDbSource(),
-                                    src.getDbName() })));
+                                new Object[]
+                                { Integer.valueOf(otherdb.size())
+                                        .toString(),
+                                    src.getDbSource(), src.getDbName() })));
                 dfetch.add(fetchr);
                 comp++;
                 // and then build the rest of the individual menus
                 ifetch = new JMenu(MessageManager.formatMessage(
-                        "label.source_from_db_source",
-                        new Object[] { src.getDbSource() }));
+                        "label.source_from_db_source", new Object[]
+                        { src.getDbSource() }));
                 icomp = 0;
                 String imname = null;
                 int i = 0;
                 for (DbSourceProxy sproxy : otherdb)
                 {
                   String dbname = sproxy.getDbName();
-                  String sname = dbname.length() > 5 ? dbname.substring(0,
-                          5) + "..." : dbname;
-                  String msname = dbname.length() > 10 ? dbname.substring(
-                          0, 10) + "..." : dbname;
+                  String sname = dbname.length() > 5
+                          ? dbname.substring(0, 5) + "..."
+                          : dbname;
+                  String msname = dbname.length() > 10
+                          ? dbname.substring(0, 10) + "..."
+                          : dbname;
                   if (imname == null)
                   {
-                    imname = MessageManager.formatMessage(
-                            "label.from_msname", new Object[] { sname });
+                    imname = MessageManager
+                            .formatMessage("label.from_msname", new Object[]
+                            { sname });
                   }
                   fetchr = new JMenuItem(msname);
                   final DbSourceProxy[] dassrc = { sproxy };
@@ -5102,8 +5115,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                     }
 
                   });
-                  fetchr.setToolTipText("<html>"
-                          + MessageManager.formatMessage(
+                  fetchr.setToolTipText(
+                          "<html>" + MessageManager.formatMessage(
                                   "label.fetch_retrieve_from", new Object[]
                                   { dbname }));
                   ifetch.add(fetchr);
@@ -5178,7 +5191,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   protected void showUnconservedMenuItem_actionPerformed(ActionEvent e)
   {
     viewport.setShowUnconserved(showNonconservedMenuItem.getState());
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(false, false);
   }
 
   /*
@@ -5267,7 +5280,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     {
       PaintRefresher.Refresh(this, viewport.getSequenceSetId());
       alignPanel.updateAnnotation();
-      alignPanel.paintAlignment(true);
+      alignPanel.paintAlignment(true, true);
     }
   }
 
@@ -5279,7 +5292,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       viewport.getAlignment().setSeqrep(null);
       PaintRefresher.Refresh(this, viewport.getSequenceSetId());
       alignPanel.updateAnnotation();
-      alignPanel.paintAlignment(true);
+      alignPanel.paintAlignment(true, true);
     }
   }
 
@@ -5308,17 +5321,14 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    */
   public void setDisplayedView(AlignmentPanel alignmentPanel)
   {
-    if (!viewport.getSequenceSetId().equals(
-            alignmentPanel.av.getSequenceSetId()))
+    if (!viewport.getSequenceSetId()
+            .equals(alignmentPanel.av.getSequenceSetId()))
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_error_cannot_show_view_alignment_frame"));
+      throw new Error(MessageManager.getString(
+              "error.implementation_error_cannot_show_view_alignment_frame"));
     }
-    if (tabbedPane != null
-            && tabbedPane.getTabCount() > 0
-            && alignPanels.indexOf(alignmentPanel) != tabbedPane
-                    .getSelectedIndex())
+    if (tabbedPane != null && tabbedPane.getTabCount() > 0 && alignPanels
+            .indexOf(alignmentPanel) != tabbedPane.getSelectedIndex())
     {
       tabbedPane.setSelectedIndex(alignPanels.indexOf(alignmentPanel));
     }
@@ -5372,7 +5382,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     this.alignPanel.av.setSortAnnotationsBy(getAnnotationSortOrder());
     this.alignPanel.av
             .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(false, false);
   }
 
   /**
@@ -5421,15 +5431,15 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       // show a warning dialog no mapped cDNA
       return;
     }
-    AlignmentI cdna = new Alignment(cdnaSeqs.toArray(new SequenceI[cdnaSeqs
-            .size()]));
+    AlignmentI cdna = new Alignment(
+            cdnaSeqs.toArray(new SequenceI[cdnaSeqs.size()]));
     GAlignFrame alignFrame = new AlignFrame(cdna, AlignFrame.DEFAULT_WIDTH,
             AlignFrame.DEFAULT_HEIGHT);
     cdna.alignAs(alignment);
     String newtitle = "cDNA " + MessageManager.getString("label.for") + " "
             + this.title;
-    Desktop.addInternalFrame(alignFrame, newtitle,
-            AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
+    Desktop.addInternalFrame(alignFrame, newtitle, AlignFrame.DEFAULT_WIDTH,
+            AlignFrame.DEFAULT_HEIGHT);
   }
 
   /**
@@ -5462,8 +5472,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       al = dna.reverseCdna(complement);
       viewport.addAlignment(al, "");
       addHistoryItem(new EditCommand(
-              MessageManager.getString("label.add_sequences"),
-              Action.PASTE, al.getSequencesArray(), 0, al.getWidth(),
+              MessageManager.getString("label.add_sequences"), Action.PASTE,
+              al.getSequencesArray(), 0, al.getWidth(),
               viewport.getAlignment()));
     } catch (Exception ex)
     {
@@ -5490,12 +5500,10 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       } catch (Exception ex)
       {
         System.err.println((ex.toString()));
-        JvOptionPane
-                .showInternalMessageDialog(Desktop.desktop, MessageManager
-                        .getString("label.couldnt_run_groovy_script"),
-                        MessageManager
-                                .getString("label.groovy_support_failed"),
-                        JvOptionPane.ERROR_MESSAGE);
+        JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                MessageManager.getString("label.couldnt_run_groovy_script"),
+                MessageManager.getString("label.groovy_support_failed"),
+                JvOptionPane.ERROR_MESSAGE);
       }
     }
     else
@@ -5535,9 +5543,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   {
     // include key modifier check in case user selects from menu
     avc.markHighlightedColumns(
-            (actionEvent.getModifiers() & ActionEvent.ALT_MASK) != 0,
-            true,
-            (actionEvent.getModifiers() & (ActionEvent.META_MASK | ActionEvent.CTRL_MASK)) != 0);
+            (actionEvent.getModifiers() & ActionEvent.ALT_MASK) != 0, true,
+            (actionEvent.getModifiers() & (ActionEvent.META_MASK
+                    | ActionEvent.CTRL_MASK)) != 0);
   }
 
   /**
@@ -5552,8 +5560,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     colourMenu.add(textColour);
     colourMenu.addSeparator();
 
-    ColourMenuHelper.addMenuItems(colourMenu, this,
-            viewport.getAlignment(), false);
+    ColourMenuHelper.addMenuItems(colourMenu, this, viewport.getAlignment(),
+            false);
 
     colourMenu.addSeparator();
     colourMenu.add(conservationMenuItem);
index 835371f..4d09084 100644 (file)
@@ -71,13 +71,11 @@ import javax.swing.JInternalFrame;
  * @author $author$
  * @version $Revision: 1.141 $
  */
-public class AlignViewport extends AlignmentViewport implements
-        SelectionSource
+public class AlignViewport extends AlignmentViewport
+        implements SelectionSource
 {
   Font font;
 
-  TreeModel currentTree = null;
-
   boolean cursorMode = false;
 
   boolean antiAlias = false;
@@ -129,8 +127,8 @@ public class AlignViewport extends AlignmentViewport implements
     // TODO remove these once 2.4.VAMSAS release finished
     if (Cache.log != null && Cache.log.isDebugEnabled() && seqsetid != null)
     {
-      Cache.log.debug("Setting viewport's sequence set id : "
-              + sequenceSetID);
+      Cache.log.debug(
+              "Setting viewport's sequence set id : " + sequenceSetID);
     }
     if (Cache.log != null && Cache.log.isDebugEnabled() && viewId != null)
     {
@@ -191,8 +189,8 @@ public class AlignViewport extends AlignmentViewport implements
     // TODO remove these once 2.4.VAMSAS release finished
     if (Cache.log != null && Cache.log.isDebugEnabled() && seqsetid != null)
     {
-      Cache.log.debug("Setting viewport's sequence set id : "
-              + sequenceSetID);
+      Cache.log.debug(
+              "Setting viewport's sequence set id : " + sequenceSetID);
     }
     if (Cache.log != null && Cache.log.isDebugEnabled() && viewId != null)
     {
@@ -225,17 +223,17 @@ public class AlignViewport extends AlignmentViewport implements
     setShowDBRefs(Cache.getDefault("SHOW_DBREFS_TOOLTIP", true));
     viewStyle.setSeqNameItalics(Cache.getDefault("ID_ITALICS", true));
     viewStyle.setWrapAlignment(Cache.getDefault("WRAP_ALIGNMENT", false));
-    viewStyle.setShowUnconserved(Cache
-            .getDefault("SHOW_UNCONSERVED", false));
+    viewStyle.setShowUnconserved(
+            Cache.getDefault("SHOW_UNCONSERVED", false));
     sortByTree = Cache.getDefault("SORT_BY_TREE", false);
     followSelection = Cache.getDefault("FOLLOW_SELECTIONS", true);
-    sortAnnotationsBy = SequenceAnnotationOrder.valueOf(Cache.getDefault(
-            Preferences.SORT_ANNOTATIONS,
-            SequenceAnnotationOrder.NONE.name()));
-    showAutocalculatedAbove = Cache.getDefault(
-            Preferences.SHOW_AUTOCALC_ABOVE, false);
-    viewStyle.setScaleProteinAsCdna(Cache.getDefault(
-            Preferences.SCALE_PROTEIN_TO_CDNA, true));
+    sortAnnotationsBy = SequenceAnnotationOrder
+            .valueOf(Cache.getDefault(Preferences.SORT_ANNOTATIONS,
+                    SequenceAnnotationOrder.NONE.name()));
+    showAutocalculatedAbove = Cache
+            .getDefault(Preferences.SHOW_AUTOCALC_ABOVE, false);
+    viewStyle.setScaleProteinAsCdna(
+            Cache.getDefault(Preferences.SCALE_PROTEIN_TO_CDNA, true));
   }
 
   void init()
@@ -284,7 +282,8 @@ public class AlignViewport extends AlignmentViewport implements
       showOccupancy = Cache.getDefault(Preferences.SHOW_OCCUPANCY, true);
     }
     initAutoAnnotation();
-    String colourProperty = alignment.isNucleotide() ? Preferences.DEFAULT_COLOUR_NUC
+    String colourProperty = alignment.isNucleotide()
+            ? Preferences.DEFAULT_COLOUR_NUC
             : Preferences.DEFAULT_COLOUR_PROT;
     String schemeName = Cache.getProperty(colourProperty);
     if (schemeName == null)
@@ -293,8 +292,8 @@ public class AlignViewport extends AlignmentViewport implements
       schemeName = Cache.getDefault(Preferences.DEFAULT_COLOUR,
               ResidueColourScheme.NONE);
     }
-    ColourSchemeI colourScheme = ColourSchemeProperty.getColourScheme(
-            alignment, schemeName);
+    ColourSchemeI colourScheme = ColourSchemeProperty
+            .getColourScheme(alignment, schemeName);
     residueShading = new ResidueShader(colourScheme);
 
     if (colourScheme instanceof UserColourScheme)
@@ -447,27 +446,6 @@ public class AlignViewport extends AlignmentViewport implements
   }
 
   /**
-   * DOCUMENT ME!
-   * 
-   * @param tree
-   *          DOCUMENT ME!
-   */
-  public void setCurrentTree(TreeModel tree)
-  {
-    currentTree = tree;
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @return DOCUMENT ME!
-   */
-  public TreeModel getCurrentTree()
-  {
-    return currentTree;
-  }
-
-  /**
    * returns the visible column regions of the alignment
    * 
    * @param selectedRegionOnly
@@ -556,8 +534,8 @@ public class AlignViewport extends AlignmentViewport implements
   public void sendSelection()
   {
     jalview.structure.StructureSelectionManager
-            .getStructureSelectionManager(Desktop.instance).sendSelection(
-                    new SequenceGroup(getSelectionGroup()),
+            .getStructureSelectionManager(Desktop.instance)
+            .sendSelection(new SequenceGroup(getSelectionGroup()),
                     new ColumnSelection(getColumnSelection()),
                     new HiddenColumns(getAlignment().getHiddenColumns()),
                     this);
@@ -573,8 +551,8 @@ public class AlignViewport extends AlignmentViewport implements
    */
   public AlignmentPanel getAlignPanel()
   {
-    AlignmentPanel[] aps = PaintRefresher.getAssociatedPanels(this
-            .getSequenceSetId());
+    AlignmentPanel[] aps = PaintRefresher
+            .getAssociatedPanels(this.getSequenceSetId());
     for (int p = 0; aps != null && p < aps.length; p++)
     {
       if (aps[p].av == this)
@@ -605,59 +583,6 @@ public class AlignViewport extends AlignmentViewport implements
             .getStructureSelectionManager(Desktop.instance);
   }
 
-  /**
-   * 
-   * @param pdbEntries
-   * @return an array of SequenceI arrays, one for each PDBEntry, listing which
-   *         sequences in the alignment hold a reference to it
-   */
-  public SequenceI[][] collateForPDB(PDBEntry[] pdbEntries)
-  {
-    List<SequenceI[]> seqvectors = new ArrayList<SequenceI[]>();
-    for (PDBEntry pdb : pdbEntries)
-    {
-      List<SequenceI> choosenSeqs = new ArrayList<SequenceI>();
-      for (SequenceI sq : alignment.getSequences())
-      {
-        Vector<PDBEntry> pdbRefEntries = sq.getDatasetSequence()
-                .getAllPDBEntries();
-        if (pdbRefEntries == null)
-        {
-          continue;
-        }
-        for (PDBEntry pdbRefEntry : pdbRefEntries)
-        {
-          if (pdbRefEntry.getId().equals(pdb.getId()))
-          {
-            if (pdbRefEntry.getChainCode() != null
-                    && pdb.getChainCode() != null)
-            {
-              if (pdbRefEntry.getChainCode().equalsIgnoreCase(
-                      pdb.getChainCode())
-                      && !choosenSeqs.contains(sq))
-              {
-                choosenSeqs.add(sq);
-                continue;
-              }
-            }
-            else
-            {
-              if (!choosenSeqs.contains(sq))
-              {
-                choosenSeqs.add(sq);
-                continue;
-              }
-            }
-
-          }
-        }
-      }
-      seqvectors
-              .add(choosenSeqs.toArray(new SequenceI[choosenSeqs.size()]));
-    }
-    return seqvectors.toArray(new SequenceI[seqvectors.size()][]);
-  }
-
   @Override
   public boolean isNormaliseSequenceLogo()
   {
@@ -709,7 +634,8 @@ public class AlignViewport extends AlignmentViewport implements
    * <ul>
    * <li>compute the equivalent edit on the mapped sequences</li>
    * <li>apply the mapped edit</li>
-   * <li>'apply' the source edit to the working copy of the source sequences</li>
+   * <li>'apply' the source edit to the working copy of the source
+   * sequences</li>
    * </ul>
    * 
    * @param command
@@ -830,8 +756,7 @@ public class AlignViewport extends AlignmentViewport implements
    */
   protected boolean openLinkedAlignment(AlignmentI al, String title)
   {
-    String[] options = new String[] {
-        MessageManager.getString("action.no"),
+    String[] options = new String[] { MessageManager.getString("action.no"),
         MessageManager.getString("label.split_window"),
         MessageManager.getString("label.new_window"), };
     final String question = JvSwingUtils.wrapTooltip(true,
@@ -873,8 +798,9 @@ public class AlignViewport extends AlignmentViewport implements
     AlignFrame newAlignFrame = new AlignFrame(al, AlignFrame.DEFAULT_WIDTH,
             AlignFrame.DEFAULT_HEIGHT);
     newAlignFrame.setTitle(title);
-    newAlignFrame.statusBar.setText(MessageManager.formatMessage(
-            "label.successfully_loaded_file", new Object[] { title }));
+    newAlignFrame.statusBar.setText(MessageManager
+            .formatMessage("label.successfully_loaded_file", new Object[]
+            { title }));
 
     // TODO if we want this (e.g. to enable reload of the alignment from file),
     // we will need to add parameters to the stack.
@@ -891,8 +817,8 @@ public class AlignViewport extends AlignmentViewport implements
 
     try
     {
-      newAlignFrame.setMaximum(jalview.bin.Cache.getDefault(
-              "SHOW_FULLSCREEN", false));
+      newAlignFrame.setMaximum(
+              jalview.bin.Cache.getDefault("SHOW_FULLSCREEN", false));
     } catch (java.beans.PropertyVetoException ex)
     {
     }
@@ -924,8 +850,8 @@ public class AlignViewport extends AlignmentViewport implements
      * is protein, the mappings to cDNA will be registered with
      * StructureSelectionManager as a side-effect.
      */
-    AlignFrame copyMe = new AlignFrame(complement,
-            AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
+    AlignFrame copyMe = new AlignFrame(complement, AlignFrame.DEFAULT_WIDTH,
+            AlignFrame.DEFAULT_HEIGHT);
     copyMe.setTitle(getAlignPanel().alignFrame.getTitle());
 
     AlignmentI al = newAlignFrame.viewport.getAlignment();
@@ -1109,5 +1035,4 @@ public class AlignViewport extends AlignmentViewport implements
     }
     fr.setTransparency(featureSettings.getTransparency());
   }
-
 }
index e62707f..3a1dbe8 100644 (file)
@@ -30,10 +30,12 @@ import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
+import jalview.io.HTMLOutput;
 import jalview.jbgui.GAlignmentPanel;
 import jalview.math.AlignmentDimension;
 import jalview.schemes.ResidueProperties;
 import jalview.structure.StructureSelectionManager;
+import jalview.util.Comparison;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
 import jalview.viewmodel.ViewportListenerI;
@@ -70,13 +72,10 @@ import javax.swing.SwingUtilities;
  * @version $Revision: 1.161 $
  */
 public class AlignmentPanel extends GAlignmentPanel implements
-        AdjustmentListener, Printable, AlignmentViewPanel,
-        ViewportListenerI
+        AdjustmentListener, Printable, AlignmentViewPanel, ViewportListenerI
 {
   public AlignViewport av;
 
-  ViewportRanges vpRanges;
-
   OverviewPanel overviewPanel;
 
   private SeqPanel seqPanel;
@@ -96,9 +95,6 @@ public class AlignmentPanel extends GAlignmentPanel implements
 
   private AnnotationLabels alabels;
 
-  // this value is set false when selection area being dragged
-  boolean fastPaint = true;
-
   private int hextent = 0;
 
   private int vextent = 0;
@@ -123,7 +119,6 @@ public class AlignmentPanel extends GAlignmentPanel implements
   {
     alignFrame = af;
     this.av = av;
-    vpRanges = av.getRanges();
     setSeqPanel(new SeqPanel(av, this));
     setIdPanel(new IdPanel(av, this));
 
@@ -155,11 +150,12 @@ public class AlignmentPanel extends GAlignmentPanel implements
         // reset the viewport ranges when the alignment panel is resized
         // in particular, this initialises the end residue value when Jalview
         // is initialised
+        ViewportRanges ranges = av.getRanges();
         if (av.getWrapAlignment())
         {
-          int widthInRes = getSeqPanel().seqCanvas
-                  .getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth());
-          vpRanges.setViewportWidth(widthInRes);
+          int widthInRes = getSeqPanel().seqCanvas.getWrappedCanvasWidth(
+                  getSeqPanel().seqCanvas.getWidth());
+          ranges.setViewportWidth(widthInRes);
         }
         else
         {
@@ -167,9 +163,9 @@ public class AlignmentPanel extends GAlignmentPanel implements
                   / av.getCharWidth();
           int heightInSeq = getSeqPanel().seqCanvas.getHeight()
                   / av.getCharHeight();
-          
-          vpRanges.setViewportWidth(widthInRes);
-          vpRanges.setViewportHeight(heightInSeq);
+
+          ranges.setViewportWidth(widthInRes);
+          ranges.setViewportHeight(heightInSeq);
         }
       }
 
@@ -213,7 +209,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
 
     alignFrame.updateEditMenuBar();
 
-    paintAlignment(true);
+    // no idea if we need to update structure
+    paintAlignment(true, true);
 
   }
 
@@ -226,11 +223,12 @@ public class AlignmentPanel extends GAlignmentPanel implements
     // to prevent drawing old image
     FontMetrics fm = getFontMetrics(av.getFont());
 
-    scalePanelHolder.setPreferredSize(new Dimension(10, av.getCharHeight()
-            + fm.getDescent()));
-    idSpaceFillerPanel1.setPreferredSize(new Dimension(10, av
-            .getCharHeight() + fm.getDescent()));
-
+    scalePanelHolder.setPreferredSize(
+            new Dimension(10, av.getCharHeight() + fm.getDescent()));
+    idSpaceFillerPanel1.setPreferredSize(
+            new Dimension(10, av.getCharHeight() + fm.getDescent()));
+    idwidthAdjuster.invalidate();
+    scalePanelHolder.invalidate();
     getIdPanel().getIdCanvas().gg = null;
     getSeqPanel().seqCanvas.img = null;
     getAnnotationPanel().adjustPanelHeight();
@@ -241,11 +239,6 @@ public class AlignmentPanel extends GAlignmentPanel implements
     getIdPanel().getIdCanvas().setPreferredSize(d);
     hscrollFillerPanel.setPreferredSize(d);
 
-    if (this.alignFrame.getSplitViewContainer() != null)
-    {
-      ((SplitFrame) this.alignFrame.getSplitViewContainer()).adjustLayout();
-    }
-
     repaint();
   }
 
@@ -289,8 +282,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
   {
     Container c = new Container();
 
-    FontMetrics fm = c.getFontMetrics(new Font(av.font.getName(),
-            Font.ITALIC, av.font.getSize()));
+    FontMetrics fm = c.getFontMetrics(
+            new Font(av.font.getName(), Font.ITALIC, av.font.getSize()));
 
     AlignmentI al = av.getAlignment();
     int i = 0;
@@ -331,8 +324,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
       }
     }
 
-    return new Dimension(maxwidth < 0 ? idWidth : Math.min(maxwidth,
-            idWidth), 12);
+    return new Dimension(
+            maxwidth < 0 ? idWidth : Math.min(maxwidth, idWidth), 12);
   }
 
   /**
@@ -341,19 +334,11 @@ public class AlignmentPanel extends GAlignmentPanel implements
    */
   public void highlightSearchResults(SearchResultsI results)
   {
-    scrollToPosition(results);
-    getSeqPanel().seqCanvas.highlightSearchResults(results);
-  }
+    boolean scrolled = scrollToPosition(results, 0, true, false);
 
-  /**
-   * Scroll the view to show the position of the highlighted region in results
-   * (if any) and redraw the overview
-   * 
-   * @param results
-   */
-  public boolean scrollToPosition(SearchResultsI results)
-  {
-    return scrollToPosition(results, 0, true, false);
+    boolean noFastPaint = scrolled && av.getWrapAlignment();
+
+    getSeqPanel().seqCanvas.highlightSearchResults(results, noFastPaint);
   }
 
   /**
@@ -371,8 +356,10 @@ public class AlignmentPanel extends GAlignmentPanel implements
   }
 
   /**
-   * Scroll the view to show the position of the highlighted region in results
-   * (if any)
+   * Scrolls the view (if necessary) to show the position of the first
+   * highlighted region in results (if any). Answers true if the view was
+   * scrolled, or false if no matched region was found, or it is already
+   * visible.
    * 
    * @param results
    * @param verticalOffset
@@ -382,116 +369,118 @@ public class AlignmentPanel extends GAlignmentPanel implements
    *          - when set, the overview will be recalculated (takes longer)
    * @param centre
    *          if true, try to centre the search results horizontally in the view
-   * @return false if results were not found
+   * @return
    */
-  public boolean scrollToPosition(SearchResultsI results,
+  protected boolean scrollToPosition(SearchResultsI results,
           int verticalOffset, boolean redrawOverview, boolean centre)
   {
     int startv, endv, starts, ends;
-    // TODO: properly locate search results in view when large numbers of hidden
-    // columns exist before highlighted region
-    // do we need to scroll the panel?
-    // TODO: tons of nullpointerexceptions raised here.
-    if (results != null && results.getSize() > 0 && av != null
-            && av.getAlignment() != null)
-    {
-      int seqIndex = av.getAlignment().findIndex(results);
-      if (seqIndex == -1)
-      {
-        return false;
-      }
-      SequenceI seq = av.getAlignment().getSequenceAt(seqIndex);
+    ViewportRanges ranges = av.getRanges();
 
-      int[] r = results.getResults(seq, 0, av.getAlignment().getWidth());
-      if (r == null)
-      {
-        return false;
-      }
-      int start = r[0];
-      int end = r[1];
+    if (results == null || results.isEmpty() || av == null
+            || av.getAlignment() == null)
+    {
+      return false;
+    }
+    int seqIndex = av.getAlignment().findIndex(results);
+    if (seqIndex == -1)
+    {
+      return false;
+    }
+    SequenceI seq = av.getAlignment().getSequenceAt(seqIndex);
 
-      /*
-       * To centre results, scroll to positions half the visible width
-       * left/right of the start/end positions
-       */
-      if (centre)
-      {
-        int offset = (vpRanges.getEndRes() - vpRanges.getStartRes() + 1) / 2
-                - 1;
-        start = Math.max(start - offset, 0);
-        end = end + offset - 1;
-      }
-      if (start < 0)
-      {
-        return false;
-      }
-      if (end == seq.getEnd())
-      {
-        return false;
-      }
-      if (av.hasHiddenColumns())
+    int[] r = results.getResults(seq, 0, av.getAlignment().getWidth());
+    if (r == null)
+    {
+      return false;
+    }
+    int start = r[0];
+    int end = r[1];
+
+    /*
+     * To centre results, scroll to positions half the visible width
+     * left/right of the start/end positions
+     */
+    if (centre)
+    {
+      int offset = (ranges.getEndRes() - ranges.getStartRes() + 1) / 2 - 1;
+      start = Math.max(start - offset, 0);
+      end = end + offset - 1;
+    }
+    if (start < 0)
+    {
+      return false;
+    }
+    if (end == seq.getEnd())
+    {
+      return false;
+    }
+
+    if (av.hasHiddenColumns())
+    {
+      HiddenColumns hidden = av.getAlignment().getHiddenColumns();
+      start = hidden.findColumnPosition(start);
+      end = hidden.findColumnPosition(end);
+      if (start == end)
       {
-        HiddenColumns hidden = av.getAlignment().getHiddenColumns();
-        start = hidden.findColumnPosition(start);
-        end = hidden.findColumnPosition(end);
-        if (start == end)
+        if (!hidden.isVisible(r[0]))
         {
-          if (!hidden.isVisible(r[0]))
-          {
-            // don't scroll - position isn't visible
-            return false;
-          }
+          // don't scroll - position isn't visible
+          return false;
         }
       }
+    }
 
-      /*
-       * allow for offset of target sequence (actually scroll to one above it)
-       */
-      seqIndex = Math.max(0, seqIndex - verticalOffset);
+    /*
+     * allow for offset of target sequence (actually scroll to one above it)
+     */
+    seqIndex = Math.max(0, seqIndex - verticalOffset);
+    boolean scrollNeeded = true;
 
-      if (!av.getWrapAlignment())
+    if (!av.getWrapAlignment())
+    {
+      if ((startv = ranges.getStartRes()) >= start)
       {
-        if ((startv = vpRanges.getStartRes()) >= start)
-        {
-          /*
-           * Scroll left to make start of search results visible
-           */
-          setScrollValues(start, seqIndex);
-        }
-        else if ((endv = vpRanges.getEndRes()) <= end)
-        {
-          /*
-           * Scroll right to make end of search results visible
-           */
-          setScrollValues(startv + end - endv, seqIndex);
-        }
-        else if ((starts = vpRanges.getStartSeq()) > seqIndex)
-        {
-          /*
-           * Scroll up to make start of search results visible
-           */
-          setScrollValues(vpRanges.getStartRes(), seqIndex);
-        }
-        else if ((ends = vpRanges.getEndSeq()) <= seqIndex)
-        {
-          /*
-           * Scroll down to make end of search results visible
-           */
-          setScrollValues(vpRanges.getStartRes(), starts + seqIndex - ends
-                  + 1);
-        }
         /*
-         * Else results are already visible - no need to scroll
+         * Scroll left to make start of search results visible
          */
+        setScrollValues(start, seqIndex);
       }
-      else
+      else if ((endv = ranges.getEndRes()) <= end)
+      {
+        /*
+         * Scroll right to make end of search results visible
+         */
+        setScrollValues(startv + end - endv, seqIndex);
+      }
+      else if ((starts = ranges.getStartSeq()) > seqIndex)
+      {
+        /*
+         * Scroll up to make start of search results visible
+         */
+        setScrollValues(ranges.getStartRes(), seqIndex);
+      }
+      else if ((ends = ranges.getEndSeq()) <= seqIndex)
       {
-        vpRanges.scrollToWrappedVisible(start);
+        /*
+         * Scroll down to make end of search results visible
+         */
+        setScrollValues(ranges.getStartRes(), starts + seqIndex - ends
+                + 1);
       }
+      /*
+       * Else results are already visible - no need to scroll
+       */
+      scrollNeeded = false;
     }
+    else
+    {
+      scrollNeeded = ranges.scrollToWrappedVisible(start);
+    }
+
+    paintAlignment(redrawOverview, false);
 
-    paintAlignment(redrawOverview);
-    return true;
+    return scrollNeeded;
   }
 
   /**
@@ -546,7 +535,9 @@ public class AlignmentPanel extends GAlignmentPanel implements
     }
     validateAnnotationDimensions(true);
     addNotify();
-    paintAlignment(true);
+    // TODO: many places call this method and also paintAlignment with various
+    // different settings. this means multiple redraws are triggered...
+    paintAlignment(true, false);
   }
 
   /**
@@ -579,8 +570,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
        */
       if (annotationHeight + alignmentHeight > availableHeight)
       {
-        annotationHeight = Math.min(annotationHeight, availableHeight - 2
-                * rowHeight);
+        annotationHeight = Math.min(annotationHeight,
+                availableHeight - 2 * rowHeight);
       }
     }
     else
@@ -590,8 +581,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
     }
     hscroll.addNotify();
 
-    annotationScroller.setPreferredSize(new Dimension(annotationScroller
-            .getWidth(), annotationHeight));
+    annotationScroller.setPreferredSize(
+            new Dimension(annotationScroller.getWidth(), annotationHeight));
 
     Dimension e = idPanel.getSize();
     alabels.setSize(new Dimension(e.width, annotationHeight));
@@ -613,7 +604,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
     fontChanged();
     setAnnotationVisible(av.isShowAnnotation());
     boolean wrap = av.getWrapAlignment();
-    vpRanges.setStartSeq(0);
+    ViewportRanges ranges = av.getRanges();
+    ranges.setStartSeq(0);
     scalePanelHolder.setVisible(!wrap);
     hscroll.setVisible(!wrap);
     idwidthAdjuster.setVisible(!wrap);
@@ -636,16 +628,16 @@ public class AlignmentPanel extends GAlignmentPanel implements
       {
         int widthInRes = getSeqPanel().seqCanvas
                 .getWrappedCanvasWidth(canvasWidth);
-        vpRanges.setViewportWidth(widthInRes);
+        ranges.setViewportWidth(widthInRes);
       }
       else
       {
-        int widthInRes = (canvasWidth / av.getCharWidth()) - 1;
-        int heightInSeq = (getSeqPanel().seqCanvas.getHeight() / av
-                .getCharHeight()) - 1;
+        int widthInRes = (canvasWidth / av.getCharWidth());
+        int heightInSeq = (getSeqPanel().seqCanvas.getHeight()
+                / av.getCharHeight());
 
-        vpRanges.setViewportWidth(widthInRes);
-        vpRanges.setViewportHeight(heightInSeq);
+        ranges.setViewportWidth(widthInRes);
+        ranges.setViewportHeight(heightInSeq);
       }
     }
 
@@ -654,7 +646,6 @@ public class AlignmentPanel extends GAlignmentPanel implements
     repaint();
   }
 
-
   /**
    * Adjust row/column scrollers to show a visible position in the alignment.
    * 
@@ -686,7 +677,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
       if (av.hasHiddenColumns())
       {
         // reset the width to exclude hidden columns
-        width = av.getAlignment().getHiddenColumns().findColumnPosition(width);
+        width = av.getAlignment().getHiddenColumns()
+                .findColumnPosition(width);
       }
 
       hextent = getSeqPanel().seqCanvas.getWidth() / av.getCharWidth();
@@ -744,10 +736,12 @@ public class AlignmentPanel extends GAlignmentPanel implements
       return;
     }
 
+    ViewportRanges ranges = av.getRanges();
+
     if (evt.getSource() == hscroll)
     {
-      int oldX = vpRanges.getStartRes();
-      int oldwidth = vpRanges.getViewportWidth();
+      int oldX = ranges.getStartRes();
+      int oldwidth = ranges.getViewportWidth();
       int x = hscroll.getValue();
       int width = getSeqPanel().seqCanvas.getWidth() / av.getCharWidth();
 
@@ -758,12 +752,12 @@ public class AlignmentPanel extends GAlignmentPanel implements
       {
         return;
       }
-      vpRanges.setViewportStartAndWidth(x, width);
+      ranges.setViewportStartAndWidth(x, width);
     }
     else if (evt.getSource() == vscroll)
     {
-      int oldY = vpRanges.getStartSeq();
-      int oldheight = vpRanges.getViewportHeight();
+      int oldY = ranges.getStartSeq();
+      int oldheight = ranges.getViewportHeight();
       int y = vscroll.getValue();
       int height = getSeqPanel().seqCanvas.getHeight() / av.getCharHeight();
 
@@ -774,12 +768,9 @@ public class AlignmentPanel extends GAlignmentPanel implements
       {
         return;
       }
-      vpRanges.setViewportStartAndHeight(y, height);
-    }
-    if (!fastPaint)
-    {
-      repaint();
+      ranges.setViewportStartAndHeight(y, height);
     }
+    repaint();
   }
 
   /**
@@ -794,6 +785,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
     {
       return; // no horizontal scroll when wrapped
     }
+    final ViewportRanges ranges = av.getRanges();
+
     if (evt.getSource() == vscroll)
     {
       int newY = vscroll.getValue();
@@ -803,8 +796,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
        * this prevents infinite recursion of events when the scroll/viewport
        * ranges values are the same
        */
-      int oldX = vpRanges.getStartRes();
-      int oldY = vpRanges.getWrappedScrollPosition(oldX);
+      int oldX = ranges.getStartRes();
+      int oldY = ranges.getWrappedScrollPosition(oldX);
       if (oldY == newY)
       {
         return;
@@ -814,9 +807,9 @@ public class AlignmentPanel extends GAlignmentPanel implements
         /*
          * limit page up/down to one width's worth of positions
          */
-        int rowSize = vpRanges.getViewportWidth();
+        int rowSize = ranges.getViewportWidth();
         int newX = newY > oldY ? oldX + rowSize : oldX - rowSize;
-        vpRanges.setViewportStartAndWidth(Math.max(0, newX), rowSize);
+        ranges.setViewportStartAndWidth(Math.max(0, newX), rowSize);
       }
     }
     else
@@ -828,29 +821,29 @@ public class AlignmentPanel extends GAlignmentPanel implements
       {
         @Override
         public void run()
-      {
+        {
           // When updating scrolling to use ViewportChange events, this code
           // could not be validated and it is not clear if it is now being
           // called. Log warning here in case it is called and unforeseen
           // problems occur
-          Cache.log
-                  .warn("Unexpected path through code: Wrapped jar file opened with wrap alignment set in preferences");
+          Cache.log.warn(
+                  "Unexpected path through code: Wrapped jar file opened with wrap alignment set in preferences");
 
           // scroll to start of panel
-          vpRanges.setStartRes(0);
-          vpRanges.setStartSeq(0);
+          ranges.setStartRes(0);
+          ranges.setStartSeq(0);
         }
       });
     }
     repaint();
   }
 
-  /**
-   * Repaint the alignment including the annotations and overview panels (if
-   * shown).
+  /* (non-Javadoc)
+   * @see jalview.api.AlignmentViewPanel#paintAlignment(boolean)
    */
   @Override
-  public void paintAlignment(boolean updateOverview)
+  public void paintAlignment(boolean updateOverview,
+          boolean updateStructures)
   {
     final AnnotationSorter sorter = new AnnotationSorter(getAlignment(),
             av.isShowAutocalculatedAbove());
@@ -858,10 +851,12 @@ public class AlignmentPanel extends GAlignmentPanel implements
             av.getSortAnnotationsBy());
     repaint();
 
-    if (updateOverview)
+    if (updateStructures)
     {
-      // TODO: determine if this paintAlignment changed structure colours
       av.getStructureSelectionManager().sequenceColoursChanged(this);
+    }
+    if (updateOverview)
+    {
 
       if (overviewPanel != null)
       {
@@ -889,7 +884,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
     /*
      * set scroll bar positions
      */
-    setScrollValues(vpRanges.getStartRes(), vpRanges.getStartSeq());
+    ViewportRanges ranges = av.getRanges();
+    setScrollValues(ranges.getStartRes(), ranges.getStartSeq());
   }
 
   /**
@@ -901,8 +897,9 @@ public class AlignmentPanel extends GAlignmentPanel implements
    */
   private void setScrollingForWrappedPanel(int topLeftColumn)
   {
-    int scrollPosition = vpRanges.getWrappedScrollPosition(topLeftColumn);
-    int maxScroll = vpRanges.getWrappedMaxScroll(topLeftColumn);
+    ViewportRanges ranges = av.getRanges();
+    int scrollPosition = ranges.getWrappedScrollPosition(topLeftColumn);
+    int maxScroll = ranges.getWrappedMaxScroll(topLeftColumn);
 
     /*
      * a scrollbar's value can be set to at most (maximum-extent)
@@ -989,7 +986,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
      * Get the horizontal offset to where we draw the sequences.
      * This is idWidth if using a single Graphics context, else zero.
      */
-    final int alignmentGraphicsOffset = idGraphics != alignmentGraphics ? 0 : idWidth;
+    final int alignmentGraphicsOffset = idGraphics != alignmentGraphics ? 0
+            : idWidth;
 
     FontMetrics fm = getFontMetrics(av.getFont());
     int charHeight = av.getCharHeight();
@@ -1026,8 +1024,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
       endSeq = alignmentHeight;
     }
 
-    int pagesHigh = ((alignmentHeight / totalSeq) + 1)
-            * pageHeight;
+    int pagesHigh = ((alignmentHeight / totalSeq) + 1) * pageHeight;
 
     if (av.isShowAnnotation())
     {
@@ -1040,8 +1037,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
     {
       return Printable.NO_SUCH_PAGE;
     }
-    final int alignmentDrawnHeight = (endSeq - startSeq) * charHeight
-            + 3;
+    final int alignmentDrawnHeight = (endSeq - startSeq) * charHeight + 3;
 
     /*
      * draw the Scale at horizontal offset, then reset to top left (0, 0)
@@ -1090,9 +1086,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
       if (av.isRightAlignIds())
       {
         fm = idGraphics.getFontMetrics();
-        xPos = idWidth
-                - fm.stringWidth(displayId)
-                - 4;
+        xPos = idWidth - fm.stringWidth(displayId) - 4;
       }
 
       idGraphics.drawString(displayId, xPos,
@@ -1107,8 +1101,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
      * single graphics context), then reset to (0, scale height)
      */
     alignmentGraphics.translate(alignmentGraphicsOffset, scaleHeight);
-    getSeqPanel().seqCanvas.drawPanel(alignmentGraphics, startRes, endRes,
-            startSeq, endSeq, 0);
+    getSeqPanel().seqCanvas.drawPanelForPrinting(alignmentGraphics, startRes,
+            endRes, startSeq, endSeq);
     alignmentGraphics.translate(-alignmentGraphicsOffset, 0);
 
     if (av.isShowAnnotation() && (endSeq == alignmentHeight))
@@ -1128,7 +1122,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
        * draw the annotations starting at 
        * (idOffset, alignmentHeight) from (0, scaleHeight)
        */
-      alignmentGraphics.translate(alignmentGraphicsOffset, alignmentDrawnHeight);
+      alignmentGraphics.translate(alignmentGraphicsOffset,
+              alignmentDrawnHeight);
       getAnnotationPanel().renderer.drawComponent(getAnnotationPanel(), av,
               alignmentGraphics, -1, startRes, endRes + 1);
     }
@@ -1182,8 +1177,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
               .findColumnPosition(maxwidth) - 1;
     }
 
-    int resWidth = getSeqPanel().seqCanvas.getWrappedCanvasWidth(pwidth
-            - idWidth);
+    int resWidth = getSeqPanel().seqCanvas
+            .getWrappedCanvasWidth(pwidth - idWidth);
 
     int totalHeight = cHeight * (maxwidth / resWidth + 1);
 
@@ -1220,16 +1215,13 @@ public class AlignmentPanel extends GAlignmentPanel implements
       }
       if (labels != null)
       {
-        pg.translate(-3,
-                ypos + (av.getAlignment().getHeight() * av.getCharHeight()));
+        pg.translate(-3, ypos
+                + (av.getAlignment().getHeight() * av.getCharHeight()));
 
         pg.setFont(av.getFont());
         labels.drawComponent(pg, idWidth);
-        pg.translate(
-                +3,
-                -ypos
-                        - (av.getAlignment().getHeight() * av
-                                .getCharHeight()));
+        pg.translate(+3, -ypos
+                - (av.getAlignment().getHeight() * av.getCharHeight()));
       }
 
       ypos += cHeight;
@@ -1237,7 +1229,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
 
     pg.translate(idWidth, 0);
 
-    getSeqPanel().seqCanvas.drawWrappedPanel(pg, pwidth - idWidth,
+    getSeqPanel().seqCanvas.drawWrappedPanelForPrinting(pg, pwidth - idWidth,
             totalHeight, 0);
 
     if ((pi * pheight) < totalHeight)
@@ -1279,8 +1271,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
       return calculateIdWidth(-1).width + 4;
     }
     Integer idwidth = null;
-    if (onscreen
-            || (idwidth = Cache.getIntegerProperty("FIGURE_FIXEDIDWIDTH")) == null)
+    if (onscreen || (idwidth = Cache
+            .getIntegerProperty("FIGURE_FIXEDIDWIDTH")) == null)
     {
       int w = getIdPanel().getWidth();
       return (w > 0 ? w : calculateIdWidth().width + 4);
@@ -1292,15 +1284,15 @@ public class AlignmentPanel extends GAlignmentPanel implements
   {
     int boarderBottomOffset = 5;
     long pSessionId = System.currentTimeMillis();
-    headless = (System.getProperty("java.awt.headless") != null && System
-            .getProperty("java.awt.headless").equals("true"));
+    headless = (System.getProperty("java.awt.headless") != null
+            && System.getProperty("java.awt.headless").equals("true"));
     if (alignFrame != null && !headless)
     {
       if (file != null)
       {
-        alignFrame.setProgressBar(MessageManager.formatMessage(
-                "status.saving_file", new Object[] { type.getLabel() }),
-                pSessionId);
+        alignFrame.setProgressBar(MessageManager
+                .formatMessage("status.saving_file", new Object[]
+                { type.getLabel() }), pSessionId);
       }
     }
     try
@@ -1327,9 +1319,9 @@ public class AlignmentPanel extends GAlignmentPanel implements
         }
 
         im = new jalview.util.ImageMaker(this, type, imageAction,
-                aDimension.getWidth(), aDimension.getHeight()
-                        + boarderBottomOffset, file, imageTitle,
-                alignFrame, pSessionId, headless);
+                aDimension.getWidth(),
+                aDimension.getHeight() + boarderBottomOffset, file,
+                imageTitle, alignFrame, pSessionId, headless);
         Graphics graphics = im.getGraphics();
         if (av.getWrapAlignment())
         {
@@ -1345,8 +1337,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
         {
           if (graphics != null)
           {
-            printUnwrapped(aDimension.getWidth(), aDimension.getHeight(),
-                    0, graphics, graphics);
+            printUnwrapped(aDimension.getWidth(), aDimension.getHeight(), 0,
+                    graphics, graphics);
             im.writeImage();
           }
         }
@@ -1391,9 +1383,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
         // this duplicates the calculation in getWrappedHeight but adjusts for
         // offscreen idWith
         width = alignFrame.getWidth() - vscroll.getPreferredSize().width
-                - alignFrame.getInsets().left
-                - alignFrame.getInsets().right - getVisibleIdWidth()
-                + getVisibleIdWidth(false);
+                - alignFrame.getInsets().left - alignFrame.getInsets().right
+                - getVisibleIdWidth() + getVisibleIdWidth(false);
       }
       else
       {
@@ -1444,33 +1435,32 @@ public class AlignmentPanel extends GAlignmentPanel implements
     {
       try
       {
-        int s, sSize = av.getAlignment().getHeight(), res, alwidth = av
-                .getAlignment().getWidth(), g, gSize, f, fSize, sy;
+        int sSize = av.getAlignment().getHeight();
+        int alwidth = av.getAlignment().getWidth();
         PrintWriter out = new PrintWriter(new FileWriter(imgMapFile));
-        out.println(jalview.io.HTMLOutput.getImageMapHTML());
+        out.println(HTMLOutput.getImageMapHTML());
         out.println("<img src=\"" + imageName
                 + "\" border=\"0\" usemap=\"#Map\" >"
                 + "<map name=\"Map\">");
 
-        for (s = 0; s < sSize; s++)
+        for (int s = 0; s < sSize; s++)
         {
-          sy = s * av.getCharHeight() + scaleHeight;
+          int sy = s * av.getCharHeight() + scaleHeight;
 
           SequenceI seq = av.getAlignment().getSequenceAt(s);
-          SequenceFeature[] features = seq.getSequenceFeatures();
           SequenceGroup[] groups = av.getAlignment().findAllGroups(seq);
-          for (res = 0; res < alwidth; res++)
+          for (int column = 0; column < alwidth; column++)
           {
-            StringBuilder text = new StringBuilder();
+            StringBuilder text = new StringBuilder(512);
             String triplet = null;
             if (av.getAlignment().isNucleotide())
             {
               triplet = ResidueProperties.nucleotideName.get(seq
-                      .getCharAt(res) + "");
+                      .getCharAt(column) + "");
             }
             else
             {
-              triplet = ResidueProperties.aa2Triplet.get(seq.getCharAt(res)
+              triplet = ResidueProperties.aa2Triplet.get(seq.getCharAt(column)
                       + "");
             }
 
@@ -1479,84 +1469,73 @@ public class AlignmentPanel extends GAlignmentPanel implements
               continue;
             }
 
-            int alIndex = seq.findPosition(res);
-            gSize = groups.length;
-            for (g = 0; g < gSize; g++)
+            int seqPos = seq.findPosition(column);
+            int gSize = groups.length;
+            for (int g = 0; g < gSize; g++)
             {
               if (text.length() < 1)
               {
                 text.append("<area shape=\"rect\" coords=\"")
-                        .append((idWidth + res * av.getCharWidth()))
+                        .append((idWidth + column * av.getCharWidth()))
                         .append(",").append(sy).append(",")
-                        .append((idWidth + (res + 1) * av.getCharWidth()))
+                        .append((idWidth + (column + 1) * av.getCharWidth()))
                         .append(",").append((av.getCharHeight() + sy))
                         .append("\"").append(" onMouseOver=\"toolTip('")
-                        .append(alIndex).append(" ").append(triplet);
+                        .append(seqPos).append(" ").append(triplet);
               }
 
-              if (groups[g].getStartRes() < res
-                      && groups[g].getEndRes() > res)
+              if (groups[g].getStartRes() < column
+                      && groups[g].getEndRes() > column)
               {
                 text.append("<br><em>").append(groups[g].getName())
                         .append("</em>");
               }
             }
 
-            if (features != null)
+            if (text.length() < 1)
             {
-              if (text.length() < 1)
-              {
-                text.append("<area shape=\"rect\" coords=\"")
-                        .append((idWidth + res * av.getCharWidth()))
-                        .append(",").append(sy).append(",")
-                        .append((idWidth + (res + 1) * av.getCharWidth()))
-                        .append(",").append((av.getCharHeight() + sy))
-                        .append("\"").append(" onMouseOver=\"toolTip('")
-                        .append(alIndex).append(" ").append(triplet);
-              }
-              fSize = features.length;
-              for (f = 0; f < fSize; f++)
+              text.append("<area shape=\"rect\" coords=\"")
+                      .append((idWidth + column * av.getCharWidth()))
+                      .append(",").append(sy).append(",")
+                      .append((idWidth + (column + 1) * av.getCharWidth()))
+                      .append(",").append((av.getCharHeight() + sy))
+                      .append("\"").append(" onMouseOver=\"toolTip('")
+                      .append(seqPos).append(" ").append(triplet);
+            }
+            if (!Comparison.isGap(seq.getCharAt(column)))
+            {
+              List<SequenceFeature> features = seq.findFeatures(column, column);
+              for (SequenceFeature sf : features)
               {
-
-                if ((features[f].getBegin() <= seq.findPosition(res))
-                        && (features[f].getEnd() >= seq.findPosition(res)))
+                if (sf.isContactFeature())
                 {
-                  if (features[f].isContactFeature())
-                  {
-                    if (features[f].getBegin() == seq.findPosition(res)
-                            || features[f].getEnd() == seq
-                                    .findPosition(res))
-                    {
-                      text.append("<br>").append(features[f].getType())
-                              .append(" ").append(features[f].getBegin())
-                              .append(":").append(features[f].getEnd());
-                    }
-                  }
-                  else
+                  text.append("<br>").append(sf.getType()).append(" ")
+                          .append(sf.getBegin()).append(":")
+                          .append(sf.getEnd());
+                }
+                else
+                {
+                  text.append("<br>");
+                  text.append(sf.getType());
+                  String description = sf.getDescription();
+                  if (description != null
+                          && !sf.getType().equals(description))
                   {
-                    text.append("<br>");
-                    text.append(features[f].getType());
-                    if (features[f].getDescription() != null
-                            && !features[f].getType().equals(
-                                    features[f].getDescription()))
-                    {
-                      text.append(" ").append(features[f].getDescription());
-                    }
-
-                    if (features[f].getValue("status") != null)
-                    {
-                      text.append(" (").append(features[f].getValue("status"))
-                              .append(")");
-                    }
+                    description = description.replace("\"", "&quot;");
+                    text.append(" ").append(description);
                   }
                 }
-
+                String status = sf.getStatus();
+                if (status != null && !"".equals(status))
+                {
+                  text.append(" (").append(status).append(")");
+                }
+              }
+              if (text.length() > 1)
+              {
+                text.append("')\"; onMouseOut=\"toolTip()\";  href=\"#\">");
+                out.println(text.toString());
               }
-            }
-            if (text.length() > 1)
-            {
-              text.append("')\"; onMouseOut=\"toolTip()\";  href=\"#\">");
-              out.println(text.toString());
             }
           }
         }
@@ -1631,13 +1610,14 @@ public class AlignmentPanel extends GAlignmentPanel implements
     if (annotationPanel != null)
     {
       annotationPanel.dispose();
+      annotationPanel = null;
     }
 
     if (av != null)
     {
       av.removePropertyChangeListener(propertyChangeListener);
-      jalview.structure.StructureSelectionManager ssm = av
-              .getStructureSelectionManager();
+      propertyChangeListener = null;
+      StructureSelectionManager ssm = av.getStructureSelectionManager();
       ssm.removeStructureViewerListener(getSeqPanel(), null);
       ssm.removeSelectionListener(getSeqPanel());
       ssm.removeCommandListener(av);
@@ -1660,9 +1640,15 @@ public class AlignmentPanel extends GAlignmentPanel implements
    */
   protected void closeChildFrames()
   {
+    if (overviewPanel != null)
+    {
+      overviewPanel.dispose();
+      overviewPanel = null;
+    }
     if (calculationDialog != null)
     {
       calculationDialog.closeFrame();
+      calculationDialog = null;
     }
   }
 
@@ -1825,7 +1811,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
    * @param verticalOffset
    *          the number of visible sequences to show above the mapped region
    */
-  public void scrollToCentre(SearchResultsI sr, int verticalOffset)
+  protected void scrollToCentre(SearchResultsI sr, int verticalOffset)
   {
     /*
      * To avoid jumpy vertical scrolling (if some sequences are gapped or not
@@ -1892,7 +1878,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
     if (adjustHeight)
     {
       // sort, repaint, update overview
-      paintAlignment(true);
+      paintAlignment(true, false);
     }
     else
     {
@@ -1903,14 +1889,15 @@ public class AlignmentPanel extends GAlignmentPanel implements
 
   @Override
   /**
-   * Property change event fired when a change is made to the viewport ranges 
+   * Property change event fired when a change is made to the viewport ranges
    * object associated with this alignment panel's viewport
    */
   public void propertyChange(PropertyChangeEvent evt)
   {
     // update this panel's scroll values based on the new viewport ranges values
-    int x = vpRanges.getStartRes();
-    int y = vpRanges.getStartSeq();
+    ViewportRanges ranges = av.getRanges();
+    int x = ranges.getStartRes();
+    int y = ranges.getStartSeq();
     setScrollValues(x, y);
 
     // now update any complementary alignment (its viewport ranges object
index f20d0e6..84883d7 100644 (file)
@@ -56,7 +56,8 @@ import javax.swing.JPanel;
 public class AnnotationChooser extends JPanel
 {
 
-  private static final Font CHECKBOX_FONT = new Font("Serif", Font.BOLD, 12);
+  private static final Font CHECKBOX_FONT = new Font("Serif", Font.BOLD,
+          12);
 
   private static final int MY_FRAME_WIDTH = 600;
 
@@ -81,7 +82,7 @@ public class AnnotationChooser extends JPanel
   private boolean applyToUnselectedSequences;
 
   // currently selected 'annotation type' checkboxes
-  private Map<String, String> selectedTypes = new HashMap<String, String>();
+  private Map<String, String> selectedTypes = new HashMap<>();
 
   /**
    * Constructor.
@@ -201,7 +202,7 @@ public class AnnotationChooser extends JPanel
     // this.ap.alabels.setSize(this.ap.alabels.getSize().width,
     // this.ap.annotationPanel.getSize().height);
     // this.ap.validate();
-    this.ap.paintAlignment(true);
+    this.ap.paintAlignment(true, false);
   }
 
   /**
@@ -232,7 +233,7 @@ public class AnnotationChooser extends JPanel
     // this.ap.alabels.setSize(this.ap.alabels.getSize().width,
     // this.ap.annotationPanel.getSize().height);
     // this.ap.validate();
-    this.ap.paintAlignment(true);
+    this.ap.paintAlignment(true, false);
   }
 
   /**
@@ -250,7 +251,7 @@ public class AnnotationChooser extends JPanel
 
     this.ap.updateAnnotation();
     // this.ap.annotationPanel.adjustPanelHeight();
-    this.ap.paintAlignment(true);
+    this.ap.paintAlignment(true, false);
   }
 
   /**
@@ -355,7 +356,7 @@ public class AnnotationChooser extends JPanel
   public static List<String> getAnnotationTypes(AlignmentI alignment,
           boolean sequenceSpecificOnly)
   {
-    List<String> result = new ArrayList<String>();
+    List<String> result = new ArrayList<>();
     for (AlignmentAnnotation aa : alignment.getAlignmentAnnotation())
     {
       if (!sequenceSpecificOnly || aa.sequenceRef != null)
index 253a7ec..153f70c 100644 (file)
@@ -79,7 +79,7 @@ public class AnnotationColourChooser extends AnnotationRowFilter
     oldcs = av.getGlobalColourScheme();
     if (av.getAlignment().getGroups() != null)
     {
-      oldgroupColours = new Hashtable<SequenceGroup, ColourSchemeI>();
+      oldgroupColours = new Hashtable<>();
       for (SequenceGroup sg : ap.av.getAlignment().getGroups())
       {
         if (sg.getColourScheme() != null)
@@ -110,8 +110,8 @@ public class AnnotationColourChooser extends AnnotationRowFilter
     if (oldcs instanceof AnnotationColourGradient)
     {
       AnnotationColourGradient acg = (AnnotationColourGradient) oldcs;
-      useOriginalColours.setSelected(acg.isPredefinedColours()
-              || acg.getBaseColour() != null);
+      useOriginalColours.setSelected(
+              acg.isPredefinedColours() || acg.getBaseColour() != null);
       if (!acg.isPredefinedColours() && acg.getBaseColour() == null)
       {
         minColour.setBackground(acg.getMinColour());
@@ -120,9 +120,9 @@ public class AnnotationColourChooser extends AnnotationRowFilter
       seqAssociated.setSelected(acg.isSeqAssociated());
 
     }
-    Vector<String> annotItems = getAnnotationItems(seqAssociated
-            .isSelected());
-    annotations = new JComboBox<String>(annotItems);
+    Vector<String> annotItems = getAnnotationItems(
+            seqAssociated.isSelected());
+    annotations = new JComboBox<>(annotItems);
 
     populateThresholdComboBox(threshold);
 
@@ -143,9 +143,8 @@ public class AnnotationColourChooser extends AnnotationRowFilter
         getThreshold().setSelectedIndex(2);
         break;
       default:
-        throw new Error(
-                MessageManager
-                        .getString("error.implementation_error_dont_know_about_threshold_setting"));
+        throw new Error(MessageManager.getString(
+                "error.implementation_error_dont_know_about_threshold_setting"));
       }
       thresholdIsMin.setSelected(acg.isThresholdIsMinMax());
       thresholdValue.setText("" + acg.getAnnotationThreshold());
@@ -212,8 +211,8 @@ public class AnnotationColourChooser extends AnnotationRowFilter
 
     useOriginalColours.setFont(JvSwingUtils.getLabelFont());
     useOriginalColours.setOpaque(false);
-    useOriginalColours.setText(MessageManager
-            .getString("label.use_original_colours"));
+    useOriginalColours.setText(
+            MessageManager.getString("label.use_original_colours"));
     useOriginalColours.addActionListener(new ActionListener()
     {
       @Override
@@ -224,8 +223,8 @@ public class AnnotationColourChooser extends AnnotationRowFilter
     });
     thresholdIsMin.setBackground(Color.white);
     thresholdIsMin.setFont(JvSwingUtils.getLabelFont());
-    thresholdIsMin.setText(MessageManager
-            .getString("label.threshold_minmax"));
+    thresholdIsMin
+            .setText(MessageManager.getString("label.threshold_minmax"));
     thresholdIsMin.addActionListener(new ActionListener()
     {
       @Override
@@ -236,8 +235,8 @@ public class AnnotationColourChooser extends AnnotationRowFilter
     });
     seqAssociated.setBackground(Color.white);
     seqAssociated.setFont(JvSwingUtils.getLabelFont());
-    seqAssociated.setText(MessageManager
-            .getString("label.per_sequence_only"));
+    seqAssociated
+            .setText(MessageManager.getString("label.per_sequence_only"));
     seqAssociated.addActionListener(new ActionListener()
     {
 
@@ -283,10 +282,10 @@ public class AnnotationColourChooser extends AnnotationRowFilter
 
   private void setDefaultMinMax()
   {
-    minColour.setBackground(Cache.getDefaultColour("ANNOTATIONCOLOUR_MIN",
-            Color.orange));
-    maxColour.setBackground(Cache.getDefaultColour("ANNOTATIONCOLOUR_MAX",
-            Color.red));
+    minColour.setBackground(
+            Cache.getDefaultColour("ANNOTATIONCOLOUR_MIN", Color.orange));
+    maxColour.setBackground(
+            Cache.getDefaultColour("ANNOTATIONCOLOUR_MAX", Color.red));
   }
 
   public void minColour_actionPerformed()
@@ -334,15 +333,15 @@ public class AnnotationColourChooser extends AnnotationRowFilter
   {
     if (slider.isEnabled())
     {
-      if (useOriginalColours.isSelected()
-              && !(av.getGlobalColourScheme() instanceof AnnotationColourGradient))
+      if (useOriginalColours.isSelected() && !(av
+              .getGlobalColourScheme() instanceof AnnotationColourGradient))
       {
         updateView();
       }
       getCurrentAnnotation().threshold.value = slider.getValue() / 1000f;
       propagateSeqAssociatedThreshold(updateAllAnnotation,
               getCurrentAnnotation());
-      ap.paintAlignment(false);
+      ap.paintAlignment(false, false);
     }
   }
 
@@ -368,11 +367,12 @@ public class AnnotationColourChooser extends AnnotationRowFilter
       return;
     }
 
-    setCurrentAnnotation(av.getAlignment().getAlignmentAnnotation()[annmap[annotations
-            .getSelectedIndex()]]);
+    setCurrentAnnotation(
+            av.getAlignment().getAlignmentAnnotation()[annmap[annotations
+                    .getSelectedIndex()]]);
 
-    int selectedThresholdItem = getSelectedThresholdItem(getThreshold()
-            .getSelectedIndex());
+    int selectedThresholdItem = getSelectedThresholdItem(
+            getThreshold().getSelectedIndex());
 
     slider.setEnabled(true);
     thresholdValue.setEnabled(true);
@@ -388,11 +388,10 @@ public class AnnotationColourChooser extends AnnotationRowFilter
     else if (selectedThresholdItem != AnnotationColourGradient.NO_THRESHOLD
             && getCurrentAnnotation().threshold == null)
     {
-      getCurrentAnnotation()
-              .setThreshold(
-                      new GraphLine(
-                              (getCurrentAnnotation().graphMax - getCurrentAnnotation().graphMin) / 2f,
-                              "Threshold", Color.black));
+      getCurrentAnnotation().setThreshold(new GraphLine(
+              (getCurrentAnnotation().graphMax
+                      - getCurrentAnnotation().graphMin) / 2f,
+              "Threshold", Color.black));
     }
 
     if (selectedThresholdItem != AnnotationColourGradient.NO_THRESHOLD)
@@ -401,9 +400,12 @@ public class AnnotationColourChooser extends AnnotationRowFilter
       float range = getCurrentAnnotation().graphMax * ONETHOUSAND
               - getCurrentAnnotation().graphMin * ONETHOUSAND;
 
-      slider.setMinimum((int) (getCurrentAnnotation().graphMin * ONETHOUSAND));
-      slider.setMaximum((int) (getCurrentAnnotation().graphMax * ONETHOUSAND));
-      slider.setValue((int) (getCurrentAnnotation().threshold.value * ONETHOUSAND));
+      slider.setMinimum(
+              (int) (getCurrentAnnotation().graphMin * ONETHOUSAND));
+      slider.setMaximum(
+              (int) (getCurrentAnnotation().graphMax * ONETHOUSAND));
+      slider.setValue(
+              (int) (getCurrentAnnotation().threshold.value * ONETHOUSAND));
       thresholdValue.setText(getCurrentAnnotation().threshold.value + "");
       slider.setMajorTickSpacing((int) (range / 10f));
       slider.setEnabled(true);
@@ -413,14 +415,12 @@ public class AnnotationColourChooser extends AnnotationRowFilter
     colorAlignmentContaining(getCurrentAnnotation(), selectedThresholdItem);
 
     ap.alignmentChanged();
-    // ensure all associated views (overviews, structures, etc) are notified of
-    // updated colours.
-    ap.paintAlignment(true);
   }
 
-  protected boolean colorAlignmentContaining(AlignmentAnnotation currentAnn, int selectedThresholdOption)
+  protected void colorAlignmentContaining(AlignmentAnnotation currentAnn,
+          int selectedThresholdOption)
   {
-  
+
     AnnotationColourGradient acg = null;
     if (useOriginalColours.isSelected())
     {
@@ -434,44 +434,29 @@ public class AnnotationColourChooser extends AnnotationRowFilter
               selectedThresholdOption);
     }
     acg.setSeqAssociated(seqAssociated.isSelected());
-  
+
     if (currentAnn.graphMin == 0f && currentAnn.graphMax == 0f)
     {
       acg.setPredefinedColours(true);
     }
-  
+
     acg.setThresholdIsMinMax(thresholdIsMin.isSelected());
-  
+
     av.setGlobalColourScheme(acg);
-  
+
     if (av.getAlignment().getGroups() != null)
     {
-  
+
       for (SequenceGroup sg : ap.av.getAlignment().getGroups())
       {
         if (sg.cs == null)
         {
           continue;
         }
-  
-        if (useOriginalColours.isSelected())
-        {
-          sg.setColourScheme(new AnnotationColourGradient(currentAnn, sg
-                  .getColourScheme(), selectedThresholdOption));
-          ((AnnotationColourGradient) sg.cs).setSeqAssociated(seqAssociated
-                  .isSelected());
-        }
-        else
-        {
-          sg.setColourScheme(new AnnotationColourGradient(currentAnn,
-                  minColour.getBackground(), maxColour.getBackground(),
-                  selectedThresholdOption));
-          ((AnnotationColourGradient) sg.cs).setSeqAssociated(seqAssociated
-                  .isSelected());
-        }
+        sg.setColourScheme(
+                acg.getInstance(sg, ap.av.getHiddenRepSequences()));
       }
     }
-    return false;
   }
 
 }
index 6fc5fad..6924b63 100644 (file)
@@ -36,7 +36,6 @@ import java.awt.event.ActionListener;
 import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
 import java.awt.event.KeyEvent;
-import java.util.ArrayList;
 
 import javax.swing.ButtonGroup;
 import javax.swing.JCheckBox;
@@ -50,8 +49,8 @@ import javax.swing.border.TitledBorder;
 import net.miginfocom.swing.MigLayout;
 
 @SuppressWarnings("serial")
-public class AnnotationColumnChooser extends AnnotationRowFilter implements
-        ItemListener
+public class AnnotationColumnChooser extends AnnotationRowFilter
+        implements ItemListener
 {
   private JPanel switchableViewsPanel = new JPanel(new CardLayout());
 
@@ -119,18 +118,16 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
     // restore Object state from the previous session if one exists
     if (lastChooser != null)
     {
-      currentSearchPanel = lastChooser
-              .getCurrentSearchPanel();
+      currentSearchPanel = lastChooser.getCurrentSearchPanel();
       currentStructureFilterPanel = lastChooser
               .getCurrentStructureFilterPanel();
-      annotations.setSelectedIndex(lastChooser
-              .getAnnotations().getSelectedIndex());
-      threshold.setSelectedIndex(lastChooser
-              .getThreshold().getSelectedIndex());
-      actionOption = lastChooser
-              .getActionOption();
-      percentThreshold.setSelected(lastChooser.percentThreshold
-              .isSelected());
+      annotations.setSelectedIndex(
+              lastChooser.getAnnotations().getSelectedIndex());
+      threshold.setSelectedIndex(
+              lastChooser.getThreshold().getSelectedIndex());
+      actionOption = lastChooser.getActionOption();
+      percentThreshold
+              .setSelected(lastChooser.percentThreshold.isSelected());
     }
 
     try
@@ -152,8 +149,8 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
     super.jbInit();
 
     JPanel thresholdPanel = new JPanel();
-    thresholdPanel.setBorder(new TitledBorder(MessageManager
-            .getString("label.threshold_filter")));
+    thresholdPanel.setBorder(new TitledBorder(
+            MessageManager.getString("label.threshold_filter")));
     thresholdPanel.setBackground(Color.white);
     thresholdPanel.setFont(JvSwingUtils.getLabelFont());
     thresholdPanel.setLayout(new MigLayout("", "[left][right]", "[][]"));
@@ -241,23 +238,12 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
 
       if (av.getAnnotationColumnSelectionState() != null)
       {
-        HiddenColumns oldHidden = av
-                .getAnnotationColumnSelectionState()
+        HiddenColumns oldHidden = av.getAnnotationColumnSelectionState()
                 .getOldHiddenColumns();
-        if (oldHidden != null)
-        {
-          ArrayList<int[]> regions = oldHidden.getHiddenColumnsCopy();
-          for (int[] positions : regions)
-          {
-            av.hideColumns(positions[0], positions[1]);
-          }
-        }
-        // TODO not clear why we need to hide all the columns (above) if we are
-        // going to copy the hidden columns over wholesale anyway
         av.getAlignment().setHiddenColumns(oldHidden);
       }
       av.sendSelection();
-      ap.paintAlignment(true);
+      ap.paintAlignment(true, true);
     }
   }
 
@@ -270,7 +256,7 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
       updateView();
       propagateSeqAssociatedThreshold(updateAllAnnotation,
               getCurrentAnnotation());
-      ap.paintAlignment(false);
+      ap.paintAlignment(false, false);
     }
   }
 
@@ -285,11 +271,12 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
 
     AnnotationFilterParameter filterParams = new AnnotationFilterParameter();
 
-    setCurrentAnnotation(av.getAlignment().getAlignmentAnnotation()[annmap[getAnnotations()
-            .getSelectedIndex()]]);
+    setCurrentAnnotation(av.getAlignment()
+            .getAlignmentAnnotation()[annmap[getAnnotations()
+                    .getSelectedIndex()]]);
 
-    int selectedThresholdItem = getSelectedThresholdItem(getThreshold()
-            .getSelectedIndex());
+    int selectedThresholdItem = getSelectedThresholdItem(
+            getThreshold().getSelectedIndex());
 
     slider.setEnabled(true);
     thresholdValue.setEnabled(true);
@@ -307,11 +294,10 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
     {
       if (getCurrentAnnotation().threshold == null)
       {
-        getCurrentAnnotation()
-                .setThreshold(
-                        new jalview.datamodel.GraphLine(
-                                (getCurrentAnnotation().graphMax - getCurrentAnnotation().graphMin) / 2f,
-                                "Threshold", Color.black));
+        getCurrentAnnotation().setThreshold(new jalview.datamodel.GraphLine(
+                (getCurrentAnnotation().graphMax
+                        - getCurrentAnnotation().graphMin) / 2f,
+                "Threshold", Color.black));
       }
 
       adjusting = true;
@@ -320,8 +306,9 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
 
       slider.setMinimum((int) (getCurrentAnnotation().graphMin * 1000));
       slider.setMaximum((int) (getCurrentAnnotation().graphMax * 1000));
-      slider.setValue((int) (getCurrentAnnotation().threshold.value * 1000));
-      
+      slider.setValue(
+              (int) (getCurrentAnnotation().threshold.value * 1000));
+
       setThresholdValueText();
 
       slider.setMajorTickSpacing((int) (range / 10f));
@@ -330,8 +317,8 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
       adjusting = false;
 
       // build filter params
-      filterParams
-              .setThresholdType(AnnotationFilterParameter.ThresholdType.NO_THRESHOLD);
+      filterParams.setThresholdType(
+              AnnotationFilterParameter.ThresholdType.NO_THRESHOLD);
       if (getCurrentAnnotation().isQuantitative())
       {
         filterParams
@@ -339,13 +326,13 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
 
         if (selectedThresholdItem == AnnotationColourGradient.ABOVE_THRESHOLD)
         {
-          filterParams
-                  .setThresholdType(AnnotationFilterParameter.ThresholdType.ABOVE_THRESHOLD);
+          filterParams.setThresholdType(
+                  AnnotationFilterParameter.ThresholdType.ABOVE_THRESHOLD);
         }
         else if (selectedThresholdItem == AnnotationColourGradient.BELOW_THRESHOLD)
         {
-          filterParams
-                  .setThresholdType(AnnotationFilterParameter.ThresholdType.BELOW_THRESHOLD);
+          filterParams.setThresholdType(
+                  AnnotationFilterParameter.ThresholdType.BELOW_THRESHOLD);
         }
       }
     }
@@ -371,17 +358,17 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
     {
       if (!currentSearchPanel.searchBox.getUserInput().isEmpty())
       {
-        filterParams.setRegexString(currentSearchPanel.searchBox
-                .getUserInput());
+        filterParams.setRegexString(
+                currentSearchPanel.searchBox.getUserInput());
         if (currentSearchPanel.displayName.isSelected())
         {
-          filterParams
-                  .addRegexSearchField(AnnotationFilterParameter.SearchableAnnotationField.DISPLAY_STRING);
+          filterParams.addRegexSearchField(
+                  AnnotationFilterParameter.SearchableAnnotationField.DISPLAY_STRING);
         }
         if (currentSearchPanel.description.isSelected())
         {
-          filterParams
-                  .addRegexSearchField(AnnotationFilterParameter.SearchableAnnotationField.DESCRIPTION);
+          filterParams.addRegexSearchField(
+                  AnnotationFilterParameter.SearchableAnnotationField.DESCRIPTION);
         }
       }
     }
@@ -393,7 +380,8 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
     av.getColumnSelection().filterAnnotations(
             getCurrentAnnotation().annotations, filterParams);
 
-    if (getActionOption() == ACTION_OPTION_HIDE)
+    boolean hideCols = getActionOption() == ACTION_OPTION_HIDE;
+    if (hideCols)
     {
       av.hideSelectedColumns();
     }
@@ -401,7 +389,8 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
 
     filterParams = null;
     av.setAnnotationColumnSelectionState(this);
-    ap.paintAlignment(true);
+    // only update overview and structures if columns were hidden
+    ap.paintAlignment(hideCols, hideCols);
   }
 
   public HiddenColumns getOldHiddenColumns()
@@ -489,8 +478,7 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
   public void selectedAnnotationChanged()
   {
     String currentView = AnnotationColumnChooser.NO_GRAPH_VIEW;
-    if (av.getAlignment()
-            .getAlignmentAnnotation()[annmap[getAnnotations()
+    if (av.getAlignment().getAlignmentAnnotation()[annmap[getAnnotations()
             .getSelectedIndex()]].isQuantitative())
     {
       currentView = AnnotationColumnChooser.GRAPH_VIEW;
@@ -568,7 +556,8 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
 
     public void syncState()
     {
-      if (aColChooser.getActionOption() == AnnotationColumnChooser.ACTION_OPTION_HIDE)
+      if (aColChooser
+              .getActionOption() == AnnotationColumnChooser.ACTION_OPTION_HIDE)
       {
         this.optionsGroup.setSelected(this.hideOption.getModel(), true);
       }
@@ -635,8 +624,8 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
         }
       });
 
-      this.setBorder(new TitledBorder(MessageManager
-              .getString("label.structures_filter")));
+      this.setBorder(new TitledBorder(
+              MessageManager.getString("label.structures_filter")));
       JvSwingUtils.jvInitComponent(this);
 
       this.add(all);
@@ -736,12 +725,12 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
 
       this.aColChooser = aColChooser;
       JvSwingUtils.jvInitComponent(this);
-      this.setBorder(new TitledBorder(MessageManager
-              .getString("label.search_filter")));
+      this.setBorder(new TitledBorder(
+              MessageManager.getString("label.search_filter")));
 
       searchBox.setPrototypeDisplayValue("XXXXXXXXXXXXXXXXXXXXXXX");
-      searchBox.setToolTipText(MessageManager
-              .getString("info.enter_search_text_here"));
+      searchBox.setToolTipText(
+              MessageManager.getString("info.enter_search_text_here"));
       searchBox.getEditor().getEditorComponent()
               .addKeyListener(new java.awt.event.KeyAdapter()
               {
@@ -756,8 +745,6 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
                 }
               });
 
-
-
       JvSwingUtils.jvInitComponent(displayName, "label.label");
       displayName.addActionListener(new ActionListener()
       {
@@ -825,15 +812,15 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements
       String defaultTtip = MessageManager
               .getString("info.enter_search_text_to_enable");
       String labelTtip = MessageManager.formatMessage(
-              "info.search_in_annotation_label", annotations
-                      .getSelectedItem().toString());
+              "info.search_in_annotation_label",
+              annotations.getSelectedItem().toString());
       String descTtip = MessageManager.formatMessage(
-              "info.search_in_annotation_description", annotations
-                      .getSelectedItem().toString());
-      displayName.setToolTipText(displayName.isEnabled() ? labelTtip
-              : defaultTtip);
-      description.setToolTipText(description.isEnabled() ? descTtip
-              : defaultTtip);
+              "info.search_in_annotation_description",
+              annotations.getSelectedItem().toString());
+      displayName.setToolTipText(
+              displayName.isEnabled() ? labelTtip : defaultTtip);
+      description.setToolTipText(
+              description.isEnabled() ? descTtip : defaultTtip);
     }
   }
 
index 0d47e36..a619997 100644 (file)
@@ -34,6 +34,7 @@ import java.awt.Color;
 import java.awt.FlowLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.util.List;
 import java.util.Map;
 
 import javax.swing.BorderFactory;
@@ -94,8 +95,8 @@ public class AnnotationExporter extends JPanel
   public void exportAnnotations(AlignmentPanel ap)
   {
     this.ap = ap;
-    annotations = ap.av.isShowAnnotation() ? null : ap.av.getAlignment()
-            .getAlignmentAnnotation();
+    annotations = ap.av.isShowAnnotation() ? null
+            : ap.av.getAlignment().getAlignmentAnnotation();
     wholeView = true;
     startExportAnnotation();
   }
@@ -123,9 +124,9 @@ public class AnnotationExporter extends JPanel
             jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
 
     chooser.setFileView(new JalviewFileView());
-    chooser.setDialogTitle(features ? MessageManager
-            .getString("label.save_features_to_file") : MessageManager
-            .getString("label.save_annotation_to_file"));
+    chooser.setDialogTitle(features
+            ? MessageManager.getString("label.save_features_to_file")
+            : MessageManager.getString("label.save_annotation_to_file"));
     chooser.setToolTipText(MessageManager.getString("action.save"));
 
     int value = chooser.showSaveDialog(this);
@@ -156,28 +157,22 @@ public class AnnotationExporter extends JPanel
             .getString("label.no_features_on_alignment");
     if (features)
     {
-      Map<String, FeatureColourI> displayedFeatureColours = ap
-              .getFeatureRenderer().getDisplayedFeatureCols();
       FeaturesFile formatter = new FeaturesFile();
       SequenceI[] sequences = ap.av.getAlignment().getSequencesArray();
       Map<String, FeatureColourI> featureColours = ap.getFeatureRenderer()
               .getDisplayedFeatureCols();
+      List<String> featureGroups = ap.getFeatureRenderer()
+              .getDisplayedFeatureGroups();
       boolean includeNonPositional = ap.av.isShowNPFeats();
       if (GFFFormat.isSelected())
       {
-        text = new FeaturesFile().printGffFormat(ap.av.getAlignment()
-                .getDataset().getSequencesArray(), displayedFeatureColours,
-                true, ap.av.isShowNPFeats());
-        text = formatter.printGffFormat(sequences, featureColours, true,
-                includeNonPositional);
+        text = formatter.printGffFormat(sequences, featureColours,
+                featureGroups, includeNonPositional);
       }
       else
       {
-        text = new FeaturesFile().printJalviewFormat(ap.av.getAlignment()
-                .getDataset().getSequencesArray(), displayedFeatureColours,
-                true, ap.av.isShowNPFeats()); // ap.av.featuresDisplayed);
         text = formatter.printJalviewFormat(sequences, featureColours,
-                true, includeNonPositional);
+                featureGroups, includeNonPositional);
       }
     }
     else
@@ -210,23 +205,23 @@ public class AnnotationExporter extends JPanel
     {
       String text = getFileContents();
       cap.setText(text);
-      Desktop.addInternalFrame(
-              cap,
-              (features ? MessageManager.formatMessage(
-                      "label.features_for_params",
-                      new String[] { ap.alignFrame.getTitle() })
-                      : MessageManager.formatMessage(
-                              "label.annotations_for_params",
-                              new String[] { ap.alignFrame.getTitle() })),
+      Desktop.addInternalFrame(cap, (features ? MessageManager
+              .formatMessage("label.features_for_params", new String[]
+              { ap.alignFrame.getTitle() })
+              : MessageManager.formatMessage("label.annotations_for_params",
+                      new String[]
+                      { ap.alignFrame.getTitle() })),
               600, 500);
     } catch (OutOfMemoryError oom)
     {
       new OOMWarning((features ? MessageManager.formatMessage(
-              "label.generating_features_for_params",
-              new String[] { ap.alignFrame.getTitle() })
+              "label.generating_features_for_params", new String[]
+              { ap.alignFrame.getTitle() })
               : MessageManager.formatMessage(
                       "label.generating_annotations_for_params",
-                      new String[] { ap.alignFrame.getTitle() })), oom);
+                      new String[]
+                      { ap.alignFrame.getTitle() })),
+              oom);
       cap.dispose();
     }
 
index e16867a..b94a615 100755 (executable)
@@ -67,8 +67,8 @@ import javax.swing.ToolTipManager;
  * @author $author$
  * @version $Revision$
  */
-public class AnnotationLabels extends JPanel implements MouseListener,
-        MouseMotionListener, ActionListener
+public class AnnotationLabels extends JPanel
+        implements MouseListener, MouseMotionListener, ActionListener
 {
   private static final Pattern LEFT_ANGLE_BRACKET_PATTERN = Pattern
           .compile("<");
@@ -267,7 +267,8 @@ public class AnnotationLabels extends JPanel implements MouseListener,
     else if (evt.getActionCommand().equals(OUTPUT_TEXT))
     {
       new AnnotationExporter().exportAnnotations(ap,
-              new AlignmentAnnotation[] { aa[selectedRow] });
+              new AlignmentAnnotation[]
+              { aa[selectedRow] });
     }
     else if (evt.getActionCommand().equals(COPYCONS_SEQ))
     {
@@ -439,9 +440,9 @@ public class AnnotationLabels extends JPanel implements MouseListener,
         // av and sequencegroup need to implement same interface for
         final JCheckBoxMenuItem cbmi = new JCheckBoxMenuItem(
                 MessageManager.getString("label.ignore_gaps_consensus"),
-                (aa[selectedRow].groupRef != null) ? aa[selectedRow].groupRef
-                        .getIgnoreGapsConsensus() : ap.av
-                        .isIgnoreGapsConsensus());
+                (aa[selectedRow].groupRef != null)
+                        ? aa[selectedRow].groupRef.getIgnoreGapsConsensus()
+                        : ap.av.isIgnoreGapsConsensus());
         final AlignmentAnnotation aaa = aa[selectedRow];
         cbmi.addActionListener(new ActionListener()
         {
@@ -452,8 +453,8 @@ public class AnnotationLabels extends JPanel implements MouseListener,
             {
               // TODO: pass on reference to ap so the view can be updated.
               aaa.groupRef.setIgnoreGapsConsensus(cbmi.getState());
-              ap.getAnnotationPanel().paint(
-                      ap.getAnnotationPanel().getGraphics());
+              ap.getAnnotationPanel()
+                      .paint(ap.getAnnotationPanel().getGraphics());
             }
             else
             {
@@ -699,12 +700,12 @@ public class AnnotationLabels extends JPanel implements MouseListener,
 
       if ((d.height - dif) > 20)
       {
-        ap.annotationScroller.setPreferredSize(new Dimension(d.width,
-                d.height - dif));
+        ap.annotationScroller
+                .setPreferredSize(new Dimension(d.width, d.height - dif));
         d = ap.annotationSpaceFillerHolder.getPreferredSize();
-        ap.annotationSpaceFillerHolder.setPreferredSize(new Dimension(
-                d.width, d.height - dif));
-        ap.paintAlignment(true);
+        ap.annotationSpaceFillerHolder
+                .setPreferredSize(new Dimension(d.width, d.height - dif));
+        ap.paintAlignment(true, false);
       }
 
       ap.addNotify();
@@ -728,8 +729,8 @@ public class AnnotationLabels extends JPanel implements MouseListener,
 
     getSelectedRow(evt.getY() - getScrollOffset());
 
-    if (selectedRow > -1
-            && ap.av.getAlignment().getAlignmentAnnotation().length > selectedRow)
+    if (selectedRow > -1 && ap.av.getAlignment()
+            .getAlignmentAnnotation().length > selectedRow)
     {
       AlignmentAnnotation aa = ap.av.getAlignment()
               .getAlignmentAnnotation()[selectedRow];
@@ -743,8 +744,8 @@ public class AnnotationLabels extends JPanel implements MouseListener,
         // tooltips
         desc.append(aa.getDescription(true).trim());
         // check to see if the description is an html fragment.
-        if (desc.length() < 6
-                || (desc.substring(0, 6).toLowerCase().indexOf("<html>") < 0))
+        if (desc.length() < 6 || (desc.substring(0, 6).toLowerCase()
+                .indexOf("<html>") < 0))
         {
           // clean the description ready for embedding in html
           desc = new StringBuffer(LEFT_ANGLE_BRACKET_PATTERN.matcher(desc)
@@ -818,17 +819,16 @@ public class AnnotationLabels extends JPanel implements MouseListener,
             ap.getSeqPanel().ap.getIdPanel().highlightSearchResults(null);
             // process modifiers
             SequenceGroup sg = ap.av.getSelectionGroup();
-            if (sg == null
-                    || sg == aa[selectedRow].groupRef
-                    || !(jalview.util.Platform.isControlDown(evt) || evt
-                            .isShiftDown()))
+            if (sg == null || sg == aa[selectedRow].groupRef
+                    || !(jalview.util.Platform.isControlDown(evt)
+                            || evt.isShiftDown()))
             {
               if (jalview.util.Platform.isControlDown(evt)
                       || evt.isShiftDown())
               {
                 // clone a new selection group from the associated group
-                ap.av.setSelectionGroup(new SequenceGroup(
-                        aa[selectedRow].groupRef));
+                ap.av.setSelectionGroup(
+                        new SequenceGroup(aa[selectedRow].groupRef));
               }
               else
               {
@@ -855,7 +855,7 @@ public class AnnotationLabels extends JPanel implements MouseListener,
               }
             }
 
-            ap.paintAlignment(false);
+            ap.paintAlignment(false, false);
             PaintRefresher.Refresh(ap, ap.av.getSequenceSetId());
             ap.av.sendSelection();
           }
@@ -870,10 +870,9 @@ public class AnnotationLabels extends JPanel implements MouseListener,
         {
           if (evt.getClickCount() == 1)
           {
-            ap.getSeqPanel().ap
-                    .getIdPanel()
-                    .highlightSearchResults(
-                            Arrays.asList(new SequenceI[] { aa[selectedRow].sequenceRef }));
+            ap.getSeqPanel().ap.getIdPanel()
+                    .highlightSearchResults(Arrays.asList(new SequenceI[]
+                    { aa[selectedRow].sequenceRef }));
           }
           else if (evt.getClickCount() >= 2)
           {
@@ -884,8 +883,8 @@ public class AnnotationLabels extends JPanel implements MouseListener,
               // we make a copy rather than edit the current selection if no
               // modifiers pressed
               // see Enhancement JAL-1557
-              if (!(jalview.util.Platform.isControlDown(evt) || evt
-                      .isShiftDown()))
+              if (!(jalview.util.Platform.isControlDown(evt)
+                      || evt.isShiftDown()))
               {
                 sg = new SequenceGroup(sg);
                 sg.clear();
@@ -913,7 +912,7 @@ public class AnnotationLabels extends JPanel implements MouseListener,
               sg.addSequence(aa[selectedRow].sequenceRef, false);
             }
             ap.av.setSelectionGroup(sg);
-            ap.paintAlignment(false);
+            ap.paintAlignment(false, false);
             PaintRefresher.Refresh(ap, ap.av.getSequenceSetId());
             ap.av.sendSelection();
           }
@@ -947,15 +946,14 @@ public class AnnotationLabels extends JPanel implements MouseListener,
     if (av.hasHiddenColumns())
     {
       omitHidden = av.getAlignment().getHiddenColumns()
-              .getVisibleSequenceStrings(0,
-              sq.getLength(), seqs);
+              .getVisibleSequenceStrings(0, sq.getLength(), seqs);
     }
 
     int[] alignmentStartEnd = new int[] { 0, ds.getWidth() - 1 };
     if (av.hasHiddenColumns())
     {
       alignmentStartEnd = av.getAlignment().getHiddenColumns()
-            .getVisibleStartAndEndIndex(av.getAlignment().getWidth());
+              .getVisibleStartAndEndIndex(av.getAlignment().getWidth());
     }
 
     String output = new FormatAdapter().formatSequences(FileFormat.Fasta,
@@ -1065,8 +1063,9 @@ public class AnnotationLabels extends JPanel implements MouseListener,
     int ofontH = fontHeight;
     int sOffset = 0;
     int visHeight = 0;
-    int[] visr = (ap != null && ap.getAnnotationPanel() != null) ? ap
-            .getAnnotationPanel().getVisibleVRange() : null;
+    int[] visr = (ap != null && ap.getAnnotationPanel() != null)
+            ? ap.getAnnotationPanel().getVisibleVRange()
+            : null;
     if (clip && visr != null)
     {
       sOffset = visr[0];
@@ -1109,8 +1108,8 @@ public class AnnotationLabels extends JPanel implements MouseListener,
             {
               if (debugRedraw)
               {
-                System.out.println("Scroll offset: " + sOffset
-                        + " after vis: " + i);
+                System.out.println(
+                        "Scroll offset: " + sOffset + " after vis: " + i);
               }
               after = true;
             }
@@ -1148,7 +1147,8 @@ public class AnnotationLabels extends JPanel implements MouseListener,
           }
           if (groupSize * (fontHeight + 8) < aa[i].height)
           {
-            graphExtras = (aa[i].height - (groupSize * (fontHeight + 8))) / 2;
+            graphExtras = (aa[i].height - (groupSize * (fontHeight + 8)))
+                    / 2;
           }
           else
           {
@@ -1162,11 +1162,12 @@ public class AnnotationLabels extends JPanel implements MouseListener,
             {
               fontHeight = -8 + (int) h;
               s = ((float) fontHeight) / (float) ofontH;
-              Font f = baseFont.deriveFont(AffineTransform
-                      .getScaleInstance(s, s));
+              Font f = baseFont
+                      .deriveFont(AffineTransform.getScaleInstance(s, s));
               g.setFont(f);
               fm = g.getFontMetrics();
-              graphExtras = (aa[i].height - (groupSize * (fontHeight + 8))) / 2;
+              graphExtras = (aa[i].height - (groupSize * (fontHeight + 8)))
+                      / 2;
             }
           }
           if (visible)
@@ -1183,8 +1184,8 @@ public class AnnotationLabels extends JPanel implements MouseListener,
 
                   g.setColor(aa[gg]._linecolour);
                   g.drawLine(x, y - graphExtras + 3,
-                          x + fm.stringWidth(aa[gg].label), y - graphExtras
-                                  + 3);
+                          x + fm.stringWidth(aa[gg].label),
+                          y - graphExtras + 3);
                 }
 
                 g.setColor(Color.black);
index 61099c3..438e81b 100755 (executable)
@@ -285,7 +285,8 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
 
     if (anot.length < av.getColumnSelection().getMax())
     {
-      Annotation[] temp = new Annotation[av.getColumnSelection().getMax() + 2];
+      Annotation[] temp = new Annotation[av.getColumnSelection().getMax()
+              + 2];
       System.arraycopy(anot, 0, temp, 0, anot.length);
       anot = temp;
       aa[activeRow].annotations = anot;
@@ -413,8 +414,8 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
           anot[index] = new Annotation(label, "", type, 0);
         }
 
-        anot[index].secondaryStructure = type != 'S' ? type : label
-                .length() == 0 ? ' ' : label.charAt(0);
+        anot[index].secondaryStructure = type != 'S' ? type
+                : label.length() == 0 ? ' ' : label.charAt(0);
         anot[index].displayCharacter = label;
 
       }
@@ -658,15 +659,18 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
   {
     if (graphStretch > -1)
     {
-      av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight += graphStretchY
-              - evt.getY();
-      if (av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight < 0)
+      av.getAlignment()
+              .getAlignmentAnnotation()[graphStretch].graphHeight += graphStretchY
+                      - evt.getY();
+      if (av.getAlignment()
+              .getAlignmentAnnotation()[graphStretch].graphHeight < 0)
       {
-        av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight = 0;
+        av.getAlignment()
+                .getAlignmentAnnotation()[graphStretch].graphHeight = 0;
       }
       graphStretchY = evt.getY();
       adjustPanelHeight();
-      ap.paintAlignment(true);
+      ap.paintAlignment(false, false);
     }
     else
     {
@@ -820,8 +824,7 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
       int seqIndex = av.getAlignment().findIndex(seqref);
       if (seqIndex != -1)
       {
-        text.append(", ")
-                .append(MessageManager.getString("label.sequence"))
+        text.append(", ").append(MessageManager.getString("label.sequence"))
                 .append(" ").append(seqIndex + 1);
         char residue = seqref.getCharAt(column);
         if (!Comparison.isGap(residue))
@@ -830,16 +833,17 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
           String name;
           if (av.getAlignment().isNucleotide())
           {
-            name = ResidueProperties.nucleotideName.get(String
-                    .valueOf(residue));
-            text.append(" Nucleotide: ").append(
-                    name != null ? name : residue);
+            name = ResidueProperties.nucleotideName
+                    .get(String.valueOf(residue));
+            text.append(" Nucleotide: ")
+                    .append(name != null ? name : residue);
           }
           else
           {
-            name = 'X' == residue ? "X" : ('*' == residue ? "STOP"
-                    : ResidueProperties.aa2Triplet.get(String
-                            .valueOf(residue)));
+            name = 'X' == residue ? "X"
+                    : ('*' == residue ? "STOP"
+                            : ResidueProperties.aa2Triplet
+                                    .get(String.valueOf(residue)));
             text.append(" Residue: ").append(name != null ? name : residue);
           }
           int residuePos = seqref.findPosition(column);
@@ -913,8 +917,8 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
         return;
       }
     }
-    imgWidth = (av.getRanges().getEndRes() - av.getRanges().getStartRes() + 1)
-            * av.getCharWidth();
+    imgWidth = (av.getRanges().getEndRes() - av.getRanges().getStartRes()
+            + 1) * av.getCharWidth();
     if (imgWidth < 1)
     {
       return;
@@ -924,8 +928,9 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
     {
       try
       {
-        image = new BufferedImage(imgWidth, ap.getAnnotationPanel()
-                .getHeight(), BufferedImage.TYPE_INT_RGB);
+        image = new BufferedImage(imgWidth,
+                ap.getAnnotationPanel().getHeight(),
+                BufferedImage.TYPE_INT_RGB);
       } catch (OutOfMemoryError oom)
       {
         try
@@ -955,8 +960,8 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
       imageFresh = true;
     }
 
-    drawComponent(gg, av.getRanges().getStartRes(), av.getRanges()
-            .getEndRes() + 1);
+    drawComponent(gg, av.getRanges().getStartRes(),
+            av.getRanges().getEndRes() + 1);
     imageFresh = false;
     g.drawImage(image, 0, 0, this);
   }
@@ -1046,8 +1051,8 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
       // and draw a faded image until the calculation
       // has completed
       if (lastImageGood
-              && (fadedImage == null || fadedImage.getWidth() != imgWidth || fadedImage
-                      .getHeight() != image.getHeight()))
+              && (fadedImage == null || fadedImage.getWidth() != imgWidth
+                      || fadedImage.getHeight() != image.getHeight()))
       {
         // System.err.println("redraw faded image ("+(fadedImage==null ?
         // "null image" : "") + " lastGood="+lastImageGood+")");
@@ -1059,8 +1064,8 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
         fadedG.setColor(Color.white);
         fadedG.fillRect(0, 0, imgWidth, image.getHeight());
 
-        fadedG.setComposite(AlphaComposite.getInstance(
-                AlphaComposite.SRC_OVER, .3f));
+        fadedG.setComposite(
+                AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .3f));
         fadedG.drawImage(image, 0, 0, this);
 
       }
@@ -1101,8 +1106,8 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
 
       return;
     }
-    lastImageGood = renderer.drawComponent(this, av, g, activeRow,
-            startRes, endRes);
+    lastImageGood = renderer.drawComponent(this, av, g, activeRow, startRes,
+            endRes);
     if (!lastImageGood && fadedImage == null)
     {
       fadedImage = oldFaded;
@@ -1180,5 +1185,14 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
     {
       fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
     }
+    else if (evt.getPropertyName().equals(ViewportRanges.STARTRESANDSEQ))
+    {
+      fastPaint(((int[]) evt.getNewValue())[0]
+              - ((int[]) evt.getOldValue())[0]);
+    }
+    else if (evt.getPropertyName().equals(ViewportRanges.MOVE_VIEWPORT))
+    {
+      repaint();
+    }
   }
 }
index a3ce528..71ad6a5 100644 (file)
@@ -80,7 +80,7 @@ public abstract class AnnotationRowFilter extends JPanel
    */
   protected boolean sliderDragging = false;
 
-  protected JComboBox<String> threshold = new JComboBox<String>();
+  protected JComboBox<String> threshold = new JComboBox<>();
 
   protected JComboBox<String> annotations;
 
@@ -98,7 +98,8 @@ public abstract class AnnotationRowFilter extends JPanel
    * @param viewport
    * @param alignPanel
    */
-  public AnnotationRowFilter(AlignViewport viewport, final AlignmentPanel alignPanel)
+  public AnnotationRowFilter(AlignViewport viewport,
+          final AlignmentPanel alignPanel)
   {
     this.av = viewport;
     this.ap = alignPanel;
@@ -148,6 +149,7 @@ public abstract class AnnotationRowFilter extends JPanel
     }
     adjusting = oldadj;
   }
+
   protected void addSliderMouseListeners()
   {
 
@@ -175,28 +177,29 @@ public abstract class AnnotationRowFilter extends JPanel
           sliderDragging = false;
           valueChanged(true);
         }
-        ap.paintAlignment(true);
       }
     });
   }
 
-/**
- * Builds and returns a list of menu items (display text) for choice of
- * annotation. Also builds maps between annotations, their positions in the
- * list, and their display labels in the list.
- * 
- * @param isSeqAssociated
- * @return
- */
+  /**
+   * Builds and returns a list of menu items (display text) for choice of
+   * annotation. Also builds maps between annotations, their positions in the
+   * list, and their display labels in the list.
+   * 
+   * @param isSeqAssociated
+   * @return
+   */
   public Vector<String> getAnnotationItems(boolean isSeqAssociated)
   {
-    annotationLabels = new HashMap<AlignmentAnnotation, String>();
+    annotationLabels = new HashMap<>();
 
-    Vector<String> list = new Vector<String>();
+    Vector<String> list = new Vector<>();
     int index = 1;
-    int[] anmap = new int[av.getAlignment().getAlignmentAnnotation().length];
+    int[] anmap = new int[av.getAlignment()
+            .getAlignmentAnnotation().length];
     seqAssociated.setEnabled(false);
-    for (int i = 0; i < av.getAlignment().getAlignmentAnnotation().length; i++)
+    for (int i = 0; i < av.getAlignment()
+            .getAlignmentAnnotation().length; i++)
     {
       AlignmentAnnotation annotation = av.getAlignment()
               .getAlignmentAnnotation()[i];
@@ -267,7 +270,7 @@ public abstract class AnnotationRowFilter extends JPanel
   public void cancel_actionPerformed()
   {
     reset();
-    ap.paintAlignment(true);
+    ap.paintAlignment(true, true);
     try
     {
       frame.setClosed(true);
@@ -298,9 +301,8 @@ public abstract class AnnotationRowFilter extends JPanel
       float f = Float.parseFloat(thresholdValue.getText());
       if (percentThreshold.isSelected())
       {
-        slider.setValue(slider.getMinimum()
-                + ((int) ((f / 100f) * (slider.getMaximum() - slider
-                        .getMinimum()))));
+        slider.setValue(slider.getMinimum() + ((int) ((f / 100f)
+                * (slider.getMaximum() - slider.getMinimum()))));
       }
       else
       {
@@ -379,9 +381,11 @@ public abstract class AnnotationRowFilter extends JPanel
     }
 
     float thr = annotation.threshold.value;
-    for (int i = 0; i < av.getAlignment().getAlignmentAnnotation().length; i++)
+    for (int i = 0; i < av.getAlignment()
+            .getAlignmentAnnotation().length; i++)
     {
-      AlignmentAnnotation aa = av.getAlignment().getAlignmentAnnotation()[i];
+      AlignmentAnnotation aa = av.getAlignment()
+              .getAlignmentAnnotation()[i];
       if (aa.label.equals(annotation.label)
               && (annotation.getCalcId() == null ? aa.getCalcId() == null
                       : annotation.getCalcId().equals(aa.getCalcId())))
@@ -408,6 +412,11 @@ public abstract class AnnotationRowFilter extends JPanel
     this.currentAnnotation = annotation;
   }
 
+  /**
+   * update associated view model and trigger any necessary repaints.
+   * 
+   * @param updateAllAnnotation
+   */
   protected abstract void valueChanged(boolean updateAllAnnotation);
 
   protected abstract void updateView();
@@ -451,8 +460,8 @@ public abstract class AnnotationRowFilter extends JPanel
         selectedAnnotationChanged();
       }
     });
-    annotations.setToolTipText(MessageManager
-            .getString("info.select_annotation_row"));
+    annotations.setToolTipText(
+            MessageManager.getString("info.select_annotation_row"));
 
     threshold.addActionListener(new ActionListener()
     {
@@ -474,7 +483,8 @@ public abstract class AnnotationRowFilter extends JPanel
       }
     });
 
-    percentThreshold.setText(MessageManager.getString("label.as_percentage"));
+    percentThreshold
+            .setText(MessageManager.getString("label.as_percentage"));
     percentThreshold.addActionListener(new ActionListener()
     {
       @Override
index 68a847e..fef7451 100644 (file)
@@ -89,8 +89,8 @@ public class AppJmol extends StructureViewerBase
    */
   public AppJmol(String[] files, String[] ids, SequenceI[][] seqs,
           AlignmentPanel ap, boolean usetoColour, boolean useToAlign,
-          boolean leaveColouringToJmol, String loadStatus,
-          Rectangle bounds, String viewid)
+          boolean leaveColouringToJmol, String loadStatus, Rectangle bounds,
+          String viewid)
   {
     PDBEntry[] pdbentrys = new PDBEntry[files.length];
     for (int i = 0; i < pdbentrys.length; i++)
@@ -133,7 +133,8 @@ public class AppJmol extends StructureViewerBase
     this.addInternalFrameListener(new InternalFrameAdapter()
     {
       @Override
-      public void internalFrameClosing(InternalFrameEvent internalFrameEvent)
+      public void internalFrameClosing(
+              InternalFrameEvent internalFrameEvent)
       {
         closeViewer(false);
       }
@@ -156,6 +157,11 @@ public class AppJmol extends StructureViewerBase
 
   IProgressIndicator progressBar = null;
 
+  @Override
+  protected IProgressIndicator getIProgressIndicator()
+  {
+    return progressBar;
+  }
   /**
    * add a single PDB structure to a new or existing Jmol view
    * 
@@ -218,7 +224,8 @@ public class AppJmol extends StructureViewerBase
     this.addInternalFrameListener(new InternalFrameAdapter()
     {
       @Override
-      public void internalFrameClosing(InternalFrameEvent internalFrameEvent)
+      public void internalFrameClosing(
+              InternalFrameEvent internalFrameEvent)
       {
         closeViewer(false);
       }
@@ -246,7 +253,7 @@ public class AppJmol extends StructureViewerBase
   @Override
   protected List<StructureViewerBase> getViewersFor(AlignmentPanel apanel)
   {
-    List<StructureViewerBase> result = new ArrayList<StructureViewerBase>();
+    List<StructureViewerBase> result = new ArrayList<>();
     JInternalFrame[] frames = Desktop.instance.getAllFrames();
 
     for (JInternalFrame frame : frames)
@@ -281,8 +288,8 @@ public class AppJmol extends StructureViewerBase
       scriptWindow.setVisible(false);
     }
 
-    jmb.allocateViewer(renderPanel, true, "", null, null, "",
-            scriptWindow, null);
+    jmb.allocateViewer(renderPanel, true, "", null, null, "", scriptWindow,
+            null);
     // jmb.newJmolPopup("Jmol");
     if (command == null)
     {
@@ -293,14 +300,12 @@ public class AppJmol extends StructureViewerBase
     jmb.setFinishedInit(true);
   }
 
-
-
   boolean allChainsSelected = false;
 
   @Override
   void showSelectedChains()
   {
-    Vector<String> toshow = new Vector<String>();
+    Vector<String> toshow = new Vector<>();
     for (int i = 0; i < chainMenu.getItemCount(); i++)
     {
       if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
@@ -410,8 +415,8 @@ public class AppJmol extends StructureViewerBase
     int waitFor = 35;
     int waitTotal = 0;
     while (addingStructures ? lastnotify >= jmb.getLoadNotifiesHandled()
-            : !(jmb.isFinishedInit() && jmb.getStructureFiles() != null && jmb
-                    .getStructureFiles().length == files.size()))
+            : !(jmb.isFinishedInit() && jmb.getStructureFiles() != null
+                    && jmb.getStructureFiles().length == files.size()))
     {
       try
       {
@@ -423,12 +428,11 @@ public class AppJmol extends StructureViewerBase
       }
       if (waitTotal > waitMax)
       {
-        System.err
-                .println("Timed out waiting for Jmol to load files after "
-                        + waitTotal + "ms");
-//        System.err.println("finished: " + jmb.isFinishedInit()
-//                + "; loaded: " + Arrays.toString(jmb.getPdbFile())
-//                + "; files: " + files.toString());
+        System.err.println("Timed out waiting for Jmol to load files after "
+                + waitTotal + "ms");
+        // System.err.println("finished: " + jmb.isFinishedInit()
+        // + "; loaded: " + Arrays.toString(jmb.getPdbFile())
+        // + "; files: " + files.toString());
         jmb.getStructureFiles();
         break;
       }
@@ -490,7 +494,7 @@ public class AppJmol extends StructureViewerBase
     // todo - record which pdbids were successfully imported.
     StringBuilder errormsgs = new StringBuilder();
 
-    List<String> files = new ArrayList<String>();
+    List<String> files = new ArrayList<>();
     String pdbid = "";
     try
     {
@@ -509,8 +513,9 @@ public class AppJmol extends StructureViewerBase
           long hdl = pdbid.hashCode() - System.currentTimeMillis();
           if (progressBar != null)
           {
-            progressBar.setProgressBar(MessageManager.formatMessage(
-                    "status.fetching_pdb", new String[] { pdbid }), hdl);
+            progressBar.setProgressBar(MessageManager
+                    .formatMessage("status.fetching_pdb", new String[]
+                    { pdbid }), hdl);
           }
           try
           {
@@ -576,9 +581,10 @@ public class AppJmol extends StructureViewerBase
     }
     if (errormsgs.length() > 0)
     {
-      JvOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager
-              .formatMessage("label.pdb_entries_couldnt_be_retrieved",
-                      new String[] { errormsgs.toString() }),
+      JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+              MessageManager.formatMessage(
+                      "label.pdb_entries_couldnt_be_retrieved", new String[]
+                      { errormsgs.toString() }),
               MessageManager.getString("label.couldnt_load_file"),
               JvOptionPane.ERROR_MESSAGE);
     }
@@ -706,8 +712,8 @@ public class AppJmol extends StructureViewerBase
           if (e == jmb.getPdbCount() - 1 || sb.length() > 20)
           {
             lines++;
-            g.drawString(sb.toString(), 20, currentSize.height / 2 - lines
-                    * g.getFontMetrics().getHeight());
+            g.drawString(sb.toString(), 20, currentSize.height / 2
+                    - lines * g.getFontMetrics().getHeight());
           }
         }
       }
index f822358..724cec1 100644 (file)
@@ -41,13 +41,20 @@ public class AppJmolBinding extends JalviewJmolBinding
   private AppJmol appJmolWindow;
 
   public AppJmolBinding(AppJmol appJmol, StructureSelectionManager sSm,
-          PDBEntry[] pdbentry, SequenceI[][] sequenceIs, DataSourceType protocol)
+          PDBEntry[] pdbentry, SequenceI[][] sequenceIs,
+          DataSourceType protocol)
   {
     super(sSm, pdbentry, sequenceIs, protocol);
     appJmolWindow = appJmol;
   }
 
   @Override
+  protected IProgressIndicator getIProgressIndicator()
+  {
+    return appJmolWindow.progressBar;
+  }
+
+  @Override
   public SequenceRenderer getSequenceRenderer(AlignmentViewPanel alignment)
   {
     return new SequenceRenderer(((AlignmentPanel) alignment).av);
@@ -198,8 +205,9 @@ public class AppJmolBinding extends JalviewJmolBinding
   public jalview.api.FeatureRenderer getFeatureRenderer(
           AlignmentViewPanel alignment)
   {
-    AlignmentPanel ap = (alignment == null) ? appJmolWindow
-            .getAlignmentPanel() : (AlignmentPanel) alignment;
+    AlignmentPanel ap = (alignment == null)
+            ? appJmolWindow.getAlignmentPanel()
+            : (AlignmentPanel) alignment;
     if (ap.av.isShowSequenceFeatures())
     {
       return ap.av.getAlignPanel().getSeqPanel().seqCanvas.fr;
index a50de77..ea16f23 100644 (file)
@@ -61,9 +61,9 @@ import fr.orsay.lri.varna.models.annotations.HighlightRegionAnnotation;
 import fr.orsay.lri.varna.models.rna.ModeleBase;
 import fr.orsay.lri.varna.models.rna.RNA;
 
-public class AppVarna extends JInternalFrame implements SelectionListener,
-        SecondaryStructureListener, InterfaceVARNASelectionListener,
-        VamsasSource
+public class AppVarna extends JInternalFrame
+        implements SelectionListener, SecondaryStructureListener,
+        InterfaceVARNASelectionListener, VamsasSource
 {
   private static final byte[] PAIRS = new byte[] { '(', ')', '[', ']', '{',
       '}', '<', '>' };
@@ -177,12 +177,15 @@ public class AppVarna extends JInternalFrame implements SelectionListener,
   {
     this(ap);
 
-    String sname = aa.sequenceRef == null ? "secondary structure (alignment)"
+    String sname = aa.sequenceRef == null
+            ? "secondary structure (alignment)"
             : seq.getName() + " structure";
     String theTitle = sname
-            + (aa.sequenceRef == null ? " trimmed to " + seq.getName() : "");
+            + (aa.sequenceRef == null ? " trimmed to " + seq.getName()
+                    : "");
     theTitle = MessageManager.formatMessage("label.varna_params",
-            new String[] { theTitle });
+            new String[]
+            { theTitle });
     setTitle(theTitle);
 
     String gappedTitle = sname + " (with gaps)";
@@ -190,7 +193,8 @@ public class AppVarna extends JInternalFrame implements SelectionListener,
     addModel(gappedModel, gappedTitle);
 
     String trimmedTitle = "trimmed " + sname;
-    RnaModel trimmedModel = new RnaModel(trimmedTitle, aa, seq, null, false);
+    RnaModel trimmedModel = new RnaModel(trimmedTitle, aa, seq, null,
+            false);
     addModel(trimmedModel, trimmedTitle);
     vab.setSelectedIndex(0);
   }
@@ -424,8 +428,8 @@ public class AppVarna extends JInternalFrame implements SelectionListener,
         end = shift.shift(end);
       }
       selectionHighlighter.highlightRegion(rna, start, end);
-      selectionHighlighter.getLastHighlight().setOutlineColor(
-              seqsel.getOutlineColour());
+      selectionHighlighter.getLastHighlight()
+              .setOutlineColor(seqsel.getOutlineColour());
       // TODO - translate column markings to positions on structure if present.
       vab.updateSelectedRNA(rna);
     }
@@ -460,7 +464,8 @@ public class AppVarna extends JInternalFrame implements SelectionListener,
   }
 
   @Override
-  public void onSelectionChanged(BaseList arg0, BaseList arg1, BaseList arg2)
+  public void onSelectionChanged(BaseList arg0, BaseList arg1,
+          BaseList arg2)
   {
     // TODO translate selected regions in VARNA to a selection on the
     // alignpanel.
@@ -577,7 +582,8 @@ public class AppVarna extends JInternalFrame implements SelectionListener,
   {
     if (!model.ann.isValidStruc())
     {
-      throw new IllegalArgumentException("Invalid RNA structure annotation");
+      throw new IllegalArgumentException(
+              "Invalid RNA structure annotation");
     }
 
     /*
@@ -622,11 +628,10 @@ public class AppVarna extends JInternalFrame implements SelectionListener,
     ShiftList offset = new ShiftList();
     int ofstart = -1;
     int sleng = seq.getLength();
-    char[] seqChars = seq.getSequence();
 
     for (int i = 0; i < sleng; i++)
     {
-      if (Comparison.isGap(seqChars[i]))
+      if (Comparison.isGap(seq.getCharAt(i)))
       {
         if (ofstart == -1)
         {
@@ -687,7 +692,8 @@ public class AppVarna extends JInternalFrame implements SelectionListener,
   {
     if (!model.ann.isValidStruc())
     {
-      throw new IllegalArgumentException("Invalid RNA structure annotation");
+      throw new IllegalArgumentException(
+              "Invalid RNA structure annotation");
     }
 
     try
index 829fc3e..ee4ef79 100644 (file)
@@ -281,8 +281,8 @@ public class AppVarnaBinding extends JalviewVarnaBinding
                       String name = r.getName();
                       if (name.equals(""))
                       {
-                        name = path.substring(path
-                                .lastIndexOf(File.separatorChar) + 1);
+                        name = path.substring(
+                                path.lastIndexOf(File.separatorChar) + 1);
                       }
                       if (mdls.size() > 1)
                       {
diff --git a/src/jalview/gui/AquaInternalFrameManager.java b/src/jalview/gui/AquaInternalFrameManager.java
new file mode 100644 (file)
index 0000000..ea809eb
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jalview.gui;
+
+import java.awt.Container;
+import java.beans.PropertyVetoException;
+import java.util.Vector;
+
+import javax.swing.DefaultDesktopManager;
+import javax.swing.DesktopManager;
+import javax.swing.JInternalFrame;
+
+/**
+ * Based on AquaInternalFrameManager
+ *
+ * DesktopManager implementation for Aqua
+ *
+ * Mac is more like Windows than it's like Motif/Basic
+ *
+ * From WindowsDesktopManager:
+ *
+ * This class implements a DesktopManager which more closely follows the MDI
+ * model than the DefaultDesktopManager. Unlike the DefaultDesktopManager
+ * policy, MDI requires that the selected and activated child frames are the
+ * same, and that that frame always be the top-most window.
+ * <p>
+ * The maximized state is managed by the DesktopManager with MDI, instead of
+ * just being a property of the individual child frame. This means that if the
+ * currently selected window is maximized and another window is selected, that
+ * new window will be maximized.
+ *
+ * Downloaded from
+ * https://raw.githubusercontent.com/frohoff/jdk8u-jdk/master/src/macosx/classes/com/apple/laf/AquaInternalFrameManager.java
+ * 
+ * Patch from Jim Procter - when the most recently opened frame is closed,
+ * correct behaviour is to go to the next most recent frame, rather than wrap
+ * around to the bottom of the window stack (as the original implementation
+ * does)
+ * 
+ * @see com.sun.java.swing.plaf.windows.WindowsDesktopManager
+ */
+public class AquaInternalFrameManager extends DefaultDesktopManager
+{
+  // Variables
+
+  /* The frame which is currently selected/activated.
+   * We store this value to enforce Mac's single-selection model.
+   */
+  JInternalFrame fCurrentFrame;
+
+  JInternalFrame fInitialFrame;
+
+  /* The list of frames, sorted by order of creation.
+   * This list is necessary because by default the order of
+   * child frames in the JDesktopPane changes during frame
+   * activation (the activated frame is moved to index 0).
+   * We preserve the creation order so that "next" and "previous"
+   * frame actions make sense.
+   */
+  Vector<JInternalFrame> fChildFrames = new Vector<>(1);
+
+  /**
+   * keep a reference to the original LAF manager so we can iconise/de-iconise
+   * correctly
+   */
+  private DesktopManager ourManager;
+
+  public AquaInternalFrameManager(DesktopManager desktopManager)
+  {
+    ourManager = desktopManager;
+  }
+
+  @Override
+  public void closeFrame(final JInternalFrame f)
+  {
+    if (f == fCurrentFrame)
+    {
+      boolean mostRecentFrame = fChildFrames
+              .indexOf(f) == fChildFrames.size() - 1;
+      if (!mostRecentFrame)
+      {
+        activateNextFrame();
+      }
+      else
+      {
+        activatePreviousFrame();
+      }
+    }
+    fChildFrames.removeElement(f);
+    super.closeFrame(f);
+  }
+
+  @Override
+  public void deiconifyFrame(final JInternalFrame f)
+  {
+    JInternalFrame.JDesktopIcon desktopIcon;
+
+    desktopIcon = f.getDesktopIcon();
+    // If the icon moved, move the frame to that spot before expanding it
+    // reshape does delta checks for us
+    f.reshape(desktopIcon.getX(), desktopIcon.getY(), f.getWidth(),
+            f.getHeight());
+    ourManager.deiconifyFrame(f);
+  }
+
+  void addIcon(final Container c,
+          final JInternalFrame.JDesktopIcon desktopIcon)
+  {
+    c.add(desktopIcon);
+  }
+
+  /**
+   * Removes the frame from its parent and adds its desktopIcon to the parent.
+   */
+  @Override
+  public void iconifyFrame(final JInternalFrame f)
+  {
+    ourManager.iconifyFrame(f);
+  }
+
+  // WindowsDesktopManager code
+  @Override
+  public void activateFrame(final JInternalFrame f)
+  {
+    try
+    {
+      if (f != null)
+      {
+        super.activateFrame(f);
+      }
+
+      // If this is the first activation, add to child list.
+      if (fChildFrames.indexOf(f) == -1)
+      {
+        fChildFrames.addElement(f);
+      }
+
+      if (fCurrentFrame != null && f != fCurrentFrame)
+      {
+        if (fCurrentFrame.isSelected())
+        {
+          fCurrentFrame.setSelected(false);
+        }
+      }
+
+      if (f != null && !f.isSelected())
+      {
+        f.setSelected(true);
+      }
+
+      fCurrentFrame = f;
+    } catch (final PropertyVetoException e)
+    {
+    }
+  }
+
+  private void switchFrame(final boolean next)
+  {
+    if (fCurrentFrame == null)
+    {
+      // initialize first frame we find
+      if (fInitialFrame != null)
+      {
+        activateFrame(fInitialFrame);
+      }
+      return;
+    }
+
+    final int count = fChildFrames.size();
+    if (count <= 1)
+    {
+      // No other child frames.
+      return;
+    }
+
+    final int currentIndex = fChildFrames.indexOf(fCurrentFrame);
+    if (currentIndex == -1)
+    {
+      // the "current frame" is no longer in the list
+      fCurrentFrame = null;
+      return;
+    }
+
+    int nextIndex;
+    if (next)
+    {
+      nextIndex = currentIndex + 1;
+      if (nextIndex == count)
+      {
+        nextIndex = 0;
+      }
+    }
+    else
+    {
+      nextIndex = currentIndex - 1;
+      if (nextIndex == -1)
+      {
+        nextIndex = count - 1;
+      }
+    }
+    final JInternalFrame f = fChildFrames.elementAt(nextIndex);
+    activateFrame(f);
+    fCurrentFrame = f;
+  }
+
+  /**
+   * Activate the next child JInternalFrame, as determined by the frames'
+   * Z-order. If there is only one child frame, it remains activated. If there
+   * are no child frames, nothing happens.
+   */
+  public void activateNextFrame()
+  {
+    switchFrame(true);
+  }
+
+  /**
+   * same as above but will activate a frame if none have been selected
+   */
+  public void activateNextFrame(final JInternalFrame f)
+  {
+    fInitialFrame = f;
+    switchFrame(true);
+  }
+
+  /**
+   * Activate the previous child JInternalFrame, as determined by the frames'
+   * Z-order. If there is only one child frame, it remains activated. If there
+   * are no child frames, nothing happens.
+   */
+  public void activatePreviousFrame()
+  {
+    switchFrame(false);
+  }
+}
\ No newline at end of file
index ddf38c6..fe0aedf 100644 (file)
@@ -52,8 +52,8 @@ public class AssociatePdbFileWithSeq
     PDBEntry entry = new PDBEntry();
     StructureFile pdbfile = null;
     pdbfile = StructureSelectionManager.getStructureSelectionManager(ssmp)
-            .setMapping(false, new SequenceI[] { sequence }, null, choice,
-                    file);
+            .setMapping(false, new SequenceI[]
+            { sequence }, null, choice, file);
     if (pdbfile == null)
     {
       // stacktrace already thrown so just return
index ab9aad7..9d68af1 100644 (file)
@@ -253,10 +253,11 @@ public class BlogReader extends JPanel
     _channelModel = new ChannelListModel();
     // Construct our jalview news channel
     Channel chan = new Channel();
-    chan.setURL(jalview.bin.Cache.getDefault(
-            "JALVIEW_NEWS_RSS",
-            jalview.bin.Cache.getDefault("www.jalview.org",
-                    "http://www.jalview.org") + "/feeds/desktop/rss"));
+    chan.setURL(
+            jalview.bin.Cache.getDefault("JALVIEW_NEWS_RSS",
+                    jalview.bin.Cache.getDefault("www.jalview.org",
+                            "http://www.jalview.org")
+                            + "/feeds/desktop/rss"));
     loadLastM();
     _channelModel.addChannel(chan);
     updating = true;
@@ -318,8 +319,8 @@ public class BlogReader extends JPanel
             public void windowClosing(WindowEvent e)
             {
               ActionEvent actionEvent = new ActionEvent(this,
-                      ActionEvent.ACTION_FIRST, (String) exitAction
-                              .getValue(Action.NAME));
+                      ActionEvent.ACTION_FIRST,
+                      (String) exitAction.getValue(Action.NAME));
               exitAction.actionPerformed(actionEvent);
             }
 
@@ -359,8 +360,8 @@ public class BlogReader extends JPanel
     java.util.Date earliest = null;
     try
     {
-      earliest = new SimpleDateFormat("YYYY-MM-DD").parse(chan
-              .getHTTPLastModified());
+      earliest = new SimpleDateFormat("YYYY-MM-DD")
+              .parse(chan.getHTTPLastModified());
     } catch (Exception x)
     {
     }
@@ -424,8 +425,8 @@ public class BlogReader extends JPanel
       }
       if (lastDate != null)
       {
-        String formatted = Cache.setDateProperty(
-                "JALVIEW_NEWS_RSS_LASTMODIFIED", lastDate);
+        String formatted = Cache
+                .setDateProperty("JALVIEW_NEWS_RSS_LASTMODIFIED", lastDate);
         Cache.log.debug("Saved last read date as " + formatted);
       }
     }
@@ -529,8 +530,8 @@ public class BlogReader extends JPanel
     _itemsValueChanged(listItems);
   }
 
-  public class LaunchJvBrowserOnItem extends AbstractAction implements
-          UpdatableAction
+  public class LaunchJvBrowserOnItem extends AbstractAction
+          implements UpdatableAction
   {
     JList _listItems = null;
 
@@ -585,7 +586,8 @@ public class BlogReader extends JPanel
   private JPopupMenu _buildChannelsPopupMenu()
   {
     JPopupMenu popup = new JPopupMenu();
-    popup.add(new JMenuItem(new MarkChannelAsRead(listChannels, listItems)));
+    popup.add(
+            new JMenuItem(new MarkChannelAsRead(listChannels, listItems)));
     popup.add(new JMenuItem(
             new MarkChannelAsUnread(listChannels, listItems)));
     return popup;
@@ -609,8 +611,9 @@ public class BlogReader extends JPanel
     }
     DefaultListModel itemsModel = (DefaultListModel) listItems.getModel();
     itemsModel.clear();
-    Iterator iter = (channel.getItems() != null) ? channel.getItems()
-            .iterator() : Collections.EMPTY_LIST.iterator();
+    Iterator iter = (channel.getItems() != null)
+            ? channel.getItems().iterator()
+            : Collections.EMPTY_LIST.iterator();
     while (iter.hasNext())
     {
       itemsModel.addElement(iter.next());
@@ -706,8 +709,8 @@ public class BlogReader extends JPanel
           button.setVerticalTextPosition(AbstractButton.BOTTOM);
           button.setHorizontalTextPosition(AbstractButton.CENTER);
         }
-        else if (Boolean.toString(true).equals(
-                general.get("radioTextRight")))
+        else if (Boolean.toString(true)
+                .equals(general.get("radioTextRight")))
         {
           button.setVerticalTextPosition(AbstractButton.CENTER);
           button.setHorizontalTextPosition(AbstractButton.RIGHT);
@@ -756,8 +759,8 @@ public class BlogReader extends JPanel
     jalview.bin.Cache.loadProperties(null);
     jalview.bin.Cache.initLogger();
     // test will advance read date each time
-    Calendar today = Calendar.getInstance(), lastread = Calendar
-            .getInstance();
+    Calendar today = Calendar.getInstance(),
+            lastread = Calendar.getInstance();
     lastread.set(1983, 01, 01);
     while (lastread.before(today))
     {
@@ -826,13 +829,10 @@ class ChannelsRenderer extends DefaultListCellRenderer
     if (value instanceof Channel)
     {
       Channel channel = (Channel) value;
-      component
-              .setText(MessageManager.formatMessage(
-                      "label.channel_title_item_count",
-                      new String[] {
-                          channel.getTitle(),
-                          Integer.valueOf(channel.getUnreadItemCount())
-                                  .toString() }));
+      component.setText(MessageManager
+              .formatMessage("label.channel_title_item_count", new String[]
+              { channel.getTitle(), Integer
+                      .valueOf(channel.getUnreadItemCount()).toString() }));
       component.setToolTipText(channel.getURL());
     }
     return component;
@@ -857,12 +857,11 @@ class ItemsRenderer extends DefaultListCellRenderer
       if (item.getPublishDate() != null)
       {
         component.setText(MessageManager.formatMessage(
-                "label.blog_item_published_on_date",
-                new String[] {
-                    DateFormat
-                            .getDateInstance(DateFormat.LONG,
-                                    MessageManager.getLocale())
-                            .format(item.getPublishDate()).toString(),
+                "label.blog_item_published_on_date", new String[]
+                { DateFormat
+                        .getDateInstance(DateFormat.LONG,
+                                MessageManager.getLocale())
+                        .format(item.getPublishDate()).toString(),
                     item.getTitle() }));
       }
       component.setToolTipText(item.getLink());
index 8a95594..e403dba 100644 (file)
@@ -105,6 +105,11 @@ public class CalculationChooser extends JPanel
 
   List<String> tips = new ArrayList<String>();
 
+  /*
+   * the most recently opened PCA results panel
+   */
+  private PCAPanel pcaPanel;
+
   /**
    * Constructor
    * 
@@ -164,14 +169,14 @@ public class CalculationChooser extends JPanel
     JPanel treePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
     treePanel.setOpaque(false);
 
-    treePanel.setBorder(BorderFactory.createTitledBorder(MessageManager
-            .getString("label.tree")));
+    treePanel.setBorder(BorderFactory
+            .createTitledBorder(MessageManager.getString("label.tree")));
 
     // then copy the inset dimensions for the border-less PCA panel
     JPanel pcaBorderless = new JPanel(new FlowLayout(FlowLayout.LEFT));
     Insets b = treePanel.getBorder().getBorderInsets(treePanel);
-    pcaBorderless.setBorder(BorderFactory.createEmptyBorder(2, b.left, 2,
-            b.right));
+    pcaBorderless.setBorder(
+            BorderFactory.createEmptyBorder(2, b.left, 2, b.right));
     pcaBorderless.setOpaque(false);
 
     pcaBorderless.add(pca, FlowLayout.LEFT);
@@ -186,7 +191,7 @@ public class CalculationChooser extends JPanel
     calcTypes.add(pca);
     calcTypes.add(neighbourJoining);
     calcTypes.add(averageDistance);
-    
+
     ActionListener calcChanged = new ActionListener()
     {
       @Override
@@ -335,8 +340,8 @@ public class CalculationChooser extends JPanel
    */
   private boolean checkEnabled(JRadioButton calc, int size, int minsize)
   {
-    String ttip = MessageManager.formatMessage(
-            "label.you_need_at_least_n_sequences", minsize);
+    String ttip = MessageManager
+            .formatMessage("label.you_need_at_least_n_sequences", minsize);
 
     calc.setEnabled(size >= minsize);
     if (!calc.isEnabled())
@@ -383,7 +388,8 @@ public class CalculationChooser extends JPanel
       @Override
       public void mouseEntered(MouseEvent e)
       {
-        scoreModelsCombo.setToolTipText(tips.get(scoreModelsCombo.getSelectedIndex()));
+        scoreModelsCombo.setToolTipText(
+                tips.get(scoreModelsCombo.getSelectedIndex()));
       }
 
       @Override
@@ -490,19 +496,17 @@ public class CalculationChooser extends JPanel
     SequenceGroup sg = viewport.getSelectionGroup();
     if (sg != null && sg.getSize() < MIN_TREE_SELECTION)
     {
-      JvOptionPane
-              .showMessageDialog(
-                      Desktop.desktop,
-                      MessageManager
-              .formatMessage("label.you_need_at_least_n_sequences",
+      JvOptionPane.showMessageDialog(Desktop.desktop,
+              MessageManager.formatMessage(
+                      "label.you_need_at_least_n_sequences",
                       MIN_TREE_SELECTION),
-                      MessageManager
-                              .getString("label.not_enough_sequences"),
-                      JvOptionPane.WARNING_MESSAGE);
+              MessageManager.getString("label.not_enough_sequences"),
+              JvOptionPane.WARNING_MESSAGE);
       return;
     }
 
-    String treeType = neighbourJoining.isSelected() ? TreeBuilder.NEIGHBOUR_JOINING
+    String treeType = neighbourJoining.isSelected()
+            ? TreeBuilder.NEIGHBOUR_JOINING
             : TreeBuilder.AVERAGE_DISTANCE;
     af.newTreePanel(treeType, modelName, params);
   }
@@ -522,18 +526,20 @@ public class CalculationChooser extends JPanel
      * this check in in case this method gets exposed programmatically in future
      */
     if (((viewport.getSelectionGroup() != null)
-            && (viewport.getSelectionGroup().getSize() < MIN_PCA_SELECTION) && (viewport
-            .getSelectionGroup().getSize() > 0))
+            && (viewport.getSelectionGroup().getSize() < MIN_PCA_SELECTION)
+            && (viewport.getSelectionGroup().getSize() > 0))
             || (viewport.getAlignment().getHeight() < MIN_PCA_SELECTION))
     {
-      JvOptionPane.showInternalMessageDialog(this, MessageManager
-              .formatMessage("label.you_need_at_least_n_sequences",
-                      MIN_PCA_SELECTION), MessageManager
-              .getString("label.sequence_selection_insufficient"),
+      JvOptionPane.showInternalMessageDialog(this,
+              MessageManager.formatMessage(
+                      "label.you_need_at_least_n_sequences",
+                      MIN_PCA_SELECTION),
+              MessageManager
+                      .getString("label.sequence_selection_insufficient"),
               JvOptionPane.WARNING_MESSAGE);
       return;
     }
-    new PCAPanel(af.alignPanel, modelName, params);
+    pcaPanel = new PCAPanel(af.alignPanel, modelName, params);
   }
 
   /**
@@ -575,7 +581,8 @@ public class CalculationChooser extends JPanel
      */
     boolean matchGap = doPCA ? false : treeMatchGaps;
 
-    return new SimilarityParams(includeGapGap, matchGap, includeGapResidue, matchOnShortestLength);
+    return new SimilarityParams(includeGapGap, matchGap, includeGapResidue,
+            matchOnShortestLength);
   }
 
   /**
@@ -590,4 +597,9 @@ public class CalculationChooser extends JPanel
     {
     }
   }
+
+  public PCAPanel getPcaPanel()
+  {
+    return pcaPanel;
+  }
 }
index eadc2ad..89de2e8 100644 (file)
@@ -91,8 +91,8 @@ public class ChimeraViewFrame extends StructureViewerBase
 
     viewerActionMenu.setText(MessageManager.getString("label.chimera"));
 
-    viewerColour.setText(MessageManager
-            .getString("label.colour_with_chimera"));
+    viewerColour
+            .setText(MessageManager.getString("label.colour_with_chimera"));
     viewerColour.setToolTipText(MessageManager
             .getString("label.let_chimera_manage_structure_colours"));
 
@@ -197,8 +197,8 @@ public class ChimeraViewFrame extends StructureViewerBase
   protected void sendFeaturesToChimera()
   {
     int count = jmb.sendFeaturesToViewer(getAlignmentPanel());
-    statusBar.setText(MessageManager.formatMessage("label.attributes_set",
-            count));
+    statusBar.setText(
+            MessageManager.formatMessage("label.attributes_set", count));
   }
 
   /**
@@ -238,7 +238,8 @@ public class ChimeraViewFrame extends StructureViewerBase
      * a new viewer
      */
     openNewChimera(ap, new PDBEntry[] { pdbentry },
-            new SequenceI[][] { seq });
+            new SequenceI[][]
+            { seq });
   }
 
   /**
@@ -277,7 +278,8 @@ public class ChimeraViewFrame extends StructureViewerBase
     this.addInternalFrameListener(new InternalFrameAdapter()
     {
       @Override
-      public void internalFrameClosing(InternalFrameEvent internalFrameEvent)
+      public void internalFrameClosing(
+              InternalFrameEvent internalFrameEvent)
       {
         closeViewer(false);
       }
@@ -356,7 +358,7 @@ public class ChimeraViewFrame extends StructureViewerBase
   @Override
   protected List<StructureViewerBase> getViewersFor(AlignmentPanel ap)
   {
-    List<StructureViewerBase> result = new ArrayList<StructureViewerBase>();
+    List<StructureViewerBase> result = new ArrayList<>();
     JInternalFrame[] frames = Desktop.instance.getAllFrames();
 
     for (JInternalFrame frame : frames)
@@ -398,9 +400,8 @@ public class ChimeraViewFrame extends StructureViewerBase
       boolean opened = jmb.openSession(chimeraSessionFile);
       if (!opened)
       {
-        System.err
-                .println("An error occurred opening Chimera session file "
-                        + chimeraSessionFile);
+        System.err.println("An error occurred opening Chimera session file "
+                + chimeraSessionFile);
       }
     }
 
@@ -413,7 +414,7 @@ public class ChimeraViewFrame extends StructureViewerBase
   @Override
   void showSelectedChains()
   {
-    List<String> toshow = new ArrayList<String>();
+    List<String> toshow = new ArrayList<>();
     for (int i = 0; i < chainMenu.getItemCount(); i++)
     {
       if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
@@ -443,10 +444,9 @@ public class ChimeraViewFrame extends StructureViewerBase
     {
       if (!closeChimera)
       {
-        String prompt = MessageManager.formatMessage(
-                "label.confirm_close_chimera",
-                        new Object[] { jmb.getViewerTitle(getViewerName(),
-                                false) });
+        String prompt = MessageManager
+                .formatMessage("label.confirm_close_chimera", new Object[]
+                { jmb.getViewerTitle(getViewerName(), false) });
         prompt = JvSwingUtils.wrapTooltip(true, prompt);
         int confirm = JvOptionPane.showConfirmDialog(this, prompt,
                 MessageManager.getString("label.close_viewer"),
@@ -484,8 +484,8 @@ public class ChimeraViewFrame extends StructureViewerBase
     // todo - record which pdbids were successfully imported.
     StringBuilder errormsgs = new StringBuilder(128);
     StringBuilder files = new StringBuilder(128);
-    List<PDBEntry> filePDB = new ArrayList<PDBEntry>();
-    List<Integer> filePDBpos = new ArrayList<Integer>();
+    List<PDBEntry> filePDB = new ArrayList<>();
+    List<Integer> filePDBpos = new ArrayList<>();
     PDBEntry thePdbEntry = null;
     StructureFile pdb = null;
     try
@@ -542,15 +542,16 @@ public class ChimeraViewFrame extends StructureViewerBase
     } catch (Exception ex)
     {
       ex.printStackTrace();
-      errormsgs.append("When retrieving pdbfiles for '"
-              + thePdbEntry.getId() + "'");
+      errormsgs.append(
+              "When retrieving pdbfiles for '" + thePdbEntry.getId() + "'");
     }
     if (errormsgs.length() > 0)
     {
 
-      JvOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager
-              .formatMessage("label.pdb_entries_couldnt_be_retrieved",
-                      new Object[] { errormsgs.toString() }),
+      JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+              MessageManager.formatMessage(
+                      "label.pdb_entries_couldnt_be_retrieved", new Object[]
+                      { errormsgs.toString() }),
               MessageManager.getString("label.couldnt_load_file"),
               JvOptionPane.ERROR_MESSAGE);
     }
@@ -597,9 +598,12 @@ public class ChimeraViewFrame extends StructureViewerBase
               stopProgressBar("", startTime);
             }
             // Explicitly map to the filename used by Chimera ;
+
             pdb = jmb.getSsm().setMapping(jmb.getSequence()[pos],
-                    jmb.getChains()[pos], pe.getFile(), protocol);
+                    jmb.getChains()[pos], pe.getFile(), protocol,
+                    progressBar);
             stashFoundChains(pdb, pe.getFile());
+
           } catch (OutOfMemoryError oomerror)
           {
             new OOMWarning(
@@ -607,8 +611,9 @@ public class ChimeraViewFrame extends StructureViewerBase
                     oomerror);
           } catch (Exception ex)
           {
-            Cache.log.error("Couldn't open " + pe.getFile()
-                    + " in Chimera viewer!", ex);
+            Cache.log.error(
+                    "Couldn't open " + pe.getFile() + " in Chimera viewer!",
+                    ex);
           } finally
           {
             Cache.log.debug("File locations are " + files);
@@ -656,7 +661,7 @@ public class ChimeraViewFrame extends StructureViewerBase
 
   /**
    * Fetch PDB data and save to a local file. Returns the full path to the file,
-   * or null if fetch fails.
+   * or null if fetch fails. TODO: refactor to common with Jmol ? duplication
    * 
    * @param processingEntry
    * @return
@@ -667,12 +672,13 @@ public class ChimeraViewFrame extends StructureViewerBase
   {
     for (int i = 0; i < pdb.getChains().size(); i++)
     {
-      String chid = new String(pdb.getId() + ":"
-              + pdb.getChains().elementAt(i).id);
+      String chid = new String(
+              pdb.getId() + ":" + pdb.getChains().elementAt(i).id);
       jmb.getChainNames().add(chid);
       jmb.getChainFile().put(chid, file);
     }
   }
+
   private String fetchPdbFile(PDBEntry processingEntry) throws Exception
   {
     // FIXME: this is duplicated code with Jmol frame ?
@@ -687,7 +693,8 @@ public class ChimeraViewFrame extends StructureViewerBase
      * Write 'fetching PDB' progress on AlignFrame as we are not yet visible
      */
     String msg = MessageManager.formatMessage("status.fetching_pdb",
-            new Object[] { pdbid });
+            new Object[]
+            { pdbid });
     getAlignmentPanel().alignFrame.setProgressBar(msg, handle);
     // long hdl = startProgressBar(MessageManager.formatMessage(
     // "status.fetching_pdb", new Object[]
@@ -755,17 +762,15 @@ public class ChimeraViewFrame extends StructureViewerBase
   @Override
   public void eps_actionPerformed(ActionEvent e)
   {
-    throw new Error(
-            MessageManager
-                    .getString("error.eps_generation_not_implemented"));
+    throw new Error(MessageManager
+            .getString("error.eps_generation_not_implemented"));
   }
 
   @Override
   public void png_actionPerformed(ActionEvent e)
   {
-    throw new Error(
-            MessageManager
-                    .getString("error.png_generation_not_implemented"));
+    throw new Error(MessageManager
+            .getString("error.png_generation_not_implemented"));
   }
 
   @Override
@@ -889,4 +894,10 @@ public class ChimeraViewFrame extends StructureViewerBase
     }
     return reply;
   }
+
+  @Override
+  protected IProgressIndicator getIProgressIndicator()
+  {
+    return progressBar;
+  }
 }
index 8ffc070..8f0b88c 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.gui;
 
 import jalview.bin.Cache;
@@ -100,9 +120,11 @@ public class ColourMenuHelper
        * the colour scheme (inspected in setColourSelected())
        */
       final String name = scheme.getSchemeName();
-      String label = MessageManager.getStringOrReturn("label.colourScheme_"
-              + name.toLowerCase().replace(" ", "_"), name);
-      final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(label);
+      String label = MessageManager.getStringOrReturn(
+              "label.colourScheme_" + name.toLowerCase().replace(" ", "_"),
+              name);
+      final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(
+              label);
       radioItem.setName(name);
       radioItem.setEnabled(scheme.isApplicableTo(coll));
       if (scheme instanceof UserColourScheme)
@@ -137,15 +159,16 @@ public class ColourMenuHelper
             ActionListener al = radioItem.getActionListeners()[0];
             radioItem.removeActionListener(al);
             int option = JvOptionPane.showInternalConfirmDialog(
-                    Desktop.desktop, MessageManager
+                    Desktop.desktop,
+                    MessageManager
                             .getString("label.remove_from_default_list"),
                     MessageManager
                             .getString("label.remove_user_defined_colour"),
                     JvOptionPane.YES_NO_OPTION);
             if (option == JvOptionPane.YES_OPTION)
             {
-              ColourSchemes.getInstance().removeColourScheme(
-                      radioItem.getName());
+              ColourSchemes.getInstance()
+                      .removeColourScheme(radioItem.getName());
               colourMenu.remove(radioItem);
               updatePreferences();
             }
@@ -183,7 +206,8 @@ public class ColourMenuHelper
         @Override
         public void actionPerformed(ActionEvent e)
         {
-          client.changeColour_actionPerformed(ResidueColourScheme.USER_DEFINED_MENU);
+          client.changeColour_actionPerformed(
+                  ResidueColourScheme.USER_DEFINED_MENU);
         }
       });
       colourMenu.add(userDefinedColour);
@@ -197,16 +221,16 @@ public class ColourMenuHelper
    * Marks as selected the colour menu item matching the given colour scheme, or
    * the first item ('None') if no match is found. If the colour scheme is a
    * user defined scheme, but not in the menu (this arises if a new scheme is
-   * defined and applied but not saved to file), then menu option
-   * "User Defined.." is selected.
+   * defined and applied but not saved to file), then menu option "User
+   * Defined.." is selected.
    * 
    * @param colourMenu
    * @param cs
    */
   public static void setColourSelected(JMenu colourMenu, ColourSchemeI cs)
   {
-    String colourName = cs == null ? ResidueColourScheme.NONE : cs
-            .getSchemeName();
+    String colourName = cs == null ? ResidueColourScheme.NONE
+            : cs.getSchemeName();
 
     JRadioButtonMenuItem none = null;
     JRadioButtonMenuItem userDefined = null;
index b776757..684f965 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.gui;
 
 import java.awt.Component;
index de7574c..4c019a6 100644 (file)
@@ -53,8 +53,8 @@ import org.apache.log4j.SimpleLayout;
  * own applications RJHM van den Bergh , rvdb@comweb.nl
  */
 
-public class Console extends WindowAdapter implements WindowListener,
-        ActionListener, Runnable
+public class Console extends WindowAdapter
+        implements WindowListener, ActionListener, Runnable
 {
   private JFrame frame;
 
@@ -305,8 +305,8 @@ public class Console extends WindowAdapter implements WindowListener,
     }
     else
     {
-      frame = initFrame("Jalview Java Console", bounds.width,
-              bounds.height, bounds.x, bounds.y);
+      frame = initFrame("Jalview Java Console", bounds.width, bounds.height,
+              bounds.x, bounds.y);
     }
     frame.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
     // desktop.add(frame);
@@ -522,8 +522,8 @@ public class Console extends WindowAdapter implements WindowListener,
       textArea.append("The error is: " + e.getMessage());
       // Need to uncomment this to ensure that line tally is synched.
       // lines += 2;
-      stderr.println("Console reports an Internal error.\nThe error is: "
-              + e);
+      stderr.println(
+              "Console reports an Internal error.\nThe error is: " + e);
     }
 
     // just for testing (Throw a Nullpointer after 1 second)
index 7768b22..2d1dfd4 100644 (file)
@@ -67,10 +67,9 @@ public class CrossRefAction implements Runnable
   public void run()
   {
     final long sttime = System.currentTimeMillis();
-    alignFrame.setProgressBar(
-            MessageManager.formatMessage(
-                    "status.searching_for_sequences_from",
-                    new Object[] { source }), sttime);
+    alignFrame.setProgressBar(MessageManager.formatMessage(
+            "status.searching_for_sequences_from", new Object[]
+            { source }), sttime);
     try
     {
       AlignmentI alignment = alignFrame.getViewport().getAlignment();
@@ -85,8 +84,8 @@ public class CrossRefAction implements Runnable
                         + " now searching for " + (dna ? "DNA" : "Protein")
                         + " Context.");
       }
-      AlignmentI xrefs = new CrossRef(sel, dataset).findXrefSequences(
-              source, dna);
+      AlignmentI xrefs = new CrossRef(sel, dataset)
+              .findXrefSequences(source, dna);
       if (xrefs == null)
       {
         return;
@@ -159,8 +158,8 @@ public class CrossRefAction implements Runnable
 
         if (copyAlignment.getHeight() <= 0)
         {
-          System.err.println("No Sequences generated for xRef type "
-                  + source);
+          System.err.println(
+                  "No Sequences generated for xRef type " + source);
           return;
         }
         /*
@@ -243,7 +242,7 @@ public class CrossRefAction implements Runnable
       String linkedTitle = MessageManager
               .getString("label.linked_view_title");
       Desktop.addInternalFrame(sf, linkedTitle, -1, -1);
-      sf.adjustDivider();
+      sf.adjustInitialLayout();
 
       // finally add the top, then bottom frame to the view list
       xrefViews.add(dna ? copyThis.alignPanel : newFrame.alignPanel);
@@ -258,8 +257,8 @@ public class CrossRefAction implements Runnable
     } finally
     {
       alignFrame.setProgressBar(MessageManager.formatMessage(
-              "status.finished_searching_for_sequences_from",
-              new Object[] { source }), sttime);
+              "status.finished_searching_for_sequences_from", new Object[]
+              { source }), sttime);
     }
   }
 
@@ -280,9 +279,8 @@ public class CrossRefAction implements Runnable
     for (int s = 0; s < sprods.length; s++)
     {
       sprods[s] = (seqs.getSequenceAt(s)).deriveSequence();
-      if (dataset.getSequences() == null
-              || !dataset.getSequences().contains(
-                      sprods[s].getDatasetSequence()))
+      if (dataset.getSequences() == null || !dataset.getSequences()
+              .contains(sprods[s].getDatasetSequence()))
       {
         dataset.addSequence(sprods[s].getDatasetSequence());
       }
index dae83d1..71a1520 100644 (file)
@@ -152,8 +152,8 @@ public class CutAndPasteHtmlTransfer extends GCutAndPasteHtmlTransfer
 
     chooser.setAcceptAllFileFilterUsed(false);
     chooser.setFileView(new JalviewFileView());
-    chooser.setDialogTitle(MessageManager
-            .getString("label.save_text_to_file"));
+    chooser.setDialogTitle(
+            MessageManager.getString("label.save_text_to_file"));
     chooser.setToolTipText(MessageManager.getString("action.save"));
 
     int value = chooser.showSaveDialog(this);
@@ -179,8 +179,8 @@ public class CutAndPasteHtmlTransfer extends GCutAndPasteHtmlTransfer
   public void toggleHtml_actionPerformed(ActionEvent e)
   {
     String txt = textarea.getText();
-    textarea.setContentType(displaySource.isSelected() ? "text/text"
-            : "text/html");
+    textarea.setContentType(
+            displaySource.isSelected() ? "text/text" : "text/html");
     textarea.setText(txt);
   }
 
index a5aa9eb..2a96daf 100644 (file)
@@ -140,8 +140,8 @@ public class CutAndPasteTransfer extends GCutAndPasteTransfer
 
     chooser.setAcceptAllFileFilterUsed(false);
     chooser.setFileView(new JalviewFileView());
-    chooser.setDialogTitle(MessageManager
-            .getString("label.save_text_to_file"));
+    chooser.setDialogTitle(
+            MessageManager.getString("label.save_text_to_file"));
     chooser.setToolTipText(MessageManager.getString("action.save"));
 
     int value = chooser.showSaveDialog(this);
@@ -150,8 +150,8 @@ public class CutAndPasteTransfer extends GCutAndPasteTransfer
     {
       try
       {
-        PrintWriter out = new PrintWriter(new FileWriter(
-                chooser.getSelectedFile()));
+        PrintWriter out = new PrintWriter(
+                new FileWriter(chooser.getSelectedFile()));
 
         out.print(getText());
         out.close();
@@ -196,8 +196,8 @@ public class CutAndPasteTransfer extends GCutAndPasteTransfer
 
     try
     {
-      textarea.append((String) contents
-              .getTransferData(DataFlavor.stringFlavor));
+      textarea.append(
+              (String) contents.getTransferData(DataFlavor.stringFlavor));
     } catch (Exception ex)
     {
     }
@@ -228,8 +228,8 @@ public class CutAndPasteTransfer extends GCutAndPasteTransfer
     }
     if (format == null)
     {
-      System.err.println(MessageManager
-              .getString("label.couldnt_read_data"));
+      System.err
+              .println(MessageManager.getString("label.couldnt_read_data"));
       if (!Jalview.isHeadlessMode())
       {
         JvOptionPane.showInternalMessageDialog(Desktop.desktop,
@@ -253,16 +253,16 @@ public class CutAndPasteTransfer extends GCutAndPasteTransfer
     {
       JvOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager
               .formatMessage("label.couldnt_read_pasted_text", new String[]
-              { ex.toString() }), MessageManager
-              .getString("label.error_parsing_text"),
+              { ex.toString() }),
+              MessageManager.getString("label.error_parsing_text"),
               JvOptionPane.WARNING_MESSAGE);
     }
 
     if (al != null && al.hasValidSequence())
     {
-      String title = MessageManager.formatMessage(
-              "label.input_cut_paste_params",
-              new String[] { format.getName() });
+      String title = MessageManager
+              .formatMessage("label.input_cut_paste_params", new String[]
+              { format.getName() });
       FeatureSettingsModelI proxyColourScheme = source
               .getFeatureColourScheme();
 
@@ -298,6 +298,7 @@ public class CutAndPasteTransfer extends GCutAndPasteTransfer
                   AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
           af.getViewport().setShowSequenceFeatures(showSeqFeatures);
           af.getViewport().setFeaturesDisplayed(fd);
+          af.setMenusForViewport();
           ColourSchemeI cs = ColourSchemeMapper.getJalviewColourScheme(
                   colourSchemeName, al);
           if (cs != null)
@@ -326,8 +327,8 @@ public class CutAndPasteTransfer extends GCutAndPasteTransfer
 
         try
         {
-          af.setMaximum(jalview.bin.Cache.getDefault("SHOW_FULLSCREEN",
-                  false));
+          af.setMaximum(
+                  jalview.bin.Cache.getDefault("SHOW_FULLSCREEN", false));
         } catch (Exception ex)
         {
         }
@@ -335,8 +336,8 @@ public class CutAndPasteTransfer extends GCutAndPasteTransfer
     }
     else
     {
-      System.err.println(MessageManager
-              .getString("label.couldnt_read_data"));
+      System.err
+              .println(MessageManager.getString("label.couldnt_read_data"));
       if (!Jalview.isHeadlessMode())
       {
         JvOptionPane.showInternalMessageDialog(Desktop.desktop,
index c5ec067..8570ac3 100644 (file)
@@ -52,8 +52,8 @@ import org.biodas.jdas.schema.sources.COORDINATES;
 import org.biodas.jdas.schema.sources.PROP;
 import org.biodas.jdas.schema.sources.VERSION;
 
-public class DasSourceBrowser extends GDasSourceBrowser implements
-        Runnable, ListSelectionListener
+public class DasSourceBrowser extends GDasSourceBrowser
+        implements Runnable, ListSelectionListener
 {
   DasSourceRegistryI sourceRegistry = null;
 
@@ -138,8 +138,8 @@ public class DasSourceBrowser extends GDasSourceBrowser implements
     for (int i = 0; i < dSize; i++)
     {
       data[i][0] = sources.get(i).getTitle(); // what's equivalent of nickname
-      data[i][1] = new Boolean(selectedSources.contains(sources.get(i)
-              .getTitle()));
+      data[i][1] = new Boolean(
+              selectedSources.contains(sources.get(i).getTitle()));
     }
 
     refreshTableData(data);
@@ -177,9 +177,8 @@ public class DasSourceBrowser extends GDasSourceBrowser implements
 
     if (nickName == null)
     {
-      fullDetails.setText(text
-              + MessageManager
-                      .getString("label.select_das_service_from_table"));
+      fullDetails.setText(text + MessageManager
+              .getString("label.select_das_service_from_table"));
       return;
     }
 
@@ -192,8 +191,8 @@ public class DasSourceBrowser extends GDasSourceBrowser implements
       }
 
       VERSION latest = ds.getVersion();
-      text.append("<font color=\"#0000FF\">Id:</font> " + ds.getUri()
-              + "<br>");
+      text.append(
+              "<font color=\"#0000FF\">Id:</font> " + ds.getUri() + "<br>");
       text.append("<font color=\"#0000FF\">Nickname:</font> "
               + ds.getTitle() + "<br>");
 
@@ -212,8 +211,10 @@ public class DasSourceBrowser extends GDasSourceBrowser implements
         text.append("<font color=\"#0000FF\">Description:</font> "
                 + ds.getDescription() + "<br>");
 
-        text.append("<font color=\"#0000FF\">Admin Email:</font> <a href=\"mailto:"
-                + ds.getEmail() + "\">" + ds.getEmail() + "</a>" + "<br>");
+        text.append(
+                "<font color=\"#0000FF\">Admin Email:</font> <a href=\"mailto:"
+                        + ds.getEmail() + "\">" + ds.getEmail() + "</a>"
+                        + "<br>");
 
         text.append("<font color=\"#0000FF\">Registered at:</font> "
                 + latest.getCreated() + "<br>");
@@ -460,8 +461,7 @@ public class DasSourceBrowser extends GDasSourceBrowser implements
     panel.add(pane12, BorderLayout.SOUTH);
 
     int reply = JvOptionPane.showInternalConfirmDialog(Desktop.desktop,
-            panel,
-            MessageManager.getString("label.enter_local_das_source"),
+            panel, MessageManager.getString("label.enter_local_das_source"),
             JvOptionPane.OK_CANCEL_OPTION);
 
     if (reply != JvOptionPane.OK_OPTION)
@@ -474,19 +474,21 @@ public class DasSourceBrowser extends GDasSourceBrowser implements
       urltf.setText(urltf.getText() + "/");
     }
 
-    jalviewSourceI local = sourceRegistry.createLocalSource(
-            urltf.getText(), nametf.getText(), seqs.isSelected(), true);
+    jalviewSourceI local = sourceRegistry.createLocalSource(urltf.getText(),
+            nametf.getText(), seqs.isSelected(), true);
     List sources = sourceRegistry.getSources();
     int osize = sources.size();
     int size = osize + (newSource ? 1 : 0);
 
     Object[][] data = new Object[size][2];
-    DASTableModel dtm = (table != null) ? (DASTableModel) ((TableSorter) table
-            .getModel()).getTableModel() : null;
+    DASTableModel dtm = (table != null)
+            ? (DASTableModel) ((TableSorter) table.getModel())
+                    .getTableModel()
+            : null;
     for (int i = 0; i < osize; i++)
     {
-      String osrc = (dtm == null || i >= osize) ? null : (String) dtm
-              .getValueAt(i, 0);
+      String osrc = (dtm == null || i >= osize) ? null
+              : (String) dtm.getValueAt(i, 0);
       if (!newSource && osrc != null
               && dtm.getValueAt(i, 0).equals(nickname))
       {
@@ -514,8 +516,8 @@ public class DasSourceBrowser extends GDasSourceBrowser implements
       @Override
       public void run()
       {
-        scrollPane.getVerticalScrollBar().setValue(
-                scrollPane.getVerticalScrollBar().getMaximum());
+        scrollPane.getVerticalScrollBar()
+                .setValue(scrollPane.getVerticalScrollBar().getMaximum());
       }
     });
 
@@ -534,13 +536,11 @@ public class DasSourceBrowser extends GDasSourceBrowser implements
 
     if (!sourceRegistry.getSource(nickname).isLocal())
     {
-      JvOptionPane
-              .showInternalMessageDialog(
-                      Desktop.desktop,
-                      MessageManager
-                              .getString("label.you_can_only_edit_or_remove_local_das_sources"),
-                      MessageManager.getString("label.public_das_source"),
-                      JvOptionPane.WARNING_MESSAGE);
+      JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+              MessageManager.getString(
+                      "label.you_can_only_edit_or_remove_local_das_sources"),
+              MessageManager.getString("label.public_das_source"),
+              JvOptionPane.WARNING_MESSAGE);
       return;
     }
 
@@ -548,8 +548,8 @@ public class DasSourceBrowser extends GDasSourceBrowser implements
     int choice = JvOptionPane.showInternalOptionDialog(Desktop.desktop,
             "Do you want to edit or remove " + nickname + "?",
             "Edit / Remove Local DAS Source",
-            JvOptionPane.YES_NO_CANCEL_OPTION, JvOptionPane.QUESTION_MESSAGE,
-            null, options, options[2]);
+            JvOptionPane.YES_NO_CANCEL_OPTION,
+            JvOptionPane.QUESTION_MESSAGE, null, options, options[2]);
 
     switch (choice)
     {
@@ -560,8 +560,7 @@ public class DasSourceBrowser extends GDasSourceBrowser implements
       sourceRegistry.removeLocalSource(sourceRegistry.getSource(nickname));
       selectedSources.remove(nickname);
       Object[][] data = new Object[sourceRegistry.getSources().size()][2];
-      int index = 0,
-      l = table.getRowCount();
+      int index = 0, l = table.getRowCount();
 
       for (int i = 0; i < l; i++)
       {
@@ -583,8 +582,8 @@ public class DasSourceBrowser extends GDasSourceBrowser implements
         @Override
         public void run()
         {
-          scrollPane.getVerticalScrollBar().setValue(
-                  scrollPane.getVerticalScrollBar().getMaximum());
+          scrollPane.getVerticalScrollBar()
+                  .setValue(scrollPane.getVerticalScrollBar().getMaximum());
         }
       });
 
@@ -618,11 +617,10 @@ public class DasSourceBrowser extends GDasSourceBrowser implements
 
       VERSION v = ds.getVersion();
       List<COORDINATES> coords = v.getCOORDINATES();
-      if (ds.isLocal()
-              || ((coords == null || coords.size() == 0)
-                      && filter1.getSelectedIndex() == 0
-                      && filter2.getSelectedIndex() == 0 && filter3
-                      .getSelectedIndex() == 0))
+      if (ds.isLocal() || ((coords == null || coords.size() == 0)
+              && filter1.getSelectedIndex() == 0
+              && filter2.getSelectedIndex() == 0
+              && filter3.getSelectedIndex() == 0))
       {
         // THIS IS A FIX FOR LOCAL SOURCES WHICH DO NOT
         // HAVE COORDINATE SYSTEMS, INFO WHICH AT PRESENT
@@ -642,12 +640,14 @@ public class DasSourceBrowser extends GDasSourceBrowser implements
       for (int j = 0; j < coords.size(); j++)
       {
         if (selectedInList(filter1.getSelectedValues(),
-                new String[] { coords.get(j).getAuthority() })
+                new String[]
+                { coords.get(j).getAuthority() })
                 && selectedInList(filter2.getSelectedValues(), new String[]
                 { coords.get(j).getSource() }))
         {
           names.add(ds.getTitle());
-          selected.add(new Boolean(selectedSources.contains(ds.getTitle())));
+          selected.add(
+                  new Boolean(selectedSources.contains(ds.getTitle())));
           break;
         }
       }
index d076ba0..128481c 100644 (file)
@@ -68,8 +68,6 @@ import java.awt.dnd.DropTargetEvent;
 import java.awt.dnd.DropTargetListener;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.awt.event.FocusEvent;
-import java.awt.event.FocusListener;
 import java.awt.event.KeyEvent;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
@@ -125,8 +123,8 @@ import javax.swing.event.MenuListener;
  * @author $author$
  * @version $Revision: 1.155 $
  */
-public class Desktop extends jalview.jbgui.GDesktop implements
-        DropTargetListener, ClipboardOwner, IProgressIndicator,
+public class Desktop extends jalview.jbgui.GDesktop
+        implements DropTargetListener, ClipboardOwner, IProgressIndicator,
         jalview.api.StructureSelectionManagerProvider
 {
   private static int DEFAULT_MIN_WIDTH = 300;
@@ -269,12 +267,14 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     public void endDraggingFrame(JComponent f)
     {
       delegate.endDraggingFrame(f);
+      desktop.repaint();
     }
 
     @Override
     public void endResizingFrame(JComponent f)
     {
       delegate.endResizingFrame(f);
+      desktop.repaint();
     }
 
     @Override
@@ -341,13 +341,9 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
             false);
-    boolean showjconsole = jalview.bin.Cache.getDefault(
-            "SHOW_JAVA_CONSOLE", false);
+    boolean showjconsole = jalview.bin.Cache.getDefault("SHOW_JAVA_CONSOLE",
+            false);
     desktop = new MyDesktopPane(selmemusage);
-    if (Platform.isAMac())
-    {
-      desktop.setDoubleBuffered(false);
-    }
     showMemusage.setSelected(selmemusage);
     desktop.setBackground(Color.white);
     getContentPane().setLayout(new BorderLayout());
@@ -360,8 +356,13 @@ public class Desktop extends jalview.jbgui.GDesktop implements
 
     // This line prevents Windows Look&Feel resizing all new windows to maximum
     // if previous window was maximised
-    desktop.setDesktopManager(new MyDesktopManager(
-            new DefaultDesktopManager()));
+    desktop.setDesktopManager(
+            new MyDesktopManager(
+                    (Platform.isWindows() ? new DefaultDesktopManager()
+                            : Platform.isAMac()
+                                    ? new AquaInternalFrameManager(
+                                            desktop.getDesktopManager())
+                                    : desktop.getDesktopManager())));
 
     Rectangle dims = getLastKnownDimensions("");
     if (dims != null)
@@ -371,26 +372,28 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     else
     {
       Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
-      setBounds((screenSize.width - 900) / 2,
-              (screenSize.height - 650) / 2, 900, 650);
+      setBounds((screenSize.width - 900) / 2, (screenSize.height - 650) / 2,
+              900, 650);
     }
     jconsole = new Console(this, showjconsole);
     // add essential build information
-    jconsole.setHeader("Jalview Version: "
-            + jalview.bin.Cache.getProperty("VERSION") + "\n"
-            + "Jalview Installation: "
-            + jalview.bin.Cache.getDefault("INSTALLATION", "unknown")
-            + "\n" + "Build Date: "
-            + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
-            + "Java version: " + System.getProperty("java.version") + "\n"
-            + System.getProperty("os.arch") + " "
-            + System.getProperty("os.name") + " "
-            + System.getProperty("os.version"));
+    jconsole.setHeader(
+            "Jalview Version: " + jalview.bin.Cache.getProperty("VERSION")
+                    + "\n" + "Jalview Installation: "
+                    + jalview.bin.Cache.getDefault("INSTALLATION",
+                            "unknown")
+                    + "\n" + "Build Date: "
+                    + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
+                    + "\n" + "Java version: "
+                    + System.getProperty("java.version") + "\n"
+                    + System.getProperty("os.arch") + " "
+                    + System.getProperty("os.name") + " "
+                    + System.getProperty("os.version"));
 
     showConsole(showjconsole);
 
     showNews.setVisible(false);
-    
+
     experimentalFeatures.setSelected(showExperimental());
 
     getIdentifiersOrgData();
@@ -429,24 +432,6 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     });
     desktop.addMouseListener(ma);
 
-    this.addFocusListener(new FocusListener()
-    {
-
-      @Override
-      public void focusLost(FocusEvent e)
-      {
-        // TODO Auto-generated method stub
-
-      }
-
-      @Override
-      public void focusGained(FocusEvent e)
-      {
-        Cache.log.debug("Relaying windows after focus gain");
-        // make sure that we sort windows properly after we gain focus
-        instance.relayerWindows();
-      }
-    });
     this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
     // Spawn a thread that shows the splashscreen
     SwingUtilities.invokeLater(new Runnable()
@@ -508,12 +493,12 @@ public class Desktop extends jalview.jbgui.GDesktop implements
             .getStructureSelectionManager(this);
     if (jalview.bin.Cache.getDefault(Preferences.ADD_SS_ANN, true))
     {
-      ssm.setAddTempFacAnnot(jalview.bin.Cache.getDefault(
-              Preferences.ADD_TEMPFACT_ANN, true));
-      ssm.setProcessSecondaryStructure(jalview.bin.Cache.getDefault(
-              Preferences.STRUCT_FROM_PDB, true));
-      ssm.setSecStructServices(jalview.bin.Cache.getDefault(
-              Preferences.USE_RNAVIEW, true));
+      ssm.setAddTempFacAnnot(jalview.bin.Cache
+              .getDefault(Preferences.ADD_TEMPFACT_ANN, true));
+      ssm.setProcessSecondaryStructure(jalview.bin.Cache
+              .getDefault(Preferences.STRUCT_FROM_PDB, true));
+      ssm.setSecStructServices(
+              jalview.bin.Cache.getDefault(Preferences.USE_RNAVIEW, true));
     }
     else
     {
@@ -584,7 +569,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
           {
             long now = System.currentTimeMillis();
             Desktop.instance.setProgressBar(
-                    MessageManager.getString("status.refreshing_news"), now);
+                    MessageManager.getString("status.refreshing_news"),
+                    now);
             jvnews.refreshNews();
             Desktop.instance.setProgressBar(null, now);
             jvnews.showNews();
@@ -608,25 +594,23 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
     String x = jalview.bin.Cache.getProperty(windowName + "SCREEN_X");
     String y = jalview.bin.Cache.getProperty(windowName + "SCREEN_Y");
-    String width = jalview.bin.Cache.getProperty(windowName
-            + "SCREEN_WIDTH");
-    String height = jalview.bin.Cache.getProperty(windowName
-            + "SCREEN_HEIGHT");
+    String width = jalview.bin.Cache
+            .getProperty(windowName + "SCREEN_WIDTH");
+    String height = jalview.bin.Cache
+            .getProperty(windowName + "SCREEN_HEIGHT");
     if ((x != null) && (y != null) && (width != null) && (height != null))
     {
-      int ix = Integer.parseInt(x), iy = Integer.parseInt(y), iw = Integer
-              .parseInt(width), ih = Integer.parseInt(height);
+      int ix = Integer.parseInt(x), iy = Integer.parseInt(y),
+              iw = Integer.parseInt(width), ih = Integer.parseInt(height);
       if (jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH") != null)
       {
         // attempt #1 - try to cope with change in screen geometry - this
         // version doesn't preserve original jv aspect ratio.
         // take ratio of current screen size vs original screen size.
-        double sw = ((1f * screenSize.width) / (1f * Integer
-                .parseInt(jalview.bin.Cache
-                        .getProperty("SCREENGEOMETRY_WIDTH"))));
-        double sh = ((1f * screenSize.height) / (1f * Integer
-                .parseInt(jalview.bin.Cache
-                        .getProperty("SCREENGEOMETRY_HEIGHT"))));
+        double sw = ((1f * screenSize.width) / (1f * Integer.parseInt(
+                jalview.bin.Cache.getProperty("SCREENGEOMETRY_WIDTH"))));
+        double sh = ((1f * screenSize.height) / (1f * Integer.parseInt(
+                jalview.bin.Cache.getProperty("SCREENGEOMETRY_HEIGHT"))));
         // rescale the bounds depending upon the current screen geometry.
         ix = (int) (ix * sw);
         iw = (int) (iw * sw);
@@ -634,19 +618,19 @@ public class Desktop extends jalview.jbgui.GDesktop implements
         ih = (int) (ih * sh);
         while (ix >= screenSize.width)
         {
-          jalview.bin.Cache.log
-                  .debug("Window geometry location recall error: shifting horizontal to within screenbounds.");
+          jalview.bin.Cache.log.debug(
+                  "Window geometry location recall error: shifting horizontal to within screenbounds.");
           ix -= screenSize.width;
         }
         while (iy >= screenSize.height)
         {
-          jalview.bin.Cache.log
-                  .debug("Window geometry location recall error: shifting vertical to within screenbounds.");
+          jalview.bin.Cache.log.debug(
+                  "Window geometry location recall error: shifting vertical to within screenbounds.");
           iy -= screenSize.height;
         }
-        jalview.bin.Cache.log.debug("Got last known dimensions for "
-                + windowName + ": x:" + ix + " y:" + iy + " width:" + iw
-                + " height:" + ih);
+        jalview.bin.Cache.log.debug(
+                "Got last known dimensions for " + windowName + ": x:" + ix
+                        + " y:" + iy + " width:" + iw + " height:" + ih);
       }
       // return dimensions for new instance
       return new Rectangle(ix, iy, iw, ih);
@@ -732,9 +716,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
       }
     } catch (Exception ex)
     {
-      System.out
-              .println("Unable to paste alignment from system clipboard:\n"
-                      + ex);
+      System.out.println(
+              "Unable to paste alignment from system clipboard:\n" + ex);
     }
   }
 
@@ -837,9 +820,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
     // IF JALVIEW IS RUNNING HEADLESS
     // ///////////////////////////////////////////////
-    if (instance == null
-            || (System.getProperty("java.awt.headless") != null && System
-                    .getProperty("java.awt.headless").equals("true")))
+    if (instance == null || (System.getProperty("java.awt.headless") != null
+            && System.getProperty("java.awt.headless").equals("true")))
     {
       return;
     }
@@ -848,8 +830,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
 
     if (!ignoreMinSize)
     {
-      frame.setMinimumSize(new Dimension(DEFAULT_MIN_WIDTH,
-              DEFAULT_MIN_HEIGHT));
+      frame.setMinimumSize(
+              new Dimension(DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT));
 
       // Set default dimension for Alignment Frame window.
       // The Alignment Frame window could be added from a number of places,
@@ -862,23 +844,16 @@ public class Desktop extends jalview.jbgui.GDesktop implements
       }
     }
 
-
     frame.setVisible(makeVisible);
     frame.setClosable(true);
     frame.setResizable(resizable);
     frame.setMaximizable(resizable);
     frame.setIconifiable(resizable);
-    if (Platform.isAMac())
-    {
-      frame.setIconifiable(false);
-      frame.setFrameIcon(null);
-      // frame.setDesktopIcon(null);
-      frame.setDoubleBuffered(false);
-    }
+
     if (frame.getX() < 1 && frame.getY() < 1)
     {
-      frame.setLocation(xOffset * openFrameCount, yOffset
-              * ((openFrameCount - 1) % 10) + yOffset);
+      frame.setLocation(xOffset * openFrameCount,
+              yOffset * ((openFrameCount - 1) % 10) + yOffset);
     }
 
     /*
@@ -894,6 +869,10 @@ public class Desktop extends jalview.jbgui.GDesktop implements
         JInternalFrame itf = desktop.getSelectedFrame();
         if (itf != null)
         {
+          if (itf instanceof AlignFrame)
+          {
+            Jalview.setCurrentAlignFrame((AlignFrame) itf);
+          }
           itf.requestFocus();
         }
       }
@@ -920,15 +899,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements
           menuItem.removeActionListener(menuItem.getActionListeners()[0]);
         }
         windowMenu.remove(menuItem);
-        JInternalFrame itf = desktop.getSelectedFrame();
-        if (itf != null)
-        {
-          itf.requestFocus();
-          if (itf instanceof AlignFrame)
-          {
-            Jalview.setCurrentAlignFrame((AlignFrame) itf);
-          }
-        }
+
         System.gc();
       };
     });
@@ -962,9 +933,9 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     {
     } catch (java.lang.ClassCastException cex)
     {
-      Cache.log
-              .warn("Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
-                      cex);
+      Cache.log.warn(
+              "Squashed a possible GUI implementation error. If you can recreate this, please look at http://issues.jalview.org/browse/JAL-869",
+              cex);
     }
   }
 
@@ -1013,8 +984,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     // Java's Transferable for native dnd
     evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
     Transferable t = evt.getTransferable();
-    List<String> files = new ArrayList<String>();
-    List<DataSourceType> protocols = new ArrayList<DataSourceType>();
+    List<String> files = new ArrayList<>();
+    List<DataSourceType> protocols = new ArrayList<>();
 
     try
     {
@@ -1032,7 +1003,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
         for (int i = 0; i < files.size(); i++)
         {
           String file = files.get(i).toString();
-          DataSourceType protocol = (protocols == null) ? DataSourceType.FILE
+          DataSourceType protocol = (protocols == null)
+                  ? DataSourceType.FILE
                   : protocols.get(i);
           FileFormatI format = null;
 
@@ -1068,12 +1040,12 @@ public class Desktop extends jalview.jbgui.GDesktop implements
   public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
   {
     String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
-    JalviewFileChooser chooser = JalviewFileChooser.forRead(
-            Cache.getProperty("LAST_DIRECTORY"), fileFormat);
+    JalviewFileChooser chooser = JalviewFileChooser
+            .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat);
 
     chooser.setFileView(new JalviewFileView());
-    chooser.setDialogTitle(MessageManager
-            .getString("label.open_local_file"));
+    chooser.setDialogTitle(
+            MessageManager.getString("label.open_local_file"));
     chooser.setToolTipText(MessageManager.getString("action.open"));
 
     int value = chooser.showOpenDialog(this);
@@ -1081,8 +1053,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     if (value == JalviewFileChooser.APPROVE_OPTION)
     {
       String choice = chooser.getSelectedFile().getPath();
-      Cache.setProperty("LAST_DIRECTORY", chooser
-              .getSelectedFile().getParent());
+      Cache.setProperty("LAST_DIRECTORY",
+              chooser.getSelectedFile().getParent());
 
       FileFormatI format = chooser.getSelectedFormat();
 
@@ -1190,8 +1162,9 @@ public class Desktop extends jalview.jbgui.GDesktop implements
       {
         JvOptionPane.showInternalMessageDialog(Desktop.desktop,
                 MessageManager.formatMessage("label.couldnt_locate",
-                        new Object[] { url }), MessageManager
-                        .getString("label.url_not_found"),
+                        new Object[]
+                        { url }),
+                MessageManager.getString("label.url_not_found"),
                 JvOptionPane.WARNING_MESSAGE);
 
         return;
@@ -1199,8 +1172,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
 
       if (viewport != null)
       {
-        new FileLoader()
-                .LoadFile(viewport, url, DataSourceType.URL, format);
+        new FileLoader().LoadFile(viewport, url, DataSourceType.URL,
+                format);
       }
       else
       {
@@ -1223,8 +1196,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     CutAndPasteTransfer cap = new CutAndPasteTransfer();
     cap.setForInput(viewPanel);
     Desktop.addInternalFrame(cap,
-            MessageManager.getString("label.cut_paste_alignmen_file"),
-            true, 600, 500);
+            MessageManager.getString("label.cut_paste_alignmen_file"), true,
+            600, 500);
   }
 
   /*
@@ -1234,12 +1207,12 @@ public class Desktop extends jalview.jbgui.GDesktop implements
   public void quit()
   {
     Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
-    jalview.bin.Cache
-            .setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
-    jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height
-            + "");
-    storeLastKnownDimensions("", new Rectangle(getBounds().x,
-            getBounds().y, getWidth(), getHeight()));
+    jalview.bin.Cache.setProperty("SCREENGEOMETRY_WIDTH",
+            screen.width + "");
+    jalview.bin.Cache.setProperty("SCREENGEOMETRY_HEIGHT",
+            screen.height + "");
+    storeLastKnownDimensions("", new Rectangle(getBounds().x, getBounds().y,
+            getWidth(), getHeight()));
 
     if (jconsole != null)
     {
@@ -1308,7 +1281,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     if (shortv)
     {
       message.append("<h1><strong>Version: "
-              + jalview.bin.Cache.getProperty("VERSION") + "</strong></h1>");
+              + jalview.bin.Cache.getProperty("VERSION")
+              + "</strong></h1>");
       message.append("<strong>Last Updated: <em>"
               + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")
               + "</em></strong>");
@@ -1323,8 +1297,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
               + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
     }
 
-    if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking").equals(
-            "Checking"))
+    if (jalview.bin.Cache.getDefault("LATEST_VERSION", "Checking")
+            .equals("Checking"))
     {
       message.append("<br>...Checking latest version...</br>");
     }
@@ -1346,16 +1320,16 @@ public class Desktop extends jalview.jbgui.GDesktop implements
                       "..Checking..")
               + " is available for download from "
               + jalview.bin.Cache.getDefault("www.jalview.org",
-                      "http://www.jalview.org") + " !!");
+                      "http://www.jalview.org")
+              + " !!");
       if (red)
       {
         message.append("</div>");
       }
     }
-    message.append("<br>Authors:  "
-            + jalview.bin.Cache
-                    .getDefault("AUTHORFNAMES",
-                            "The Jalview Authors (See AUTHORS file for current list)")
+    message.append("<br>Authors:  " + jalview.bin.Cache.getDefault(
+            "AUTHORFNAMES",
+            "The Jalview Authors (See AUTHORS file for current list)")
             + "<br><br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
             + "<br><br>For help, see the FAQ at <a href=\"http://www.jalview.org/faq\">www.jalview.org/faq</a> and/or join the jalview-discuss@jalview.org mailing list"
             + "<br><br>If  you use Jalview, please cite:"
@@ -1486,8 +1460,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
   {
     showConsole.setSelected(selected);
     // TODO: decide if we should update properties file
-    Cache.setProperty("SHOW_JAVA_CONSOLE", Boolean.valueOf(selected)
-            .toString());
+    Cache.setProperty("SHOW_JAVA_CONSOLE",
+            Boolean.valueOf(selected).toString());
     jconsole.setVisible(selected);
   }
 
@@ -1610,8 +1584,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
         {
           // TODO: refactor to Jalview desktop session controller action.
           setProgressBar(MessageManager.formatMessage(
-                  "label.saving_jalview_project",
-                  new Object[] { choice.getName() }), choice.hashCode());
+                  "label.saving_jalview_project", new Object[]
+                  { choice.getName() }), choice.hashCode());
           jalview.bin.Cache.setProperty("LAST_DIRECTORY",
                   choice.getParent());
           // TODO catch and handle errors for savestate
@@ -1621,17 +1595,20 @@ public class Desktop extends jalview.jbgui.GDesktop implements
             new Jalview2XML().saveState(choice);
           } catch (OutOfMemoryError oom)
           {
-            new OOMWarning("Whilst saving current state to "
-                    + choice.getName(), oom);
+            new OOMWarning(
+                    "Whilst saving current state to " + choice.getName(),
+                    oom);
           } catch (Exception ex)
           {
             Cache.log.error(
                     "Problems whilst trying to save to " + choice.getName(),
                     ex);
-            JvOptionPane.showMessageDialog(me, MessageManager.formatMessage(
-                    "label.error_whilst_saving_current_state_to",
-                    new Object[] { choice.getName() }), MessageManager
-                    .getString("label.couldnt_save_project"),
+            JvOptionPane.showMessageDialog(me,
+                    MessageManager.formatMessage(
+                            "label.error_whilst_saving_current_state_to",
+                            new Object[]
+                            { choice.getName() }),
+                    MessageManager.getString("label.couldnt_save_project"),
                     JvOptionPane.WARNING_MESSAGE);
           }
           setProgressBar(null, choice.hashCode());
@@ -1660,9 +1637,11 @@ public class Desktop extends jalview.jbgui.GDesktop implements
   public void loadState_actionPerformed(ActionEvent e)
   {
     JalviewFileChooser chooser = new JalviewFileChooser(
-            Cache.getProperty("LAST_DIRECTORY"), new String[] {
-                "jvp", "jar" }, new String[] { "Jalview Project",
-                "Jalview Project (old)" }, "Jalview Project");
+            Cache.getProperty("LAST_DIRECTORY"), new String[]
+            { "jvp", "jar" },
+            new String[]
+            { "Jalview Project", "Jalview Project (old)" },
+            "Jalview Project");
     chooser.setFileView(new JalviewFileView());
     chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
 
@@ -1673,17 +1652,15 @@ public class Desktop extends jalview.jbgui.GDesktop implements
       final File selectedFile = chooser.getSelectedFile();
       setProjectFile(selectedFile);
       final String choice = selectedFile.getAbsolutePath();
-      Cache.setProperty("LAST_DIRECTORY",
-              selectedFile.getParent());
+      Cache.setProperty("LAST_DIRECTORY", selectedFile.getParent());
       new Thread(new Runnable()
       {
         @Override
         public void run()
         {
-          setProgressBar(
-                  MessageManager.formatMessage(
-                          "label.loading_jalview_project",
-                          new Object[] { choice }), choice.hashCode());
+          setProgressBar(MessageManager.formatMessage(
+                  "label.loading_jalview_project", new Object[]
+                  { choice }), choice.hashCode());
           try
           {
             new Jalview2XML().loadJalviewAlign(choice);
@@ -1692,13 +1669,14 @@ public class Desktop extends jalview.jbgui.GDesktop implements
             new OOMWarning("Whilst loading project from " + choice, oom);
           } catch (Exception ex)
           {
-            Cache.log.error("Problems whilst loading project from "
-                    + choice, ex);
-            JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
-                    .formatMessage(
+            Cache.log.error(
+                    "Problems whilst loading project from " + choice, ex);
+            JvOptionPane.showMessageDialog(Desktop.desktop,
+                    MessageManager.formatMessage(
                             "label.error_whilst_loading_project_from",
-                            new Object[] { choice }), MessageManager
-                    .getString("label.couldnt_load_project"),
+                            new Object[]
+                            { choice }),
+                    MessageManager.getString("label.couldnt_load_project"),
                     JvOptionPane.WARNING_MESSAGE);
           }
           setProgressBar(null, choice.hashCode());
@@ -1715,14 +1693,15 @@ public class Desktop extends jalview.jbgui.GDesktop implements
 
   JPanel progressPanel;
 
-  ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
+  ArrayList<JPanel> fileLoadingPanels = new ArrayList<>();
 
   public void startLoading(final String fileName)
   {
     if (fileLoadingCount == 0)
     {
-      fileLoadingPanels.add(addProgressPanel(MessageManager.formatMessage(
-              "label.loading_file", new Object[] { fileName })));
+      fileLoadingPanels.add(addProgressPanel(MessageManager
+              .formatMessage("label.loading_file", new Object[]
+              { fileName })));
     }
     fileLoadingCount++;
   }
@@ -1743,8 +1722,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
 
     thisprogress.add(progressBar, BorderLayout.CENTER);
     progressPanel.add(thisprogress);
-    ((GridLayout) progressPanel.getLayout())
-            .setRows(((GridLayout) progressPanel.getLayout()).getRows() + 1);
+    ((GridLayout) progressPanel.getLayout()).setRows(
+            ((GridLayout) progressPanel.getLayout()).getRows() + 1);
     ++totalProgressCount;
     instance.validate();
     return thisprogress;
@@ -1806,7 +1785,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements
       // TODO: verify that frames are recoverable when in headless mode
       return null;
     }
-    List<AlignmentPanel> aps = new ArrayList<AlignmentPanel>();
+    List<AlignmentPanel> aps = new ArrayList<>();
     AlignFrame[] frames = getAlignFrames();
     if (frames == null)
     {
@@ -1841,16 +1820,15 @@ public class Desktop extends jalview.jbgui.GDesktop implements
    */
   public static AlignmentViewport[] getViewports(String sequenceSetId)
   {
-    List<AlignmentViewport> viewp = new ArrayList<AlignmentViewport>();
+    List<AlignmentViewport> viewp = new ArrayList<>();
     if (desktop != null)
     {
       AlignFrame[] frames = Desktop.getAlignFrames();
 
       for (AlignFrame afr : frames)
       {
-        if (sequenceSetId == null
-                || afr.getViewport().getSequenceSetId()
-                        .equals(sequenceSetId))
+        if (sequenceSetId == null || afr.getViewport().getSequenceSetId()
+                .equals(sequenceSetId))
         {
           if (afr.alignPanels != null)
           {
@@ -1972,10 +1950,10 @@ public class Desktop extends jalview.jbgui.GDesktop implements
               jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
 
       chooser.setFileView(new JalviewFileView());
-      chooser.setDialogTitle(MessageManager
-              .getString("label.open_saved_vamsas_session"));
-      chooser.setToolTipText(MessageManager
-              .getString("label.select_vamsas_session_opened_as_new_vamsas_session"));
+      chooser.setDialogTitle(
+              MessageManager.getString("label.open_saved_vamsas_session"));
+      chooser.setToolTipText(MessageManager.getString(
+              "label.select_vamsas_session_opened_as_new_vamsas_session"));
 
       int value = chooser.showOpenDialog(this);
 
@@ -1984,22 +1962,21 @@ public class Desktop extends jalview.jbgui.GDesktop implements
         String fle = chooser.getSelectedFile().toString();
         if (!vamsasImport(chooser.getSelectedFile()))
         {
-          JvOptionPane
-                  .showInternalMessageDialog(
-                          Desktop.desktop,
-                          MessageManager.formatMessage(
-                                  "label.couldnt_import_as_vamsas_session",
-                                  new Object[] { fle }),
-                          MessageManager
-                                  .getString("label.vamsas_document_import_failed"),
-                          JvOptionPane.ERROR_MESSAGE);
+          JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                  MessageManager.formatMessage(
+                          "label.couldnt_import_as_vamsas_session",
+                          new Object[]
+                          { fle }),
+                  MessageManager
+                          .getString("label.vamsas_document_import_failed"),
+                  JvOptionPane.ERROR_MESSAGE);
         }
       }
     }
     else
     {
-      jalview.bin.Cache.log
-              .error("Implementation error - load session from a running session is not supported.");
+      jalview.bin.Cache.log.error(
+              "Implementation error - load session from a running session is not supported.");
     }
   }
 
@@ -2015,8 +1992,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     if (v_client != null)
     {
 
-      jalview.bin.Cache.log
-              .error("Implementation error - load session from a running session is not supported.");
+      jalview.bin.Cache.log.error(
+              "Implementation error - load session from a running session is not supported.");
       return false;
     }
 
@@ -2041,7 +2018,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     {
       jalview.bin.Cache.log.error(
               "Failed to create new vamsas session from contents of URL "
-                      + url, ex);
+                      + url,
+              ex);
       return false;
     }
     setupVamsasConnectedGui();
@@ -2060,22 +2038,22 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     if (v_client != null)
     {
 
-      jalview.bin.Cache.log
-              .error("Implementation error - load session from a running session is not supported.");
+      jalview.bin.Cache.log.error(
+              "Implementation error - load session from a running session is not supported.");
       return false;
     }
 
     setProgressBar(MessageManager.formatMessage(
-            "status.importing_vamsas_session_from",
-            new Object[] { file.getName() }), file.hashCode());
+            "status.importing_vamsas_session_from", new Object[]
+            { file.getName() }), file.hashCode());
     try
     {
       v_client = new jalview.gui.VamsasApplication(this, file, null);
     } catch (Exception ex)
     {
       setProgressBar(MessageManager.formatMessage(
-              "status.importing_vamsas_session_from",
-              new Object[] { file.getName() }), file.hashCode());
+              "status.importing_vamsas_session_from", new Object[]
+              { file.getName() }), file.hashCode());
       jalview.bin.Cache.log.error(
               "New vamsas session from existing session file failed:", ex);
       return false;
@@ -2083,8 +2061,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     setupVamsasConnectedGui();
     v_client.initial_update(); // TODO: thread ?
     setProgressBar(MessageManager.formatMessage(
-            "status.importing_vamsas_session_from",
-            new Object[] { file.getName() }), file.hashCode());
+            "status.importing_vamsas_session_from", new Object[]
+            { file.getName() }), file.hashCode());
     return v_client.inSession();
   }
 
@@ -2092,9 +2070,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
   {
     if (v_client != null)
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.try_join_vamsas_session_another"));
+      throw new Error(MessageManager
+              .getString("error.try_join_vamsas_session_another"));
     }
     if (mysesid == null)
     {
@@ -2152,8 +2129,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     vamsasSave.setVisible(false);
     vamsasStop.setVisible(false);
     vamsasImport.setVisible(true);
-    vamsasStart.setText(MessageManager
-            .getString("label.new_vamsas_session"));
+    vamsasStart
+            .setText(MessageManager.getString("label.new_vamsas_session"));
   }
 
   @Override
@@ -2177,21 +2154,22 @@ public class Desktop extends jalview.jbgui.GDesktop implements
         sess = VamsasApplication.getSessionList();
       } catch (Exception e)
       {
-        jalview.bin.Cache.log.warn(
-                "Problem getting current sessions list.", e);
+        jalview.bin.Cache.log.warn("Problem getting current sessions list.",
+                e);
         sess = null;
       }
       if (sess != null)
       {
-        jalview.bin.Cache.log.debug("Got current sessions list: "
-                + sess.length + " entries.");
+        jalview.bin.Cache.log.debug(
+                "Got current sessions list: " + sess.length + " entries.");
         VamsasStMenu.removeAll();
         for (int i = 0; i < sess.length; i++)
         {
           JMenuItem sessit = new JMenuItem();
           sessit.setText(sess[i]);
-          sessit.setToolTipText(MessageManager.formatMessage(
-                  "label.connect_to_session", new Object[] { sess[i] }));
+          sessit.setToolTipText(MessageManager
+                  .formatMessage("label.connect_to_session", new Object[]
+                  { sess[i] }));
           final Desktop dsktp = this;
           final String mysesid = sess[i];
           sessit.addActionListener(new ActionListener()
@@ -2243,7 +2221,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements
   {
     if (v_client != null)
     {
-   // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
+      // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
       JalviewFileChooser chooser = new JalviewFileChooser("vdj",
               "Vamsas Document");
 
@@ -2256,9 +2234,9 @@ public class Desktop extends jalview.jbgui.GDesktop implements
       if (value == JalviewFileChooser.APPROVE_OPTION)
       {
         java.io.File choice = chooser.getSelectedFile();
-        JPanel progpanel = addProgressPanel(MessageManager.formatMessage(
-                "label.saving_vamsas_doc",
-                new Object[] { choice.getName() }));
+        JPanel progpanel = addProgressPanel(MessageManager
+                .formatMessage("label.saving_vamsas_doc", new Object[]
+                { choice.getName() }));
         Cache.setProperty("LAST_DIRECTORY", choice.getParent());
         String warnmsg = null;
         String warnttl = null;
@@ -2269,15 +2247,15 @@ public class Desktop extends jalview.jbgui.GDesktop implements
         {
           warnttl = "Serious Problem saving Vamsas Document";
           warnmsg = ex.toString();
-          jalview.bin.Cache.log.error("Error Whilst saving document to "
-                  + choice, ex);
+          jalview.bin.Cache.log
+                  .error("Error Whilst saving document to " + choice, ex);
 
         } catch (Exception ex)
         {
           warnttl = "Problem saving Vamsas Document.";
           warnmsg = ex.toString();
-          jalview.bin.Cache.log.warn("Exception Whilst saving document to "
-                  + choice, ex);
+          jalview.bin.Cache.log.warn(
+                  "Exception Whilst saving document to " + choice, ex);
 
         }
         removeProgressPanel(progpanel);
@@ -2285,7 +2263,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements
         {
           JvOptionPane.showInternalMessageDialog(Desktop.desktop,
 
-          warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE);
+                  warnmsg, warnttl, JvOptionPane.ERROR_MESSAGE);
         }
       }
     }
@@ -2310,8 +2288,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     }
     if (b)
     {
-      vamUpdate = this.addProgressPanel(MessageManager
-              .getString("label.updating_vamsas_session"));
+      vamUpdate = this.addProgressPanel(
+              MessageManager.getString("label.updating_vamsas_session"));
     }
     vamsasStart.setVisible(!b);
     vamsasStop.setVisible(!b);
@@ -2355,17 +2333,18 @@ public class Desktop extends jalview.jbgui.GDesktop implements
           // SEQUENCE_ID which is not the default EMBL_EBI link
           ListIterator<String> li = links.listIterator();
           boolean check = false;
-          List<JLabel> urls = new ArrayList<JLabel>();
+          List<JLabel> urls = new ArrayList<>();
           while (li.hasNext())
           {
             String link = li.next();
             if (link.contains(SEQUENCE_ID)
-                    && !link.equals(UrlConstants.DEFAULT_STRING))
+                    && !UrlConstants.isDefaultString(link))
             {
               check = true;
               int barPos = link.indexOf("|");
-              String urlMsg = barPos == -1 ? link : link.substring(0,
-                      barPos) + ": " + link.substring(barPos + 1);
+              String urlMsg = barPos == -1 ? link
+                      : link.substring(0, barPos) + ": "
+                              + link.substring(barPos + 1);
               urls.add(new JLabel(urlMsg));
             }
           }
@@ -2379,12 +2358,10 @@ public class Desktop extends jalview.jbgui.GDesktop implements
           JPanel msgPanel = new JPanel();
           msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
           msgPanel.add(Box.createVerticalGlue());
-          JLabel msg = new JLabel(
-                  MessageManager
-                          .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
-          JLabel msg2 = new JLabel(
-                  MessageManager
-                          .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
+          JLabel msg = new JLabel(MessageManager
+                  .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
+          JLabel msg2 = new JLabel(MessageManager
+                  .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
           msgPanel.add(msg);
           for (JLabel url : urls)
           {
@@ -2414,7 +2391,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements
         }
       }
     });
-    }
+  }
 
   /**
    * Proxy class for JDesktopPane which optionally displays the current memory
@@ -2450,6 +2427,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements
         Thread worker = new Thread(this);
         worker.start();
       }
+      repaint();
     }
 
     public boolean isShowMemoryUsage()
@@ -2503,24 +2481,16 @@ public class Desktop extends jalview.jbgui.GDesktop implements
         FontMetrics fm = g.getFontMetrics();
         if (fm != null)
         {
-          g.drawString(MessageManager.formatMessage(
-                  "label.memory_stats",
-                  new Object[] { df.format(totalFreeMemory),
-                      df.format(maxMemory), df.format(percentUsage) }), 10,
-                  getHeight() - fm.getHeight());
+          g.drawString(MessageManager.formatMessage("label.memory_stats",
+                  new Object[]
+                  { df.format(totalFreeMemory), df.format(maxMemory),
+                      df.format(percentUsage) }),
+                  10, getHeight() - fm.getHeight());
         }
       }
     }
   }
 
-  /**
-   * fixes stacking order after a modal dialog to ensure windows that should be
-   * on top actually are
-   */
-  public void relayerWindows()
-  {
-
-  }
 
   /**
    * Accessor method to quickly get all the AlignmentFrames loaded.
@@ -2541,7 +2511,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     {
       return null;
     }
-    List<AlignFrame> avp = new ArrayList<AlignFrame>();
+    List<AlignFrame> avp = new ArrayList<>();
     // REVERSE ORDER
     for (int i = frames.length - 1; i > -1; i--)
     {
@@ -2586,7 +2556,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     {
       return null;
     }
-    List<GStructureViewer> avp = new ArrayList<GStructureViewer>();
+    List<GStructureViewer> avp = new ArrayList<>();
     // REVERSE ORDER
     for (int i = frames.length - 1; i > -1; i--)
     {
@@ -2618,7 +2588,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements
       jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
       JvOptionPane.showInternalMessageDialog(Desktop.desktop,
 
-      MessageManager.getString("label.couldnt_create_groovy_shell"),
+              MessageManager.getString("label.couldnt_create_groovy_shell"),
               MessageManager.getString("label.groovy_support_failed"),
               JvOptionPane.ERROR_MESSAGE);
     }
@@ -2674,9 +2644,10 @@ public class Desktop extends jalview.jbgui.GDesktop implements
    */
   protected void addQuitHandler()
   {
-    getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
-            KeyStroke.getKeyStroke(KeyEvent.VK_Q, Toolkit
-                    .getDefaultToolkit().getMenuShortcutKeyMask()), "Quit");
+    getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
+            .put(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
+                    Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
+                    "Quit");
     getRootPane().getActionMap().put("Quit", new AbstractAction()
     {
       @Override
@@ -2728,8 +2699,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
   {
     if (progressBars == null)
     {
-      progressBars = new Hashtable<Long, JPanel>();
-      progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
+      progressBars = new Hashtable<>();
+      progressBarHandlers = new Hashtable<>();
     }
 
     if (progressBars.get(new Long(id)) != null)
@@ -2760,9 +2731,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     if (progressBarHandlers == null
             || !progressBars.containsKey(new Long(id)))
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.call_setprogressbar_before_registering_handler"));
+      throw new Error(MessageManager.getString(
+              "error.call_setprogressbar_before_registering_handler"));
     }
     progressBarHandlers.put(new Long(id), handler);
     final JPanel progressPanel = progressBars.get(new Long(id));
@@ -2778,10 +2748,10 @@ public class Desktop extends jalview.jbgui.GDesktop implements
         public void actionPerformed(ActionEvent e)
         {
           handler.cancelActivity(id);
-          us.setProgressBar(MessageManager.formatMessage(
-                  "label.cancelled_params",
-                  new Object[] { ((JLabel) progressPanel.getComponent(0))
-                          .getText() }), id);
+          us.setProgressBar(MessageManager
+                  .formatMessage("label.cancelled_params", new Object[]
+                  { ((JLabel) progressPanel.getComponent(0)).getText() }),
+                  id);
         }
       });
       progressPanel.add(cancel, BorderLayout.EAST);
@@ -2814,7 +2784,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
   {
     if (desktop != null)
     {
-      AlignmentPanel[] aps = getAlignmentPanels(viewport.getSequenceSetId());
+      AlignmentPanel[] aps = getAlignmentPanels(
+              viewport.getSequenceSetId());
       for (int panel = 0; aps != null && panel < aps.length; panel++)
       {
         if (aps[panel] != null && aps[panel].av == viewport)
@@ -2883,8 +2854,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
 
     if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
     {
-      t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
-              changeSupport);
+      t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer()
+              .startDiscoverer(changeSupport);
     }
     Thread t3 = null;
     {
@@ -2900,8 +2871,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements
         } catch (Exception e)
         {
         }
-        alive = (t1 != null && t1.isAlive())
-                || (t2 != null && t2.isAlive())
+        alive = (t1 != null && t1.isAlive()) || (t2 != null && t2.isAlive())
                 || (t3 != null && t3.isAlive())
                 || (t0 != null && t0.isAlive());
       }
@@ -2956,20 +2926,16 @@ public class Desktop extends jalview.jbgui.GDesktop implements
                  * 
                  * jd.waitForInput();
                  */
-                JvOptionPane
-                        .showConfirmDialog(
-                                Desktop.desktop,
-                                new JLabel(
-                                        "<html><table width=\"450\"><tr><td>"
-                                                + ermsg
-                                                + "</td></tr></table>"
-                                                + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
-                                                + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
-                                                + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
-                                                + " Tools->Preferences dialog box to change them.</p></html>"),
-                                "Web Service Configuration Problem",
-                                JvOptionPane.DEFAULT_OPTION,
-                                JvOptionPane.ERROR_MESSAGE);
+                JvOptionPane.showConfirmDialog(Desktop.desktop,
+                        new JLabel("<html><table width=\"450\"><tr><td>"
+                                + ermsg + "</td></tr></table>"
+                                + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
+                                + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
+                                + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
+                                + " Tools->Preferences dialog box to change them.</p></html>"),
+                        "Web Service Configuration Problem",
+                        JvOptionPane.DEFAULT_OPTION,
+                        JvOptionPane.ERROR_MESSAGE);
                 serviceChangedDialog = null;
 
               }
@@ -2978,8 +2944,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
         }
         else
         {
-          Cache.log
-                  .error("Errors reported by JABA discovery service. Check web services preferences.\n"
+          Cache.log.error(
+                  "Errors reported by JABA discovery service. Check web services preferences.\n"
                           + ermsg);
         }
       }
@@ -3019,9 +2985,9 @@ public class Desktop extends jalview.jbgui.GDesktop implements
         {
           if (progress != null)
           {
-            progress.setProgressBar(MessageManager.formatMessage(
-                    "status.opening_params", new Object[] { url }), this
-                    .hashCode());
+            progress.setProgressBar(MessageManager
+                    .formatMessage("status.opening_params", new Object[]
+                    { url }), this.hashCode());
           }
           jalview.util.BrowserLauncher.openURL(url);
         } catch (Exception ex)
@@ -3077,8 +3043,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
           }
           else
           {
-            System.err.println("Couldn't handle string " + url
-                    + " as a URL.");
+            System.err.println(
+                    "Couldn't handle string " + url + " as a URL.");
           }
         }
         // ignore any exceptions due to dud links.
@@ -3154,10 +3120,11 @@ public class Desktop extends jalview.jbgui.GDesktop implements
   {
     invalidate();
     File of;
-    ImageMaker im = new jalview.util.ImageMaker(this, ImageMaker.TYPE.EPS,
-            "View of Desktop", getWidth(), getHeight(), of = new File(
-                    "Jalview_snapshot" + System.currentTimeMillis()
-                            + ".eps"), "View of desktop", null, 0, false);
+    ImageMaker im = new jalview.util.ImageMaker(
+            this, ImageMaker.TYPE.EPS, "View of Desktop", getWidth(),
+            getHeight(), of = new File("Jalview_snapshot"
+                    + System.currentTimeMillis() + ".eps"),
+            "View of desktop", null, 0, false);
     try
     {
       paintAll(im.getGraphics());
@@ -3270,9 +3237,9 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
     myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
             source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
-    myBottomFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
-            source.getY(), myBottomFrame.getWidth(), myBottomFrame
-                    .getHeight()));
+    myBottomFrame.viewport
+            .setExplodedGeometry(new Rectangle(source.getX(), source.getY(),
+                    myBottomFrame.getWidth(), myBottomFrame.getHeight()));
     myTopFrame.viewport.setGatherViewsHere(true);
     myBottomFrame.viewport.setGatherViewsHere(true);
     String topViewId = myTopFrame.viewport.getSequenceSetId();
@@ -3297,10 +3264,10 @@ public class Desktop extends jalview.jbgui.GDesktop implements
             gatherThis = true;
             topPanel.av.setGatherViewsHere(false);
             bottomPanel.av.setGatherViewsHere(false);
-            topPanel.av.setExplodedGeometry(new Rectangle(sf.getLocation(),
-                    topFrame.getSize()));
-            bottomPanel.av.setExplodedGeometry(new Rectangle(sf
-                    .getLocation(), bottomFrame.getSize()));
+            topPanel.av.setExplodedGeometry(
+                    new Rectangle(sf.getLocation(), topFrame.getSize()));
+            bottomPanel.av.setExplodedGeometry(
+                    new Rectangle(sf.getLocation(), bottomFrame.getSize()));
             myTopFrame.addAlignmentPanel(topPanel, false);
             myBottomFrame.addAlignmentPanel(bottomPanel, false);
           }
@@ -3328,8 +3295,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements
 
   public static void transferFromDropTarget(List<String> files,
           List<DataSourceType> protocols, DropTargetDropEvent evt,
-          Transferable t)
-          throws Exception
+          Transferable t) throws Exception
   {
 
     DataFlavor uriListFlavor = new DataFlavor(
@@ -3361,8 +3327,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
         // fallback to text: workaround - on OSX where there's a JVM bug
         Cache.log.debug("standard URIListFlavor failed. Trying text");
         // try text fallback
-        data = (String) t.getTransferData(new DataFlavor(
-                "text/plain;class=java.lang.String"));
+        data = (String) t.getTransferData(
+                new DataFlavor("text/plain;class=java.lang.String"));
         if (Cache.log.isDebugEnabled())
         {
           Cache.log.debug("fallback returned " + data);
@@ -3402,12 +3368,12 @@ public class Desktop extends jalview.jbgui.GDesktop implements
       {
         if (data == null || !added)
         {
-          Cache.log
-                  .debug("Couldn't resolve drop data. Here are the supported flavors:");
+          Cache.log.debug(
+                  "Couldn't resolve drop data. Here are the supported flavors:");
           for (DataFlavor fl : t.getTransferDataFlavors())
           {
-            Cache.log.debug("Supported transfer dataflavor: "
-                    + fl.toString());
+            Cache.log.debug(
+                    "Supported transfer dataflavor: " + fl.toString());
             Object df = t.getTransferData(fl);
             if (df != null)
             {
index fa67999..d8f0d9a 100644 (file)
@@ -59,7 +59,8 @@ public class EPSOptions extends JPanel
     bg.add(text);
 
     JOptionPane pane = new JOptionPane(null, JvOptionPane.DEFAULT_OPTION,
-            JvOptionPane.DEFAULT_OPTION, null, new Object[] { this });
+            JvOptionPane.DEFAULT_OPTION, null, new Object[]
+            { this });
 
     dialog = pane.createDialog(Desktop.desktop, "EPS Rendering options");
     dialog.setVisible(true);
index 4172819..d8db546 100644 (file)
@@ -31,6 +31,8 @@ import java.awt.Dimension;
 import java.awt.FlowLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 
@@ -117,8 +119,9 @@ public class FeatureColourChooser extends JalviewDialog
     this.fr = frender;
     this.type = theType;
     ap = fr.ap;
-    String title = MessageManager.formatMessage(
-            "label.graduated_color_for_params", new String[] { theType });
+    String title = MessageManager
+            .formatMessage("label.graduated_color_for_params", new String[]
+            { theType });
     initDialogFrame(this, true, blocking, title, 480, 185);
 
     slider.addChangeListener(new ChangeListener()
@@ -144,7 +147,7 @@ public class FeatureColourChooser extends JalviewDialog
          */
         if (ap != null)
         {
-          ap.paintAlignment(true);
+          ap.paintAlignment(true, true);
         }
       }
     });
@@ -205,7 +208,8 @@ public class FeatureColourChooser extends JalviewDialog
       slider.setEnabled(true);
       slider.setValue((int) (cs.getThreshold() * scaleFactor));
       thresholdValue.setEnabled(true);
-      threshline = new GraphLine((max - min) / 2f, "Threshold", Color.black);
+      threshline = new GraphLine((max - min) / 2f, "Threshold",
+              Color.black);
       threshline.value = cs.getThreshold();
     }
 
@@ -286,20 +290,28 @@ public class FeatureColourChooser extends JalviewDialog
         thresholdValue_actionPerformed();
       }
     });
+    thresholdValue.addFocusListener(new FocusAdapter()
+    {
+      @Override
+      public void focusLost(FocusEvent e)
+      {
+        thresholdValue_actionPerformed();
+      }
+    });
     slider.setPaintLabels(false);
     slider.setPaintTicks(true);
     slider.setBackground(Color.white);
     slider.setEnabled(false);
     slider.setOpaque(false);
     slider.setPreferredSize(new Dimension(100, 32));
-    slider.setToolTipText(MessageManager
-            .getString("label.adjust_threshold"));
+    slider.setToolTipText(
+            MessageManager.getString("label.adjust_threshold"));
     thresholdValue.setEnabled(false);
     thresholdValue.setColumns(7);
     jPanel3.setBackground(Color.white);
     thresholdIsMin.setBackground(Color.white);
-    thresholdIsMin.setText(MessageManager
-            .getString("label.threshold_minmax"));
+    thresholdIsMin
+            .setText(MessageManager.getString("label.threshold_minmax"));
     thresholdIsMin.setToolTipText(MessageManager
             .getString("label.toggle_absolute_relative_display_threshold"));
     thresholdIsMin.addActionListener(new ActionListener()
@@ -313,9 +325,8 @@ public class FeatureColourChooser extends JalviewDialog
     colourByLabel.setBackground(Color.white);
     colourByLabel
             .setText(MessageManager.getString("label.colour_by_label"));
-    colourByLabel
-            .setToolTipText(MessageManager
-                    .getString("label.display_features_same_type_different_label_using_different_colour"));
+    colourByLabel.setToolTipText(MessageManager.getString(
+            "label.display_features_same_type_different_label_using_different_colour"));
     colourByLabel.addActionListener(new ActionListener()
     {
       @Override
@@ -385,9 +396,9 @@ public class FeatureColourChooser extends JalviewDialog
    * feature type, and repaints the alignment, and optionally the Overview
    * and/or structure viewer if open
    * 
-   * @param updateOverview
+   * @param updateStructsAndOverview
    */
-  void changeColour(boolean updateOverview)
+  void changeColour(boolean updateStructsAndOverview)
   {
     // Check if combobox is still adjusting
     if (adjusting)
@@ -433,7 +444,8 @@ public class FeatureColourChooser extends JalviewDialog
       /*
        * todo not yet implemented: visual indication of feature threshold
        */
-      threshline = new GraphLine((max - min) / 2f, "Threshold", Color.black);
+      threshline = new GraphLine((max - min) / 2f, "Threshold",
+              Color.black);
     }
 
     if (hasThreshold)
@@ -495,7 +507,7 @@ public class FeatureColourChooser extends JalviewDialog
     }
     fr.setColour(type, acg);
     cs = acg;
-    ap.paintAlignment(updateOverview);
+    ap.paintAlignment(updateStructsAndOverview, updateStructsAndOverview);
   }
 
   @Override
@@ -527,7 +539,7 @@ public class FeatureColourChooser extends JalviewDialog
   void reset()
   {
     fr.setColour(type, oldcs);
-    ap.paintAlignment(true);
+    ap.paintAlignment(true, true);
     cs = null;
   }
 
@@ -553,7 +565,7 @@ public class FeatureColourChooser extends JalviewDialog
       /*
        * force repaint of any Overview window or structure
        */
-      ap.paintAlignment(true);
+      ap.paintAlignment(true, true);
     } catch (NumberFormatException ex)
     {
     }
@@ -596,8 +608,8 @@ public class FeatureColourChooser extends JalviewDialog
   {
     if (colourEditor != null)
     {
-      System.err
-              .println("IMPLEMENTATION ISSUE: overwriting action listener for FeatureColourChooser");
+      System.err.println(
+              "IMPLEMENTATION ISSUE: overwriting action listener for FeatureColourChooser");
     }
     colourEditor = graduatedColorEditor;
   }
index 55c4323..9c4b009 100644 (file)
@@ -41,6 +41,7 @@ import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.List;
@@ -63,8 +64,8 @@ import javax.swing.event.DocumentListener;
  * @author $author$
  * @version $Revision$
  */
-public class FeatureRenderer extends
-        jalview.renderer.seqfeatures.FeatureRenderer
+public class FeatureRenderer
+        extends jalview.renderer.seqfeatures.FeatureRenderer
 {
   /*
    * defaults for creating a new feature are the last created
@@ -234,20 +235,26 @@ public class FeatureRenderer extends
     if (!create && features.size() > 1)
     {
       /*
-       * more than one feature at selected position - add a drop-down
-       * to choose the feature to amend
+       * more than one feature at selected position - 
+       * add a drop-down to choose the feature to amend
+       * space pad text if necessary to make entries distinct
        */
       gridPanel = new JPanel(new GridLayout(4, 1));
       JPanel choosePanel = new JPanel();
-      choosePanel.add(new JLabel(MessageManager
-              .getString("label.select_feature")
-              + ":"));
-      final JComboBox<String> overlaps = new JComboBox<String>();
+      choosePanel.add(new JLabel(
+              MessageManager.getString("label.select_feature") + ":"));
+      final JComboBox<String> overlaps = new JComboBox<>();
+      List<String> added = new ArrayList<>();
       for (SequenceFeature sf : features)
       {
-        String text = sf.getType() + "/" + sf.getBegin() + "-"
-                + sf.getEnd() + " (" + sf.getFeatureGroup() + ")";
+        String text = String.format("%s/%d-%d (%s)", sf.getType(),
+                sf.getBegin(), sf.getEnd(), sf.getFeatureGroup());
+        while (added.contains(text))
+        {
+          text += " ";
+        }
         overlaps.addItem(text);
+        added.add(text);
       }
       choosePanel.add(overlaps);
 
@@ -271,14 +278,14 @@ public class FeatureRenderer extends
             highlight.addResult(sequences.get(0), sf.getBegin(),
                     sf.getEnd());
 
-            alignPanel.getSeqPanel().seqCanvas.highlightSearchResults(highlight);
-
+            alignPanel.getSeqPanel().seqCanvas.highlightSearchResults(
+                    highlight, false);
           }
           FeatureColourI col = getFeatureStyle(name.getText());
           if (col == null)
           {
-            col = new FeatureColour(ColorUtils
-                    .createColourFromName(name.getText()));
+            col = new FeatureColour(
+                    ColorUtils.createColourFromName(name.getText()));
           }
           oldcol = fcol = col;
           updateColourButton(mainPanel, colour, col);
@@ -315,9 +322,8 @@ public class FeatureRenderer extends
     mainPanel.add(gridPanel, BorderLayout.NORTH);
 
     JPanel descriptionPanel = new JPanel();
-    descriptionPanel.add(new JLabel(MessageManager
-            .getString("label.description:"),
-            JLabel.RIGHT));
+    descriptionPanel.add(new JLabel(
+            MessageManager.getString("label.description:"), JLabel.RIGHT));
     description.setFont(JvSwingUtils.getTextAreaFont());
     description.setLineWrap(true);
     descriptionPanel.add(new JScrollPane(description));
@@ -371,10 +377,11 @@ public class FeatureRenderer extends
           MessageManager.getString("action.cancel") };
     }
 
-    String title = create ? MessageManager
-            .getString("label.create_new_sequence_features")
+    String title = create
+            ? MessageManager.getString("label.create_new_sequence_features")
             : MessageManager.formatMessage("label.amend_delete_features",
-                    new String[] { sequences.get(0).getName() });
+                    new String[]
+                    { sequences.get(0).getName() });
 
     /*
      * show the dialog
@@ -386,7 +393,10 @@ public class FeatureRenderer extends
 
     FeaturesFile ffile = new FeaturesFile();
 
-    String enteredType = name.getText().trim();
+    final String enteredType = name.getText().trim();
+    final String enteredGroup = group.getText().trim();
+    final String enteredDescription = description.getText().replaceAll("\n", " ");
+
     if (reply == JvOptionPane.OK_OPTION && enteredType.length() > 0)
     {
       /*
@@ -395,7 +405,7 @@ public class FeatureRenderer extends
       if (useLastDefaults)
       {
         lastFeatureAdded = enteredType;
-        lastFeatureGroupAdded = group.getText().trim();
+        lastFeatureGroupAdded = enteredGroup;
         // TODO: determine if the null feature group is valid
         if (lastFeatureGroupAdded.length() < 1)
         {
@@ -421,26 +431,37 @@ public class FeatureRenderer extends
       {
         /*
          * YES_OPTION corresponds to the Amend button
-         * need to refresh Feature Settings if type, group or colour changed
+         * need to refresh Feature Settings if type, group or colour changed;
+         * note we don't force the feature to be visible - the user has been
+         * warned if a hidden feature type or group was entered
          */
-        sf.type = enteredType;
-        sf.featureGroup = group.getText().trim();
-        sf.description = description.getText().replaceAll("\n", " ");
-        boolean refreshSettings = (!featureType.equals(sf.type) || !featureGroup
-                .equals(sf.featureGroup));
+        boolean refreshSettings = (!featureType.equals(enteredType) || !featureGroup
+                .equals(enteredGroup));
         refreshSettings |= (fcol != oldcol);
-
-        setColour(sf.type, fcol);
-
+        setColour(enteredType, fcol);
+        int newBegin = sf.begin;
+        int newEnd = sf.end;
         try
         {
-          sf.begin = ((Integer) start.getValue()).intValue();
-          sf.end = ((Integer) end.getValue()).intValue();
+          newBegin = ((Integer) start.getValue()).intValue();
+          newEnd = ((Integer) end.getValue()).intValue();
         } catch (NumberFormatException ex)
         {
+          // JSpinner doesn't accept invalid format data :-)
         }
 
-        ffile.parseDescriptionHTML(sf, false);
+        /*
+         * replace the feature by deleting it and adding a new one
+         * (to ensure integrity of SequenceFeatures data store)
+         */
+        sequences.get(0).deleteFeature(sf);
+        SequenceFeature newSf = new SequenceFeature(sf, enteredType,
+                newBegin, newEnd, enteredGroup, sf.getScore());
+        newSf.setDescription(enteredDescription);
+        ffile.parseDescriptionHTML(newSf, false);
+        // amend features dialog only updates one sequence at a time
+        sequences.get(0).addSequenceFeature(newSf);
+
         if (refreshSettings)
         {
           featuresAdded();
@@ -455,19 +476,18 @@ public class FeatureRenderer extends
         for (int i = 0; i < sequences.size(); i++)
         {
           SequenceFeature sf = features.get(i);
-          sf.type = enteredType;
-          // fix for JAL-1538 - always set feature group here
-          sf.featureGroup = group.getText().trim();
-          sf.description = description.getText().replaceAll("\n", " ");
-          sequences.get(i).addSequenceFeature(sf);
-          ffile.parseDescriptionHTML(sf, false);
+          SequenceFeature sf2 = new SequenceFeature(enteredType,
+                  enteredDescription, sf.getBegin(), sf.getEnd(),
+                  enteredGroup);
+          ffile.parseDescriptionHTML(sf2, false);
+          sequences.get(i).addSequenceFeature(sf2);
         }
 
         setColour(enteredType, fcol);
 
         featuresAdded();
 
-        alignPanel.paintAlignment(true);
+        alignPanel.paintAlignment(true, true);
 
         return true;
       }
@@ -477,7 +497,7 @@ public class FeatureRenderer extends
       }
     }
 
-    alignPanel.paintAlignment(true);
+    alignPanel.paintAlignment(true, true);
 
     return true;
   }
@@ -514,7 +534,8 @@ public class FeatureRenderer extends
     {
       String msg = MessageManager.formatMessage("label.warning_hidden",
               MessageManager.getString("label.group"), group);
-      JvOptionPane.showMessageDialog(panel, msg, "", JvOptionPane.OK_OPTION);
+      JvOptionPane.showMessageDialog(panel, msg, "",
+              JvOptionPane.OK_OPTION);
     }
   }
 
index 34f0b4a..3f1d9c7 100644 (file)
@@ -23,7 +23,7 @@ package jalview.gui;
 import jalview.api.FeatureColourI;
 import jalview.api.FeatureSettingsControllerI;
 import jalview.bin.Cache;
-import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.AlignmentI;
 import jalview.datamodel.SequenceI;
 import jalview.gui.Help.HelpId;
 import jalview.io.JalviewFileChooser;
@@ -97,8 +97,8 @@ import javax.swing.table.AbstractTableModel;
 import javax.swing.table.TableCellEditor;
 import javax.swing.table.TableCellRenderer;
 
-public class FeatureSettings extends JPanel implements
-        FeatureSettingsControllerI
+public class FeatureSettings extends JPanel
+        implements FeatureSettingsControllerI
 {
   DasSourceBrowser dassourceBrowser;
 
@@ -131,6 +131,11 @@ public class FeatureSettings extends JPanel implements
   private static final int MIN_WIDTH = 400;
 
   private static final int MIN_HEIGHT = 400;
+  
+  /**
+   * when true, constructor is still executing - so ignore UI events
+   */
+  protected volatile boolean inConstruction = true;
 
   /**
    * Constructor
@@ -142,8 +147,8 @@ public class FeatureSettings extends JPanel implements
     this.af = af;
     fr = af.getFeatureRenderer();
     // allow transparency to be recovered
-    transparency.setMaximum(100 - (int) ((originalTransparency = fr
-            .getTransparency()) * 100));
+    transparency.setMaximum(100
+            - (int) ((originalTransparency = fr.getTransparency()) * 100));
 
     try
     {
@@ -291,17 +296,19 @@ public class FeatureSettings extends JPanel implements
     }
     frame.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
 
-    frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
-    {
-      @Override
-      public void internalFrameClosed(
-              javax.swing.event.InternalFrameEvent evt)
-      {
-        fr.removePropertyChangeListener(change);
-        dassourceBrowser.fs = null;
-      };
-    });
+    frame.addInternalFrameListener(
+            new javax.swing.event.InternalFrameAdapter()
+            {
+              @Override
+              public void internalFrameClosed(
+                      javax.swing.event.InternalFrameEvent evt)
+              {
+                fr.removePropertyChangeListener(change);
+                dassourceBrowser.fs = null;
+              };
+            });
     frame.setLayer(JLayeredPane.PALETTE_LAYER);
+    inConstruction = false;
   }
 
   protected void popupSort(final int selectedRow, final String type,
@@ -310,8 +317,9 @@ public class FeatureSettings extends JPanel implements
   {
     final FeatureColourI featureColour = (FeatureColourI) typeCol;
 
-    JPopupMenu men = new JPopupMenu(MessageManager.formatMessage(
-            "label.settings_for_param", new String[] { type }));
+    JPopupMenu men = new JPopupMenu(MessageManager
+            .formatMessage("label.settings_for_param", new String[]
+            { type }));
     JMenuItem scr = new JMenuItem(
             MessageManager.getString("label.sort_by_score"));
     men.add(scr);
@@ -322,8 +330,9 @@ public class FeatureSettings extends JPanel implements
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        me.af.avc.sortAlignmentByFeatureScore(Arrays
-                .asList(new String[] { type }));
+        me.af.avc
+                .sortAlignmentByFeatureScore(Arrays.asList(new String[]
+                { type }));
       }
 
     });
@@ -335,8 +344,9 @@ public class FeatureSettings extends JPanel implements
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        me.af.avc.sortAlignmentByFeatureDensity(Arrays
-                .asList(new String[] { type }));
+        me.af.avc
+                .sortAlignmentByFeatureDensity(Arrays.asList(new String[]
+                { type }));
       }
 
     });
@@ -406,8 +416,7 @@ public class FeatureSettings extends JPanel implements
               else
               {
                 // probably the color chooser!
-                table.setValueAt(
-                        new FeatureColour(colorChooser.getColor()),
+                table.setValueAt(new FeatureColour(colorChooser.getColor()),
                         selectedRow, 1);
                 table.validate();
                 me.updateFeatureRenderer(
@@ -431,8 +440,8 @@ public class FeatureSettings extends JPanel implements
                 false, type);
       }
     });
-    JMenuItem clearCols = new JMenuItem(
-            MessageManager.getString("label.select_columns_not_containing"));
+    JMenuItem clearCols = new JMenuItem(MessageManager
+            .getString("label.select_columns_not_containing"));
     clearCols.addActionListener(new ActionListener()
     {
       @Override
@@ -475,50 +484,26 @@ public class FeatureSettings extends JPanel implements
   private boolean handlingUpdate = false;
 
   /**
-   * contains a float[3] for each feature type string. created by setTableData
+   * holds {featureCount, totalExtent} for each feature type
    */
   Map<String, float[]> typeWidth = null;
 
   @Override
   synchronized public void discoverAllFeatureData()
   {
-    Vector<String> allFeatures = new Vector<String>();
-    Vector<String> allGroups = new Vector<String>();
-    SequenceFeature[] tmpfeatures;
-    String group;
-    for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
-    {
-      tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
-              .getSequenceFeatures();
-      if (tmpfeatures == null)
-      {
-        continue;
-      }
+    Set<String> allGroups = new HashSet<>();
+    AlignmentI alignment = af.getViewport().getAlignment();
 
-      int index = 0;
-      while (index < tmpfeatures.length)
+    for (int i = 0; i < alignment.getHeight(); i++)
+    {
+      SequenceI seq = alignment.getSequenceAt(i);
+      for (String group : seq.getFeatures().getFeatureGroups(true))
       {
-        if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
+        if (group != null && !allGroups.contains(group))
         {
-          index++;
-          continue;
-        }
-
-        if (tmpfeatures[index].getFeatureGroup() != null)
-        {
-          group = tmpfeatures[index].featureGroup;
-          if (!allGroups.contains(group))
-          {
-            allGroups.addElement(group);
-            checkGroupState(group);
-          }
+          allGroups.add(group);
+          checkGroupState(group);
         }
-
-        if (!allFeatures.contains(tmpfeatures[index].getType()))
-        {
-          allFeatures.addElement(tmpfeatures[index].getType());
-        }
-        index++;
       }
     }
 
@@ -549,19 +534,15 @@ public class FeatureSettings extends JPanel implements
     final String grp = group;
     final JCheckBox check = new JCheckBox(group, visible);
     check.setFont(new Font("Serif", Font.BOLD, 12));
+    check.setToolTipText(group);
     check.addItemListener(new ItemListener()
     {
       @Override
       public void itemStateChanged(ItemEvent evt)
       {
         fr.setGroupVisibility(check.getText(), check.isSelected());
-        af.alignPanel.getSeqPanel().seqCanvas.repaint();
-        if (af.alignPanel.overviewPanel != null)
-        {
-          af.alignPanel.overviewPanel.updateOverviewImage();
-        }
-
         resetTable(new String[] { grp });
+        af.alignPanel.paintAlignment(true, true);
       }
     });
     groupPanel.add(check);
@@ -572,79 +553,67 @@ public class FeatureSettings extends JPanel implements
 
   synchronized void resetTable(String[] groupChanged)
   {
-    if (resettingTable == true)
+    if (resettingTable)
     {
       return;
     }
     resettingTable = true;
-    typeWidth = new Hashtable<String, float[]>();
+    typeWidth = new Hashtable<>();
     // TODO: change avWidth calculation to 'per-sequence' average and use long
     // rather than float
-    float[] avWidth = null;
-    SequenceFeature[] tmpfeatures;
-    String group = null, type;
-    Vector<String> visibleChecks = new Vector<String>();
-    Set<String> foundGroups = new HashSet<String>();
-
-    // Find out which features should be visible depending on which groups
-    // are selected / deselected
-    // and recompute average width ordering
+
+    Set<String> displayableTypes = new HashSet<>();
+    Set<String> foundGroups = new HashSet<>();
+
+    /*
+     * determine which feature types may be visible depending on 
+     * which groups are selected, and recompute average width data
+     */
     for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
     {
 
-      tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
-              .getSequenceFeatures();
-      if (tmpfeatures == null)
-      {
-        continue;
-      }
+      SequenceI seq = af.getViewport().getAlignment().getSequenceAt(i);
 
-      int index = 0;
-      while (index < tmpfeatures.length)
+      /*
+       * get the sequence's groups for positional features
+       * and keep track of which groups are visible
+       */
+      Set<String> groups = seq.getFeatures().getFeatureGroups(true);
+      Set<String> visibleGroups = new HashSet<>();
+      for (String group : groups)
       {
-        group = tmpfeatures[index].featureGroup;
-        foundGroups.add(group);
-
-        if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
-        {
-          index++;
-          continue;
-        }
-
         if (group == null || checkGroupState(group))
         {
-          type = tmpfeatures[index].getType();
-          if (!visibleChecks.contains(type))
-          {
-            visibleChecks.addElement(type);
-          }
-        }
-        if (!typeWidth.containsKey(tmpfeatures[index].getType()))
-        {
-          typeWidth.put(tmpfeatures[index].getType(),
-                  avWidth = new float[3]);
-        }
-        else
-        {
-          avWidth = typeWidth.get(tmpfeatures[index].getType());
+          visibleGroups.add(group);
         }
-        avWidth[0]++;
-        if (tmpfeatures[index].getBegin() > tmpfeatures[index].getEnd())
-        {
-          avWidth[1] += 1 + tmpfeatures[index].getBegin()
-                  - tmpfeatures[index].getEnd();
-        }
-        else
+      }
+      foundGroups.addAll(groups);
+
+      /*
+       * get distinct feature types for visible groups
+       * record distinct visible types, and their count and total length
+       */
+      Set<String> types = seq.getFeatures().getFeatureTypesForGroups(true,
+              visibleGroups.toArray(new String[visibleGroups.size()]));
+      for (String type : types)
+      {
+        displayableTypes.add(type);
+        float[] avWidth = typeWidth.get(type);
+        if (avWidth == null)
         {
-          avWidth[1] += 1 + tmpfeatures[index].getEnd()
-                  - tmpfeatures[index].getBegin();
+          avWidth = new float[2];
+          typeWidth.put(type, avWidth);
         }
-        index++;
+        // todo this could include features with a non-visible group
+        // - do we greatly care?
+        // todo should we include non-displayable features here, and only
+        // update when features are added?
+        avWidth[0] += seq.getFeatures().getFeatureCount(true, type);
+        avWidth[1] += seq.getFeatures().getTotalFeatureLength(type);
       }
     }
 
-    int fSize = visibleChecks.size();
-    Object[][] data = new Object[fSize][3];
+    Object[][] data = new Object[displayableTypes.size()][3];
     int dataIndex = 0;
 
     if (fr.hasRenderOrder())
@@ -660,28 +629,29 @@ public class FeatureSettings extends JPanel implements
       List<String> frl = fr.getRenderOrder();
       for (int ro = frl.size() - 1; ro > -1; ro--)
       {
-        type = frl.get(ro);
+        String type = frl.get(ro);
 
-        if (!visibleChecks.contains(type))
+        if (!displayableTypes.contains(type))
         {
           continue;
         }
 
         data[dataIndex][0] = type;
         data[dataIndex][1] = fr.getFeatureStyle(type);
-        data[dataIndex][2] = new Boolean(af.getViewport()
-                .getFeaturesDisplayed().isVisible(type));
+        data[dataIndex][2] = new Boolean(
+                af.getViewport().getFeaturesDisplayed().isVisible(type));
         dataIndex++;
-        visibleChecks.removeElement(type);
+        displayableTypes.remove(type);
       }
     }
 
-    fSize = visibleChecks.size();
-    for (int i = 0; i < fSize; i++)
+    /*
+     * process any extra features belonging only to 
+     * a group which was just selected
+     */
+    while (!displayableTypes.isEmpty())
     {
-      // These must be extra features belonging to the group
-      // which was just selected
-      type = visibleChecks.elementAt(i).toString();
+      String type = displayableTypes.iterator().next();
       data[dataIndex][0] = type;
 
       data[dataIndex][1] = fr.getFeatureStyle(type);
@@ -694,6 +664,7 @@ public class FeatureSettings extends JPanel implements
 
       data[dataIndex][2] = new Boolean(true);
       dataIndex++;
+      displayableTypes.remove(type);
     }
 
     if (originalData == null)
@@ -712,8 +683,8 @@ public class FeatureSettings extends JPanel implements
     table.setModel(new FeatureTableModel(data));
     table.getColumnModel().getColumn(0).setPreferredWidth(200);
 
-    groupPanel.setLayout(new GridLayout(fr.getFeatureGroupsSize() / 4 + 1,
-            4));
+    groupPanel.setLayout(
+            new GridLayout(fr.getFeatureGroupsSize() / 4 + 1, 4));
     pruneGroups(foundGroups);
     groupPanel.validate();
 
@@ -834,8 +805,8 @@ public class FeatureSettings extends JPanel implements
     JalviewFileChooser chooser = new JalviewFileChooser("fc",
             "Sequence Feature Colours");
     chooser.setFileView(new JalviewFileView());
-    chooser.setDialogTitle(MessageManager
-            .getString("label.load_feature_colours"));
+    chooser.setDialogTitle(
+            MessageManager.getString("label.load_feature_colours"));
     chooser.setToolTipText(MessageManager.getString("action.load"));
 
     int value = chooser.showOpenDialog(this);
@@ -846,8 +817,8 @@ public class FeatureSettings extends JPanel implements
 
       try
       {
-        InputStreamReader in = new InputStreamReader(new FileInputStream(
-                file), "UTF-8");
+        InputStreamReader in = new InputStreamReader(
+                new FileInputStream(file), "UTF-8");
 
         JalviewUserColours jucs = JalviewUserColours.unmarshal(in);
 
@@ -926,8 +897,8 @@ public class FeatureSettings extends JPanel implements
     JalviewFileChooser chooser = new JalviewFileChooser("fc",
             "Sequence Feature Colours");
     chooser.setFileView(new JalviewFileView());
-    chooser.setDialogTitle(MessageManager
-            .getString("label.save_feature_colours"));
+    chooser.setDialogTitle(
+            MessageManager.getString("label.save_feature_colours"));
     chooser.setToolTipText(MessageManager.getString("action.save"));
 
     int value = chooser.showSaveDialog(this);
@@ -969,13 +940,13 @@ public class FeatureSettings extends JPanel implements
             col.setRGB(Format.getHexString(fcol.getMaxColour()));
             col.setMin(fcol.getMin());
             col.setMax(fcol.getMax());
-            col.setMinRGB(jalview.util.Format.getHexString(fcol
-                    .getMinColour()));
+            col.setMinRGB(
+                    jalview.util.Format.getHexString(fcol.getMinColour()));
             col.setAutoScale(fcol.isAutoScaled());
             col.setThreshold(fcol.getThreshold());
             col.setColourByLabel(fcol.isColourByLabel());
-            col.setThreshType(fcol.isAboveThreshold() ? "ABOVE" : (fcol
-                    .isBelowThreshold() ? "BELOW" : "NONE"));
+            col.setThreshType(fcol.isAboveThreshold() ? "ABOVE"
+                    : (fcol.isBelowThreshold() ? "BELOW" : "NONE"));
           }
           ucs.addColour(col);
         }
@@ -1088,7 +1059,7 @@ public class FeatureSettings extends JPanel implements
   {
     if (fr.setFeaturePriority(data, visibleNew))
     {
-      af.alignPanel.paintAlignment(true);
+      af.alignPanel.paintAlignment(true, true);
     }
   }
 
@@ -1178,8 +1149,8 @@ public class FeatureSettings extends JPanel implements
       }
     });
     sortByDens.setFont(JvSwingUtils.getLabelFont());
-    sortByDens.setText(MessageManager
-            .getString("label.sequence_sort_by_density"));
+    sortByDens.setText(
+            MessageManager.getString("label.sequence_sort_by_density"));
     sortByDens.addActionListener(new ActionListener()
     {
       @Override
@@ -1267,14 +1238,17 @@ public class FeatureSettings extends JPanel implements
       @Override
       public void stateChanged(ChangeEvent evt)
       {
-        fr.setTransparency((100 - transparency.getValue()) / 100f);
-        af.alignPanel.paintAlignment(true);
+        if (!inConstruction)
+        {
+          fr.setTransparency((100 - transparency.getValue()) / 100f);
+          af.alignPanel.paintAlignment(true,true);
+        }
       }
     });
 
     transparency.setMaximum(70);
-    transparency.setToolTipText(MessageManager
-            .getString("label.transparency_tip"));
+    transparency.setToolTipText(
+            MessageManager.getString("label.transparency_tip"));
     fetchDAS.setText(MessageManager.getString("label.fetch_das_features"));
     fetchDAS.addActionListener(new ActionListener()
     {
@@ -1484,15 +1458,10 @@ public class FeatureSettings extends JPanel implements
   public void noDasSourceActive()
   {
     complete();
-    JvOptionPane
-            .showInternalConfirmDialog(
-                    Desktop.desktop,
-                    MessageManager
-                            .getString("label.no_das_sources_selected_warn"),
-                    MessageManager
-                            .getString("label.no_das_sources_selected_title"),
-                    JvOptionPane.DEFAULT_OPTION,
-                    JvOptionPane.INFORMATION_MESSAGE);
+    JvOptionPane.showInternalConfirmDialog(Desktop.desktop,
+            MessageManager.getString("label.no_das_sources_selected_warn"),
+            MessageManager.getString("label.no_das_sources_selected_title"),
+            JvOptionPane.DEFAULT_OPTION, JvOptionPane.INFORMATION_MESSAGE);
   }
 
   // ///////////////////////////////////////////////////////////////////////
@@ -1589,9 +1558,8 @@ public class FeatureSettings extends JPanel implements
     }
 
     @Override
-    public Component getTableCellRendererComponent(JTable tbl,
-            Object color, boolean isSelected, boolean hasFocus, int row,
-            int column)
+    public Component getTableCellRendererComponent(JTable tbl, Object color,
+            boolean isSelected, boolean hasFocus, int row, int column)
     {
       FeatureColourI cellColour = (FeatureColourI) color;
       // JLabel comp = new JLabel();
@@ -1799,8 +1767,8 @@ class FeatureIcon implements Icon
   }
 }
 
-class ColorEditor extends AbstractCellEditor implements TableCellEditor,
-        ActionListener
+class ColorEditor extends AbstractCellEditor
+        implements TableCellEditor, ActionListener
 {
   FeatureSettings me;
 
index 457d871..84540f4 100755 (executable)
@@ -101,14 +101,15 @@ public class Finder extends GFinder
     frame = new JInternalFrame();
     frame.setContentPane(this);
     frame.setLayer(JLayeredPane.PALETTE_LAYER);
-    frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
-    {
-      @Override
-      public void internalFrameClosing(InternalFrameEvent e)
-      {
-        closeAction();
-      }
-    });
+    frame.addInternalFrameListener(
+            new javax.swing.event.InternalFrameAdapter()
+            {
+              @Override
+              public void internalFrameClosing(InternalFrameEvent e)
+              {
+                closeAction();
+              }
+            });
     addEscapeHandler();
     Desktop.addInternalFrame(frame, MessageManager.getString("label.find"),
             MY_WIDTH, MY_HEIGHT);
@@ -121,8 +122,8 @@ public class Finder extends GFinder
    */
   private void addEscapeHandler()
   {
-    getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
-            KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "Cancel");
+    getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
+            .put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "Cancel");
     getRootPane().getActionMap().put("Cancel", new AbstractAction()
     {
       @Override
@@ -133,7 +134,6 @@ public class Finder extends GFinder
     });
   }
 
-
   /**
    * Performs the 'Find Next' action.
    * 
@@ -223,7 +223,8 @@ public class Finder extends GFinder
     for (SearchResultMatchI match : searchResults.getResults())
     {
       seqs.add(match.getSequence().getDatasetSequence());
-      features.add(new SequenceFeature(searchString, desc, null, match
+      features.add(new SequenceFeature(searchString, desc,
+              match
               .getStart(), match.getEnd(), desc));
     }
 
@@ -315,8 +316,8 @@ public class Finder extends GFinder
       if (doFindAll)
       {
         // then we report the matches that were found
-        String message = (idMatch.size() > 0) ? "" + idMatch.size()
-                + " IDs" : "";
+        String message = (idMatch.size() > 0) ? "" + idMatch.size() + " IDs"
+                : "";
         if (searchResults != null)
         {
           if (idMatch.size() > 0 && searchResults.getSize() > 0)
index 06f29e9..f3c8e8f 100755 (executable)
@@ -126,7 +126,8 @@ public class FontChooser extends GFontChooser
     {
       oldComplementFont = ((AlignViewport) ap.av.getCodingComplement())
               .getFont();
-      oldComplementSmooth = ((AlignViewport) ap.av.getCodingComplement()).antiAlias;
+      oldComplementSmooth = ((AlignViewport) ap.av
+              .getCodingComplement()).antiAlias;
       scaleAsCdna.setVisible(true);
       scaleAsCdna.setSelected(ap.av.isScaleProteinAsCdna());
       fontAsCdna.setVisible(true);
@@ -170,9 +171,9 @@ public class FontChooser extends GFontChooser
     fontStyle.setSelectedIndex(oldFont.getStyle());
 
     FontMetrics fm = getGraphics().getFontMetrics(oldFont);
-    monospaced.setSelected(fm.getStringBounds("M", getGraphics())
-            .getWidth() == fm.getStringBounds("|", getGraphics())
-            .getWidth());
+    monospaced.setSelected(
+            fm.getStringBounds("M", getGraphics()).getWidth() == fm
+                    .getStringBounds("|", getGraphics()).getWidth());
 
     init = false;
   }
@@ -182,10 +183,11 @@ public class FontChooser extends GFontChooser
   {
     ap.av.antiAlias = smoothFont.isSelected();
     ap.getAnnotationPanel().image = null;
-    ap.paintAlignment(true);
+    ap.paintAlignment(true, false);
     if (ap.av.getCodingComplement() != null && ap.av.isProteinFontAsCdna())
     {
-      ((AlignViewport) ap.av.getCodingComplement()).antiAlias = ap.av.antiAlias;
+      ((AlignViewport) ap.av
+              .getCodingComplement()).antiAlias = ap.av.antiAlias;
       SplitFrame sv = (SplitFrame) ap.alignFrame.getSplitViewContainer();
       sv.adjustLayout();
       sv.repaint();
@@ -233,13 +235,14 @@ public class FontChooser extends GFontChooser
       ap.av.setScaleProteinAsCdna(oldProteinScale);
       ap.av.setProteinFontAsCdna(oldMirrorFont);
       ap.av.antiAlias = oldSmoothFont;
-      ap.paintAlignment(true);
+      ap.fontChanged();
 
       if (scaleAsCdna.isVisible() && scaleAsCdna.isEnabled())
       {
         ap.av.getCodingComplement().setScaleProteinAsCdna(oldProteinScale);
         ap.av.getCodingComplement().setProteinFontAsCdna(oldMirrorFont);
-        ((AlignViewport) ap.av.getCodingComplement()).antiAlias = oldComplementSmooth;
+        ((AlignViewport) ap.av
+                .getCodingComplement()).antiAlias = oldComplementSmooth;
         ap.av.getCodingComplement().setFont(oldComplementFont, true);
         SplitFrame splitFrame = (SplitFrame) ap.alignFrame
                 .getSplitViewContainer();
@@ -284,8 +287,9 @@ public class FontChooser extends GFontChooser
     double iw = iBounds.getWidth();
     if (mw < 1 || iw < 1)
     {
-      String message = iBounds.getHeight() < 1 ? MessageManager
-              .getString("label.font_doesnt_have_letters_defined")
+      String message = iBounds.getHeight() < 1
+              ? MessageManager
+                      .getString("label.font_doesnt_have_letters_defined")
               : MessageManager.getString("label.font_too_small");
       JvOptionPane.showInternalMessageDialog(this, message,
               MessageManager.getString("label.invalid_font"),
@@ -298,8 +302,8 @@ public class FontChooser extends GFontChooser
       {
         fontSize.setSelectedItem(lastSelected.getSize());
       }
-      if (!lastSelected.getName().equals(
-              fontName.getSelectedItem().toString()))
+      if (!lastSelected.getName()
+              .equals(fontName.getSelectedItem().toString()))
       {
         fontName.setSelectedItem(lastSelected.getName());
       }
@@ -323,22 +327,17 @@ public class FontChooser extends GFontChooser
       ap.fontChanged();
 
       /*
-       * adjust other half of split frame if any, if either same
-       * font, or proportionate scaling, is selected
+       * adjust other half of split frame if present, whether or not same font or
+       * scale to cDNA is selected, because a font change may affect character
+       * width, and this is kept the same in both panels
        */
-      if (fontAsCdna.isEnabled())
+      if (fontAsCdna.isVisible())
       {
         if (fontAsCdna.isSelected())
         {
-          /*
-           * copy the font
-           */
           ap.av.getCodingComplement().setFont(newFont, true);
         }
 
-        /*
-         * adjust layout for font change / reset / sizing
-         */
         SplitFrame splitFrame = (SplitFrame) ap.alignFrame
                 .getSplitViewContainer();
         splitFrame.adjustLayout();
@@ -421,8 +420,8 @@ public class FontChooser extends GFontChooser
   protected void scaleAsCdna_actionPerformed()
   {
     ap.av.setScaleProteinAsCdna(scaleAsCdna.isSelected());
-    ap.av.getCodingComplement().setScaleProteinAsCdna(
-            scaleAsCdna.isSelected());
+    ap.av.getCodingComplement()
+            .setScaleProteinAsCdna(scaleAsCdna.isSelected());
     final SplitFrame splitFrame = (SplitFrame) ap.alignFrame
             .getSplitViewContainer();
     splitFrame.adjustLayout();
index 12af734..9e0f712 100644 (file)
@@ -59,7 +59,8 @@ public class HTMLOptions extends JPanel
     bg.add(text);
 
     JOptionPane pane = new JOptionPane(null, JvOptionPane.DEFAULT_OPTION,
-            JvOptionPane.DEFAULT_OPTION, null, new Object[] { this });
+            JvOptionPane.DEFAULT_OPTION, null, new Object[]
+            { this });
 
     dialog = pane.createDialog(Desktop.desktop, "HTML Rendering options");
     dialog.setVisible(true);
index 981e94c..35bd871 100644 (file)
@@ -34,7 +34,8 @@ public interface IProgressIndicator
    * is removed with a second call with same ID.
    * 
    * @param message
-   *          - displayed message for operation
+   *          - displayed message for operation. Please ensure message is
+   *          internationalised.
    * @param id
    *          - unique handle for this indicator
    */
index 052c527..085b259 100755 (executable)
@@ -266,8 +266,8 @@ public class IdCanvas extends JPanel implements ViewportListenerI
   {
     if (av.isSeqNameItalics())
     {
-      setIdfont(new Font(av.getFont().getName(), Font.ITALIC, av.getFont()
-              .getSize()));
+      setIdfont(new Font(av.getFont().getName(), Font.ITALIC,
+              av.getFont().getSize()));
     }
     else
     {
@@ -323,9 +323,8 @@ public class IdCanvas extends JPanel implements ViewportListenerI
         currentColor = Color.black;
         currentTextColor = Color.white;
       }
-      else if ((av.getSelectionGroup() != null)
-              && av.getSelectionGroup().getSequences(null)
-                      .contains(sequence))
+      else if ((av.getSelectionGroup() != null) && av.getSelectionGroup()
+              .getSequences(null).contains(sequence))
       {
         currentColor = Color.lightGray;
         currentTextColor = Color.black;
@@ -444,7 +443,8 @@ public class IdCanvas extends JPanel implements ViewportListenerI
   void drawMarker(int i, int starty, int yoffset)
   {
 
-    SequenceI[] hseqs = av.getAlignment().getHiddenSequences().hiddenSequences;
+    SequenceI[] hseqs = av.getAlignment()
+            .getHiddenSequences().hiddenSequences;
     // Use this method here instead of calling hiddenSeq adjust
     // 3 times.
     int hSize = hseqs.length;
@@ -479,32 +479,36 @@ public class IdCanvas extends JPanel implements ViewportListenerI
     if (below)
     {
       gg.fillPolygon(
-              new int[] { getWidth() - av.getCharHeight(),
+              new int[]
+              { getWidth() - av.getCharHeight(),
                   getWidth() - av.getCharHeight(), getWidth() },
-              new int[] {
-                  (i - starty) * av.getCharHeight() + yoffset,
+              new int[]
+              { (i - starty) * av.getCharHeight() + yoffset,
                   (i - starty) * av.getCharHeight() + yoffset
                           + av.getCharHeight() / 4,
-                  (i - starty) * av.getCharHeight() + yoffset }, 3);
+                  (i - starty) * av.getCharHeight() + yoffset },
+              3);
     }
     if (above)
     {
       gg.fillPolygon(
-              new int[] { getWidth() - av.getCharHeight(),
+              new int[]
+              { getWidth() - av.getCharHeight(),
                   getWidth() - av.getCharHeight(), getWidth() },
-              new int[] {
-                  (i - starty + 1) * av.getCharHeight() + yoffset,
+              new int[]
+              { (i - starty + 1) * av.getCharHeight() + yoffset,
                   (i - starty + 1) * av.getCharHeight() + yoffset
                           - av.getCharHeight() / 4,
-                  (i - starty + 1) * av.getCharHeight() + yoffset }, 3);
+                  (i - starty + 1) * av.getCharHeight() + yoffset },
+              3);
 
     }
   }
 
   void setHiddenFont(SequenceI seq)
   {
-    Font bold = new Font(av.getFont().getName(), Font.BOLD, av.getFont()
-            .getSize());
+    Font bold = new Font(av.getFont().getName(), Font.BOLD,
+            av.getFont().getSize());
 
     if (av.isReferenceSeq(seq) || av.isHiddenRepSequence(seq))
     {
@@ -555,10 +559,19 @@ public class IdCanvas extends JPanel implements ViewportListenerI
   {
     String propertyName = evt.getPropertyName();
     if (propertyName.equals(ViewportRanges.STARTSEQ)
-            || (av.getWrapAlignment() && propertyName
-                    .equals(ViewportRanges.STARTRES)))
+            || (av.getWrapAlignment()
+                    && propertyName.equals(ViewportRanges.STARTRES)))
     {
       fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
     }
+    else if (propertyName.equals(ViewportRanges.STARTRESANDSEQ))
+    {
+      fastPaint(((int[]) evt.getNewValue())[1]
+              - ((int[]) evt.getOldValue())[1]);
+    }
+    else if (propertyName.equals(ViewportRanges.MOVE_VIEWPORT))
+    {
+      repaint();
+    }
   }
 }
index 2d24512..1f2a3ad 100755 (executable)
@@ -48,8 +48,8 @@ import javax.swing.ToolTipManager;
  * @author $author$
  * @version $Revision$
  */
-public class IdPanel extends JPanel implements MouseListener,
-        MouseMotionListener, MouseWheelListener
+public class IdPanel extends JPanel
+        implements MouseListener, MouseMotionListener, MouseWheelListener
 {
   private IdCanvas idCanvas;
 
@@ -138,7 +138,7 @@ public class IdPanel extends JPanel implements MouseListener,
     }
 
     lastid = seq;
-    alignPanel.paintAlignment(false);
+    alignPanel.paintAlignment(false, false);
   }
 
   /**
@@ -154,7 +154,7 @@ public class IdPanel extends JPanel implements MouseListener,
       {
         av.getRanges().scrollRight(true);
       }
-      else if (!av.getWrapAlignment())
+      else
       {
         av.getRanges().scrollUp(false);
       }
@@ -165,7 +165,7 @@ public class IdPanel extends JPanel implements MouseListener,
       {
         av.getRanges().scrollRight(false);
       }
-      else if (!av.getWrapAlignment())
+      else
       {
         av.getRanges().scrollUp(true);
       }
@@ -293,8 +293,8 @@ public class IdPanel extends JPanel implements MouseListener,
     }
 
     if ((av.getSelectionGroup() == null)
-            || (!jalview.util.Platform.isControlDown(e) && !e.isShiftDown() && av
-                    .getSelectionGroup() != null))
+            || (!jalview.util.Platform.isControlDown(e) && !e.isShiftDown()
+                    && av.getSelectionGroup() != null))
     {
       av.setSelectionGroup(new SequenceGroup());
       av.getSelectionGroup().setStartRes(0);
@@ -313,7 +313,7 @@ public class IdPanel extends JPanel implements MouseListener,
 
     av.isSelectionGroupChanged(true);
 
-    alignPanel.paintAlignment(false);
+    alignPanel.paintAlignment(false, false);
   }
 
   /**
@@ -325,23 +325,19 @@ public class IdPanel extends JPanel implements MouseListener,
   {
     int seq2 = alignPanel.getSeqPanel().findSeq(e);
     Sequence sq = (Sequence) av.getAlignment().getSequenceAt(seq2);
-    // build a new links menu based on the current links + any non-positional
-    // features
+
+    /*
+     *  build a new links menu based on the current links
+     *  and any non-positional features
+     */
     List<String> nlinks = Preferences.sequenceUrlLinks.getLinksForMenu();
-    SequenceFeature sfs[] = sq == null ? null : sq.getSequenceFeatures();
-    if (sfs != null)
+    for (SequenceFeature sf : sq.getFeatures().getNonPositionalFeatures())
     {
-      for (SequenceFeature sf : sfs)
+      if (sf.links != null)
       {
-        if (sf.begin == sf.end && sf.begin == 0)
+        for (String link : sf.links)
         {
-          if (sf.links != null && sf.links.size() > 0)
-          {
-            for (int l = 0, lSize = sf.links.size(); l < lSize; l++)
-            {
-              nlinks.add(sf.links.elementAt(l));
-            }
-          }
+          nlinks.add(link);
         }
       }
     }
@@ -395,8 +391,8 @@ public class IdPanel extends JPanel implements MouseListener,
 
     for (int i = start; i <= end; i++)
     {
-      av.getSelectionGroup().addSequence(
-              av.getAlignment().getSequenceAt(i), i == end);
+      av.getSelectionGroup().addSequence(av.getAlignment().getSequenceAt(i),
+              i == end);
     }
   }
 
@@ -511,7 +507,7 @@ public class IdPanel extends JPanel implements MouseListener,
           running = false;
         }
 
-        alignPanel.paintAlignment(false);
+        alignPanel.paintAlignment(false, false);
 
         try
         {
index 0c03db1..8400543 100755 (executable)
@@ -37,8 +37,8 @@ import javax.swing.JPanel;
  * @author $author$
  * @version $Revision$
  */
-public class IdwidthAdjuster extends JPanel implements MouseListener,
-        MouseMotionListener
+public class IdwidthAdjuster extends JPanel
+        implements MouseListener, MouseMotionListener
 {
   boolean active = false;
 
@@ -75,6 +75,7 @@ public class IdwidthAdjuster extends JPanel implements MouseListener,
    * @param evt
    *          DOCUMENT ME!
    */
+  @Override
   public void mousePressed(MouseEvent evt)
   {
     oldX = evt.getX();
@@ -86,6 +87,7 @@ public class IdwidthAdjuster extends JPanel implements MouseListener,
    * @param evt
    *          DOCUMENT ME!
    */
+  @Override
   public void mouseReleased(MouseEvent evt)
   {
     active = false;
@@ -112,6 +114,7 @@ public class IdwidthAdjuster extends JPanel implements MouseListener,
    * @param evt
    *          DOCUMENT ME!
    */
+  @Override
   public void mouseEntered(MouseEvent evt)
   {
     active = true;
@@ -124,6 +127,7 @@ public class IdwidthAdjuster extends JPanel implements MouseListener,
    * @param evt
    *          DOCUMENT ME!
    */
+  @Override
   public void mouseExited(MouseEvent evt)
   {
     active = false;
@@ -136,6 +140,7 @@ public class IdwidthAdjuster extends JPanel implements MouseListener,
    * @param evt
    *          DOCUMENT ME!
    */
+  @Override
   public void mouseDragged(MouseEvent evt)
   {
     active = true;
@@ -149,7 +154,7 @@ public class IdwidthAdjuster extends JPanel implements MouseListener,
     {
       viewport.setIdWidth(newWidth);
 
-      ap.paintAlignment(true);
+      ap.paintAlignment(true, false);
     }
 
     oldX = evt.getX();
@@ -161,6 +166,7 @@ public class IdwidthAdjuster extends JPanel implements MouseListener,
    * @param evt
    *          DOCUMENT ME!
    */
+  @Override
   public void mouseMoved(MouseEvent evt)
   {
   }
@@ -171,6 +177,7 @@ public class IdwidthAdjuster extends JPanel implements MouseListener,
    * @param evt
    *          DOCUMENT ME!
    */
+  @Override
   public void mouseClicked(MouseEvent evt)
   {
   }
@@ -181,6 +188,7 @@ public class IdwidthAdjuster extends JPanel implements MouseListener,
    * @param g
    *          DOCUMENT ME!
    */
+  @Override
   public void paintComponent(Graphics g)
   {
     g.setColor(Color.white);
index d92f6c0..0a6b9d6 100644 (file)
@@ -93,10 +93,8 @@ public class JDatabaseTree extends JalviewDialog implements KeyListener
   public JDatabaseTree(jalview.ws.SequenceFetcher sfetch)
   {
     mainPanel.add(this);
-    initDialogFrame(mainPanel, true, false,
-            MessageManager
-                    .getString("label.select_database_retrieval_source"),
-            650, 490);
+    initDialogFrame(mainPanel, true, false, MessageManager
+            .getString("label.select_database_retrieval_source"), 650, 490);
     /*
      * Dynamically generated database list will need a translation function from
      * internal source to externally distinct names. UNIPROT and UP_NAME are
@@ -154,8 +152,8 @@ public class JDatabaseTree extends JalviewDialog implements KeyListener
     dbviews = new JTree(new DefaultTreeModel(root, false));
     dbviews.setCellRenderer(new DbTreeRenderer(this));
 
-    dbviews.getSelectionModel().setSelectionMode(
-            TreeSelectionModel.SINGLE_TREE_SELECTION);
+    dbviews.getSelectionModel()
+            .setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
     svp = new JScrollPane(dbviews);
     svp.setMinimumSize(new Dimension(100, 200));
     svp.setPreferredSize(new Dimension(200, 400));
@@ -186,8 +184,8 @@ public class JDatabaseTree extends JalviewDialog implements KeyListener
         }
       }
     });
-    JPanel jc = new JPanel(new BorderLayout()), j = new JPanel(
-            new FlowLayout());
+    JPanel jc = new JPanel(new BorderLayout()),
+            j = new JPanel(new FlowLayout());
     jc.add(svp, BorderLayout.CENTER);
 
     java.awt.Font f;
@@ -241,9 +239,8 @@ public class JDatabaseTree extends JalviewDialog implements KeyListener
       }
       else
       {
-        throw new Error(
-                MessageManager
-                        .getString("error.implementation_error_cant_reorder_tree"));
+        throw new Error(MessageManager
+                .getString("error.implementation_error_cant_reorder_tree"));
       }
     }
     jalview.util.QuickSort.sort(names, nodes);
@@ -254,8 +251,8 @@ public class JDatabaseTree extends JalviewDialog implements KeyListener
     }
   }
 
-  private class DbTreeRenderer extends DefaultTreeCellRenderer implements
-          TreeCellRenderer
+  private class DbTreeRenderer extends DefaultTreeCellRenderer
+          implements TreeCellRenderer
   {
     JDatabaseTree us;
 
@@ -378,8 +375,8 @@ public class JDatabaseTree extends JalviewDialog implements KeyListener
     {
       for (TreePath tp : tsel)
       {
-        DefaultMutableTreeNode admt, dmt = (DefaultMutableTreeNode) tp
-                .getLastPathComponent();
+        DefaultMutableTreeNode admt,
+                dmt = (DefaultMutableTreeNode) tp.getLastPathComponent();
         if (dmt.getUserObject() != null)
         {
           /*
@@ -394,13 +391,13 @@ public class JDatabaseTree extends JalviewDialog implements KeyListener
           {
             if (allowMultiSelections)
             {
-              srcs.addAll(sfetcher.getSourceProxy((String) dmt
-                      .getUserObject()));
+              srcs.addAll(sfetcher
+                      .getSourceProxy((String) dmt.getUserObject()));
             }
             else
             {
-              srcs.add(sfetcher
-                      .getSourceProxy((String) dmt.getUserObject()).get(0));
+              srcs.add(sfetcher.getSourceProxy((String) dmt.getUserObject())
+                      .get(0));
               forcedFirstChild = true;
             }
           }
@@ -445,22 +442,26 @@ public class JDatabaseTree extends JalviewDialog implements KeyListener
     if (allowMultiSelections)
     {
       dbstatus.setText(MessageManager.formatMessage(
-              "label.selected_database_to_fetch_from", new String[] {
-                  Integer.valueOf(srcs.size()).toString(),
+              "label.selected_database_to_fetch_from", new String[]
+              { Integer.valueOf(srcs.size()).toString(),
                   (srcs.size() == 1 ? "" : "s"),
-                  (srcs.size() > 0 ? " with " + x + " test quer"
-                          + (x == 1 ? "y" : "ies") : ".") }));
+                  (srcs.size() > 0
+                          ? " with " + x + " test quer"
+                                  + (x == 1 ? "y" : "ies")
+                          : ".") }));
     }
     else
     {
       if (nm.length() > 0)
       {
-        dbstatus.setText(MessageManager.formatMessage(
-                "label.database_param", new String[] { nm }));
+        dbstatus.setText(MessageManager
+                .formatMessage("label.database_param", new String[]
+                { nm }));
         if (qr.length() > 0)
         {
-          dbstatex.setText(MessageManager.formatMessage(
-                  "label.example_param", new String[] { qr }));
+          dbstatex.setText(MessageManager
+                  .formatMessage("label.example_param", new String[]
+                  { qr }));
         }
       }
       else
index ffbe6a1..4a15024 100644 (file)
@@ -32,6 +32,7 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.GraphLine;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.RnaViewerModel;
+import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.datamodel.StructureViewerModel;
@@ -215,34 +216,6 @@ public class Jalview2XML
     }
   }
 
-  void clearSeqRefs()
-  {
-    if (_cleartables)
-    {
-      if (seqRefIds != null)
-      {
-        seqRefIds.clear();
-      }
-      if (seqsToIds != null)
-      {
-        seqsToIds.clear();
-      }
-      if (incompleteSeqs != null)
-      {
-        incompleteSeqs.clear();
-      }
-      // seqRefIds = null;
-      // seqsToIds = null;
-    }
-    else
-    {
-      // do nothing
-      warn("clearSeqRefs called when _cleartables was not set. Doing nothing.");
-      // seqRefIds = new Hashtable();
-      // seqsToIds = new IdentityHashMap();
-    }
-  }
-
   void initSeqRefs()
   {
     if (seqsToIds == null)
@@ -360,7 +333,8 @@ public class Jalview2XML
   }
 
   public SeqFref newAlcodMapRef(final String sref,
-          final AlignedCodonFrame _cf, final jalview.datamodel.Mapping _jmap)
+          final AlignedCodonFrame _cf,
+          final jalview.datamodel.Mapping _jmap)
   {
 
     SeqFref fref = new SeqFref(sref, "Codon Frame")
@@ -412,8 +386,8 @@ public class Jalview2XML
           }
         } catch (Exception x)
         {
-          System.err
-                  .println("IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "
+          System.err.println(
+                  "IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "
                           + ref.getSref());
           x.printStackTrace();
           failedtoresolve++;
@@ -436,9 +410,9 @@ public class Jalview2XML
     }
     if (incompleteSeqs != null && incompleteSeqs.size() > 0)
     {
-      System.err.println("Jalview Project Import: There are "
-              + incompleteSeqs.size()
-              + " sequences which may have incomplete metadata.");
+      System.err.println(
+              "Jalview Project Import: There are " + incompleteSeqs.size()
+                      + " sequences which may have incomplete metadata.");
       if (incompleteSeqs.size() < 10)
       {
         for (SequenceI s : incompleteSeqs.values())
@@ -448,8 +422,8 @@ public class Jalview2XML
       }
       else
       {
-        System.err
-                .println("Too many to report. Skipping output of incomplete sequences.");
+        System.err.println(
+                "Too many to report. Skipping output of incomplete sequences.");
       }
     }
   }
@@ -559,9 +533,8 @@ public class Jalview2XML
       {
         AlignFrame af = frames.get(i);
         // skip ?
-        if (skipList != null
-                && skipList
-                        .containsKey(af.getViewport().getSequenceSetId()))
+        if (skipList != null && skipList
+                .containsKey(af.getViewport().getSequenceSetId()))
         {
           continue;
         }
@@ -581,8 +554,8 @@ public class Jalview2XML
 
           saveState(apanel, fileName, jout, viewIds);
 
-          String dssid = getDatasetIdRef(af.getViewport().getAlignment()
-                  .getDataset());
+          String dssid = getDatasetIdRef(
+                  af.getViewport().getAlignment().getDataset());
           if (!dsses.containsKey(dssid))
           {
             dsses.put(dssid, af);
@@ -628,8 +601,8 @@ public class Jalview2XML
 
     if (shortName.indexOf(File.separatorChar) > -1)
     {
-      shortName = shortName.substring(shortName
-              .lastIndexOf(File.separatorChar) + 1);
+      shortName = shortName
+              .substring(shortName.lastIndexOf(File.separatorChar) + 1);
     }
 
     int count = 1;
@@ -762,8 +735,8 @@ public class Jalview2XML
     object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
 
     object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
-    object.setVersion(jalview.bin.Cache.getDefault("VERSION",
-            "Development Build"));
+    object.setVersion(
+            jalview.bin.Cache.getDefault("VERSION", "Development Build"));
 
     /**
      * rjal is full height alignment, jal is actual alignment with full metadata
@@ -856,8 +829,8 @@ public class Jalview2XML
         if (av.hasHiddenRows())
         {
           // use rjal, contains the full height alignment
-          jseq.setHidden(av.getAlignment().getHiddenSequences()
-                  .isHidden(jds));
+          jseq.setHidden(
+                  av.getAlignment().getHiddenSequences().isHidden(jds));
 
           if (av.isHiddenRepSequence(jds))
           {
@@ -882,48 +855,43 @@ public class Jalview2XML
 
       // TODO: omit sequence features from each alignment view's XML dump if we
       // are storing dataset
-      if (jds.getSequenceFeatures() != null)
+      List<jalview.datamodel.SequenceFeature> sfs = jds
+              .getSequenceFeatures();
+      for (SequenceFeature sf : sfs)
       {
-        jalview.datamodel.SequenceFeature[] sf = jds.getSequenceFeatures();
-        int index = 0;
-        while (index < sf.length)
-        {
-          Features features = new Features();
+        Features features = new Features();
 
-          features.setBegin(sf[index].getBegin());
-          features.setEnd(sf[index].getEnd());
-          features.setDescription(sf[index].getDescription());
-          features.setType(sf[index].getType());
-          features.setFeatureGroup(sf[index].getFeatureGroup());
-          features.setScore(sf[index].getScore());
-          if (sf[index].links != null)
+        features.setBegin(sf.getBegin());
+        features.setEnd(sf.getEnd());
+        features.setDescription(sf.getDescription());
+        features.setType(sf.getType());
+        features.setFeatureGroup(sf.getFeatureGroup());
+        features.setScore(sf.getScore());
+        if (sf.links != null)
+        {
+          for (int l = 0; l < sf.links.size(); l++)
           {
-            for (int l = 0; l < sf[index].links.size(); l++)
-            {
-              OtherData keyValue = new OtherData();
-              keyValue.setKey("LINK_" + l);
-              keyValue.setValue(sf[index].links.elementAt(l).toString());
-              features.addOtherData(keyValue);
-            }
+            OtherData keyValue = new OtherData();
+            keyValue.setKey("LINK_" + l);
+            keyValue.setValue(sf.links.elementAt(l).toString());
+            features.addOtherData(keyValue);
           }
-          if (sf[index].otherDetails != null)
+        }
+        if (sf.otherDetails != null)
+        {
+          String key;
+          Iterator<String> keys = sf.otherDetails.keySet().iterator();
+          while (keys.hasNext())
           {
-            String key;
-            Iterator<String> keys = sf[index].otherDetails.keySet()
-                    .iterator();
-            while (keys.hasNext())
-            {
-              key = keys.next();
-              OtherData keyValue = new OtherData();
-              keyValue.setKey(key);
-              keyValue.setValue(sf[index].otherDetails.get(key).toString());
-              features.addOtherData(keyValue);
-            }
+            key = keys.next();
+            OtherData keyValue = new OtherData();
+            keyValue.setKey(key);
+            keyValue.setValue(sf.otherDetails.get(key).toString());
+            features.addOtherData(keyValue);
           }
-
-          jseq.addFeatures(features);
-          index++;
         }
+
+        jseq.addFeatures(features);
       }
 
       if (jdatasq.getAllPDBEntries() != null)
@@ -952,8 +920,8 @@ public class Jalview2XML
             if (frames[f] instanceof StructureViewerBase)
             {
               StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
-              matchedFile = saveStructureState(ap, jds, pdb, entry,
-                      viewIds, matchedFile, viewFrame);
+              matchedFile = saveStructureState(ap, jds, pdb, entry, viewIds,
+                      matchedFile, viewFrame);
               /*
                * Only store each structure viewer's state once in the project
                * jar. First time through only (storeDS==false)
@@ -969,8 +937,8 @@ public class Jalview2XML
                           viewerState.getBytes());
                 } catch (IOException e)
                 {
-                  System.err.println("Error saving viewer state: "
-                          + e.getMessage());
+                  System.err.println(
+                          "Error saving viewer state: " + e.getMessage());
                 }
               }
             }
@@ -1042,8 +1010,8 @@ public class Jalview2XML
           {
             AlcodMap alcmap = new AlcodMap();
             alcmap.setDnasq(seqHash(dnas[m]));
-            alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
-                    false));
+            alcmap.setMapping(
+                    createVamsasMapping(pmaps[m], dnas[m], null, false));
             alc.addAlcodMap(alcmap);
             hasMap = true;
           }
@@ -1088,7 +1056,7 @@ public class Jalview2XML
 
     // SAVE TREES
     // /////////////////////////////////
-    if (!storeDS && av.currentTree != null)
+    if (!storeDS && av.getCurrentTree() != null)
     {
       // FIND ANY ASSOCIATED TREES
       // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
@@ -1106,7 +1074,7 @@ public class Jalview2XML
             {
               Tree tree = new Tree();
               tree.setTitle(tp.getTitle());
-              tree.setCurrentTree((av.currentTree == tp.getTree()));
+              tree.setCurrentTree((av.getCurrentTree() == tp.getTree()));
               tree.setNewick(tp.getTree().print());
               tree.setThreshold(tp.treeCanvas.threshold);
 
@@ -1180,16 +1148,15 @@ public class Jalview2XML
         ColourSchemeI colourScheme = sg.getColourScheme();
         if (colourScheme != null)
         {
-          ResidueShaderI groupColourScheme = sg
-                  .getGroupColourScheme();
+          ResidueShaderI groupColourScheme = sg.getGroupColourScheme();
           if (groupColourScheme.conservationApplied())
           {
             jGroup.setConsThreshold(groupColourScheme.getConservationInc());
 
             if (colourScheme instanceof jalview.schemes.UserColourScheme)
             {
-              jGroup.setColour(setUserColourScheme(colourScheme,
-                      userColours, jms));
+              jGroup.setColour(
+                      setUserColourScheme(colourScheme, userColours, jms));
             }
             else
             {
@@ -1205,8 +1172,8 @@ public class Jalview2XML
           }
           else if (colourScheme instanceof jalview.schemes.UserColourScheme)
           {
-            jGroup.setColour(setUserColourScheme(colourScheme,
-                    userColours, jms));
+            jGroup.setColour(
+                    setUserColourScheme(colourScheme, userColours, jms));
           }
           else
           {
@@ -1241,8 +1208,8 @@ public class Jalview2XML
       // /////////SAVE VIEWPORT
       Viewport view = new Viewport();
       view.setTitle(ap.alignFrame.getTitle());
-      view.setSequenceSetId(makeHashCode(av.getSequenceSetId(),
-              av.getSequenceSetId()));
+      view.setSequenceSetId(
+              makeHashCode(av.getSequenceSetId(), av.getSequenceSetId()));
       view.setId(av.getViewId());
       if (av.getCodingComplement() != null)
       {
@@ -1280,7 +1247,8 @@ public class Jalview2XML
         view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
                 userColours, jms));
       }
-      else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
+      else if (av
+              .getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
       {
         AnnotationColours ac = constructAnnotationColours(
                 (jalview.schemes.AnnotationColourGradient) av
@@ -1292,8 +1260,8 @@ public class Jalview2XML
       }
       else
       {
-        view.setBgColour(ColourSchemeProperty.getColourName(av
-                .getGlobalColourScheme()));
+        view.setBgColour(ColourSchemeProperty
+                .getColourName(av.getGlobalColourScheme()));
       }
 
       ResidueShaderI vcs = av.getResidueShading();
@@ -1368,16 +1336,16 @@ public class Jalview2XML
               setting.setAutoScale(fcol.isAutoScaled());
               setting.setThreshold(fcol.getThreshold());
               // -1 = No threshold, 0 = Below, 1 = Above
-              setting.setThreshstate(fcol.isAboveThreshold() ? 1 : (fcol
-                      .isBelowThreshold() ? 0 : -1));
+              setting.setThreshstate(fcol.isAboveThreshold() ? 1
+                      : (fcol.isBelowThreshold() ? 0 : -1));
             }
             else
             {
               setting.setColour(fcol.getColour().getRGB());
             }
 
-            setting.setDisplay(av.getFeaturesDisplayed().isVisible(
-                    featureType));
+            setting.setDisplay(
+                    av.getFeaturesDisplayed().isVisible(featureType));
             float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
                     .getOrder(featureType);
             if (rorder > -1)
@@ -1404,7 +1372,7 @@ public class Jalview2XML
           g.setName(grp);
           g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
                   .getFeatureRenderer().checkGroupVisibility(grp, false))
-                  .booleanValue());
+                          .booleanValue());
           fs.addGroup(g);
           groupsAdded.addElement(grp);
         }
@@ -1421,8 +1389,7 @@ public class Jalview2XML
         }
         else
         {
-          ArrayList<int[]> hiddenRegions = hidden
-                  .getHiddenColumnsCopy();
+          ArrayList<int[]> hiddenRegions = hidden.getHiddenColumnsCopy();
           for (int[] region : hiddenRegions)
           {
             HiddenColumns hc = new HiddenColumns();
@@ -1463,8 +1430,8 @@ public class Jalview2XML
         System.out.println("Writing jar entry " + fileName);
         JarEntry entry = new JarEntry(fileName);
         jout.putNextEntry(entry);
-        PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
-                UTF_8));
+        PrintWriter pout = new PrintWriter(
+                new OutputStreamWriter(jout, UTF_8));
         Marshaller marshaller = new Marshaller(pout);
         marshaller.marshal(object);
         pout.flush();
@@ -1665,8 +1632,8 @@ public class Jalview2XML
       final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
       final String pdbId = pdbentry.getId();
       if (!pdbId.equals(entry.getId())
-              && !(entry.getId().length() > 4 && entry.getId()
-                      .toLowerCase().startsWith(pdbId.toLowerCase())))
+              && !(entry.getId().length() > 4 && entry.getId().toLowerCase()
+                      .startsWith(pdbId.toLowerCase())))
       {
         /*
          * not interested in a binding to a different PDB entry here
@@ -1679,8 +1646,8 @@ public class Jalview2XML
       }
       else if (!matchedFile.equals(pdbentry.getFile()))
       {
-        Cache.log
-                .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
+        Cache.log.warn(
+                "Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
                         + pdbentry.getFile());
       }
       // record the
@@ -1689,7 +1656,8 @@ public class Jalview2XML
       // match is ambiguous (e.g.
       // 1QIP==1qipA)
 
-      for (int smap = 0; smap < viewFrame.getBinding().getSequence()[peid].length; smap++)
+      for (int smap = 0; smap < viewFrame.getBinding()
+              .getSequence()[peid].length; smap++)
       {
         // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
         if (jds == viewFrame.getBinding().getSequence()[peid][smap])
@@ -1733,12 +1701,13 @@ public class Jalview2XML
     ac.setAnnotation(acg.getAnnotation().annotationId);
     if (acg.getBaseColour() instanceof UserColourScheme)
     {
-      ac.setColourScheme(setUserColourScheme(acg.getBaseColour(),
-              userColours, jms));
+      ac.setColourScheme(
+              setUserColourScheme(acg.getBaseColour(), userColours, jms));
     }
     else
     {
-      ac.setColourScheme(ColourSchemeProperty.getColourName(acg.getBaseColour()));
+      ac.setColourScheme(
+              ColourSchemeProperty.getColourName(acg.getBaseColour()));
     }
 
     ac.setMaxColour(acg.getMaxColour().getRGB());
@@ -1781,11 +1750,10 @@ public class Jalview2XML
         if (groupIdr == null)
         {
           // make a locally unique String
-          groupRefs.put(
-                  annotation.groupRef,
+          groupRefs.put(annotation.groupRef,
                   groupIdr = ("" + System.currentTimeMillis()
-                          + annotation.groupRef.getName() + groupRefs
-                          .size()));
+                          + annotation.groupRef.getName()
+                          + groupRefs.size()));
         }
         an.setGroupRef(groupIdr.toString());
       }
@@ -1865,7 +1833,8 @@ public class Jalview2XML
           }
           if (annotation.annotations[a].displayCharacter != null)
           {
-            ae.setDisplayCharacter(annotation.annotations[a].displayCharacter);
+            ae.setDisplayCharacter(
+                    annotation.annotations[a].displayCharacter);
           }
 
           if (!Float.isNaN(annotation.annotations[a].value))
@@ -1876,8 +1845,8 @@ public class Jalview2XML
           ae.setPosition(a);
           if (annotation.annotations[a].secondaryStructure > ' ')
           {
-            ae.setSecondaryStructure(annotation.annotations[a].secondaryStructure
-                    + "");
+            ae.setSecondaryStructure(
+                    annotation.annotations[a].secondaryStructure + "");
           }
 
           if (annotation.annotations[a].colour != null
@@ -1939,8 +1908,8 @@ public class Jalview2XML
       // need to be able to recover 1) settings 2) user-defined presets or
       // recreate settings from preset 3) predefined settings provided by
       // service - or settings that can be transferred (or discarded)
-      vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
-              "|\\n|"));
+      vCalcIdParam.setParameters(
+              settings.getWsParamFile().replace("\n", "|\\n|"));
       vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
       // todo - decide if updateImmediately is needed for any projects.
 
@@ -2000,8 +1969,8 @@ public class Jalview2XML
       }
     }
     throw new Error(MessageManager.formatMessage(
-            "error.unsupported_version_calcIdparam",
-            new Object[] { calcIdParam.toString() }));
+            "error.unsupported_version_calcIdparam", new Object[]
+            { calcIdParam.toString() }));
   }
 
   /**
@@ -2243,8 +2212,8 @@ public class Jalview2XML
 
     for (int i = 0; i < 24; i++)
     {
-      newColours[i] = new java.awt.Color(Integer.parseInt(colours
-              .getUserColourScheme().getColour(i).getRGB(), 16));
+      newColours[i] = new java.awt.Color(Integer.parseInt(
+              colours.getUserColourScheme().getColour(i).getRGB(), 16));
     }
 
     jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
@@ -2255,8 +2224,9 @@ public class Jalview2XML
       newColours = new java.awt.Color[23];
       for (int i = 0; i < 23; i++)
       {
-        newColours[i] = new java.awt.Color(Integer.parseInt(colours
-                .getUserColourScheme().getColour(i + 24).getRGB(), 16));
+        newColours[i] = new java.awt.Color(Integer.parseInt(
+                colours.getUserColourScheme().getColour(i + 24).getRGB(),
+                16));
       }
       ucs.setLowerCaseColours(newColours);
     }
@@ -2297,6 +2267,7 @@ public class Jalview2XML
 
       jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
       af = loadJalviewAlign(jprovider);
+      af.setMenusForViewport();
 
     } catch (MalformedURLException e)
     {
@@ -2410,8 +2381,8 @@ public class Jalview2XML
           if (true) // !skipViewport(object))
           {
             _af = loadFromObject(object, file, true, jprovider);
-            if (_af != null
-                    && object.getJalviewModelSequence().getViewportCount() > 0)
+            if (_af != null && object.getJalviewModelSequence()
+                    .getViewportCount() > 0)
             {
               if (af == null)
               {
@@ -2443,8 +2414,8 @@ public class Jalview2XML
     {
       ex.printStackTrace();
       errorMessage = "Couldn't locate Jalview XML file : " + file;
-      System.err.println("Exception whilst loading jalview XML file : "
-              + ex + "\n");
+      System.err.println(
+              "Exception whilst loading jalview XML file : " + ex + "\n");
     } catch (Exception ex)
     {
       System.err.println("Parsing as Jalview Version 2 file failed.");
@@ -2473,8 +2444,8 @@ public class Jalview2XML
       }
       ex.printStackTrace();
 
-      System.err.println("Exception whilst loading jalview XML file : "
-              + ex + "\n");
+      System.err.println(
+              "Exception whilst loading jalview XML file : " + ex + "\n");
     } catch (OutOfMemoryError e)
     {
       // Don't use the OOM Window here
@@ -2500,8 +2471,9 @@ public class Jalview2XML
     {
       if (ds.getCodonFrames() != null)
       {
-        StructureSelectionManager.getStructureSelectionManager(
-                Desktop.instance).registerMappings(ds.getCodonFrames());
+        StructureSelectionManager
+                .getStructureSelectionManager(Desktop.instance)
+                .registerMappings(ds.getCodonFrames());
       }
     }
     if (errorMessage != null)
@@ -2651,12 +2623,11 @@ public class Jalview2XML
           @Override
           public void run()
           {
-            JvOptionPane
-                    .showInternalMessageDialog(Desktop.desktop,
-                            finalErrorMessage, "Error "
-                                    + (saving ? "saving" : "loading")
-                                    + " Jalview file",
-                            JvOptionPane.WARNING_MESSAGE);
+            JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                    finalErrorMessage,
+                    "Error " + (saving ? "saving" : "loading")
+                            + " Jalview file",
+                    JvOptionPane.WARNING_MESSAGE);
           }
         });
       }
@@ -2858,8 +2829,8 @@ public class Jalview2XML
           if (tmpSeq.getStart() != jseqs[i].getStart()
                   || tmpSeq.getEnd() != jseqs[i].getEnd())
           {
-            System.err
-                    .println("Warning JAL-2154 regression: updating start/end for sequence "
+            System.err.println(
+                    "Warning JAL-2154 regression: updating start/end for sequence "
                             + tmpSeq.toString() + " to " + jseqs[i]);
           }
         }
@@ -2932,7 +2903,8 @@ public class Jalview2XML
     }
     else
     {
-      boolean isdsal = object.getJalviewModelSequence().getViewportCount() == 0;
+      boolean isdsal = object.getJalviewModelSequence()
+              .getViewportCount() == 0;
       if (isdsal)
       {
         // we are importing a dataset record, so
@@ -2985,12 +2957,11 @@ public class Jalview2XML
           Features[] features = jseqs[i].getFeatures();
           for (int f = 0; f < features.length; f++)
           {
-            jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
-                    features[f].getType(), features[f].getDescription(),
-                    features[f].getStatus(), features[f].getBegin(),
-                    features[f].getEnd(), features[f].getFeatureGroup());
-
-            sf.setScore(features[f].getScore());
+            SequenceFeature sf = new SequenceFeature(features[f].getType(),
+                    features[f].getDescription(), features[f].getBegin(),
+                    features[f].getEnd(), features[f].getScore(),
+                    features[f].getFeatureGroup());
+            sf.setStatus(features[f].getStatus());
             for (int od = 0; od < features[f].getOtherDataCount(); od++)
             {
               OtherData keyValue = features[f].getOtherData(od);
@@ -3012,7 +2983,8 @@ public class Jalview2XML
         {
           // adds dbrefs to datasequence's set (since Jalview 2.10)
           addDBRefs(
-                  al.getSequenceAt(i).getDatasetSequence() == null ? al.getSequenceAt(i)
+                  al.getSequenceAt(i).getDatasetSequence() == null
+                          ? al.getSequenceAt(i)
                           : al.getSequenceAt(i).getDatasetSequence(),
                   vamsasSeq[i]);
         }
@@ -3057,8 +3029,9 @@ public class Jalview2XML
                 }
               }
             }
-            StructureSelectionManager.getStructureSelectionManager(
-                    Desktop.instance).registerPDBEntry(entry);
+            StructureSelectionManager
+                    .getStructureSelectionManager(Desktop.instance)
+                    .registerPDBEntry(entry);
             // adds PDBEntry to datasequence's set (since Jalview 2.10)
             if (al.getSequenceAt(i).getDatasetSequence() != null)
             {
@@ -3103,8 +3076,8 @@ public class Jalview2XML
               else
               {
                 // defer to later
-                frefedSequence.add(newAlcodMapRef(maps[m].getDnasq(), cf,
-                        mapping));
+                frefedSequence.add(
+                        newAlcodMapRef(maps[m].getDnasq(), cf, mapping));
               }
             }
           }
@@ -3145,9 +3118,8 @@ public class Jalview2XML
             annotation.setAutoCalculated(true);
           }
         }
-        if (autoForView
-                || (annotation.hasAutoCalculated() && annotation
-                        .isAutoCalculated()))
+        if (autoForView || (annotation.hasAutoCalculated()
+                && annotation.isAutoCalculated()))
         {
           // remove ID - we don't recover annotation from other views for
           // view-specific annotation
@@ -3189,10 +3161,12 @@ public class Jalview2XML
 
             anot[anpos] = new jalview.datamodel.Annotation(
 
-            ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
-                    (ae[aa].getSecondaryStructure() == null || ae[aa]
-                            .getSecondaryStructure().length() == 0) ? ' '
-                            : ae[aa].getSecondaryStructure().charAt(0),
+                    ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
+                    (ae[aa].getSecondaryStructure() == null
+                            || ae[aa].getSecondaryStructure().length() == 0)
+                                    ? ' '
+                                    : ae[aa].getSecondaryStructure()
+                                            .charAt(0),
                     ae[aa].getValue()
 
             );
@@ -3226,10 +3200,11 @@ public class Jalview2XML
           jaa._linecolour = firstColour;
           if (annotation.getThresholdLine() != null)
           {
-            jaa.setThreshold(new jalview.datamodel.GraphLine(annotation
-                    .getThresholdLine().getValue(), annotation
-                    .getThresholdLine().getLabel(), new java.awt.Color(
-                    annotation.getThresholdLine().getColour())));
+            jaa.setThreshold(new jalview.datamodel.GraphLine(
+                    annotation.getThresholdLine().getValue(),
+                    annotation.getThresholdLine().getLabel(),
+                    new java.awt.Color(
+                            annotation.getThresholdLine().getColour())));
 
           }
           if (autoForView || annotation.isAutoCalculated())
@@ -3360,7 +3335,8 @@ public class Jalview2XML
           }
           else
           {
-            cs = ColourSchemeProperty.getColourScheme(al, jGroup.getColour());
+            cs = ColourSchemeProperty.getColourScheme(al,
+                    jGroup.getColour());
           }
         }
         int pidThreshold = jGroup.getPidThreshold();
@@ -3387,13 +3363,15 @@ public class Jalview2XML
                 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
                 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
         sg.getGroupColourScheme().setThreshold(pidThreshold, true);
-        sg.getGroupColourScheme().setConservationInc(jGroup.getConsThreshold());
+        sg.getGroupColourScheme()
+                .setConservationInc(jGroup.getConsThreshold());
         sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
 
         sg.textColour = new java.awt.Color(jGroup.getTextCol1());
         sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
-        sg.setShowNonconserved(jGroup.hasShowUnconserved() ? jGroup
-                .isShowUnconserved() : false);
+        sg.setShowNonconserved(
+                jGroup.hasShowUnconserved() ? jGroup.isShowUnconserved()
+                        : false);
         sg.thresholdTextColour = jGroup.getTextColThreshold();
         if (jGroup.hasShowConsensusHistogram())
         {
@@ -3414,8 +3392,8 @@ public class Jalview2XML
         }
         if (jGroup.getConsThreshold() != 0)
         {
-          Conservation c = new Conservation("All", sg.getSequences(null),
-                  0, sg.getWidth() - 1);
+          Conservation c = new Conservation("All", sg.getSequences(null), 0,
+                  sg.getWidth() - 1);
           c.calculate();
           c.verdict(false, 25);
           sg.cs.setConservation(c);
@@ -3424,8 +3402,8 @@ public class Jalview2XML
         if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
         {
           // re-instate unique group/annotation row reference
-          List<AlignmentAnnotation> jaal = groupAnnotRefs.get(jGroup
-                  .getId());
+          List<AlignmentAnnotation> jaal = groupAnnotRefs
+                  .get(jGroup.getId());
           if (jaal != null)
           {
             for (AlignmentAnnotation jaa : jaal)
@@ -3471,8 +3449,8 @@ public class Jalview2XML
     // to the same sequenceSet. We must modify this id on load
     // so that each load of the file gives a unique id
     String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
-    String viewId = (view.getId() == null ? null : view.getId()
-            + uniqueSetSuffix);
+    String viewId = (view.getId() == null ? null
+            : view.getId() + uniqueSetSuffix);
     AlignFrame af = null;
     AlignViewport av = null;
     // now check to see if we really need to create a new viewport.
@@ -3485,8 +3463,8 @@ public class Jalview2XML
       // XML.
       // and then recover its containing af to allow the settings to be applied.
       // TODO: fix for vamsas demo
-      System.err
-              .println("About to recover a viewport for existing alignment: Sequence set ID is "
+      System.err.println(
+              "About to recover a viewport for existing alignment: Sequence set ID is "
                       + uniqueSeqSetId);
       Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
       if (seqsetobj != null)
@@ -3494,14 +3472,14 @@ public class Jalview2XML
         if (seqsetobj instanceof String)
         {
           uniqueSeqSetId = (String) seqsetobj;
-          System.err
-                  .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
+          System.err.println(
+                  "Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
                           + uniqueSeqSetId);
         }
         else
         {
-          System.err
-                  .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
+          System.err.println(
+                  "Warning : Collision between sequence set ID string and existing jalview object mapping.");
         }
 
       }
@@ -3510,8 +3488,8 @@ public class Jalview2XML
      * indicate that annotation colours are applied across all groups (pre
      * Jalview 2.8.1 behaviour)
      */
-    boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan(
-            "2.8.1", object.getVersion());
+    boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
+            object.getVersion());
 
     AlignmentPanel ap = null;
     boolean isnewview = true;
@@ -3586,15 +3564,15 @@ public class Jalview2XML
       for (int i = 0; i < jseq.getRnaViewerCount(); i++)
       {
         RnaViewer viewer = jseq.getRnaViewer(i);
-        AppVarna appVarna = findOrCreateVarnaViewer(viewer,
-                uniqueSetSuffix, ap);
+        AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
+                ap);
 
         for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
         {
           SecondaryStructure ss = viewer.getSecondaryStructure(j);
           SequenceI seq = seqRefIds.get(jseq.getId());
-          AlignmentAnnotation ann = this.annotationIds.get(ss
-                  .getAnnotationId());
+          AlignmentAnnotation ann = this.annotationIds
+                  .get(ss.getAnnotationId());
 
           /*
            * add the structure to the Varna display (with session state copied
@@ -3648,10 +3626,9 @@ public class Jalview2XML
     /*
      * viewer not found - make it
      */
-    RnaViewerModel model = new RnaViewerModel(postLoadId,
-            viewer.getTitle(), viewer.getXpos(), viewer.getYpos(),
-            viewer.getWidth(), viewer.getHeight(),
-            viewer.getDividerLocation());
+    RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
+            viewer.getXpos(), viewer.getYpos(), viewer.getWidth(),
+            viewer.getHeight(), viewer.getDividerLocation());
     AppVarna varna = new AppVarna(model, ap);
 
     return varna;
@@ -3695,8 +3672,8 @@ public class Jalview2XML
           // TODO: should check if tp has been manipulated by user - if so its
           // settings shouldn't be modified
           tp.setTitle(tree.getTitle());
-          tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
-                  .getWidth(), tree.getHeight()));
+          tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(),
+                  tree.getWidth(), tree.getHeight()));
           tp.av = av; // af.viewport; // TODO: verify 'associate with all
           // views'
           // works still
@@ -3716,13 +3693,13 @@ public class Jalview2XML
 
         if (tree.getFontName() != null)
         {
-          tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
-                  .getFontStyle(), tree.getFontSize()));
+          tp.setTreeFont(new java.awt.Font(tree.getFontName(),
+                  tree.getFontStyle(), tree.getFontSize()));
         }
         else
         {
-          tp.setTreeFont(new java.awt.Font(view.getFontName(), view
-                  .getFontStyle(), tree.getFontSize()));
+          tp.setTreeFont(new java.awt.Font(view.getFontName(),
+                  view.getFontStyle(), tree.getFontSize()));
         }
 
         tp.showPlaceholders(tree.getMarkUnlinked());
@@ -3793,12 +3770,12 @@ public class Jalview2XML
             // TODO: NOW: check that this recovers the PDB file correctly.
             String pdbFile = loadPDBFile(jprovider, ids[p].getId(),
                     ids[p].getFile());
-            jalview.datamodel.SequenceI seq = seqRefIds.get(jseqs[i]
-                    .getId() + "");
+            jalview.datamodel.SequenceI seq = seqRefIds
+                    .get(jseqs[i].getId() + "");
             if (sviewid == null)
             {
-              sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
-                      + "," + height;
+              sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
+                      + height;
             }
             if (!structureViewers.containsKey(sviewid))
             {
@@ -3817,8 +3794,9 @@ public class Jalview2XML
             // linkAlignPanel,superposeWithAlignpanel}} from hash
             StructureViewerModel jmoldat = structureViewers.get(sviewid);
             jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
-                    | (structureState.hasAlignwithAlignPanel() ? structureState
-                            .getAlignwithAlignPanel() : false));
+                    | (structureState.hasAlignwithAlignPanel()
+                            ? structureState.getAlignwithAlignPanel()
+                            : false));
 
             /*
              * Default colour by linked panel to false if not specified (e.g.
@@ -3826,8 +3804,9 @@ public class Jalview2XML
              */
             boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
             colourWithAlignPanel |= (structureState
-                    .hasColourwithAlignPanel() ? structureState
-                    .getColourwithAlignPanel() : false);
+                    .hasColourwithAlignPanel()
+                            ? structureState.getColourwithAlignPanel()
+                            : false);
             jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
 
             /*
@@ -3835,8 +3814,9 @@ public class Jalview2XML
              * pre-2.7 projects)
              */
             boolean colourByViewer = jmoldat.isColourByViewer();
-            colourByViewer &= structureState.hasColourByJmol() ? structureState
-                    .getColourByJmol() : true;
+            colourByViewer &= structureState.hasColourByJmol()
+                    ? structureState.getColourByJmol()
+                    : true;
             jmoldat.setColourByViewer(colourByViewer);
 
             if (jmoldat.getStateData().length() < structureState
@@ -3852,8 +3832,7 @@ public class Jalview2XML
               StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
               if (seqstrmaps == null)
               {
-                jmoldat.getFileData().put(
-                        mapkey,
+                jmoldat.getFileData().put(mapkey,
                         seqstrmaps = jmoldat.new StructureData(pdbFile,
                                 ids[p].getId()));
               }
@@ -3881,8 +3860,8 @@ public class Jalview2XML
         createOrLinkStructureViewer(entry, af, ap, jprovider);
       } catch (Exception e)
       {
-        System.err.println("Error loading structure viewer: "
-                + e.getMessage());
+        System.err.println(
+                "Error loading structure viewer: " + e.getMessage());
         // failed - try the next one
       }
     }
@@ -3974,8 +3953,8 @@ public class Jalview2XML
 
     // TODO use StructureViewer as a factory here, see JAL-1761
     final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
-    final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs
-            .size()][]);
+    final SequenceI[][] seqsArray = allseqs
+            .toArray(new SequenceI[allseqs.size()][]);
     String newViewId = viewerData.getKey();
 
     ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
@@ -4086,8 +4065,8 @@ public class Jalview2XML
        */
       histbug += 10;
       int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
-      String val = (diff == -1) ? null : newFileLoc
-              .substring(histbug, diff);
+      String val = (diff == -1) ? null
+              : newFileLoc.substring(histbug, diff);
       if (val != null && val.length() >= 4)
       {
         if (val.contains("e")) // eh? what can it be?
@@ -4105,8 +4084,8 @@ public class Jalview2XML
       }
     }
 
-    final String[] pdbf = pdbfilenames.toArray(new String[pdbfilenames
-            .size()]);
+    final String[] pdbf = pdbfilenames
+            .toArray(new String[pdbfilenames.size()]);
     final String[] id = pdbids.toArray(new String[pdbids.size()]);
     final SequenceI[][] sq = seqmaps
             .toArray(new SequenceI[seqmaps.size()][]);
@@ -4125,10 +4104,11 @@ public class Jalview2XML
           JalviewStructureDisplayI sview = null;
           try
           {
-            sview = new StructureViewer(alf.alignPanel
-                    .getStructureSelectionManager()).createView(
-                    StructureViewer.ViewerType.JMOL, pdbf, id, sq,
-                    alf.alignPanel, svattrib, fileloc, rect, sviewid);
+            sview = new StructureViewer(
+                    alf.alignPanel.getStructureSelectionManager())
+                            .createView(StructureViewer.ViewerType.JMOL,
+                                    pdbf, id, sq, alf.alignPanel, svattrib,
+                                    fileloc, rect, sviewid);
             addNewStructureViewer(sview);
           } catch (OutOfMemoryError ex)
           {
@@ -4188,9 +4168,8 @@ public class Jalview2XML
         /*
          * Post jalview 2.4 schema includes structure view id
          */
-        if (sviewid != null
-                && ((StructureViewerBase) frame).getViewId()
-                        .equals(sviewid))
+        if (sviewid != null && ((StructureViewerBase) frame).getViewId()
+                .equals(sviewid))
         {
           comp = (StructureViewerBase) frame;
           break; // break added in 2.9
@@ -4243,7 +4222,8 @@ public class Jalview2XML
       StructureData filedat = oldFiles.get(id);
       String pdbFile = filedat.getFilePath();
       SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
-      binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE);
+      binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
+              null);
       binding.addSequenceForStructFile(pdbFile, seq);
     }
     // and add the AlignmentPanel's reference to the view panel
@@ -4362,8 +4342,9 @@ public class Jalview2XML
 
     for (int i = 0; i < JSEQ.length; i++)
     {
-      af.viewport.setSequenceColour(af.viewport.getAlignment()
-              .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
+      af.viewport.setSequenceColour(
+              af.viewport.getAlignment().getSequenceAt(i),
+              new java.awt.Color(JSEQ[i].getColour()));
     }
 
     if (al.hasSeqrep())
@@ -4403,8 +4384,8 @@ public class Jalview2XML
         for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
         {
           isRepresentative = true;
-          SequenceI sequenceToHide = al.getSequenceAt(JSEQ[s]
-                  .getHiddenSequences(r));
+          SequenceI sequenceToHide = al
+                  .getSequenceAt(JSEQ[s].getHiddenSequences(r));
           hidden.addSequence(sequenceToHide, false);
           // remove from hiddenSeqs list so we don't try to hide it twice
           hiddenSeqs.remove(sequenceToHide);
@@ -4417,8 +4398,8 @@ public class Jalview2XML
         }
       }
 
-      SequenceI[] hseqs = hiddenSeqs.toArray(new SequenceI[hiddenSeqs
-              .size()]);
+      SequenceI[] hseqs = hiddenSeqs
+              .toArray(new SequenceI[hiddenSeqs.size()]);
       af.viewport.hideSequence(hseqs);
 
     }
@@ -4434,9 +4415,8 @@ public class Jalview2XML
     af.viewport.setIncrement(view.getConsThreshold());
     af.viewport.setShowJVSuffix(view.getShowFullId());
     af.viewport.setRightAlignIds(view.getRightAlignIds());
-    af.viewport.setFont(
-            new java.awt.Font(view.getFontName(), view.getFontStyle(), view
-                    .getFontSize()), true);
+    af.viewport.setFont(new java.awt.Font(view.getFontName(),
+            view.getFontStyle(), view.getFontSize()), true);
     ViewStyleI vs = af.viewport.getViewStyle();
     vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
     af.viewport.setViewStyle(vs);
@@ -4453,8 +4433,8 @@ public class Jalview2XML
     af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
     af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
     af.viewport.setThresholdTextColour(view.getTextColThreshold());
-    af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
-            .isShowUnconserved() : false);
+    af.viewport.setShowUnconserved(
+            view.hasShowUnconserved() ? view.isShowUnconserved() : false);
     af.viewport.getRanges().setStartRes(view.getStartRes());
 
     if (view.getViewName() != null)
@@ -4491,14 +4471,14 @@ public class Jalview2XML
     af.viewport.setGlobalColourScheme(cs);
     af.viewport.getResidueShading().setThreshold(view.getPidThreshold(),
             view.getIgnoreGapsinConsensus());
-    af.viewport.getResidueShading().setConsensus(
-            af.viewport.getSequenceConsensusHash());
+    af.viewport.getResidueShading()
+            .setConsensus(af.viewport.getSequenceConsensusHash());
     af.viewport.setColourAppliesToAllGroups(false);
 
     if (view.getConservationSelected() && cs != null)
     {
-      af.viewport.getResidueShading().setConservationInc(
-              view.getConsThreshold());
+      af.viewport.getResidueShading()
+              .setConservationInc(view.getConsThreshold());
     }
 
     af.changeColour(cs);
@@ -4526,8 +4506,8 @@ public class Jalview2XML
     }
     if (view.hasShowConsensusHistogram())
     {
-      af.viewport.setShowConsensusHistogram(view
-              .getShowConsensusHistogram());
+      af.viewport
+              .setShowConsensusHistogram(view.getShowConsensusHistogram());
     }
     else
     {
@@ -4580,17 +4560,18 @@ public class Jalview2XML
       Map<String, FeatureColourI> featureColours = new Hashtable<>();
       Map<String, Float> featureOrder = new Hashtable<>();
 
-      for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
+      for (int fs = 0; fs < jms.getFeatureSettings()
+              .getSettingCount(); fs++)
       {
         Setting setting = jms.getFeatureSettings().getSetting(fs);
         if (setting.hasMincolour())
         {
-          FeatureColourI gc = setting.hasMin() ? new FeatureColour(
-                  new Color(setting.getMincolour()), new Color(
-                          setting.getColour()), setting.getMin(),
-                  setting.getMax()) : new FeatureColour(new Color(
-                  setting.getMincolour()), new Color(setting.getColour()),
-                  0, 1);
+          FeatureColourI gc = setting.hasMin()
+                  ? new FeatureColour(new Color(setting.getMincolour()),
+                          new Color(setting.getColour()), setting.getMin(),
+                          setting.getMax())
+                  : new FeatureColour(new Color(setting.getMincolour()),
+                          new Color(setting.getColour()), 0, 1);
           if (setting.hasThreshold())
           {
             gc.setThreshold(setting.getThreshold());
@@ -4619,8 +4600,8 @@ public class Jalview2XML
         }
         else
         {
-          featureColours.put(setting.getType(), new FeatureColour(
-                  new Color(setting.getColour())));
+          featureColours.put(setting.getType(),
+                  new FeatureColour(new Color(setting.getColour())));
         }
         renderOrder[fs] = setting.getType();
         if (setting.hasOrder())
@@ -4629,8 +4610,8 @@ public class Jalview2XML
         }
         else
         {
-          featureOrder.put(setting.getType(), new Float(fs
-                  / jms.getFeatureSettings().getSettingCount()));
+          featureOrder.put(setting.getType(), new Float(
+                  fs / jms.getFeatureSettings().getSettingCount()));
         }
         if (setting.getDisplay())
         {
@@ -4646,8 +4627,8 @@ public class Jalview2XML
       // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
       // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
       // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
-      FeatureRendererSettings frs = new FeatureRendererSettings(
-              renderOrder, fgtable, featureColours, 1.0f, featureOrder);
+      FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
+              fgtable, featureColours, 1.0f, featureOrder);
       af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
               .transferSettings(frs);
 
@@ -4657,9 +4638,9 @@ public class Jalview2XML
     {
       for (int c = 0; c < view.getHiddenColumnsCount(); c++)
       {
-        af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
-                .getHiddenColumns(c).getEnd() // +1
-                );
+        af.viewport.hideColumns(view.getHiddenColumns(c).getStart(),
+                view.getHiddenColumns(c).getEnd() // +1
+        );
       }
     }
     if (view.getCalcIdParam() != null)
@@ -4744,7 +4725,8 @@ public class Jalview2XML
     /*
      * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
      */
-    if (matchedAnnotation == null && annAlignment.getAlignmentAnnotation() != null)
+    if (matchedAnnotation == null
+            && annAlignment.getAlignmentAnnotation() != null)
     {
       for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
       {
@@ -4764,22 +4746,22 @@ public class Jalview2XML
     }
     if (matchedAnnotation.getThreshold() == null)
     {
-      matchedAnnotation.setThreshold(new GraphLine(viewAnnColour.getThreshold(),
-              "Threshold", Color.black));
+      matchedAnnotation.setThreshold(new GraphLine(
+              viewAnnColour.getThreshold(), "Threshold", Color.black));
     }
 
     AnnotationColourGradient cs = null;
     if (viewAnnColour.getColourScheme().equals("None"))
     {
-      cs = new AnnotationColourGradient(matchedAnnotation, new Color(
-              viewAnnColour.getMinColour()), new Color(
-              viewAnnColour.getMaxColour()),
+      cs = new AnnotationColourGradient(matchedAnnotation,
+              new Color(viewAnnColour.getMinColour()),
+              new Color(viewAnnColour.getMaxColour()),
               viewAnnColour.getAboveThreshold());
     }
     else if (viewAnnColour.getColourScheme().startsWith("ucs"))
     {
-      cs = new AnnotationColourGradient(matchedAnnotation, getUserColourScheme(
-              jms, viewAnnColour.getColourScheme()),
+      cs = new AnnotationColourGradient(matchedAnnotation,
+              getUserColourScheme(jms, viewAnnColour.getColourScheme()),
               viewAnnColour.getAboveThreshold());
     }
     else
@@ -4838,8 +4820,9 @@ public class Jalview2XML
       for (JvAnnotRow auan : autoAlan)
       {
         visan.put(auan.template.label
-                + (auan.template.getCalcId() == null ? "" : "\t"
-                        + auan.template.getCalcId()), auan);
+                + (auan.template.getCalcId() == null ? ""
+                        : "\t" + auan.template.getCalcId()),
+                auan);
       }
       int hSize = al.getAlignmentAnnotation().length;
       List<JvAnnotRow> reorder = new ArrayList<>();
@@ -4942,8 +4925,9 @@ public class Jalview2XML
       return false;
     }
     String id;
-    if (skipList.containsKey(id = object.getJalviewModelSequence()
-            .getViewport()[0].getSequenceSetId()))
+    if (skipList.containsKey(
+            id = object.getJalviewModelSequence().getViewport()[0]
+                    .getSequenceSetId()))
     {
       if (Cache.log != null && Cache.log.isDebugEnabled())
       {
@@ -4975,8 +4959,8 @@ public class Jalview2XML
   private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
           boolean ignoreUnrefed)
   {
-    jalview.datamodel.AlignmentI ds = getDatasetFor(vamsasSet
-            .getDatasetId());
+    jalview.datamodel.AlignmentI ds = getDatasetFor(
+            vamsasSet.getDatasetId());
     Vector dseqs = null;
     if (ds == null)
     {
@@ -5125,8 +5109,8 @@ public class Jalview2XML
         }
         // TODO: merges will never happen if we 'know' we have the real dataset
         // sequence - this should be detected when id==dssid
-        System.err
-                .println("DEBUG Notice:  Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
+        System.err.println(
+                "DEBUG Notice:  Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
         // + (pre ? "prepended" : "") + " "
         // + (post ? "appended" : ""));
       }
@@ -5232,8 +5216,9 @@ public class Jalview2XML
     {
       DBRef dr = sequence.getDBRef(d);
       jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
-              sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
-                      .getVersion(), sequence.getDBRef(d).getAccessionId());
+              sequence.getDBRef(d).getSource(),
+              sequence.getDBRef(d).getVersion(),
+              sequence.getDBRef(d).getAccessionId());
       if (dr.getMapping() != null)
       {
         entry.setMap(addMapping(dr.getMapping()));
@@ -5262,8 +5247,8 @@ public class Jalview2XML
       fto[_i] = mf.getStart();
       fto[_i + 1] = mf.getEnd();
     }
-    jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
-            fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
+    jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
+            fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
     if (m.getMappingChoice() != null)
     {
       MappingChoice mc = m.getMappingChoice();
@@ -5299,8 +5284,8 @@ public class Jalview2XML
         }
         else
         {
-          System.err
-                  .println("Warning - making up dataset sequence id for DbRef sequence map reference");
+          System.err.println(
+                  "Warning - making up dataset sequence id for DbRef sequence map reference");
           sqid = ((Object) ms).toString(); // make up a new hascode for
           // undefined dataset sequence hash
           // (unlikely to happen)
@@ -5330,28 +5315,25 @@ public class Jalview2XML
 
   }
 
-  public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
-          boolean keepSeqRefs)
+  /**
+   * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
+   * view as XML (but not to file), and then reloading it
+   * 
+   * @param ap
+   * @return
+   */
+  public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
   {
     initSeqRefs();
     JalviewModel jm = saveState(ap, null, null, null);
 
-    if (!keepSeqRefs)
-    {
-      clearSeqRefs();
-      jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
-    }
-    else
-    {
-      uniqueSetSuffix = "";
-      jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
-      // overwrite the
-      // view we just
-      // copied
-    }
+    uniqueSetSuffix = "";
+    jm.getJalviewModelSequence().getViewport(0).setId(null);
+    // we don't overwrite the view we just copied
+
     if (this.frefedSequence == null)
     {
-      frefedSequence = new Vector();
+      frefedSequence = new Vector<SeqFref>();
     }
 
     viewportsAdded.clear();
@@ -5371,32 +5353,8 @@ public class Jalview2XML
     return af.alignPanel;
   }
 
-  /**
-   * flag indicating if hashtables should be cleared on finalization TODO this
-   * flag may not be necessary
-   */
-  private final boolean _cleartables = true;
-
   private Hashtable jvids2vobj;
 
-  /*
-   * (non-Javadoc)
-   * 
-   * @see java.lang.Object#finalize()
-   */
-  @Override
-  protected void finalize() throws Throwable
-  {
-    // really make sure we have no buried refs left.
-    if (_cleartables)
-    {
-      clearSeqRefs();
-    }
-    this.seqRefIds = null;
-    this.seqsToIds = null;
-    super.finalize();
-  }
-
   private void warn(String msg)
   {
     warn(msg, null);
index 8d71ccf..331e738 100755 (executable)
@@ -36,6 +36,7 @@ import jalview.binding.Tree;
 import jalview.binding.UserColours;
 import jalview.binding.Viewport;
 import jalview.datamodel.PDBEntry;
+import jalview.datamodel.SequenceFeature;
 import jalview.io.FileFormat;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ColourSchemeProperty;
@@ -93,8 +94,8 @@ public class Jalview2XML_V1
 
     for (int i = 0; i < csize; i++)
     {
-      newColours[i] = new java.awt.Color(Integer.parseInt(colours
-              .getUserColourScheme().getColour(i).getRGB(), 16));
+      newColours[i] = new java.awt.Color(Integer.parseInt(
+              colours.getUserColourScheme().getColour(i).getRGB(), 16));
     }
 
     return new jalview.schemes.UserColourScheme(newColours);
@@ -152,12 +153,13 @@ public class Jalview2XML_V1
           public void run()
           {
 
-            System.err.println("Couldn't locate Jalview XML file : " + ex
-                    + "\n");
+            System.err.println(
+                    "Couldn't locate Jalview XML file : " + ex + "\n");
             JvOptionPane.showInternalMessageDialog(Desktop.desktop,
                     MessageManager.formatMessage("label.couldnt_locate",
-                            new String[] { file }), MessageManager
-                            .getString("label.url_not_found"),
+                            new String[]
+                            { file }),
+                    MessageManager.getString("label.url_not_found"),
                     JvOptionPane.WARNING_MESSAGE);
           }
         });
@@ -178,7 +180,8 @@ public class Jalview2XML_V1
             JvOptionPane.showInternalMessageDialog(Desktop.desktop,
                     MessageManager.formatMessage(
                             "label.error_loading_file_params", new String[]
-                            { file }), MessageManager
+                            { file }),
+                    MessageManager
                             .getString("label.error_loading_jalview_file"),
                     JvOptionPane.WARNING_MESSAGE);
           }
@@ -224,11 +227,10 @@ public class Jalview2XML_V1
         Features[] features = JSEQ[i].getFeatures();
         for (int f = 0; f < features.length; f++)
         {
-          jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
-                  features[f].getType(), features[f].getDescription(),
-                  features[f].getStatus(), features[f].getBegin(),
+          SequenceFeature sf = new SequenceFeature(features[f].getType(),
+                  features[f].getDescription(), features[f].getBegin(),
                   features[f].getEnd(), null);
-
+          sf.setStatus(features[f].getStatus());
           al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf);
         }
       }
@@ -251,8 +253,9 @@ public class Jalview2XML_V1
             }
           }
           al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
-          StructureSelectionManager.getStructureSelectionManager(
-                  Desktop.instance).registerPDBEntry(entry);
+          StructureSelectionManager
+                  .getStructureSelectionManager(Desktop.instance)
+                  .registerPDBEntry(entry);
         }
 
       }
@@ -308,8 +311,9 @@ public class Jalview2XML_V1
 
     for (int i = 0; i < JSEQ.length; i++)
     {
-      af.viewport.setSequenceColour(af.viewport.getAlignment()
-              .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
+      af.viewport.setSequenceColour(
+              af.viewport.getAlignment().getSequenceAt(i),
+              new java.awt.Color(JSEQ[i].getColour()));
     }
 
     // af.changeColour() );
@@ -331,7 +335,8 @@ public class Jalview2XML_V1
           }
           else
           {
-            cs = ColourSchemeProperty.getColourScheme(al, groups[i].getColour());
+            cs = ColourSchemeProperty.getColourScheme(al,
+                    groups[i].getColour());
           }
         }
         int pidThreshold = groups[i].getPidThreshold();
@@ -350,12 +355,13 @@ public class Jalview2XML_V1
                 groups[i].getStart(), groups[i].getEnd());
         sg.getGroupColourScheme().setThreshold(pidThreshold, true);
 
-        sg.setOutlineColour(new java.awt.Color(groups[i].getOutlineColour()));
+        sg.setOutlineColour(
+                new java.awt.Color(groups[i].getOutlineColour()));
 
         if (groups[i].getConsThreshold() != 0)
         {
-          Conservation c = new Conservation("All", sg.getSequences(null),
-                  0, sg.getWidth() - 1);
+          Conservation c = new Conservation("All", sg.getSequences(null), 0,
+                  sg.getWidth() - 1);
           c.calculate();
           c.verdict(false, 25);
           sg.cs.setConservation(c);
@@ -374,9 +380,8 @@ public class Jalview2XML_V1
     af.viewport.setColourText(view.getShowColourText());
     af.viewport.setConservationSelected(view.getConservationSelected());
     af.viewport.setShowJVSuffix(view.getShowFullId());
-    af.viewport.setFont(
-            new java.awt.Font(view.getFontName(), view.getFontStyle(), view
-                    .getFontSize()), true);
+    af.viewport.setFont(new java.awt.Font(view.getFontName(),
+            view.getFontStyle(), view.getFontSize()), true);
 
     af.viewport.setRenderGaps(view.getRenderGaps());
     af.viewport.setWrapAlignment(view.getWrapAlignment());
@@ -405,17 +410,17 @@ public class Jalview2XML_V1
       // }
     }
 
-    af.viewport.getResidueShading().setThreshold(
-            view.getPidThreshold(), true);
-    af.viewport.getResidueShading().setConsensus(
-            af.viewport.getSequenceConsensusHash());
+    af.viewport.getResidueShading().setThreshold(view.getPidThreshold(),
+            true);
+    af.viewport.getResidueShading()
+            .setConsensus(af.viewport.getSequenceConsensusHash());
     af.viewport.setColourAppliesToAllGroups(false);
     af.alignPanel.updateLayout();
     af.changeColour(cs);
     if (view.getConservationSelected() && cs != null)
     {
-      af.viewport.getResidueShading().setConservationInc(
-              view.getConsThreshold());
+      af.viewport.getResidueShading()
+              .setConservationInc(view.getConsThreshold());
     }
 
     af.viewport.setColourAppliesToAllGroups(true);
@@ -427,7 +432,8 @@ public class Jalview2XML_V1
       Hashtable featureColours = new Hashtable();
       String[] renderOrder = new String[jms.getFeatureSettings()
               .getSettingCount()];
-      for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
+      for (int fs = 0; fs < jms.getFeatureSettings()
+              .getSettingCount(); fs++)
       {
         Setting setting = jms.getFeatureSettings().getSetting(fs);
 
@@ -442,8 +448,8 @@ public class Jalview2XML_V1
                   new Integer(setting.getColour()));
         }
       }
-      FeatureRendererSettings frs = new FeatureRendererSettings(
-              renderOrder, new Hashtable(), featureColours, 1.0f, null);
+      FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
+              new Hashtable(), featureColours, 1.0f, null);
       af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
               .transferSettings(frs);
     }
@@ -474,13 +480,13 @@ public class Jalview2XML_V1
 
           if (tree.getFontName() != null)
           {
-            tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
-                    .getFontStyle(), tree.getFontSize()));
+            tp.setTreeFont(new java.awt.Font(tree.getFontName(),
+                    tree.getFontStyle(), tree.getFontSize()));
           }
           else
           {
-            tp.setTreeFont(new java.awt.Font(view.getFontName(), view
-                    .getFontStyle(), tree.getFontSize()));
+            tp.setTreeFont(new java.awt.Font(view.getFontName(),
+                    view.getFontStyle(), tree.getFontSize()));
           }
 
           tp.showPlaceholders(tree.getMarkUnlinked());
index c9b35d8..2f11c30 100644 (file)
@@ -114,8 +114,8 @@ public class JalviewChimeraBindingModel extends JalviewChimeraBinding
   protected void sendAsynchronousCommand(final String command,
           final String progressMsg)
   {
-    final long handle = progressMsg == null ? 0 : cvf
-            .startProgressBar(progressMsg);
+    final long handle = progressMsg == null ? 0
+            : cvf.startProgressBar(progressMsg);
     SwingUtilities.invokeLater(new Runnable()
     {
       @Override
index 539f3c2..7b2e430 100644 (file)
@@ -41,16 +41,18 @@ public class JvOptionPane extends JOptionPane
   public static int showConfirmDialog(Component parentComponent,
           Object message) throws HeadlessException
   {
-    return isInteractiveMode() ? JOptionPane.showConfirmDialog(
-            parentComponent, message) : (int) getMockResponse();
+    return isInteractiveMode()
+            ? JOptionPane.showConfirmDialog(parentComponent, message)
+            : (int) getMockResponse();
   }
 
   public static int showConfirmDialog(Component parentComponent,
           Object message, String title, int optionType)
           throws HeadlessException
   {
-    return isInteractiveMode() ? JOptionPane.showConfirmDialog(
-            parentComponent, message, title, optionType)
+    return isInteractiveMode()
+            ? JOptionPane.showConfirmDialog(parentComponent, message, title,
+                    optionType)
             : (int) getMockResponse();
   }
 
@@ -58,8 +60,9 @@ public class JvOptionPane extends JOptionPane
           Object message, String title, int optionType, int messageType)
           throws HeadlessException
   {
-    return isInteractiveMode() ? JOptionPane.showConfirmDialog(
-            parentComponent, message, title, optionType, messageType)
+    return isInteractiveMode()
+            ? JOptionPane.showConfirmDialog(parentComponent, message, title,
+                    optionType, messageType)
             : (int) getMockResponse();
   }
 
@@ -67,31 +70,36 @@ public class JvOptionPane extends JOptionPane
           Object message, String title, int optionType, int messageType,
           Icon icon) throws HeadlessException
   {
-    return isInteractiveMode() ? JOptionPane.showConfirmDialog(
-            parentComponent, message, title, optionType, messageType, icon)
+    return isInteractiveMode()
+            ? JOptionPane.showConfirmDialog(parentComponent, message, title,
+                    optionType, messageType, icon)
             : (int) getMockResponse();
   }
 
   public static int showInternalConfirmDialog(Component parentComponent,
           Object message)
   {
-    return isInteractiveMode() ? JOptionPane.showInternalConfirmDialog(
-            parentComponent, message) : (int) getMockResponse();
+    return isInteractiveMode()
+            ? JOptionPane.showInternalConfirmDialog(parentComponent,
+                    message)
+            : (int) getMockResponse();
   }
 
   public static int showInternalConfirmDialog(Component parentComponent,
           Object message, String title, int optionType)
   {
-    return isInteractiveMode() ? JOptionPane.showConfirmDialog(
-            parentComponent, message, title, optionType)
+    return isInteractiveMode()
+            ? JOptionPane.showConfirmDialog(parentComponent, message, title,
+                    optionType)
             : (int) getMockResponse();
   }
 
   public static int showInternalConfirmDialog(Component parentComponent,
           Object message, String title, int optionType, int messageType)
   {
-    return isInteractiveMode() ? JOptionPane.showConfirmDialog(
-            parentComponent, message, title, optionType, messageType)
+    return isInteractiveMode()
+            ? JOptionPane.showConfirmDialog(parentComponent, message, title,
+                    optionType, messageType)
             : (int) getMockResponse();
   }
 
@@ -99,8 +107,9 @@ public class JvOptionPane extends JOptionPane
           Object message, String title, int optionType, int messageType,
           Icon icon)
   {
-    return isInteractiveMode() ? JOptionPane.showInternalConfirmDialog(
-            parentComponent, message, title, optionType, messageType, icon)
+    return isInteractiveMode()
+            ? JOptionPane.showInternalConfirmDialog(parentComponent,
+                    message, title, optionType, messageType, icon)
             : (int) getMockResponse();
   }
 
@@ -109,9 +118,10 @@ public class JvOptionPane extends JOptionPane
           Icon icon, Object[] options, Object initialValue)
           throws HeadlessException
   {
-    return isInteractiveMode() ? JOptionPane.showOptionDialog(
-            parentComponent, message, title, optionType, messageType, icon,
-            options, initialValue) : (int) getMockResponse();
+    return isInteractiveMode()
+            ? JOptionPane.showOptionDialog(parentComponent, message, title,
+                    optionType, messageType, icon, options, initialValue)
+            : (int) getMockResponse();
   }
 
   public static void showMessageDialog(Component parentComponent,
@@ -208,22 +218,25 @@ public class JvOptionPane extends JOptionPane
   public static String showInputDialog(Object message,
           Object initialSelectionValue)
   {
-    return isInteractiveMode() ? JOptionPane.showInputDialog(message,
-            initialSelectionValue) : getMockResponse().toString();
+    return isInteractiveMode()
+            ? JOptionPane.showInputDialog(message, initialSelectionValue)
+            : getMockResponse().toString();
   }
 
   public static String showInputDialog(Component parentComponent,
           Object message) throws HeadlessException
   {
-    return isInteractiveMode() ? JOptionPane.showInputDialog(
-            parentComponent, message) : getMockResponse().toString();
+    return isInteractiveMode()
+            ? JOptionPane.showInputDialog(parentComponent, message)
+            : getMockResponse().toString();
   }
 
   public static String showInputDialog(Component parentComponent,
           Object message, Object initialSelectionValue)
   {
-    return isInteractiveMode() ? JOptionPane.showInputDialog(
-            parentComponent, message, initialSelectionValue)
+    return isInteractiveMode()
+            ? JOptionPane.showInputDialog(parentComponent, message,
+                    initialSelectionValue)
             : getMockResponse().toString();
   }
 
@@ -231,8 +244,9 @@ public class JvOptionPane extends JOptionPane
           Object message, String title, int messageType)
           throws HeadlessException
   {
-    return isInteractiveMode() ? JOptionPane.showInputDialog(
-            parentComponent, message, title, messageType)
+    return isInteractiveMode()
+            ? JOptionPane.showInputDialog(parentComponent, message, title,
+                    messageType)
             : getMockResponse().toString();
   }
 
@@ -241,24 +255,27 @@ public class JvOptionPane extends JOptionPane
           Object[] selectionValues, Object initialSelectionValue)
           throws HeadlessException
   {
-    return isInteractiveMode() ? JOptionPane.showInputDialog(
-            parentComponent, message, title, messageType, icon,
-            selectionValues, initialSelectionValue) : getMockResponse()
-            .toString();
+    return isInteractiveMode()
+            ? JOptionPane.showInputDialog(parentComponent, message, title,
+                    messageType, icon, selectionValues,
+                    initialSelectionValue)
+            : getMockResponse().toString();
   }
 
   public static String showInternalInputDialog(Component parentComponent,
           Object message)
   {
-    return isInteractiveMode() ? JOptionPane.showInternalInputDialog(
-            parentComponent, message) : getMockResponse().toString();
+    return isInteractiveMode()
+            ? JOptionPane.showInternalInputDialog(parentComponent, message)
+            : getMockResponse().toString();
   }
 
   public static String showInternalInputDialog(Component parentComponent,
           Object message, String title, int messageType)
   {
-    return isInteractiveMode() ? JOptionPane.showInternalInputDialog(
-            parentComponent, message, title, messageType)
+    return isInteractiveMode()
+            ? JOptionPane.showInternalInputDialog(parentComponent, message,
+                    title, messageType)
             : getMockResponse().toString();
   }
 
@@ -266,10 +283,11 @@ public class JvOptionPane extends JOptionPane
           Object message, String title, int messageType, Icon icon,
           Object[] selectionValues, Object initialSelectionValue)
   {
-    return isInteractiveMode() ? JOptionPane.showInternalInputDialog(
-            parentComponent, message, title, messageType, icon,
-            selectionValues, initialSelectionValue) : getMockResponse()
-            .toString();
+    return isInteractiveMode()
+            ? JOptionPane.showInternalInputDialog(parentComponent, message,
+                    title, messageType, icon, selectionValues,
+                    initialSelectionValue)
+            : getMockResponse().toString();
   }
 
   private static void outputMessage(Object message)
index 052c314..0a765cb 100644 (file)
@@ -60,7 +60,8 @@ public final class JvSwingUtils
    */
   public static String wrapTooltip(boolean enclose, String ttext)
   {
-    Objects.requireNonNull(ttext, "Tootip text to format must not be null!");
+    Objects.requireNonNull(ttext,
+            "Tootip text to format must not be null!");
     ttext = ttext.trim();
     boolean maxLengthExceeded = false;
 
@@ -119,8 +120,8 @@ public final class JvSwingUtils
     for (int i = 0, iSize = menu.getMenuComponentCount(); i < iSize; i++)
     {
       if (menu.getMenuComponent(i) instanceof JMenu
-              && ((JMenu) menu.getMenuComponent(i)).getText().equals(
-                      submenu))
+              && ((JMenu) menu.getMenuComponent(i)).getText()
+                      .equals(submenu))
       {
         submenuinstance = (JMenu) menu.getMenuComponent(i);
       }
@@ -198,8 +199,10 @@ public final class JvSwingUtils
 
   public static Font getLabelFont(boolean bold, boolean italic)
   {
-    return new java.awt.Font("Verdana", (!bold && !italic) ? Font.PLAIN
-            : (bold ? Font.BOLD : 0) + (italic ? Font.ITALIC : 0), 11);
+    return new java.awt.Font("Verdana",
+            (!bold && !italic) ? Font.PLAIN
+                    : (bold ? Font.BOLD : 0) + (italic ? Font.ITALIC : 0),
+            11);
   }
 
   /**
@@ -275,8 +278,8 @@ public final class JvSwingUtils
      * of possible positions.
      */
     float fraction = proportion
-            * (scrollbar.getMaximum() - scrollbar.getMinimum() - scrollbar
-                    .getModel().getExtent())
+            * (scrollbar.getMaximum() - scrollbar.getMinimum()
+                    - scrollbar.getModel().getExtent())
             + (scrollbar.getModel().getExtent() / 2f);
     return Math.min(Math.round(fraction), scrollbar.getMaximum());
   }
index f519b85..7b9da79 100644 (file)
@@ -56,8 +56,8 @@ public class OOMWarning implements Runnable
       {
         if (jalview.bin.Cache.log != null)
         {
-          jalview.bin.Cache.log
-                  .error("Out of Memory when " + action, oomex);
+          jalview.bin.Cache.log.error("Out of Memory when " + action,
+                  oomex);
         }
         else
         {
@@ -78,12 +78,10 @@ public class OOMWarning implements Runnable
   @Override
   public void run()
   {
-    JvOptionPane
-            .showInternalMessageDialog(desktop,
-            MessageManager.formatMessage("warn.out_of_memory_when_action",
-                    new String[] { action }), MessageManager
-                    .getString("label.out_of_memory"),
-                    JvOptionPane.WARNING_MESSAGE);
+    JvOptionPane.showInternalMessageDialog(desktop, MessageManager
+            .formatMessage("warn.out_of_memory_when_action", new String[]
+            { action }), MessageManager.getString("label.out_of_memory"),
+            JvOptionPane.WARNING_MESSAGE);
     // hope that there's enough memory left that no more appear.
     oomInprogress = false;
   }
index e584eb7..5342c90 100644 (file)
@@ -76,8 +76,8 @@ public class OptsAndParamsPage
    */
   boolean compact = false;
 
-  public class OptionBox extends JPanel implements MouseListener,
-          ActionListener
+  public class OptionBox extends JPanel
+          implements MouseListener, ActionListener
   {
     JCheckBox enabled = new JCheckBox();
 
@@ -110,21 +110,20 @@ public class OptsAndParamsPage
       {
         hasLink = true;
 
-        enabled.setToolTipText(JvSwingUtils
-                .wrapTooltip(
-                        true,
-                        ((desc == null || desc.trim().length() == 0) ? MessageManager
-                                .getString("label.opt_and_params_further_details")
-                                : desc)
-                                + "<br><img src=\"" + linkImageURL + "\"/>"));
+        enabled.setToolTipText(JvSwingUtils.wrapTooltip(true,
+                ((desc == null || desc.trim().length() == 0)
+                        ? MessageManager.getString(
+                                "label.opt_and_params_further_details")
+                        : desc) + "<br><img src=\"" + linkImageURL
+                        + "\"/>"));
         enabled.addMouseListener(this);
       }
       else
       {
         if (desc != null && desc.trim().length() > 0)
         {
-          enabled.setToolTipText(JvSwingUtils.wrapTooltip(true,
-                  opt.getDescription()));
+          enabled.setToolTipText(
+                  JvSwingUtils.wrapTooltip(true, opt.getDescription()));
         }
       }
       add(enabled, BorderLayout.NORTH);
@@ -271,8 +270,8 @@ public class OptsAndParamsPage
 
   }
 
-  public class ParamBox extends JPanel implements ChangeListener,
-          ActionListener, MouseListener
+  public class ParamBox extends JPanel
+          implements ChangeListener, ActionListener, MouseListener
   {
     boolean adjusting = false;
 
@@ -308,7 +307,8 @@ public class OptsAndParamsPage
 
     JTextField valueField = null;
 
-    public ParamBox(final OptsParametersContainerI pmlayout, ParameterI parm)
+    public ParamBox(final OptsParametersContainerI pmlayout,
+            ParameterI parm)
     {
       pmdialogbox = pmlayout;
       finfo = parm.getFurtherDetails();
@@ -349,20 +349,16 @@ public class OptsAndParamsPage
               && parm.getDescription().trim().length() > 0)
       {
         // Only create description boxes if there actually is a description.
-        ttipText = (JvSwingUtils
-                .wrapTooltip(
-                        true,
-                        parm.getDescription()
-                                + (finfo != null ? "<br><img src=\""
-                                        + linkImageURL
-                                        + "\"/>"
-                                        + MessageManager
-                                                .getString("label.opt_and_params_further_details")
-                                        : "")));
-      }
-
-      JvSwingUtils.mgAddtoLayout(this, ttipText,
-              new JLabel(parm.getName()), controlPanel, "");
+        ttipText = (JvSwingUtils.wrapTooltip(true,
+                parm.getDescription() + (finfo != null ? "<br><img src=\""
+                        + linkImageURL + "\"/>"
+                        + MessageManager.getString(
+                                "label.opt_and_params_further_details")
+                        : "")));
+      }
+
+      JvSwingUtils.mgAddtoLayout(this, ttipText, new JLabel(parm.getName()),
+              controlPanel, "");
       updateControls(parm);
       validate();
     }
@@ -399,21 +395,18 @@ public class OptsAndParamsPage
         // Only create description boxes if there actually is a description.
         if (finfo != null)
         {
-          showDesc.setToolTipText(JvSwingUtils.wrapTooltip(
-                  true,
-                  MessageManager
-                          .formatMessage(
-                                  "label.opt_and_params_show_brief_desc_image_link",
-                                  new String[] { linkImageURL
-                                          .toExternalForm() })));
+          showDesc.setToolTipText(JvSwingUtils.wrapTooltip(true,
+                  MessageManager.formatMessage(
+                          "label.opt_and_params_show_brief_desc_image_link",
+                          new String[]
+                          { linkImageURL.toExternalForm() })));
           showDesc.addMouseListener(this);
         }
         else
         {
-          showDesc.setToolTipText(JvSwingUtils.wrapTooltip(
-                  true,
-                  MessageManager
-                          .getString("label.opt_and_params_show_brief_desc")));
+          showDesc.setToolTipText(
+                  JvSwingUtils.wrapTooltip(true, MessageManager.getString(
+                          "label.opt_and_params_show_brief_desc")));
         }
         showDesc.addActionListener(new ActionListener()
         {
@@ -578,9 +571,8 @@ public class OptsAndParamsPage
     {
       if (!adjusting)
       {
-        valueField.setText(""
-                + ((integ) ? ("" + slider.getValue()) : ("" + slider
-                        .getValue() / 1000f)));
+        valueField.setText("" + ((integ) ? ("" + slider.getValue())
+                : ("" + slider.getValue() / 1000f)));
         checkIfModified();
       }
 
@@ -790,8 +782,9 @@ public class OptsAndParamsPage
   {
 
     JPopupMenu mnu = new JPopupMenu();
-    JMenuItem mitem = new JMenuItem(MessageManager.formatMessage(
-            "label.view_params", new String[] { finfo }));
+    JMenuItem mitem = new JMenuItem(
+            MessageManager.formatMessage("label.view_params", new String[]
+            { finfo }));
     mitem.addActionListener(new ActionListener()
     {
 
@@ -878,8 +871,8 @@ public class OptsAndParamsPage
       else
       {
         throw new Error(MessageManager.formatMessage(
-                "error.invalid_value_for_option", new String[] { string,
-                    option.getName() }));
+                "error.invalid_value_for_option", new String[]
+                { string, option.getName() }));
       }
 
     }
index 27f9c3f..2991889 100644 (file)
@@ -21,7 +21,9 @@
 package jalview.gui;
 
 import jalview.api.AlignViewportI;
+import jalview.bin.Cache;
 import jalview.renderer.OverviewRenderer;
+import jalview.renderer.OverviewResColourFinder;
 import jalview.viewmodel.OverviewDimensions;
 
 import java.awt.Color;
@@ -41,6 +43,8 @@ public class OverviewCanvas extends JComponent
 
   private volatile boolean updaterunning = false;
 
+  private boolean dispose = false;
+
   private BufferedImage miniMe;
 
   private BufferedImage lastMiniMe = null;
@@ -57,16 +61,29 @@ public class OverviewCanvas extends JComponent
 
   private AlignViewportI av;
 
+  private OverviewResColourFinder cf;
+
+  private ProgressPanel progressPanel;
+
   public OverviewCanvas(OverviewDimensions overviewDims,
-          AlignViewportI alignvp)
+          AlignViewportI alignvp, ProgressPanel pp)
   {
     od = overviewDims;
     av = alignvp;
+    progressPanel = pp;
 
     sr = new SequenceRenderer(av);
     sr.renderGaps = false;
-    sr.forOverview = true;
     fr = new jalview.renderer.seqfeatures.FeatureRenderer(av);
+
+    boolean useLegacy = Cache.getDefault(Preferences.USE_LEGACY_GAP, false);
+    Color gapCol = Cache.getDefaultColour(Preferences.GAP_COLOUR,
+            jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_GAP);
+    Color hiddenCol = Cache.getDefaultColour(Preferences.HIDDEN_COLOUR,
+            jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_HIDDEN);
+    cf = new OverviewResColourFinder(useLegacy, gapCol, hiddenCol);
+
+    setSize(od.getWidth(), od.getHeight());
   }
 
   /**
@@ -126,7 +143,11 @@ public class OverviewCanvas extends JComponent
 
     setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
 
-    or = new OverviewRenderer(sr, fr, od);
+    or = new OverviewRenderer(fr, od, av.getAlignment(),
+            av.getResidueShading(), cf);
+
+    or.addPropertyChangeListener(progressPanel);
+
     miniMe = or.draw(od.getRows(av.getAlignment()),
             od.getColumns(av.getAlignment()));
 
@@ -142,10 +163,15 @@ public class OverviewCanvas extends JComponent
     }
     System.gc();
 
+    or.removePropertyChangeListener(progressPanel);
+    or = null;
     if (restart)
     {
       restart = false;
-      draw(showSequenceFeatures, showAnnotation, transferRenderer);
+      if (!dispose)
+      {
+        draw(showSequenceFeatures, showAnnotation, transferRenderer);
+      }
     }
     else
     {
@@ -157,6 +183,8 @@ public class OverviewCanvas extends JComponent
   @Override
   public void paintComponent(Graphics g)
   {
+    // super.paintComponent(g);
+
     if (restart)
     {
       if (lastMiniMe == null)
@@ -173,16 +201,71 @@ public class OverviewCanvas extends JComponent
     }
     else if (lastMiniMe != null)
     {
-      g.drawImage(lastMiniMe, 0, 0, this);
-      if (lastMiniMe != miniMe)
+      // is this a resize?
+      if ((getWidth() > 0) && (getHeight() > 0)
+              && ((getWidth() != od.getWidth())
+                      || (getHeight() != od.getHeight())))
       {
-        g.setColor(TRANS_GREY);
-        g.fillRect(0, 0, getWidth(), getHeight());
+        // if there is annotation, scale the alignment and annotation
+        // separately
+        if (od.getGraphHeight() > 0)
+        {
+          BufferedImage topImage = lastMiniMe.getSubimage(0, 0,
+                  od.getWidth(), od.getSequencesHeight());
+          BufferedImage bottomImage = lastMiniMe.getSubimage(0,
+                  od.getSequencesHeight(), od.getWidth(),
+                  od.getGraphHeight());
+
+          // must be done at this point as we rely on using old width/height
+          // above, and new width/height below
+          od.setWidth(getWidth());
+          od.setHeight(getHeight());
+
+          // stick the images back together so lastMiniMe is consistent in the
+          // event of a repaint - BUT probably not thread safe
+          lastMiniMe = new BufferedImage(od.getWidth(), od.getHeight(),
+                  BufferedImage.TYPE_INT_RGB);
+          Graphics lg = lastMiniMe.getGraphics();
+          lg.drawImage(topImage, 0, 0, od.getWidth(),
+                  od.getSequencesHeight(), null);
+          lg.drawImage(bottomImage, 0, od.getSequencesHeight(),
+                  od.getWidth(), od.getGraphHeight(), this);
+          lg.dispose();
+        }
+        else
+        {
+          od.setWidth(getWidth());
+          od.setHeight(getHeight());
+        }
+
+        // make sure the box is in the right place
+        od.setBoxPosition(av.getAlignment().getHiddenSequences(),
+                av.getAlignment().getHiddenColumns());
       }
+      // fall back to normal behaviour
+      g.drawImage(lastMiniMe, 0, 0, getWidth(), getHeight(), this);
     }
-
+    else
+    {
+      g.drawImage(lastMiniMe, 0, 0, getWidth(), getHeight(), this);
+    }
+    
+    // draw the box
     g.setColor(Color.red);
     od.drawBox(g);
   }
 
+
+  public void dispose()
+  {
+    dispose = true;
+    synchronized (this)
+    {
+      restart = true;
+      if (or != null)
+      {
+        or.setRedraw(true);
+      }
+    }
+  }
 }
index c81ac2f..43b4310 100755 (executable)
@@ -20,6 +20,8 @@
  */
 package jalview.gui;
 
+import jalview.bin.Cache;
+import jalview.renderer.OverviewRenderer;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
 import jalview.viewmodel.OverviewDimensions;
@@ -38,8 +40,10 @@ import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseMotionAdapter;
 import java.beans.PropertyChangeEvent;
+import java.beans.PropertyVetoException;
 
 import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JInternalFrame;
 import javax.swing.JPanel;
 import javax.swing.JPopupMenu;
 import javax.swing.SwingUtilities;
@@ -51,8 +55,8 @@ import javax.swing.SwingUtilities;
  * @author $author$
  * @version $Revision$
  */
-public class OverviewPanel extends JPanel implements Runnable,
-        ViewportListenerI
+public class OverviewPanel extends JPanel
+        implements Runnable, ViewportListenerI
 {
   private OverviewDimensions od;
 
@@ -68,6 +72,8 @@ public class OverviewPanel extends JPanel implements Runnable,
 
   private boolean draggingBox = false;
 
+  private ProgressPanel progressPanel;
+
   /**
    * Creates a new OverviewPanel object.
    * 
@@ -79,30 +85,62 @@ public class OverviewPanel extends JPanel implements Runnable,
     this.av = alPanel.av;
     this.ap = alPanel;
 
-    od = new OverviewDimensionsShowHidden(av.getRanges(),
-            (av.isShowAnnotation() && av
-                    .getAlignmentConservationAnnotation() != null));
-
-    setSize(od.getWidth(), od.getHeight());
+    showHidden = Cache.getDefault(Preferences.SHOW_OV_HIDDEN_AT_START,
+            true);
+    if (showHidden)
+    {
+      od = new OverviewDimensionsShowHidden(av.getRanges(),
+            (av.isShowAnnotation()
+                    && av.getAlignmentConservationAnnotation() != null));
+    }
+    else
+    {
+      od = new OverviewDimensionsHideHidden(av.getRanges(),
+              (av.isShowAnnotation()
+                      && av.getAlignmentConservationAnnotation() != null));
+    }
 
-    oviewCanvas = new OverviewCanvas(od, av);
     setLayout(new BorderLayout());
+    progressPanel = new ProgressPanel(OverviewRenderer.UPDATE,
+            MessageManager.getString("label.oview_calc"), getWidth());
+    this.add(progressPanel, BorderLayout.SOUTH);
+    oviewCanvas = new OverviewCanvas(od, av, progressPanel);
+
     add(oviewCanvas, BorderLayout.CENTER);
 
     av.getRanges().addPropertyChangeListener(this);
 
+    // without this the overview window does not size to fit the overview canvas
+    setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
+
     addComponentListener(new ComponentAdapter()
     {
       @Override
       public void componentResized(ComponentEvent evt)
       {
-        if ((getWidth() != od.getWidth())
-                || (getHeight() != (od.getHeight())))
+        // Resize is called on the initial display of the overview.
+        // This code adjusts sizes to account for the progress bar if it has not
+        // already been accounted for, which triggers another resize call for
+        // the correct sizing, at which point the overview image is updated.
+        // (This avoids a double recalculation of the image.)
+        if (getWidth() == od.getWidth() && getHeight() == od.getHeight()
+                + progressPanel.getHeight())
         {
           updateOverviewImage();
-          setBoxPosition();
+        }
+        else
+        {
+          if ((getWidth() > 0) && (getHeight() > 0))
+          {
+            od.setWidth(getWidth());
+            od.setHeight(getHeight() - progressPanel.getHeight());
+          }
+
+          setPreferredSize(new Dimension(od.getWidth(),
+                  od.getHeight() + progressPanel.getHeight()));
         }
       }
+
     });
 
     addMouseMotionListener(new MouseMotionAdapter()
@@ -116,15 +154,15 @@ public class OverviewPanel extends JPanel implements Runnable,
           {
             // set the mouse position as a fixed point in the box
             // and drag relative to that position
-            od.adjustViewportFromMouse(evt.getX(),
-                    evt.getY(), av.getAlignment().getHiddenSequences(),
+            od.adjustViewportFromMouse(evt.getX(), evt.getY(),
+                    av.getAlignment().getHiddenSequences(),
                     av.getAlignment().getHiddenColumns());
           }
           else
           {
-            od.updateViewportFromMouse(evt.getX(), evt.getY(), av
-                  .getAlignment().getHiddenSequences(), av.getAlignment()
-                  .getHiddenColumns());
+            od.updateViewportFromMouse(evt.getX(), evt.getY(),
+                    av.getAlignment().getHiddenSequences(),
+                    av.getAlignment().getHiddenColumns());
           }
         }
       }
@@ -158,13 +196,13 @@ public class OverviewPanel extends JPanel implements Runnable,
           }
         }
         else
-        // if (!av.getWrapAlignment())
         {
+          // don't do anything if the mouse press is in the overview's box
+          // (wait to see if it's a drag instead)
+          // otherwise update the viewport
           if (!od.isPositionInBox(evt.getX(), evt.getY()))
           {
-            // don't do anything if the mouse press is in the overview's box
-            // (wait to see if it's a drag instead)
-            // otherwise update the viewport
+            draggingBox = false;
             od.updateViewportFromMouse(evt.getX(), evt.getY(),
                     av.getAlignment().getHiddenSequences(),
                     av.getAlignment().getHiddenColumns());
@@ -180,15 +218,6 @@ public class OverviewPanel extends JPanel implements Runnable,
       }
 
       @Override
-      public void mouseReleased(MouseEvent evt)
-      {
-        if (draggingBox)
-        {
-          draggingBox = false;
-        }
-      }
-
-      @Override
       public void mouseClicked(MouseEvent evt)
       {
         if (SwingUtilities.isRightMouseButton(evt))
@@ -197,8 +226,6 @@ public class OverviewPanel extends JPanel implements Runnable,
         }
       }
     });
-
-    updateOverviewImage();
   }
 
   /*
@@ -235,15 +262,15 @@ public class OverviewPanel extends JPanel implements Runnable,
     {
       showHidden = false;
       od = new OverviewDimensionsHideHidden(av.getRanges(),
-              (av.isShowAnnotation() && av
-                      .getAlignmentConservationAnnotation() != null));
+              (av.isShowAnnotation()
+                      && av.getAlignmentConservationAnnotation() != null));
     }
     else
     {
       showHidden = true;
       od = new OverviewDimensionsShowHidden(av.getRanges(),
-              (av.isShowAnnotation() && av
-                      .getAlignmentConservationAnnotation() != null));
+              (av.isShowAnnotation()
+                      && av.getAlignmentConservationAnnotation() != null));
     }
     oviewCanvas.resetOviewDims(od);
     updateOverviewImage();
@@ -266,10 +293,11 @@ public class OverviewPanel extends JPanel implements Runnable,
     if ((getWidth() > 0) && (getHeight() > 0))
     {
       od.setWidth(getWidth());
-      od.setHeight(getHeight());
+      od.setHeight(getHeight() - progressPanel.getHeight());
     }
     
-    setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
+    setPreferredSize(new Dimension(od.getWidth(),
+            od.getHeight() + progressPanel.getHeight()));
 
     if (oviewCanvas.restartDraw())
     {
@@ -279,16 +307,21 @@ public class OverviewPanel extends JPanel implements Runnable,
     Thread thread = new Thread(this);
     thread.start();
     repaint();
+
+    
   }
 
   @Override
   public void run()
   {
-    oviewCanvas.draw(av.isShowSequenceFeatures(),
-            (av.isShowAnnotation() && av
-                    .getAlignmentConservationAnnotation() != null), ap
-                    .getSeqPanel().seqCanvas.getFeatureRenderer());
-    setBoxPosition();
+    if (oviewCanvas != null)
+    {
+      oviewCanvas.draw(av.isShowSequenceFeatures(),
+              (av.isShowAnnotation()
+                      && av.getAlignmentConservationAnnotation() != null),
+              ap.getSeqPanel().seqCanvas.getFeatureRenderer());
+      setBoxPosition();
+    }
   }
 
   /**
@@ -296,17 +329,36 @@ public class OverviewPanel extends JPanel implements Runnable,
    * changed
    * 
    */
+  private void setBoxPositionOnly()
+  {
+    if (od != null)
+    {
+      int oldX = od.getBoxX();
+      int oldY = od.getBoxY();
+      int oldWidth = od.getBoxWidth();
+      int oldHeight = od.getBoxHeight();
+      od.setBoxPosition(av.getAlignment().getHiddenSequences(),
+              av.getAlignment().getHiddenColumns());
+      repaint(oldX - 1, oldY - 1, oldWidth + 2, oldHeight + 2);
+      repaint(od.getBoxX(), od.getBoxY(), od.getBoxWidth(),
+              od.getBoxHeight());
+    }
+  }
+
   private void setBoxPosition()
   {
-    od.setBoxPosition(av.getAlignment().getHiddenSequences(), av
-            .getAlignment().getHiddenColumns());
-    repaint();
+    if (od != null)
+    {
+      od.setBoxPosition(av.getAlignment().getHiddenSequences(),
+              av.getAlignment().getHiddenColumns());
+      repaint();
+    }
   }
 
   @Override
   public void propertyChange(PropertyChangeEvent evt)
   {
-    setBoxPosition();
+    setBoxPositionOnly();
   }
 
   /**
@@ -316,9 +368,25 @@ public class OverviewPanel extends JPanel implements Runnable,
   {
     try
     {
-      av.getRanges().removePropertyChangeListener(this);
+      if (av != null)
+      {
+        av.getRanges().removePropertyChangeListener(this);
+      }
+
+      oviewCanvas.dispose();
+
+      /*
+       * close the parent frame (which also removes it from the
+       * Desktop Windows menu)
+       */
+      ((JInternalFrame) SwingUtilities.getAncestorOfClass(
+              JInternalFrame.class, (this))).setClosed(true);
+    } catch (PropertyVetoException e)
+    {
+      // ignore
     } finally
     {
+      progressPanel = null;
       av = null;
       oviewCanvas = null;
       ap = null;
index d8e6b06..9f52d26 100644 (file)
@@ -59,8 +59,8 @@ import javax.swing.event.InternalFrameEvent;
  * @author $author$
  * @version $Revision$
  */
-public class PCAPanel extends GPCAPanel implements Runnable,
-        IProgressIndicator
+public class PCAPanel extends GPCAPanel
+        implements Runnable, IProgressIndicator
 {
 
   private IProgressIndicator progressBar;
@@ -79,6 +79,8 @@ public class PCAPanel extends GPCAPanel implements Runnable,
 
   int top = 0;
 
+  private boolean working;
+
   /**
    * Creates a new PCAPanel object using default score model and parameters
    * 
@@ -86,9 +88,12 @@ public class PCAPanel extends GPCAPanel implements Runnable,
    */
   public PCAPanel(AlignmentPanel alignPanel)
   {
-    this(alignPanel, ScoreModels.getInstance()
-            .getDefaultModel(!alignPanel.av.getAlignment().isNucleotide())
-            .getName(), SimilarityParams.SeqSpace);
+    this(alignPanel,
+            ScoreModels.getInstance()
+                    .getDefaultModel(
+                            !alignPanel.av.getAlignment().isNucleotide())
+                    .getName(),
+            SimilarityParams.SeqSpace);
   }
 
   /**
@@ -131,8 +136,8 @@ public class PCAPanel extends GPCAPanel implements Runnable,
       seqs = av.getSelectionGroup().getSequencesInOrder(av.getAlignment());
     }
 
-    ScoreModelI scoreModel = ScoreModels.getInstance().getScoreModel(
-            modelName, ap);
+    ScoreModelI scoreModel = ScoreModels.getInstance()
+            .getScoreModel(modelName, ap);
     pcaModel = new PCAModel(seqstrings, seqs, nucleotide, scoreModel,
             params);
     PaintRefresher.Register(this, av.getSequenceSetId());
@@ -189,8 +194,8 @@ public class PCAPanel extends GPCAPanel implements Runnable,
           {
             if (!pcaModel.getScoreModelName().equals(name))
             {
-              ScoreModelI sm2 = ScoreModels.getInstance().getScoreModel(
-                      name, ap);
+              ScoreModelI sm2 = ScoreModels.getInstance()
+                      .getScoreModel(name, ap);
               pcaModel.setScoreModel(sm2);
               Thread worker = new Thread(PCAPanel.this);
               worker.start();
@@ -231,6 +236,7 @@ public class PCAPanel extends GPCAPanel implements Runnable,
       message = MessageManager.getString("label.pca_calculating");
     }
     progress.setProgressBar(message, progId);
+    working = true;
     try
     {
       calcSettings.setEnabled(false);
@@ -249,6 +255,7 @@ public class PCAPanel extends GPCAPanel implements Runnable,
     } catch (OutOfMemoryError er)
     {
       new OOMWarning("calculating PCA", er);
+      working = false;
       return;
     } finally
     {
@@ -263,6 +270,7 @@ public class PCAPanel extends GPCAPanel implements Runnable,
               .getString("label.principal_component_analysis"), 475, 450);
       this.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
     }
+    working = false;
   }
 
   @Override
@@ -271,8 +279,8 @@ public class PCAPanel extends GPCAPanel implements Runnable,
     if (!pcaModel.isNucleotide())
     {
       pcaModel.setNucleotide(true);
-      pcaModel.setScoreModel(ScoreModels.getInstance().getDefaultModel(
-              false));
+      pcaModel.setScoreModel(
+              ScoreModels.getInstance().getDefaultModel(false));
       Thread worker = new Thread(this);
       worker.start();
     }
@@ -286,8 +294,8 @@ public class PCAPanel extends GPCAPanel implements Runnable,
     if (pcaModel.isNucleotide())
     {
       pcaModel.setNucleotide(false);
-      pcaModel.setScoreModel(ScoreModels.getInstance()
-              .getDefaultModel(true));
+      pcaModel.setScoreModel(
+              ScoreModels.getInstance().getDefaultModel(true));
       Thread worker = new Thread(this);
       worker.start();
     }
@@ -385,8 +393,8 @@ public class PCAPanel extends GPCAPanel implements Runnable,
     // make this an abstract function of all jalview analysis windows
     if (pcaModel.getSeqtrings() == null)
     {
-      jalview.bin.Cache.log
-              .info("Unexpected call to originalSeqData_actionPerformed - should have hidden this menu action.");
+      jalview.bin.Cache.log.info(
+              "Unexpected call to originalSeqData_actionPerformed - should have hidden this menu action.");
       return;
     }
     // decide if av alignment is sufficiently different to original data to
@@ -413,8 +421,9 @@ public class PCAPanel extends GPCAPanel implements Runnable,
       // AlignmentOrder origorder = new AlignmentOrder(alAndColsel[0]);
 
       AlignmentI al = new Alignment((SequenceI[]) alAndColsel[0]);
-      AlignmentI dataset = (av != null && av.getAlignment() != null) ? av
-              .getAlignment().getDataset() : null;
+      AlignmentI dataset = (av != null && av.getAlignment() != null)
+              ? av.getAlignment().getDataset()
+              : null;
       if (dataset != null)
       {
         al.setDataset(dataset);
@@ -424,8 +433,7 @@ public class PCAPanel extends GPCAPanel implements Runnable,
       {
         // make a new frame!
         AlignFrame af = new AlignFrame(al, (HiddenColumns) alAndColsel[1],
-                AlignFrame.DEFAULT_WIDTH,
-                AlignFrame.DEFAULT_HEIGHT);
+                AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
 
         // >>>This is a fix for the moment, until a better solution is
         // found!!<<<
@@ -435,8 +443,8 @@ public class PCAPanel extends GPCAPanel implements Runnable,
         // msaorder);
 
         Desktop.addInternalFrame(af, MessageManager.formatMessage(
-                "label.original_data_for_params",
-                new String[] { this.title }), AlignFrame.DEFAULT_WIDTH,
+                "label.original_data_for_params", new String[]
+                { this.title }), AlignFrame.DEFAULT_WIDTH,
                 AlignFrame.DEFAULT_HEIGHT);
       }
     }
@@ -567,8 +575,8 @@ public class PCAPanel extends GPCAPanel implements Runnable,
 
   void buildAssociatedViewMenu()
   {
-    AlignmentPanel[] aps = PaintRefresher.getAssociatedPanels(av
-            .getSequenceSetId());
+    AlignmentPanel[] aps = PaintRefresher
+            .getAssociatedPanels(av.getSequenceSetId());
     if (aps.length == 1 && rc.av == aps[0].av)
     {
       associateViewsMenu.setVisible(false);
@@ -577,7 +585,8 @@ public class PCAPanel extends GPCAPanel implements Runnable,
 
     associateViewsMenu.setVisible(true);
 
-    if ((viewMenu.getItem(viewMenu.getItemCount() - 2) instanceof JMenuItem))
+    if ((viewMenu
+            .getItem(viewMenu.getItemCount() - 2) instanceof JMenuItem))
     {
       viewMenu.insertSeparator(viewMenu.getItemCount() - 1);
     }
@@ -608,7 +617,8 @@ public class PCAPanel extends GPCAPanel implements Runnable,
       associateViewsMenu.add(item);
     }
 
-    final JRadioButtonMenuItem itemf = new JRadioButtonMenuItem("All Views");
+    final JRadioButtonMenuItem itemf = new JRadioButtonMenuItem(
+            "All Views");
 
     buttonGroup.add(itemf);
 
@@ -641,9 +651,9 @@ public class PCAPanel extends GPCAPanel implements Runnable,
       cap.setText(pcaModel.getPointsasCsv(false,
               xCombobox.getSelectedIndex(), yCombobox.getSelectedIndex(),
               zCombobox.getSelectedIndex()));
-      Desktop.addInternalFrame(cap, MessageManager.formatMessage(
-              "label.points_for_params", new String[] { this.getTitle() }),
-              500, 500);
+      Desktop.addInternalFrame(cap, MessageManager
+              .formatMessage("label.points_for_params", new String[]
+              { this.getTitle() }), 500, 500);
     } catch (OutOfMemoryError oom)
     {
       new OOMWarning("exporting PCA points", oom);
@@ -668,8 +678,8 @@ public class PCAPanel extends GPCAPanel implements Runnable,
               xCombobox.getSelectedIndex(), yCombobox.getSelectedIndex(),
               zCombobox.getSelectedIndex()));
       Desktop.addInternalFrame(cap, MessageManager.formatMessage(
-              "label.transformed_points_for_params",
-              new String[] { this.getTitle() }), 500, 500);
+              "label.transformed_points_for_params", new String[]
+              { this.getTitle() }), 500, 500);
     } catch (OutOfMemoryError oom)
     {
       new OOMWarning("exporting transformed PCA points", oom);
@@ -783,4 +793,14 @@ public class PCAPanel extends GPCAPanel implements Runnable,
     top = t;
     zCombobox.setSelectedIndex(2);
   }
+
+  /**
+   * Answers true if PCA calculation is in progress, else false
+   * 
+   * @return
+   */
+  public boolean isWorking()
+  {
+    return working;
+  }
 }
index b129971..ced5544 100755 (executable)
@@ -26,9 +26,9 @@ import jalview.datamodel.SequenceI;
 import java.awt.Component;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 
 /**
  * Route datamodel/view update events for a sequence set to any display
@@ -74,26 +74,21 @@ public class PaintRefresher
    */
   public static void RemoveComponent(Component comp)
   {
-    List<String> emptied = new ArrayList<String>();
-    for (Entry<String, List<Component>> registered : components.entrySet())
+    if (components == null)
     {
-      String id = registered.getKey();
-      List<Component> comps = components.get(id);
+      return;
+    }
+
+    Iterator<String> it = components.keySet().iterator();
+    while (it.hasNext())
+    {
+      List<Component> comps = components.get(it.next());
       comps.remove(comp);
       if (comps.isEmpty())
       {
-        emptied.add(id);
+        it.remove();
       }
     }
-
-    /*
-     * Remove now empty ids after the above (to avoid
-     * ConcurrentModificationException).
-     */
-    for (String id : emptied)
-    {
-      components.remove(id);
-    }
   }
 
   public static void Refresh(Component source, String id)
@@ -188,8 +183,8 @@ public class PaintRefresher
           {
             // raise an implementation warning here - not sure if this situation
             // will ever occur
-            System.err
-                    .println("IMPLEMENTATION PROBLEM: DATASET out of sync due to an insert whilst calling PaintRefresher.validateSequences(AlignmentI, ALignmentI)");
+            System.err.println(
+                    "IMPLEMENTATION PROBLEM: DATASET out of sync due to an insert whilst calling PaintRefresher.validateSequences(AlignmentI, ALignmentI)");
           }
           List<SequenceI> alsq;
           synchronized (alsq = comp.getSequences())
index 22f1368..d081794 100755 (executable)
@@ -22,7 +22,8 @@ package jalview.gui;
 
 import jalview.analysis.AlignSeq;
 import jalview.datamodel.Alignment;
-import jalview.datamodel.Sequence;
+import jalview.datamodel.AlignmentView;
+import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.jbgui.GPairwiseAlignPanel;
 import jalview.util.MessageManager;
@@ -40,49 +41,56 @@ import java.util.Vector;
 public class PairwiseAlignPanel extends GPairwiseAlignPanel
 {
 
+  private static final String DASHES = "---------------------\n";
+
   AlignmentViewport av;
 
-  Vector sequences;
+  Vector<SequenceI> sequences;
 
   /**
    * Creates a new PairwiseAlignPanel object.
    * 
-   * @param av
+   * @param viewport
    *          DOCUMENT ME!
    */
-  public PairwiseAlignPanel(AlignmentViewport av)
+  public PairwiseAlignPanel(AlignmentViewport viewport)
   {
     super();
-    this.av = av;
+    this.av = viewport;
 
-    sequences = new Vector();
+    sequences = new Vector<SequenceI>();
 
-    SequenceI[] seqs;
-    String[] seqStrings = av.getViewAsString(true);
+    SequenceGroup selectionGroup = viewport.getSelectionGroup();
+    boolean isSelection = selectionGroup != null
+            && selectionGroup.getSize() > 0;
+    AlignmentView view = viewport.getAlignmentView(isSelection);
+    // String[] seqStrings = viewport.getViewAsString(true);
+    String[] seqStrings = view.getSequenceStrings(viewport
+            .getGapCharacter());
 
-    if (av.getSelectionGroup() == null)
+    SequenceI[] seqs;
+    if (isSelection)
     {
-      seqs = av.getAlignment().getSequencesArray();
+      seqs = (SequenceI[]) view.getAlignmentAndHiddenColumns(viewport
+              .getGapCharacter())[0];
     }
     else
     {
-      seqs = av.getSelectionGroup().getSequencesInOrder(av.getAlignment());
+      seqs = av.getAlignment().getSequencesArray();
     }
 
-    String type = (av.getAlignment().isNucleotide()) ? AlignSeq.DNA
+    String type = (viewport.getAlignment().isNucleotide()) ? AlignSeq.DNA
             : AlignSeq.PEP;
 
     float[][] scores = new float[seqs.length][seqs.length];
-    double totscore = 0;
+    double totscore = 0D;
     int count = seqs.length;
-
-    Sequence seq;
+    boolean first = true;
 
     for (int i = 1; i < count; i++)
     {
       for (int j = 0; j < i; j++)
       {
-
         AlignSeq as = new AlignSeq(seqs[i], seqStrings[i], seqs[j],
                 seqStrings[j], type);
 
@@ -94,9 +102,15 @@ public class PairwiseAlignPanel extends GPairwiseAlignPanel
         as.calcScoreMatrix();
         as.traceAlignment();
 
+        if (!first)
+        {
+          System.out.println(DASHES);
+          textarea.append(DASHES);
+        }
+        first = false;
         as.printAlignment(System.out);
-        scores[i][j] = (float) as.getMaxScore()
-                / (float) as.getASeq1().length;
+        scores[i][j] = as.getMaxScore()
+                / as.getASeq1().length;
         totscore = totscore + scores[i][j];
 
         textarea.append(as.getOutput());
@@ -107,28 +121,53 @@ public class PairwiseAlignPanel extends GPairwiseAlignPanel
 
     if (count > 2)
     {
-      System.out
-              .println("Pairwise alignment scaled similarity score matrix\n");
+      printScoreMatrix(seqs, scores, totscore);
+    }
+  }
 
-      for (int i = 0; i < count; i++)
-      {
-        jalview.util.Format.print(System.out, "%s \n", ("" + i) + " "
-                + seqs[i].getName());
-      }
+  /**
+   * Prints a matrix of seqi-seqj pairwise alignment scores to sysout
+   * 
+   * @param seqs
+   * @param scores
+   * @param totscore
+   */
+  protected void printScoreMatrix(SequenceI[] seqs, float[][] scores,
+          double totscore)
+  {
+    System.out
+            .println("Pairwise alignment scaled similarity score matrix\n");
 
-      System.out.println("\n");
+    for (int i = 0; i < seqs.length; i++)
+    {
+      System.out.println(String.format("%3d %s", i + 1,
+              seqs[i].getDisplayId(true)));
+    }
+
+    /*
+     * table heading columns for sequences 1, 2, 3...
+     */
+    System.out.print("\n ");
+    for (int i = 0; i < seqs.length; i++)
+    {
+      System.out.print(String.format("%7d", i + 1));
+    }
+    System.out.println();
 
-      for (int i = 0; i < count; i++)
+    for (int i = 0; i < seqs.length; i++)
+    {
+      System.out.print(String.format("%3d", i + 1));
+      for (int j = 0; j < i; j++)
       {
-        for (int j = 0; j < i; j++)
-        {
-          jalview.util.Format.print(System.out, "%7.3f", scores[i][j]
-                  / totscore);
-        }
+        /*
+         * as a fraction of tot score, outputs are 0 <= score <= 1
+         */
+        System.out.print(String.format("%7.3f", scores[i][j] / totscore));
       }
-
-      System.out.println("\n");
+      System.out.println();
     }
+
+    System.out.println("\n");
   }
 
   /**
@@ -137,13 +176,14 @@ public class PairwiseAlignPanel extends GPairwiseAlignPanel
    * @param e
    *          DOCUMENT ME!
    */
+  @Override
   protected void viewInEditorButton_actionPerformed(ActionEvent e)
   {
-    Sequence[] seq = new Sequence[sequences.size()];
+    SequenceI[] seq = new SequenceI[sequences.size()];
 
     for (int i = 0; i < sequences.size(); i++)
     {
-      seq[i] = (Sequence) sequences.elementAt(i);
+      seq[i] = sequences.elementAt(i);
     }
 
     AlignFrame af = new AlignFrame(new Alignment(seq),
index 756b77b..850a09a 100644 (file)
@@ -180,7 +180,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
    * @param seq
    *          DOCUMENT ME!
    */
-  public PopupMenu(final AlignmentPanel ap, Sequence seq, List<String> links)
+  public PopupMenu(final AlignmentPanel ap, Sequence seq,
+          List<String> links)
   {
     this(ap, seq, links, null);
   }
@@ -225,8 +226,9 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
      * 'reference annotations' that may be added to the alignment. First for the
      * currently selected sequence (if there is one):
      */
-    final List<SequenceI> selectedSequence = (seq == null ? Collections
-            .<SequenceI> emptyList() : Arrays.asList(seq));
+    final List<SequenceI> selectedSequence = (seq == null
+            ? Collections.<SequenceI> emptyList()
+            : Arrays.asList(seq));
     buildAnnotationTypesMenus(seqShowAnnotationsMenu,
             seqHideAnnotationsMenu, selectedSequence);
     configureReferenceAnnotationsMenu(seqAddReferenceAnnotations,
@@ -235,9 +237,9 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
     /*
      * And repeat for the current selection group (if there is one):
      */
-    final List<SequenceI> selectedGroup = (ap.av.getSelectionGroup() == null ? Collections
-            .<SequenceI> emptyList() : ap.av.getSelectionGroup()
-            .getSequences());
+    final List<SequenceI> selectedGroup = (ap.av.getSelectionGroup() == null
+            ? Collections.<SequenceI> emptyList()
+            : ap.av.getSelectionGroup().getSequences());
     buildAnnotationTypesMenus(groupShowAnnotationsMenu,
             groupHideAnnotationsMenu, selectedGroup);
     configureReferenceAnnotationsMenu(groupAddReferenceAnnotations,
@@ -257,13 +259,13 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
       sequenceMenu.setText(sequence.getName());
       if (seq == ap.av.getAlignment().getSeqrep())
       {
-        makeReferenceSeq.setText(MessageManager
-                .getString("action.unmark_as_reference"));
+        makeReferenceSeq.setText(
+                MessageManager.getString("action.unmark_as_reference"));
       }
       else
       {
-        makeReferenceSeq.setText(MessageManager
-                .getString("action.set_as_reference"));
+        makeReferenceSeq.setText(
+                MessageManager.getString("action.set_as_reference"));
       }
 
       if (!ap.av.getAlignment().isNucleotide())
@@ -290,8 +292,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
                */
               menuItem = new JMenuItem();
               menuItem.setText(MessageManager.formatMessage(
-                      "label.2d_rna_structure_line",
-                      new Object[] { aa.label }));
+                      "label.2d_rna_structure_line", new Object[]
+                      { aa.label }));
               menuItem.addActionListener(new ActionListener()
               {
                 @Override
@@ -318,8 +320,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
               // TODO: make rnastrucF a bit more nice
               menuItem = new JMenuItem();
               menuItem.setText(MessageManager.formatMessage(
-                      "label.2d_rna_sequence_name",
-                      new Object[] { seq.getName() }));
+                      "label.2d_rna_sequence_name", new Object[]
+                      { seq.getName() }));
               menuItem.addActionListener(new ActionListener()
               {
                 @Override
@@ -354,9 +356,9 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
       if (ap.av.getSelectionGroup() != null
               && ap.av.getSelectionGroup().getSize() > 1)
       {
-        menuItem = new JMenuItem(MessageManager.formatMessage(
-                "label.represent_group_with",
-                new Object[] { seq.getName() }));
+        menuItem = new JMenuItem(MessageManager
+                .formatMessage("label.represent_group_with", new Object[]
+                { seq.getName() }));
         menuItem.addActionListener(new ActionListener()
         {
           @Override
@@ -417,8 +419,9 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
     }
 
     SequenceGroup sg = ap.av.getSelectionGroup();
-    boolean isDefinedGroup = (sg != null) ? ap.av.getAlignment()
-            .getGroups().contains(sg) : false;
+    boolean isDefinedGroup = (sg != null)
+            ? ap.av.getAlignment().getGroups().contains(sg)
+            : false;
 
     if (sg != null && sg.getSize() > 0)
     {
@@ -452,7 +455,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
         buildGroupURLMenu(sg, groupLinks);
       }
       // Add a 'show all structures' for the current selection
-      Hashtable<String, PDBEntry> pdbe = new Hashtable<String, PDBEntry>(), reppdb = new Hashtable<String, PDBEntry>();
+      Hashtable<String, PDBEntry> pdbe = new Hashtable<>(), reppdb = new Hashtable<>();
+
       SequenceI sqass = null;
       for (SequenceI sq : ap.av.getSequenceSelection())
       {
@@ -472,9 +476,9 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
       }
       if (pdbe.size() > 0)
       {
-        final PDBEntry[] pe = pdbe.values().toArray(
-                new PDBEntry[pdbe.size()]), pr = reppdb.values().toArray(
-                new PDBEntry[reppdb.size()]);
+        final PDBEntry[] pe = pdbe.values()
+                .toArray(new PDBEntry[pdbe.size()]),
+                pr = reppdb.values().toArray(new PDBEntry[reppdb.size()]);
         final JMenuItem gpdbview, rpdbview;
       }
     }
@@ -519,7 +523,7 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
   void addFeatureLinks(final SequenceI seq, List<String> links)
   {
     JMenu linkMenu = new JMenu(MessageManager.getString("action.link"));
-    Map<String, List<String>> linkset = new LinkedHashMap<String, List<String>>();
+    Map<String, List<String>> linkset = new LinkedHashMap<>();
 
     for (String link : links)
     {
@@ -586,9 +590,11 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
     showMenu.removeAll();
     hideMenu.removeAll();
 
-    final List<String> all = Arrays.asList(new String[] { MessageManager
-            .getString("label.all") });
-    addAnnotationTypeToShowHide(showMenu, forSequences, "", all, true, true);
+    final List<String> all = Arrays
+            .asList(new String[]
+            { MessageManager.getString("label.all") });
+    addAnnotationTypeToShowHide(showMenu, forSequences, "", all, true,
+            true);
     addAnnotationTypeToShowHide(hideMenu, forSequences, "", all, true,
             false);
     showMenu.addSeparator();
@@ -603,8 +609,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
      * the insertion order, which is the order of the annotations on the
      * alignment.
      */
-    Map<String, List<List<String>>> shownTypes = new LinkedHashMap<String, List<List<String>>>();
-    Map<String, List<List<String>>> hiddenTypes = new LinkedHashMap<String, List<List<String>>>();
+    Map<String, List<List<String>>> shownTypes = new LinkedHashMap<>();
+    Map<String, List<List<String>>> hiddenTypes = new LinkedHashMap<>();
     AlignmentAnnotationUtils.getShownHiddenTypes(shownTypes, hiddenTypes,
             AlignmentAnnotationUtils.asList(annotations), forSequences);
 
@@ -710,12 +716,12 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
 
     SequenceI[] seqs = ap.av.getSelectionAsNewSequence();
     String[][] idandseqs = GroupUrlLink.formStrings(seqs);
-    Hashtable<String, Object[]> commonDbrefs = new Hashtable<String, Object[]>();
+    Hashtable<String, Object[]> commonDbrefs = new Hashtable<>();
     for (int sq = 0; sq < seqs.length; sq++)
     {
 
-      int start = seqs[sq].findPosition(sg.getStartRes()), end = seqs[sq]
-              .findPosition(sg.getEndRes());
+      int start = seqs[sq].findPosition(sg.getStartRes()),
+              end = seqs[sq].findPosition(sg.getEndRes());
       // just collect ids from dataset sequence
       // TODO: check if IDs collected from selecton group intersects with the
       // current selection, too
@@ -742,8 +748,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
 
           if (((String[]) sarray[1])[sq] == null)
           {
-            if (!dbr[d].hasMap()
-                    || (dbr[d].getMap().locateMappedRange(start, end) != null))
+            if (!dbr[d].hasMap() || (dbr[d].getMap()
+                    .locateMappedRange(start, end) != null))
             {
               ((String[]) sarray[1])[sq] = dbr[d].getAccessionId();
               ((int[]) sarray[0])[0]++;
@@ -815,9 +821,10 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
         int type = urlLink.getGroupURLType() & 3;
         // first two bits ofurlLink type bitfield are sequenceids and sequences
         // TODO: FUTURE: ensure the groupURL menu structure can be generalised
-        addshowLink(linkMenus[type], label
-                + (((type & 1) == 1) ? ("("
-                        + (usingNames ? "Names" : ltarget) + ")") : ""),
+        addshowLink(linkMenus[type],
+                label + (((type & 1) == 1)
+                        ? ("(" + (usingNames ? "Names" : ltarget) + ")")
+                        : ""),
                 urlLink, urlset);
         addMenu = true;
       }
@@ -839,7 +846,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
     }
   }
 
-  private void addshowLinks(JMenu linkMenu, Collection<List<String>> linkset)
+  private void addshowLinks(JMenu linkMenu,
+          Collection<List<String>> linkset)
   {
     for (List<String> linkstrset : linkset)
     {
@@ -860,8 +868,9 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
   private void addshowLink(JMenu linkMenu, String label, final String url)
   {
     JMenuItem item = new JMenuItem(label);
-    item.setToolTipText(MessageManager.formatMessage(
-            "label.open_url_param", new Object[] { url }));
+    item.setToolTipText(MessageManager.formatMessage("label.open_url_param",
+            new Object[]
+            { url }));
     item.addActionListener(new ActionListener()
     {
       @Override
@@ -898,9 +907,9 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
           final GroupUrlLink urlgenerator, final Object[] urlstub)
   {
     JMenuItem item = new JMenuItem(label);
-    item.setToolTipText(MessageManager.formatMessage(
-            "label.open_url_seqs_param",
-            new Object[] { urlgenerator.getUrl_prefix(),
+    item.setToolTipText(MessageManager
+            .formatMessage("label.open_url_seqs_param", new Object[]
+            { urlgenerator.getUrl_prefix(),
                 urlgenerator.getNumberInvolved(urlstub) }));
     // TODO: put in info about what is being sent.
     item.addActionListener(new ActionListener()
@@ -948,8 +957,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
       }
     });
     sequenceMenu.setText(MessageManager.getString("label.sequence"));
-    sequenceName.setText(MessageManager
-            .getString("label.edit_name_description"));
+    sequenceName.setText(
+            MessageManager.getString("label.edit_name_description"));
     sequenceName.addActionListener(new ActionListener()
     {
       @Override
@@ -958,8 +967,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
         sequenceName_actionPerformed();
       }
     });
-    chooseAnnotations.setText(MessageManager
-            .getString("action.choose_annotations"));
+    chooseAnnotations
+            .setText(MessageManager.getString("action.choose_annotations"));
     chooseAnnotations.addActionListener(new ActionListener()
     {
       @Override
@@ -968,8 +977,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
         chooseAnnotations_actionPerformed(e);
       }
     });
-    sequenceDetails.setText(MessageManager
-            .getString("label.sequence_details"));
+    sequenceDetails
+            .setText(MessageManager.getString("label.sequence_details"));
     sequenceDetails.addActionListener(new ActionListener()
     {
       @Override
@@ -978,8 +987,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
         sequenceDetails_actionPerformed();
       }
     });
-    sequenceSelDetails.setText(MessageManager
-            .getString("label.sequence_details"));
+    sequenceSelDetails
+            .setText(MessageManager.getString("label.sequence_details"));
     sequenceSelDetails.addActionListener(new ActionListener()
     {
       @Override
@@ -999,8 +1008,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
         unGroupMenuItem_actionPerformed();
       }
     });
-    createGroupMenuItem.setText(MessageManager
-            .getString("action.create_group"));
+    createGroupMenuItem
+            .setText(MessageManager.getString("action.create_group"));
     createGroupMenuItem.addActionListener(new ActionListener()
     {
       @Override
@@ -1048,8 +1057,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
         showColourText_actionPerformed();
       }
     });
-    displayNonconserved.setText(MessageManager
-            .getString("label.show_non_conserved"));
+    displayNonconserved
+            .setText(MessageManager.getString("label.show_non_conserved"));
     displayNonconserved.setState(true);
     displayNonconserved.addActionListener(new ActionListener()
     {
@@ -1105,18 +1114,18 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
         changeCase(e);
       }
     });
-    outputMenu.setText(MessageManager.getString("label.out_to_textbox")
-            + "...");
-    seqShowAnnotationsMenu.setText(MessageManager
-            .getString("label.show_annotations"));
-    seqHideAnnotationsMenu.setText(MessageManager
-            .getString("label.hide_annotations"));
-    groupShowAnnotationsMenu.setText(MessageManager
-            .getString("label.show_annotations"));
-    groupHideAnnotationsMenu.setText(MessageManager
-            .getString("label.hide_annotations"));
-    sequenceFeature.setText(MessageManager
-            .getString("label.create_sequence_feature"));
+    outputMenu.setText(
+            MessageManager.getString("label.out_to_textbox") + "...");
+    seqShowAnnotationsMenu
+            .setText(MessageManager.getString("label.show_annotations"));
+    seqHideAnnotationsMenu
+            .setText(MessageManager.getString("label.hide_annotations"));
+    groupShowAnnotationsMenu
+            .setText(MessageManager.getString("label.show_annotations"));
+    groupHideAnnotationsMenu
+            .setText(MessageManager.getString("label.hide_annotations"));
+    sequenceFeature.setText(
+            MessageManager.getString("label.create_sequence_feature"));
     sequenceFeature.addActionListener(new ActionListener()
     {
       @Override
@@ -1126,8 +1135,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
       }
     });
     jMenu1.setText(MessageManager.getString("label.group"));
-    pdbStructureDialog.setText(MessageManager
-            .getString("label.show_pdbstruct_dialog"));
+    pdbStructureDialog.setText(
+            MessageManager.getString("label.show_pdbstruct_dialog"));
     pdbStructureDialog.addActionListener(new ActionListener()
     {
       @Override
@@ -1142,12 +1151,12 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
       }
     });
 
-    rnaStructureMenu.setText(MessageManager
-            .getString("label.view_rna_structure"));
+    rnaStructureMenu
+            .setText(MessageManager.getString("label.view_rna_structure"));
 
     // colStructureMenu.setText("Colour By Structure");
-    editSequence.setText(MessageManager.getString("label.edit_sequence")
-            + "...");
+    editSequence.setText(
+            MessageManager.getString("label.edit_sequence") + "...");
     editSequence.addActionListener(new ActionListener()
     {
       @Override
@@ -1156,8 +1165,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
         editSequence_actionPerformed(actionEvent);
       }
     });
-    makeReferenceSeq.setText(MessageManager
-            .getString("label.mark_as_representative"));
+    makeReferenceSeq.setText(
+            MessageManager.getString("label.mark_as_representative"));
     makeReferenceSeq.addActionListener(new ActionListener()
     {
 
@@ -1168,8 +1177,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
 
       }
     });
-    hideInsertions.setText(MessageManager
-            .getString("label.hide_insertions"));
+    hideInsertions
+            .setText(MessageManager.getString("label.hide_insertions"));
     hideInsertions.addActionListener(new ActionListener()
     {
 
@@ -1233,7 +1242,7 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
     jMenu1.add(outline);
     jMenu1.add(displayNonconserved);
   }
-  
+
   /**
    * Constructs the entries for the colour menu
    */
@@ -1250,8 +1259,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
       }
     });
 
-    abovePIDColour.setText(MessageManager
-            .getString("label.above_identity_threshold"));
+    abovePIDColour.setText(
+            MessageManager.getString("label.above_identity_threshold"));
     abovePIDColour.addActionListener(new ActionListener()
     {
       @Override
@@ -1261,8 +1270,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
       }
     });
 
-    modifyPID.setText(MessageManager
-            .getString("label.modify_identity_threshold"));
+    modifyPID.setText(
+            MessageManager.getString("label.modify_identity_threshold"));
     modifyPID.addActionListener(new ActionListener()
     {
       @Override
@@ -1272,15 +1281,15 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
       }
     });
 
-    conservationMenuItem.setText(MessageManager
-            .getString("action.by_conservation"));
+    conservationMenuItem
+            .setText(MessageManager.getString("action.by_conservation"));
     conservationMenuItem.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        conservationMenuItem_actionPerformed(conservationMenuItem
-                .isSelected());
+        conservationMenuItem_actionPerformed(
+                conservationMenuItem.isSelected());
       }
     });
 
@@ -1341,8 +1350,7 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
       // int threshold = SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup()
       // .getName());
       // sg.cs.setThreshold(threshold, ap.av.isIgnoreGapsConsensus());
-      SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup()
-              .getName());
+      SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup().getName());
       SliderPanel.showPIDSlider();
     }
   }
@@ -1369,11 +1377,11 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
      * Temporary store to hold distinct calcId / type pairs for the tooltip.
      * Using TreeMap means calcIds are shown in alphabetical order.
      */
-    SortedMap<String, String> tipEntries = new TreeMap<String, String>();
-    final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<SequenceI, List<AlignmentAnnotation>>();
+    SortedMap<String, String> tipEntries = new TreeMap<>();
+    final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<>();
     AlignmentI al = this.ap.av.getAlignment();
-    AlignmentUtils.findAddableReferenceAnnotations(forSequences,
-            tipEntries, candidates, al);
+    AlignmentUtils.findAddableReferenceAnnotations(forSequences, tipEntries,
+            candidates, al);
     if (!candidates.isEmpty())
     {
       StringBuilder tooltip = new StringBuilder(64);
@@ -1460,8 +1468,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
     if (ap.av.getSelectionGroup() != null)
     {
       // mark just the columns in the selection group to be hidden
-      inserts.set(ap.av.getSelectionGroup().getStartRes(), ap.av
-              .getSelectionGroup().getEndRes() + 1);
+      inserts.set(ap.av.getSelectionGroup().getStartRes(),
+              ap.av.getSelectionGroup().getEndRes() + 1);
 
       // and clear that part of the mask
       mask.andNot(inserts);
@@ -1517,30 +1525,27 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
     StringBuilder contents = new StringBuilder(128);
     for (SequenceI seq : sequences)
     {
-      contents.append("<p><h2>"
-              + MessageManager
-                      .formatMessage(
-                              "label.create_sequence_details_report_annotation_for",
-                              new Object[] { seq.getDisplayId(true) })
-              + "</h2></p><p>");
-      new SequenceAnnotationReport(null)
-              .createSequenceAnnotationReport(
-                      contents,
-                      seq,
-                      true,
-                      true,
-                      (ap.getSeqPanel().seqCanvas.fr != null) ? ap
-                              .getSeqPanel().seqCanvas.fr.getMinMax()
-                              : null);
+      contents.append("<p><h2>" + MessageManager.formatMessage(
+              "label.create_sequence_details_report_annotation_for",
+              new Object[]
+              { seq.getDisplayId(true) }) + "</h2></p><p>");
+      new SequenceAnnotationReport(null).createSequenceAnnotationReport(
+              contents, seq, true, true,
+              (ap.getSeqPanel().seqCanvas.fr != null)
+                      ? ap.getSeqPanel().seqCanvas.fr.getMinMax()
+                      : null);
       contents.append("</p>");
     }
     cap.setText("<html>" + contents.toString() + "</html>");
 
-    Desktop.addInternalFrame(cap, MessageManager.formatMessage(
-            "label.sequence_details_for",
-            (sequences.length == 1 ? new Object[] { sequences[0]
-                    .getDisplayId(true) } : new Object[] { MessageManager
-                    .getString("label.selection") })), 500, 400);
+    Desktop.addInternalFrame(cap,
+            MessageManager.formatMessage("label.sequence_details_for",
+                    (sequences.length == 1 ? new Object[]
+                    { sequences[0].getDisplayId(true) }
+                            : new Object[]
+                            { MessageManager
+                                    .getString("label.selection") })),
+            500, 400);
 
   }
 
@@ -1556,7 +1561,9 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
   void refresh()
   {
     ap.updateAnnotation();
-    ap.paintAlignment(true);
+    // removed paintAlignment(true) here:
+    // updateAnnotation calls paintAlignment already, so don't need to call
+    // again
 
     PaintRefresher.Refresh(this, ap.av.getSequenceSetId());
   }
@@ -1588,8 +1595,7 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
               sg.getStartRes(), sg.getEndRes() + 1));
 
       int threshold = SliderPanel.setPIDSliderSource(ap,
-              sg.getGroupColourScheme(), getGroup()
-              .getName());
+              sg.getGroupColourScheme(), getGroup().getName());
 
       sg.cs.setThreshold(threshold, ap.av.isIgnoreGapsConsensus());
 
@@ -1635,9 +1641,9 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
     if (selected)
     {
       // JBPNote: Conservation name shouldn't be i18n translated
-      Conservation c = new Conservation("Group", sg.getSequences(ap.av
-              .getHiddenRepSequences()), sg.getStartRes(),
-              sg.getEndRes() + 1);
+      Conservation c = new Conservation("Group",
+              sg.getSequences(ap.av.getHiddenRepSequences()),
+              sg.getStartRes(), sg.getEndRes() + 1);
 
       c.calculate();
       c.verdict(false, ap.av.getConsPercGaps());
@@ -1669,8 +1675,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
 
     SequenceGroup sg = getGroup();
     EditNameDialog dialog = new EditNameDialog(sg.getName(),
-            sg.getDescription(), "       "
-                    + MessageManager.getString("label.group_name") + " ",
+            sg.getDescription(),
+            "       " + MessageManager.getString("label.group_name") + " ",
             MessageManager.getString("label.group_description") + " ",
             MessageManager.getString("label.edit_group_name_description"),
             ap.alignFrame);
@@ -1715,8 +1721,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
             "       " + MessageManager.getString("label.sequence_name")
                     + " ",
             MessageManager.getString("label.sequence_description") + " ",
-            MessageManager
-                    .getString("label.edit_sequence_name_description"),
+            MessageManager.getString(
+                    "label.edit_sequence_name_description"),
             ap.alignFrame);
 
     if (!dialog.accept)
@@ -1728,24 +1734,22 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
     {
       if (dialog.getName().indexOf(" ") > -1)
       {
-        JvOptionPane
-                .showMessageDialog(
-                        ap,
-                        MessageManager
-                                .getString("label.spaces_converted_to_backslashes"),
-                        MessageManager
-                                .getString("label.no_spaces_allowed_sequence_name"),
-                        JvOptionPane.WARNING_MESSAGE);
+        JvOptionPane.showMessageDialog(ap,
+                MessageManager
+                        .getString("label.spaces_converted_to_backslashes"),
+                MessageManager
+                        .getString("label.no_spaces_allowed_sequence_name"),
+                JvOptionPane.WARNING_MESSAGE);
       }
 
       sequence.setName(dialog.getName().replace(' ', '_'));
-      ap.paintAlignment(false);
+      ap.paintAlignment(false, false);
     }
 
     sequence.setDescription(dialog.getDescription());
 
-    ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
-            .getSequences());
+    ap.av.firePropertyChange("alignment", null,
+            ap.av.getAlignment().getSequences());
 
   }
 
@@ -1893,8 +1897,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
 
       ap.alignFrame.addHistoryItem(caseCommand);
 
-      ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
-              .getSequences());
+      ap.av.firePropertyChange("alignment", null,
+              ap.av.getAlignment().getSequences());
 
     }
   }
@@ -1903,9 +1907,9 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
   {
     CutAndPasteTransfer cap = new CutAndPasteTransfer();
     cap.setForInput(null);
-    Desktop.addInternalFrame(cap, MessageManager.formatMessage(
-            "label.alignment_output_command",
-            new Object[] { e.getActionCommand() }), 600, 500);
+    Desktop.addInternalFrame(cap, MessageManager
+            .formatMessage("label.alignment_output_command", new Object[]
+            { e.getActionCommand() }), 600, 500);
 
     String[] omitHidden = null;
 
@@ -1913,8 +1917,10 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
     // or we simply trust the user wants
     // wysiwig behaviour
 
-    FileFormatI fileFormat = FileFormats.getInstance().forName(e.getActionCommand());
-    cap.setText(new FormatAdapter(ap).formatSequences(fileFormat, ap, true));
+    FileFormatI fileFormat = FileFormats.getInstance()
+            .forName(e.getActionCommand());
+    cap.setText(
+            new FormatAdapter(ap).formatSequences(fileFormat, ap, true));
   }
 
   public void sequenceFeature_actionPerformed()
@@ -1925,8 +1931,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
       return;
     }
 
-    List<SequenceI> seqs = new ArrayList<SequenceI>();
-    List<SequenceFeature> features = new ArrayList<SequenceFeature>();
+    List<SequenceI> seqs = new ArrayList<>();
+    List<SequenceFeature> features = new ArrayList<>();
 
     /*
      * assemble dataset sequences, and template new sequence features,
@@ -1940,7 +1946,7 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
       if (start <= end)
       {
         seqs.add(sg.getSequenceAt(i).getDatasetSequence());
-        features.add(new SequenceFeature(null, null, null, start, end, null));
+        features.add(new SequenceFeature(null, null, start, end, null));
       }
     }
 
@@ -1949,11 +1955,12 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
      */
     if (!seqs.isEmpty())
     {
-      if (ap.getSeqPanel().seqCanvas.getFeatureRenderer().amendFeatures(
-              seqs, features, true, ap))
+      if (ap.getSeqPanel().seqCanvas.getFeatureRenderer()
+              .amendFeatures(seqs, features, true, ap))
       {
         ap.alignFrame.setShowSeqFeatures(true);
-        ap.highlightSearchResults(null);
+        ap.av.setSearchResults(null); // clear highlighting
+        ap.repaint(); // draw new/amended features
       }
     }
   }
@@ -1999,8 +2006,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
 
       EditNameDialog dialog = new EditNameDialog(
               sequence.getSequenceAsString(sg.getStartRes(),
-                      sg.getEndRes() + 1), null,
-              MessageManager.getString("label.edit_sequence"), null,
+                      sg.getEndRes() + 1),
+              null, MessageManager.getString("label.edit_sequence"), null,
               MessageManager.getString("label.edit_sequence"),
               ap.alignFrame);
 
@@ -2008,15 +2015,15 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
       {
         EditCommand editCommand = new EditCommand(
                 MessageManager.getString("label.edit_sequences"),
-                Action.REPLACE, dialog.getName().replace(' ',
-                        ap.av.getGapCharacter()),
+                Action.REPLACE,
+                dialog.getName().replace(' ', ap.av.getGapCharacter()),
                 sg.getSequencesAsArray(ap.av.getHiddenRepSequences()),
                 sg.getStartRes(), sg.getEndRes() + 1, ap.av.getAlignment());
 
         ap.alignFrame.addHistoryItem(editCommand);
 
-        ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
-                .getSequences());
+        ap.av.firePropertyChange("alignment", null,
+                ap.av.getAlignment().getSequences());
       }
     }
   }
index cccdd2e..aa8369a 100755 (executable)
@@ -109,6 +109,14 @@ public class Preferences extends GPreferences
 
   public static final String SHOW_OCCUPANCY = "SHOW_OCCUPANCY";
 
+  public static final String SHOW_OV_HIDDEN_AT_START = "SHOW_OV_HIDDEN_AT_START";
+
+  public static final String USE_LEGACY_GAP = "USE_LEGACY_GAP";
+
+  public static final String GAP_COLOUR = "GAP_COLOUR";
+
+  public static final String HIDDEN_COLOUR = "HIDDEN_COLOUR";
+
   private static final int MIN_FONT_SIZE = 1;
 
   private static final int MAX_FONT_SIZE = 30;
@@ -155,7 +163,7 @@ public class Preferences extends GPreferences
      * .properties file as '|' separated strings
      */
 
-    groupURLLinks = new ArrayList<String>();
+    groupURLLinks = new ArrayList<>();
   }
 
   JInternalFrame frame;
@@ -213,18 +221,18 @@ public class Preferences extends GPreferences
     showUnconserved
             .setSelected(Cache.getDefault("SHOW_UNCONSERVED", false));
     showOccupancy.setSelected(Cache.getDefault(SHOW_OCCUPANCY, false));
-    showGroupConsensus.setSelected(Cache.getDefault("SHOW_GROUP_CONSENSUS",
-            false));
-    showGroupConservation.setSelected(Cache.getDefault(
-            "SHOW_GROUP_CONSERVATION", false));
-    showConsensHistogram.setSelected(Cache.getDefault(
-            "SHOW_CONSENSUS_HISTOGRAM", true));
-    showConsensLogo.setSelected(Cache.getDefault("SHOW_CONSENSUS_LOGO",
-            false));
-    showNpTooltip.setSelected(Cache
-            .getDefault("SHOW_NPFEATS_TOOLTIP", true));
-    showDbRefTooltip.setSelected(Cache.getDefault("SHOW_DBREFS_TOOLTIP",
-            true));
+    showGroupConsensus
+            .setSelected(Cache.getDefault("SHOW_GROUP_CONSENSUS", false));
+    showGroupConservation.setSelected(
+            Cache.getDefault("SHOW_GROUP_CONSERVATION", false));
+    showConsensHistogram.setSelected(
+            Cache.getDefault("SHOW_CONSENSUS_HISTOGRAM", true));
+    showConsensLogo
+            .setSelected(Cache.getDefault("SHOW_CONSENSUS_LOGO", false));
+    showNpTooltip
+            .setSelected(Cache.getDefault("SHOW_NPFEATS_TOOLTIP", true));
+    showDbRefTooltip
+            .setSelected(Cache.getDefault("SHOW_DBREFS_TOOLTIP", true));
 
     String[] fonts = java.awt.GraphicsEnvironment
             .getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
@@ -244,12 +252,12 @@ public class Preferences extends GPreferences
 
     fontNameCB.setSelectedItem(Cache.getDefault("FONT_NAME", "SansSerif"));
     fontSizeCB.setSelectedItem(Cache.getDefault("FONT_SIZE", "10"));
-    fontStyleCB.setSelectedItem(Cache.getDefault("FONT_STYLE", Font.PLAIN
-            + ""));
+    fontStyleCB.setSelectedItem(
+            Cache.getDefault("FONT_STYLE", Font.PLAIN + ""));
 
     smoothFont.setSelected(Cache.getDefault("ANTI_ALIAS", false));
-    scaleProteinToCdna.setSelected(Cache.getDefault(SCALE_PROTEIN_TO_CDNA,
-            false));
+    scaleProteinToCdna
+            .setSelected(Cache.getDefault(SCALE_PROTEIN_TO_CDNA, false));
 
     idItalics.setSelected(Cache.getDefault("ID_ITALICS", true));
 
@@ -303,10 +311,25 @@ public class Preferences extends GPreferences
     protColour.setSelectedItem(newProp != null ? newProp : oldProp);
     newProp = Cache.getDefault(DEFAULT_COLOUR_NUC, null);
     nucColour.setSelectedItem(newProp != null ? newProp : oldProp);
-    minColour.setBackground(Cache.getDefaultColour("ANNOTATIONCOLOUR_MIN",
-            Color.orange));
-    maxColour.setBackground(Cache.getDefaultColour("ANNOTATIONCOLOUR_MAX",
-            Color.red));
+    minColour.setBackground(
+            Cache.getDefaultColour("ANNOTATIONCOLOUR_MIN", Color.orange));
+    maxColour.setBackground(
+            Cache.getDefaultColour("ANNOTATIONCOLOUR_MAX", Color.red));
+
+    /*
+     * Set overview panel defaults
+     */
+    gapColour.setBackground(
+            Cache.getDefaultColour(GAP_COLOUR,
+                    jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_GAP));
+    hiddenColour.setBackground(
+            Cache.getDefaultColour(HIDDEN_COLOUR,
+                    jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_HIDDEN));
+    useLegacyGap.setSelected(Cache.getDefault(USE_LEGACY_GAP, false));
+    gapLabel.setEnabled(!useLegacyGap.isSelected());
+    gapColour.setEnabled(!useLegacyGap.isSelected());
+    showHiddenAtStart
+            .setSelected(Cache.getDefault(SHOW_OV_HIDDEN_AT_START, true));
 
     /*
      * Set Structure tab defaults.
@@ -319,8 +342,8 @@ public class Preferences extends GPreferences
     addSecondaryStructure.setEnabled(structSelected);
     addTempFactor.setSelected(Cache.getDefault(ADD_TEMPFACT_ANN, false));
     addTempFactor.setEnabled(structSelected);
-    structViewer.setSelectedItem(Cache.getDefault(STRUCTURE_DISPLAY,
-            ViewerType.JMOL.name()));
+    structViewer.setSelectedItem(
+            Cache.getDefault(STRUCTURE_DISPLAY, ViewerType.JMOL.name()));
     chimeraPath.setText(Cache.getDefault(CHIMERA_PATH, ""));
     chimeraPath.addActionListener(new ActionListener()
     {
@@ -359,12 +382,12 @@ public class Preferences extends GPreferences
             SortOrder.DESCENDING));
     sortKeys.add(new RowSorter.SortKey(m.getSelectedColumn(),
             SortOrder.DESCENDING));
-    sortKeys.add(new RowSorter.SortKey(m.getNameColumn(),
-            SortOrder.ASCENDING));
+    sortKeys.add(
+            new RowSorter.SortKey(m.getNameColumn(), SortOrder.ASCENDING));
 
     sorter.setSortKeys(sortKeys);
     sorter.sort();
-    
+
     // set up filtering
     ActionListener onReset;
     onReset = new ActionListener()
@@ -413,35 +436,35 @@ public class Preferences extends GPreferences
       @Override
       public void changedUpdate(DocumentEvent e)
       {
-        sorter.setRowFilter(RowFilter.regexFilter(caseInsensitiveFlag
-                + filterTB.getText()));
+        sorter.setRowFilter(RowFilter
+                .regexFilter(caseInsensitiveFlag + filterTB.getText()));
       }
 
       @Override
       public void removeUpdate(DocumentEvent e)
       {
-        sorter.setRowFilter(RowFilter.regexFilter(caseInsensitiveFlag
-                + filterTB.getText()));
+        sorter.setRowFilter(RowFilter
+                .regexFilter(caseInsensitiveFlag + filterTB.getText()));
       }
 
       @Override
       public void insertUpdate(DocumentEvent e)
       {
-        sorter.setRowFilter(RowFilter.regexFilter(caseInsensitiveFlag
-                + filterTB.getText()));
+        sorter.setRowFilter(RowFilter
+                .regexFilter(caseInsensitiveFlag + filterTB.getText()));
       }
     });
 
     // set up list selection functionality
-    linkUrlTable.getSelectionModel().addListSelectionListener(
-            new UrlListSelectionHandler());
+    linkUrlTable.getSelectionModel()
+            .addListSelectionListener(new UrlListSelectionHandler());
 
     // set up radio buttons
     int onClickCol = ((UrlLinkTableModel) linkUrlTable.getModel())
             .getPrimaryColumn();
     String onClickName = linkUrlTable.getColumnName(onClickCol);
-    linkUrlTable.getColumn(onClickName).setCellRenderer(
-               new RadioButtonRenderer());
+    linkUrlTable.getColumn(onClickName)
+            .setCellRenderer(new RadioButtonRenderer());
     linkUrlTable.getColumn(onClickName)
             .setCellEditor(new RadioButtonEditor());
 
@@ -451,8 +474,8 @@ public class Preferences extends GPreferences
       if (linkUrlTable.getModel().getColumnClass(column)
               .equals(Boolean.class))
       {
-        TableColumn tableColumn = linkUrlTable.getColumnModel().getColumn(
-                column);
+        TableColumn tableColumn = linkUrlTable.getColumnModel()
+                .getColumn(column);
         int preferredWidth = tableColumn.getMinWidth();
 
         TableCellRenderer cellRenderer = linkUrlTable.getCellRenderer(0,
@@ -504,6 +527,8 @@ public class Preferences extends GPreferences
     userIdWidthlabel.setEnabled(!autoIdWidth.isSelected());
     Integer wi = Cache.getIntegerProperty("FIGURE_USERIDWIDTH");
     userIdWidth.setText(wi == null ? "" : wi.toString());
+    // TODO: refactor to use common enum via FormatAdapter and allow extension
+    // for new flat file formats
     blcjv.setSelected(Cache.getDefault("BLC_JVSUFFIX", true));
     clustaljv.setSelected(Cache.getDefault("CLUSTAL_JVSUFFIX", true));
     fastajv.setSelected(Cache.getDefault("FASTA_JVSUFFIX", true));
@@ -512,14 +537,14 @@ public class Preferences extends GPreferences
     pileupjv.setSelected(Cache.getDefault("PILEUP_JVSUFFIX", true));
     pirjv.setSelected(Cache.getDefault("PIR_JVSUFFIX", true));
     modellerOutput.setSelected(Cache.getDefault("PIR_MODELLER", false));
-    embbedBioJSON.setSelected(Cache.getDefault("EXPORT_EMBBED_BIOJSON",
-            true));
+    embbedBioJSON
+            .setSelected(Cache.getDefault("EXPORT_EMBBED_BIOJSON", true));
 
     /*
      * Set Editing tab defaults
      */
-    autoCalculateConsCheck.setSelected(Cache.getDefault(
-            "AUTO_CALC_CONSENSUS", true));
+    autoCalculateConsCheck
+            .setSelected(Cache.getDefault("AUTO_CALC_CONSENSUS", true));
     padGaps.setSelected(Cache.getDefault("PAD_GAPS", false));
     sortByTree.setSelected(Cache.getDefault("SORT_BY_TREE", false));
 
@@ -561,15 +586,15 @@ public class Preferences extends GPreferences
     Cache.applicationProperties.setProperty("SHOW_IDENTITY",
             Boolean.toString(identity.isSelected()));
 
-    Cache.applicationProperties.setProperty("GAP_SYMBOL", gapSymbolCB
-            .getSelectedItem().toString());
+    Cache.applicationProperties.setProperty("GAP_SYMBOL",
+            gapSymbolCB.getSelectedItem().toString());
 
-    Cache.applicationProperties.setProperty("FONT_NAME", fontNameCB
-            .getSelectedItem().toString());
-    Cache.applicationProperties.setProperty("FONT_STYLE", fontStyleCB
-            .getSelectedItem().toString());
-    Cache.applicationProperties.setProperty("FONT_SIZE", fontSizeCB
-            .getSelectedItem().toString());
+    Cache.applicationProperties.setProperty("FONT_NAME",
+            fontNameCB.getSelectedItem().toString());
+    Cache.applicationProperties.setProperty("FONT_STYLE",
+            fontStyleCB.getSelectedItem().toString());
+    Cache.applicationProperties.setProperty("FONT_SIZE",
+            fontSizeCB.getSelectedItem().toString());
 
     Cache.applicationProperties.setProperty("ID_ITALICS",
             Boolean.toString(idItalics.isSelected()));
@@ -602,8 +627,8 @@ public class Preferences extends GPreferences
     Cache.applicationProperties.setProperty("SHOW_STARTUP_FILE",
             Boolean.toString(startupCheckbox.isSelected()));
 
-    Cache.applicationProperties.setProperty("SORT_ALIGNMENT", sortby
-            .getSelectedItem().toString());
+    Cache.applicationProperties.setProperty("SORT_ALIGNMENT",
+            sortby.getSelectedItem().toString());
 
     // convert description of sort order to enum name for save
     SequenceAnnotationOrder annSortOrder = SequenceAnnotationOrder
@@ -615,22 +640,32 @@ public class Preferences extends GPreferences
     }
 
     final boolean showAutocalcFirst = sortAutocalc.getSelectedIndex() == 0;
-    Cache.applicationProperties.setProperty(SHOW_AUTOCALC_ABOVE, Boolean
-            .valueOf(showAutocalcFirst).toString());
+    Cache.applicationProperties.setProperty(SHOW_AUTOCALC_ABOVE,
+            Boolean.valueOf(showAutocalcFirst).toString());
 
     /*
      * Save Colours settings
      */
-    Cache.applicationProperties.setProperty(DEFAULT_COLOUR_PROT, protColour
-            .getSelectedItem().toString());
-    Cache.applicationProperties.setProperty(DEFAULT_COLOUR_NUC, nucColour
-            .getSelectedItem().toString());
+    Cache.applicationProperties.setProperty(DEFAULT_COLOUR_PROT,
+            protColour.getSelectedItem().toString());
+    Cache.applicationProperties.setProperty(DEFAULT_COLOUR_NUC,
+            nucColour.getSelectedItem().toString());
     Cache.setColourProperty("ANNOTATIONCOLOUR_MIN",
             minColour.getBackground());
     Cache.setColourProperty("ANNOTATIONCOLOUR_MAX",
             maxColour.getBackground());
 
     /*
+     * Save Overview settings
+     */
+    Cache.setColourProperty(GAP_COLOUR, gapColour.getBackground());
+    Cache.setColourProperty(HIDDEN_COLOUR, hiddenColour.getBackground());
+    Cache.applicationProperties.setProperty(USE_LEGACY_GAP,
+            Boolean.toString(useLegacyGap.isSelected()));
+    Cache.applicationProperties.setProperty(SHOW_OV_HIDDEN_AT_START,
+            Boolean.toString(showHiddenAtStart.isSelected()));
+
+    /*
      * Save Structure settings
      */
     Cache.applicationProperties.setProperty(ADD_TEMPFACT_ANN,
@@ -641,8 +676,8 @@ public class Preferences extends GPreferences
             Boolean.toString(useRnaView.isSelected()));
     Cache.applicationProperties.setProperty(STRUCT_FROM_PDB,
             Boolean.toString(structFromPdb.isSelected()));
-    Cache.applicationProperties.setProperty(STRUCTURE_DISPLAY, structViewer
-            .getSelectedItem().toString());
+    Cache.applicationProperties.setProperty(STRUCTURE_DISPLAY,
+            structViewer.getSelectedItem().toString());
     Cache.setOrRemove(CHIMERA_PATH, chimeraPath.getText());
     Cache.applicationProperties.setProperty("MAP_WITH_SIFTS",
             Boolean.toString(siftsMapping.isSelected()));
@@ -804,11 +839,11 @@ public class Preferences extends GPreferences
   public void startupFileTextfield_mouseClicked()
   {
     String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
-    JalviewFileChooser chooser = JalviewFileChooser.forRead(
-            Cache.getProperty("LAST_DIRECTORY"), fileFormat);
+    JalviewFileChooser chooser = JalviewFileChooser
+            .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat);
     chooser.setFileView(new JalviewFileView());
-    chooser.setDialogTitle(MessageManager
-            .getString("label.select_startup_file"));
+    chooser.setDialogTitle(
+            MessageManager.getString("label.select_startup_file"));
 
     int value = chooser.showOpenDialog(this);
 
@@ -820,8 +855,8 @@ public class Preferences extends GPreferences
         Cache.applicationProperties.setProperty("DEFAULT_FILE_FORMAT",
                 format.getName());
       }
-      startupFileTextfield.setText(chooser.getSelectedFile()
-              .getAbsolutePath());
+      startupFileTextfield
+              .setText(chooser.getSelectedFile().getAbsolutePath());
     }
   }
 
@@ -874,15 +909,16 @@ public class Preferences extends GPreferences
     {
       if (JvOptionPane.showInternalConfirmDialog(Desktop.desktop, link,
               MessageManager.getString("label.new_sequence_url_link"),
-              JvOptionPane.OK_CANCEL_OPTION, -1, null) == JvOptionPane.OK_OPTION)
+              JvOptionPane.OK_CANCEL_OPTION, -1,
+              null) == JvOptionPane.OK_OPTION)
       {
         if (link.checkValid())
         {
           if (((UrlLinkTableModel) linkUrlTable.getModel())
                   .isUniqueName(link.getName()))
           {
-            ((UrlLinkTableModel) linkUrlTable.getModel()).insertRow(
-                    link.getName(), link.getURL());
+            ((UrlLinkTableModel) linkUrlTable.getModel())
+                    .insertRow(link.getName(), link.getURL());
             valid = true;
           }
           else
@@ -925,7 +961,8 @@ public class Preferences extends GPreferences
     {
       if (JvOptionPane.showInternalConfirmDialog(Desktop.desktop, link,
               MessageManager.getString("label.edit_sequence_url_link"),
-              JvOptionPane.OK_CANCEL_OPTION, -1, null) == JvOptionPane.OK_OPTION)
+              JvOptionPane.OK_CANCEL_OPTION, -1,
+              null) == JvOptionPane.OK_OPTION)
       {
         if (link.checkValid())
         {
@@ -971,13 +1008,12 @@ public class Preferences extends GPreferences
     ((UrlLinkTableModel) linkUrlTable.getModel()).removeRow(modelIndex);
   }
 
-
   @Override
   public void defaultBrowser_mouseClicked(MouseEvent e)
   {
     JFileChooser chooser = new JFileChooser(".");
-    chooser.setDialogTitle(MessageManager
-            .getString("label.select_default_browser"));
+    chooser.setDialogTitle(
+            MessageManager.getString("label.select_default_browser"));
 
     int value = chooser.showOpenDialog(this);
 
@@ -1034,6 +1070,63 @@ public class Preferences extends GPreferences
   }
 
   @Override
+  public void gapColour_actionPerformed(JPanel gap)
+  {
+    if (!useLegacyGap.isSelected())
+    {
+      Color col = JColorChooser.showDialog(this,
+              MessageManager.getString("label.select_gap_colour"),
+              gapColour.getBackground());
+      if (col != null)
+      {
+        gap.setBackground(col);
+      }
+      gap.repaint();
+    }
+  }
+
+  @Override
+  public void hiddenColour_actionPerformed(JPanel hidden)
+  {
+    Color col = JColorChooser.showDialog(this,
+            MessageManager.getString("label.select_hidden_colour"),
+            hiddenColour.getBackground());
+    if (col != null)
+    {
+      hidden.setBackground(col);
+    }
+    hidden.repaint();
+  }
+
+  @Override
+  protected void useLegacyGaps_actionPerformed(ActionEvent e)
+  {
+    boolean enabled = useLegacyGap.isSelected();
+    if (enabled)
+    {
+      gapColour.setBackground(
+              jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_LEGACY_GAP);
+    }
+    else
+    {
+      gapColour.setBackground(
+              jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_GAP);
+    }
+    gapColour.setEnabled(!enabled);
+    gapLabel.setEnabled(!enabled);
+  }
+
+  @Override
+  protected void resetOvDefaults_actionPerformed(ActionEvent e)
+  {
+    useLegacyGap.setSelected(false);
+    useLegacyGaps_actionPerformed(null);
+    showHiddenAtStart.setSelected(true);
+    hiddenColour.setBackground(
+            jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_HIDDEN);
+  }
+
+  @Override
   protected void userIdWidth_actionPerformed()
   {
     try
@@ -1050,8 +1143,9 @@ public class Preferences extends GPreferences
       }
     } catch (NumberFormatException x)
     {
-      JvOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager
-              .getString("warn.user_defined_width_requirements"),
+      JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+              MessageManager
+                      .getString("warn.user_defined_width_requirements"),
               MessageManager.getString("label.invalid_id_column_width"),
               JvOptionPane.WARNING_MESSAGE);
       userIdWidth.setText("");
@@ -1115,8 +1209,7 @@ public class Preferences extends GPreferences
     if (!found)
     {
       String[] options = { "OK", "Help" };
-      int showHelp = JvOptionPane.showInternalOptionDialog(
-              Desktop.desktop,
+      int showHelp = JvOptionPane.showInternalOptionDialog(Desktop.desktop,
               JvSwingUtils.wrapTooltip(true,
                       MessageManager.getString("label.chimera_missing")),
               "", JvOptionPane.YES_NO_OPTION, JvOptionPane.WARNING_MESSAGE,
@@ -1188,7 +1281,7 @@ public class Preferences extends GPreferences
       return name.hashCode() + code.hashCode();
     }
   }
-  
+
   private class UrlListSelectionHandler implements ListSelectionListener
   {
 
@@ -1228,5 +1321,5 @@ public class Preferences extends GPreferences
         editLink.setEnabled(false);
       }
     }
-}
+  }
 }
index c04754f..011d810 100644 (file)
@@ -89,8 +89,8 @@ public class ProgressBar implements IProgressIndicator
     }
     this.statusPanel = container;
     this.statusBar = statusBar;
-    this.progressBars = new Hashtable<Long, JPanel>();
-    this.progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
+    this.progressBars = new Hashtable<>();
+    this.progressBarHandlers = new Hashtable<>();
 
   }
 
@@ -119,46 +119,52 @@ public class ProgressBar implements IProgressIndicator
    * execution.
    */
   @Override
-  public void setProgressBar(String message, long id)
+  public void setProgressBar(final String message, final long id)
   {
-    Long longId = Long.valueOf(id);
-
-    JPanel progressPanel = progressBars.get(longId);
-    if (progressPanel != null)
+    SwingUtilities.invokeLater(new Runnable()
     {
-      /*
-       * Progress bar is displayed for this id - remove it now, and any handler
-       */
-      progressBars.remove(id);
-      if (message != null && statusBar != null)
-      {
-        statusBar.setText(message);
-      }
-      if (progressBarHandlers.containsKey(longId))
+      @Override
+      public void run()
       {
-        progressBarHandlers.remove(longId);
-      }
-      removeRow(progressPanel);
-    }
-    else
-    {
-      /*
-       * No progress bar for this id - add one now
-       */
-      progressPanel = new JPanel(new BorderLayout(10, 5));
+        JPanel progressPanel = progressBars.get(id);
+        if (progressPanel != null)
+        {
+          /*
+           * Progress bar is displayed for this id - remove it now, and any handler
+           */
+          progressBars.remove(id);
+          if (message != null && statusBar != null)
+          {
+            statusBar.setText(message);
+          }
+          if (progressBarHandlers.containsKey(id))
+          {
+            progressBarHandlers.remove(id);
+          }
+          removeRow(progressPanel);
+        }
+        else
+        {
+          /*
+           * No progress bar for this id - add one now
+           */
+          progressPanel = new JPanel(new BorderLayout(10, 5));
 
-      JProgressBar progressBar = new JProgressBar();
-      progressBar.setIndeterminate(true);
+          JProgressBar progressBar = new JProgressBar();
+          progressBar.setIndeterminate(true);
 
-      progressPanel.add(new JLabel(message), BorderLayout.WEST);
-      progressPanel.add(progressBar, BorderLayout.CENTER);
+          progressPanel.add(new JLabel(message), BorderLayout.WEST);
+          progressPanel.add(progressBar, BorderLayout.CENTER);
 
-      addRow(progressPanel);
+          addRow(progressPanel);
 
-      progressBars.put(longId, progressPanel);
-    }
+          progressBars.put(id, progressPanel);
+        }
+
+        refreshLayout();
+      }
+    });
 
-    refreshLayout();
   }
 
   /**
@@ -215,41 +221,50 @@ public class ProgressBar implements IProgressIndicator
   public void registerHandler(final long id,
           final IProgressIndicatorHandler handler)
   {
-    Long longId = Long.valueOf(id);
-    final JPanel progressPanel = progressBars.get(longId);
-    if (progressPanel == null)
-    {
-      System.err
-              .println("call setProgressBar before registering the progress bar's handler.");
-      return;
-    }
-
-    /*
-     * Nothing useful to do if not a Cancel handler
-     */
-    if (!handler.canCancel())
-    {
-      return;
-    }
-
-    progressBarHandlers.put(longId, handler);
-    JButton cancel = new JButton(MessageManager.getString("action.cancel"));
     final IProgressIndicator us = this;
-    cancel.addActionListener(new ActionListener()
-    {
 
+    SwingUtilities.invokeLater(new Runnable()
+    {
       @Override
-      public void actionPerformed(ActionEvent e)
+      public void run()
       {
-        handler.cancelActivity(id);
-        us.setProgressBar(MessageManager.formatMessage(
-                "label.cancelled_params",
-                new Object[] { ((JLabel) progressPanel.getComponent(0))
-                        .getText() }), id);
+        final JPanel progressPanel = progressBars.get(id);
+        if (progressPanel == null)
+        {
+          System.err.println(
+                  "call setProgressBar before registering the progress bar's handler.");
+          return;
+        }
+
+        /*
+         * Nothing useful to do if not a Cancel handler
+         */
+        if (!handler.canCancel())
+        {
+          return;
+        }
+
+        progressBarHandlers.put(id, handler);
+        JButton cancel = new JButton(
+                MessageManager.getString("action.cancel"));
+        cancel.addActionListener(new ActionListener()
+        {
+
+          @Override
+          public void actionPerformed(ActionEvent e)
+          {
+            handler.cancelActivity(id);
+            us.setProgressBar(MessageManager
+                    .formatMessage("label.cancelled_params", new Object[]
+                    { ((JLabel) progressPanel.getComponent(0)).getText() }),
+                    id);
+          }
+        });
+        progressPanel.add(cancel, BorderLayout.EAST);
+        refreshLayout();
+
       }
     });
-    progressPanel.add(cancel, BorderLayout.EAST);
-    refreshLayout();
   }
 
 }
diff --git a/src/jalview/gui/ProgressPanel.java b/src/jalview/gui/ProgressPanel.java
new file mode 100644 (file)
index 0000000..170e9eb
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.gui;
+
+import jalview.api.RendererListenerI;
+
+import java.awt.BorderLayout;
+import java.awt.CardLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.beans.PropertyChangeEvent;
+
+import javax.swing.BorderFactory;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JProgressBar;
+import javax.swing.border.EmptyBorder;
+
+/**
+ * A class to manage a panel containing a label and progress bar updated by an
+ * event firing
+ * 
+ * @author kmourao
+ *
+ */
+public class ProgressPanel extends JPanel implements RendererListenerI
+{
+  // max value of progress bar: values expected to be %s
+  private final int MAXVALUE = 100;
+
+  private final String VISIBLE = "VISIBLE";
+
+  private final String INVISIBLE = "INVISIBLE";
+
+  // name of event property which updates the progress bar
+  private String eventName;
+
+  private JProgressBar progressBar;
+
+  private JLabel progressLabel;
+
+  private JPanel labelPanel = new JPanel();
+
+  private CardLayout labelLayout = new CardLayout();
+
+  private JPanel barPanel = new JPanel();
+
+  private CardLayout barLayout = new CardLayout();
+
+  /**
+   * Construct a JPanel containing a progress bar and a label.
+   * 
+   * @param eventPropertyName
+   *          The name of the event property to update the progress bar
+   * @param label
+   *          The label to place next to the progress bar
+   */
+  public ProgressPanel(String eventPropertyName, String label, int maxwidth)
+  {
+    super(new BorderLayout(10, 0));
+    setBorder(new EmptyBorder(0, 3, 0, 0));
+
+    eventName = eventPropertyName;
+    String labelText = label;
+
+    final int w = maxwidth;
+
+    progressBar = new JProgressBar()
+    {
+      @Override
+      public Dimension getMaximumSize()
+      {
+        return new Dimension(w, 1);
+      }
+    };
+    progressBar.setMinimum(0);
+    progressBar.setPreferredSize(progressBar.getMaximumSize());
+    progressLabel = new JLabel(labelText);
+    progressLabel.setFont(new java.awt.Font("Verdana", 0, 11));
+
+    // Use a CardLayout to stop the progress bar panel moving around when
+    // changing visibility
+    labelPanel.setLayout(labelLayout);
+    barPanel.setLayout(barLayout);
+  
+    labelPanel.add(progressLabel, VISIBLE);
+    labelPanel.add(new JPanel(), INVISIBLE);
+    barPanel.add(progressBar, VISIBLE);
+    barPanel.add(new JPanel(), INVISIBLE);
+
+    labelLayout.show(labelPanel, VISIBLE);
+    barLayout.show(barPanel, VISIBLE);
+
+    add(labelPanel, BorderLayout.WEST);
+    add(barPanel, BorderLayout.CENTER);
+    add(new JLabel(" "), BorderLayout.EAST);
+
+    setBorder(BorderFactory.createLineBorder(Color.black));
+    // setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
+  }
+
+  @Override
+  /**
+   * Update the progress bar in response to the event. Expects the value
+   * supplied by the event to be in the range 0-100 i.e. a percentage
+   */
+  public void propertyChange(PropertyChangeEvent evt)
+  {
+    if (evt.getPropertyName().equals(eventName))
+    {
+      int progress = (int) evt.getNewValue();
+      progressBar.setValue(progress);
+
+      // switch progress bar to visible if it is not visible and current
+      // progress is less than MAXVALUE
+      // switch progress bar to invisible if it is visible and we reached
+      // MAXVALUE
+      if (progress < MAXVALUE && !progressBar.isVisible())
+      {
+        labelLayout.show(labelPanel, VISIBLE);
+        barLayout.show(barPanel, VISIBLE);
+      }
+      if (progress >= MAXVALUE)
+      {
+        labelLayout.show(labelPanel, INVISIBLE);
+        barLayout.show(barPanel, INVISIBLE);
+      }
+    }
+  }
+}
index fb90ce7..cb59452 100644 (file)
@@ -24,8 +24,6 @@ import jalview.bin.Cache;
 
 import java.awt.Component;
 
-import javax.swing.JOptionPane;
-
 public class PromptUserConfig implements Runnable
 {
   /**
@@ -120,6 +118,7 @@ public class PromptUserConfig implements Runnable
     this.allowCancel = allowCancel;
   }
 
+  @Override
   public void run()
   {
     if (property == null)
@@ -201,18 +200,12 @@ public class PromptUserConfig implements Runnable
     }
     try
     {
-      int reply = JvOptionPane.showConfirmDialog(
-              Desktop.desktop, // component,
+      int reply = JvOptionPane.showConfirmDialog(Desktop.desktop, // component,
               dialogText, dialogTitle,
               (allowCancel) ? JvOptionPane.YES_NO_CANCEL_OPTION
                       : JvOptionPane.YES_NO_OPTION,
               JvOptionPane.QUESTION_MESSAGE);
-      // now, ask the desktop to relayer any external windows that might have
-      // been obsured
-      if (Desktop.instance != null)
-      {
-        Desktop.instance.relayerWindows();
-      }
+
       // and finish parsing the result
       jalview.bin.Cache.log.debug("Got response : " + reply);
       if (reply == JvOptionPane.YES_OPTION)
@@ -245,7 +238,8 @@ public class PromptUserConfig implements Runnable
     {
       jalview.bin.Cache.log.warn(
               "Unexpected exception when prompting user for yes/no setting for property "
-                      + property, e);
+                      + property,
+              e);
     }
   }
 }
index cbbcf70..c4390c0 100755 (executable)
@@ -54,7 +54,7 @@ public class RedundancyPanel extends GSliderPanel implements Runnable
 
   AlignmentPanel ap;
 
-  Stack<CommandI> historyList = new Stack<CommandI>();
+  Stack<CommandI> historyList = new Stack<>();
 
   // simpler than synching with alignFrame.
 
@@ -101,9 +101,10 @@ public class RedundancyPanel extends GSliderPanel implements Runnable
 
     frame = new JInternalFrame();
     frame.setContentPane(this);
-    Desktop.addInternalFrame(frame, MessageManager
-            .getString("label.redundancy_threshold_selection"), 400, 100,
-            false);
+    Desktop.addInternalFrame(frame,
+            MessageManager
+                    .getString("label.redundancy_threshold_selection"),
+            400, 100, false);
     frame.addInternalFrameListener(new InternalFrameAdapter()
     {
       @Override
@@ -174,8 +175,8 @@ public class RedundancyPanel extends GSliderPanel implements Runnable
     progress.setVisible(false);
     progress = null;
 
-    label.setText(MessageManager
-            .getString("label.enter_redundancy_threshold"));
+    label.setText(
+            MessageManager.getString("label.enter_redundancy_threshold"));
     slider.setVisible(true);
     applyButton.setEnabled(true);
     valueField.setVisible(true);
@@ -193,7 +194,7 @@ public class RedundancyPanel extends GSliderPanel implements Runnable
     }
 
     float value = slider.getValue();
-    List<SequenceI> redundantSequences = new ArrayList<SequenceI>();
+    List<SequenceI> redundantSequences = new ArrayList<>();
     for (int i = 0; i < redundancy.length; i++)
     {
       if (value <= redundancy[i])
@@ -263,8 +264,8 @@ public class RedundancyPanel extends GSliderPanel implements Runnable
       ap.alignFrame.addHistoryItem(cut);
 
       PaintRefresher.Refresh(this, ap.av.getSequenceSetId(), true, true);
-      ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
-              .getSequences());
+      ap.av.firePropertyChange("alignment", null,
+              ap.av.getAlignment().getSequences());
     }
 
   }
@@ -289,12 +290,12 @@ public class RedundancyPanel extends GSliderPanel implements Runnable
     {
       command.undoCommand(af.getViewAlignments());
       ap.av.getHistoryList().remove(command);
-      ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
-              .getSequences());
+      ap.av.firePropertyChange("alignment", null,
+              ap.av.getAlignment().getSequences());
       af.updateEditMenuBar();
     }
 
-    ap.paintAlignment(true);
+    ap.paintAlignment(true, true);
 
     if (historyList.size() == 0)
     {
index 19a9b51..8ae5408 100644 (file)
@@ -53,8 +53,8 @@ public class RestInputParamEditDialog extends GRestInputParamEditDialog
               .newInstance());
     } catch (Throwable x)
     {
-      System.err
-              .println("Unexpected exception when instantiating rest input type.");
+      System.err.println(
+              "Unexpected exception when instantiating rest input type.");
       x.printStackTrace();
     }
     return null;
@@ -103,8 +103,9 @@ public class RestInputParamEditDialog extends GRestInputParamEditDialog
   {
     okcancel.add(frame.cancel);
     okcancel.add(frame.ok);
-    frame.initDialogFrame(dpane, true, true, "Edit parameter for service "
-            + currentservice.getName(), 600, 800);
+    frame.initDialogFrame(dpane, true, true,
+            "Edit parameter for service " + currentservice.getName(), 600,
+            800);
 
     initTypeLists();
     reply = JvOptionPane.CANCEL_OPTION;
@@ -159,14 +160,14 @@ public class RestInputParamEditDialog extends GRestInputParamEditDialog
         newType.token = tok.getText().trim();
         try
         {
-          newType.configureFromArgumentI(opanps.get(
-                  newType.getURLtokenPrefix()).getCurrentSettings());
+          newType.configureFromArgumentI(opanps
+                  .get(newType.getURLtokenPrefix()).getCurrentSettings());
           current = newType;
           updated = true;
         } catch (InvalidArgumentException ex)
         {
-          System.err
-                  .println("IMPLEMENTATION ERROR: Invalid argument for type : "
+          System.err.println(
+                  "IMPLEMENTATION ERROR: Invalid argument for type : "
                           + typeList.getSelectedValue() + "\n");
           ex.printStackTrace();
         }
@@ -186,7 +187,8 @@ public class RestInputParamEditDialog extends GRestInputParamEditDialog
       try
       {
         JPanel inopts = new JPanel(new MigLayout());
-        ArrayList<JPanel> opts = new ArrayList<JPanel>(), prms = new ArrayList<JPanel>();
+        ArrayList<JPanel> opts = new ArrayList<JPanel>(),
+                prms = new ArrayList<JPanel>();
         jtype = (InputType) (type.getConstructor().newInstance());
         typeclass.put(jtype.getURLtokenPrefix(), type);
         // and populate parameters from this type
@@ -213,8 +215,8 @@ public class RestInputParamEditDialog extends GRestInputParamEditDialog
         types.add(jtype.getURLtokenPrefix());
       } catch (Throwable x)
       {
-        System.err
-                .println("Unexpected exception when instantiating rest input type.");
+        System.err.println(
+                "Unexpected exception when instantiating rest input type.");
         x.printStackTrace();
       }
     }
index ec8e7f1..2e2593b 100644 (file)
@@ -241,8 +241,8 @@ public class RestServiceEditorPane extends GRestServiceEditorPane
   protected void iprmsAdd_actionPerformed(ActionEvent e)
   {
     RestInputParamEditDialog dialog = new RestInputParamEditDialog(this,
-            currentservice, "param"
-                    + (1 + currentservice.getInputParams().size()));
+            currentservice,
+            "param" + (1 + currentservice.getInputParams().size()));
     if (dialog.wasUpdated())
     {
       currentservice.getInputParams().put(dialog.current.token,
@@ -274,8 +274,8 @@ public class RestServiceEditorPane extends GRestServiceEditorPane
               MessageManager.getString("label.select_return_type"));
       for (final JvDataType type : JvDataType.values())
       {
-        popup.add(new JMenuItem(type.name())).addActionListener(
-                new ActionListener()
+        popup.add(new JMenuItem(type.name()))
+                .addActionListener(new ActionListener()
                 {
 
                   @Override
@@ -304,8 +304,9 @@ public class RestServiceEditorPane extends GRestServiceEditorPane
       currentservice.addResultDatatype(JvDataType.ANNOTATION);
     }
     initGuiWith(currentservice);
-    rdata.setSelectedIndex(p == -1 ? currentservice.getResultDataTypes()
-            .size() - 1 : p + 1);
+    rdata.setSelectedIndex(
+            p == -1 ? currentservice.getResultDataTypes().size() - 1
+                    : p + 1);
   }
 
   @Override
@@ -354,26 +355,26 @@ public class RestServiceEditorPane extends GRestServiceEditorPane
     StringBuffer warnings = new StringBuffer();
     for (String its : _iparam)
     {
-      Matcher mtch = Pattern.compile("(\\S+)\\s(\\S+):\\[(.+)]").matcher(
-              its);
+      Matcher mtch = Pattern.compile("(\\S+)\\s(\\S+):\\[(.+)]")
+              .matcher(its);
       if (mtch.find())
       {
-        if (!RestServiceDescription.parseTypeString(mtch.group(2) + ":"
-                + mtch.group(3), mtch.group(1), mtch.group(2),
-                mtch.group(3), inputTypes, warnings))
+        if (!RestServiceDescription.parseTypeString(
+                mtch.group(2) + ":" + mtch.group(3), mtch.group(1),
+                mtch.group(2), mtch.group(3), inputTypes, warnings))
         {
-          System.err
-                  .println("IMPLEMENTATION PROBLEM: Cannot parse RestService input parameter string '"
+          System.err.println(
+                  "IMPLEMENTATION PROBLEM: Cannot parse RestService input parameter string '"
                           + its + "'" + "\n" + warnings);
         }
       }
     }
-    char gc = gapChar.getSelectedItem() == null ? ' ' : ((String) gapChar
-            .getSelectedItem()).charAt(0);
+    char gc = gapChar.getSelectedItem() == null ? ' '
+            : ((String) gapChar.getSelectedItem()).charAt(0);
     RestServiceDescription newService = new RestServiceDescription(
-            (String) action.getSelectedItem(), descr.getText().trim(), name
-                    .getText().trim(), url.getText().trim(), urlsuff
-                    .getText().trim(), inputTypes, hSeparable.isSelected(),
+            (String) action.getSelectedItem(), descr.getText().trim(),
+            name.getText().trim(), url.getText().trim(),
+            urlsuff.getText().trim(), inputTypes, hSeparable.isSelected(),
             vSeparable.isSelected(), gc);
 
     if (newService.isValid())
@@ -388,8 +389,8 @@ public class RestServiceEditorPane extends GRestServiceEditorPane
         } catch (Throwable x)
         {
 
-          System.err
-                  .println("IMPLEMENTATION PROBLEM: Cannot parse RestService output parameter string '"
+          System.err.println(
+                  "IMPLEMENTATION PROBLEM: Cannot parse RestService output parameter string '"
                           + its + "'" + "\n" + warnings);
         }
       }
@@ -398,8 +399,8 @@ public class RestServiceEditorPane extends GRestServiceEditorPane
     }
     else
     {
-      System.err
-              .println("IMPLEMENTATION PROBLEM: Restservice generated from GUI is invalid\n"
+      System.err.println(
+              "IMPLEMENTATION PROBLEM: Restservice generated from GUI is invalid\n"
                       + warnings);
 
     }
@@ -432,19 +433,19 @@ public class RestServiceEditorPane extends GRestServiceEditorPane
             }
             else
             {
-              parseRes.setText(MessageManager
-                      .formatMessage(
-                              "label.parsing_failed_syntax_errors_shown_below_param",
-                              new String[] { rsd.getInvalidMessage() }));
+              parseRes.setText(MessageManager.formatMessage(
+                      "label.parsing_failed_syntax_errors_shown_below_param",
+                      new String[]
+                      { rsd.getInvalidMessage() }));
               parseWarnings.setVisible(true);
             }
           } catch (Throwable e)
           {
             e.printStackTrace();
-            parseRes.setText(MessageManager
-                    .formatMessage(
-                            "label.parsing_failed_unrecoverable_exception_thrown_param",
-                            new String[] { e.toString() }));
+            parseRes.setText(MessageManager.formatMessage(
+                    "label.parsing_failed_unrecoverable_exception_thrown_param",
+                    new String[]
+                    { e.toString() }));
             parseWarnings.setVisible(true);
           }
         }
@@ -470,13 +471,10 @@ public class RestServiceEditorPane extends GRestServiceEditorPane
             final Thread runner = Thread.currentThread();
             JFrame df = new JFrame();
             df.getContentPane().setLayout(new BorderLayout());
-            df.getContentPane().add(
-                    (nulserv = !nulserv) ? new RestServiceEditorPane(
-                            jalview.ws.rest.RestClient
-                                    .makeShmmrRestClient()
-                                    .getRestDescription())
-                            : new RestServiceEditorPane(),
-                    BorderLayout.CENTER);
+            df.getContentPane().add((nulserv = !nulserv)
+                    ? new RestServiceEditorPane(jalview.ws.rest.RestClient
+                            .makeShmmrRestClient().getRestDescription())
+                    : new RestServiceEditorPane(), BorderLayout.CENTER);
             df.setBounds(100, 100, 600, 400);
             df.addComponentListener(new ComponentListener()
             {
@@ -557,8 +555,8 @@ public class RestServiceEditorPane extends GRestServiceEditorPane
 
       }
     };
-    JPanel pane = new JPanel(new BorderLayout()), okcancel = new JPanel(
-            new FlowLayout());
+    JPanel pane = new JPanel(new BorderLayout()),
+            okcancel = new JPanel(new FlowLayout());
     pane.add(this, BorderLayout.CENTER);
     okcancel.add(jvd.ok);
     okcancel.add(jvd.cancel);
index 0719fa0..4ef18d4 100755 (executable)
@@ -390,8 +390,9 @@ public class RotatableCanvas extends JPanel implements MouseListener,
     if (points == null)
     {
       g.setFont(new Font("Verdana", Font.PLAIN, 18));
-      g.drawString(MessageManager.getString("label.calculating_pca")
-              + "....", 20, getHeight() / 2);
+      g.drawString(
+              MessageManager.getString("label.calculating_pca") + "....",
+              20, getHeight() / 2);
     }
     else
     {
@@ -434,9 +435,9 @@ public class RotatableCanvas extends JPanel implements MouseListener,
 
     for (int i = 0; i < 3; i++)
     {
-      g.drawLine(getWidth() / 2, getHeight() / 2, (int) ((axes[i][0]
-              * scale * max[0]) + (getWidth() / 2)), (int) ((axes[i][1]
-              * scale * max[1]) + (getHeight() / 2)));
+      g.drawLine(getWidth() / 2, getHeight() / 2,
+              (int) ((axes[i][0] * scale * max[0]) + (getWidth() / 2)),
+              (int) ((axes[i][1] * scale * max[1]) + (getHeight() / 2)));
     }
   }
 
@@ -673,8 +674,8 @@ public class RotatableCanvas extends JPanel implements MouseListener,
         {
           aps[a].av.setSelectionGroup(new SequenceGroup());
           aps[a].av.getSelectionGroup().addOrRemove(found, true);
-          aps[a].av.getSelectionGroup().setEndRes(
-                  aps[a].av.getAlignment().getWidth() - 1);
+          aps[a].av.getSelectionGroup()
+                  .setEndRes(aps[a].av.getAlignment().getWidth() - 1);
         }
       }
       PaintRefresher.Refresh(this, av.getSequenceSetId());
@@ -772,8 +773,10 @@ public class RotatableCanvas extends JPanel implements MouseListener,
     for (int i = 0; i < npoint; i++)
     {
       SequencePoint sp = (SequencePoint) points.elementAt(i);
-      int tmp1 = (int) (((sp.coord[0] - centre[0]) * scale) + ((float) getWidth() / 2.0));
-      int tmp2 = (int) (((sp.coord[1] - centre[1]) * scale) + ((float) getHeight() / 2.0));
+      int tmp1 = (int) (((sp.coord[0] - centre[0]) * scale)
+              + ((float) getWidth() / 2.0));
+      int tmp2 = (int) (((sp.coord[1] - centre[1]) * scale)
+              + ((float) getHeight() / 2.0));
 
       if ((tmp1 > x1) && (tmp1 < x2) && (tmp2 > y1) && (tmp2 < y2))
       {
index ea8e360..e3d03a4 100644 (file)
@@ -59,7 +59,8 @@ public class SVGOptions extends JPanel
     bg.add(text);
 
     JOptionPane pane = new JOptionPane(null, JvOptionPane.DEFAULT_OPTION,
-            JvOptionPane.DEFAULT_OPTION, null, new Object[] { this });
+            JvOptionPane.DEFAULT_OPTION, null, new Object[]
+            { this });
 
     dialog = pane.createDialog(Desktop.desktop, "SVG Rendering options");
     dialog.setVisible(true);
index 2302ebe..798c833 100755 (executable)
@@ -54,8 +54,8 @@ import javax.swing.ToolTipManager;
  * The panel containing the sequence ruler (when not in wrapped mode), and
  * supports a range of mouse operations to select, hide or reveal columns.
  */
-public class ScalePanel extends JPanel implements MouseMotionListener,
-        MouseListener, ViewportListenerI
+public class ScalePanel extends JPanel
+        implements MouseMotionListener, MouseListener, ViewportListenerI
 {
   protected int offy = 4;
 
@@ -168,7 +168,7 @@ public class ScalePanel extends JPanel implements MouseMotionListener,
         {
           av.showColumn(reveal[0]);
           reveal = null;
-          ap.paintAlignment(true);
+          ap.paintAlignment(true, true);
           av.sendSelection();
         }
       });
@@ -184,7 +184,7 @@ public class ScalePanel extends JPanel implements MouseMotionListener,
           {
             av.showAllHiddenColumns();
             reveal = null;
-            ap.paintAlignment(true);
+            ap.paintAlignment(true, true);
             av.sendSelection();
           }
         });
@@ -202,14 +202,13 @@ public class ScalePanel extends JPanel implements MouseMotionListener,
         public void actionPerformed(ActionEvent e)
         {
           av.hideColumns(res, res);
-          if (av.getSelectionGroup() != null
-                  && av.getSelectionGroup().getSize() == av.getAlignment()
-                          .getHeight())
+          if (av.getSelectionGroup() != null && av.getSelectionGroup()
+                  .getSize() == av.getAlignment().getHeight())
           {
             av.setSelectionGroup(null);
           }
 
-          ap.paintAlignment(true);
+          ap.paintAlignment(true, true);
           av.sendSelection();
         }
       });
@@ -261,7 +260,7 @@ public class ScalePanel extends JPanel implements MouseMotionListener,
       sg.setEndRes(max);
     }
     av.setSelectionGroup(sg);
-    ap.paintAlignment(false);
+    ap.paintAlignment(false, false);
     av.sendSelection();
   }
 
@@ -298,7 +297,7 @@ public class ScalePanel extends JPanel implements MouseMotionListener,
       }
       else
       {
-        ap.paintAlignment(false);
+        ap.paintAlignment(false, false);
       }
       return;
     }
@@ -317,7 +316,7 @@ public class ScalePanel extends JPanel implements MouseMotionListener,
       }
     }
     stretchingGroup = false;
-    ap.paintAlignment(false);
+    ap.paintAlignment(false, false);
     av.sendSelection();
   }
 
@@ -347,7 +346,7 @@ public class ScalePanel extends JPanel implements MouseMotionListener,
     {
       stretchingGroup = true;
       cs.stretchGroup(res, sg, min, max);
-      ap.paintAlignment(false);
+      ap.paintAlignment(false, false);
     }
   }
 
@@ -416,8 +415,8 @@ public class ScalePanel extends JPanel implements MouseMotionListener,
      */
     if (!av.getWrapAlignment())
     {
-      drawScale(g, av.getRanges().getStartRes(),
-              av.getRanges().getEndRes(), getWidth(), getHeight());
+      drawScale(g, av.getRanges().getStartRes(), av.getRanges().getEndRes(),
+              getWidth(), getHeight());
     }
   }
 
@@ -498,10 +497,13 @@ public class ScalePanel extends JPanel implements MouseMotionListener,
             continue;
           }
 
-          gg.fillPolygon(new int[] {
-              -1 + res * avCharWidth - avCharHeight / 4,
-              -1 + res * avCharWidth + avCharHeight / 4,
-              -1 + res * avCharWidth }, new int[] { y, y, y + 2 * yOf }, 3);
+          gg.fillPolygon(
+                  new int[]
+                  { -1 + res * avCharWidth - avCharHeight / 4,
+                      -1 + res * avCharWidth + avCharHeight / 4,
+                      -1 + res * avCharWidth },
+                  new int[]
+                  { y, y, y + 2 * yOf }, 3);
         }
       }
     }
@@ -547,7 +549,9 @@ public class ScalePanel extends JPanel implements MouseMotionListener,
     // Here we only want to fastpaint on a scroll, with resize using a normal
     // paint, so scroll events are identified as changes to the horizontal or
     // vertical start value.
-    if (evt.getPropertyName().equals(ViewportRanges.STARTRES))
+    if (evt.getPropertyName().equals(ViewportRanges.STARTRES)
+            || evt.getPropertyName().equals(ViewportRanges.STARTRESANDSEQ)
+            || evt.getPropertyName().equals(ViewportRanges.MOVE_VIEWPORT))
     {
       // scroll event, repaint panel
       repaint();
index a134afa..1e1105f 100755 (executable)
@@ -27,9 +27,11 @@ import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.renderer.ScaleRenderer;
 import jalview.renderer.ScaleRenderer.ScaleMark;
+import jalview.util.Comparison;
 import jalview.viewmodel.ViewportListenerI;
 import jalview.viewmodel.ViewportRanges;
 
+import java.awt.AlphaComposite;
 import java.awt.BasicStroke;
 import java.awt.BorderLayout;
 import java.awt.Color;
@@ -45,49 +47,58 @@ import java.util.List;
 import javax.swing.JComponent;
 
 /**
- * DOCUMENT ME!
+ * The Swing component on which the alignment sequences, and annotations (if
+ * shown), are drawn. This includes scales above, left and right (if shown) in
+ * Wrapped mode, but not the scale above in Unwrapped mode.
  * 
- * @author $author$
- * @version $Revision$
  */
 public class SeqCanvas extends JComponent implements ViewportListenerI
 {
-  final FeatureRenderer fr;
+  private static final String ZEROS = "0000000000";
 
-  final SequenceRenderer sr;
+  final FeatureRenderer fr;
 
   BufferedImage img;
 
-  Graphics2D gg;
+  AlignViewport av;
 
-  int imgWidth;
+  int cursorX = 0;
 
-  int imgHeight;
+  int cursorY = 0;
 
-  AlignViewport av;
+  private final SequenceRenderer seqRdr;
 
-  boolean fastPaint = false;
+  private boolean fastPaint = false;
 
-  int LABEL_WEST;
+  private boolean fastpainting = false;
 
-  int LABEL_EAST;
+  private AnnotationPanel annotations;
 
-  int cursorX = 0;
+  /*
+   * measurements for drawing a wrapped alignment
+   */
+  private int labelWidthEast; // label right width in pixels if shown
 
-  int cursorY = 0;
+  private int labelWidthWest; // label left width in pixels if shown
+
+  private int wrappedSpaceAboveAlignment; // gap between widths
+
+  private int wrappedRepeatHeightPx; // height in pixels of wrapped width
+
+  private int wrappedVisibleWidths; // number of wrapped widths displayed
+
+  private Graphics2D gg;
 
   /**
    * Creates a new SeqCanvas object.
    * 
-   * @param av
-   *          DOCUMENT ME!
+   * @param ap
    */
   public SeqCanvas(AlignmentPanel ap)
   {
     this.av = ap.av;
-    updateViewport();
     fr = new FeatureRenderer(ap);
-    sr = new SequenceRenderer(av);
+    seqRdr = new SequenceRenderer(av);
     setLayout(new BorderLayout());
     PaintRefresher.Register(this, av.getSequenceSetId());
     setBackground(Color.white);
@@ -97,7 +108,7 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
 
   public SequenceRenderer getSequenceRenderer()
   {
-    return sr;
+    return seqRdr;
   }
 
   public FeatureRenderer getFeatureRenderer()
@@ -105,31 +116,36 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
     return fr;
   }
 
-  int charHeight = 0, charWidth = 0;
-
-  private void updateViewport()
-  {
-    charHeight = av.getCharHeight();
-    charWidth = av.getCharWidth();
-  }
-
   /**
-   * DOCUMENT ME!
+   * Draws the scale above a region of a wrapped alignment, consisting of a
+   * column number every major interval (10 columns).
    * 
    * @param g
-   *          DOCUMENT ME!
+   *          the graphics context to draw on, positioned at the start (bottom
+   *          left) of the line on which to draw any scale marks
    * @param startx
-   *          DOCUMENT ME!
+   *          start alignment column (0..)
    * @param endx
-   *          DOCUMENT ME!
+   *          end alignment column (0..)
    * @param ypos
-   *          DOCUMENT ME!
+   *          y offset to draw at
    */
   private void drawNorthScale(Graphics g, int startx, int endx, int ypos)
   {
-    updateViewport();
-    for (ScaleMark mark : new ScaleRenderer().calculateMarks(av, startx,
-            endx))
+    int charHeight = av.getCharHeight();
+    int charWidth = av.getCharWidth();
+
+    /*
+     * white fill the scale space (for the fastPaint case)
+     */
+    g.setColor(Color.white);
+    g.fillRect(0, ypos - charHeight - charHeight / 2, getWidth(),
+            charHeight * 3 / 2 + 2);
+    g.setColor(Color.black);
+
+    List<ScaleMark> marks = new ScaleRenderer().calculateMarks(av, startx,
+            endx);
+    for (ScaleMark mark : marks)
     {
       int mpos = mark.column; // (i - startx - 1)
       if (mpos < 0)
@@ -144,488 +160,820 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
         {
           g.drawString(mstring, mpos * charWidth, ypos - (charHeight / 2));
         }
-        g.drawLine((mpos * charWidth) + (charWidth / 2), (ypos + 2)
-                - (charHeight / 2), (mpos * charWidth) + (charWidth / 2),
-                ypos - 2);
+
+        /*
+         * draw a tick mark below the column number, centred on the column;
+         * height of tick mark is 4 pixels less than half a character
+         */
+        int xpos = (mpos * charWidth) + (charWidth / 2);
+        g.drawLine(xpos, (ypos + 2) - (charHeight / 2), xpos, ypos - 2);
       }
     }
   }
 
   /**
-   * DOCUMENT ME!
+   * Draw the scale to the left or right of a wrapped alignment
    * 
    * @param g
-   *          DOCUMENT ME!
+   *          graphics context, positioned at the start of the scale to be drawn
    * @param startx
-   *          DOCUMENT ME!
+   *          first column of wrapped width (0.. excluding any hidden columns)
    * @param endx
-   *          DOCUMENT ME!
+   *          last column of wrapped width (0.. excluding any hidden columns)
    * @param ypos
-   *          DOCUMENT ME!
+   *          vertical offset at which to begin the scale
+   * @param left
+   *          if true, scale is left of residues, if false, scale is right
    */
-  void drawWestScale(Graphics g, int startx, int endx, int ypos)
+  void drawVerticalScale(Graphics g, final int startx, final int endx,
+          final int ypos, final boolean left)
   {
-    FontMetrics fm = getFontMetrics(av.getFont());
-    ypos += charHeight;
+    int charHeight = av.getCharHeight();
+    int charWidth = av.getCharWidth();
 
-    if (av.hasHiddenColumns())
-    {
-      startx = av.getAlignment().getHiddenColumns()
-              .adjustForHiddenColumns(startx);
-      endx = av.getAlignment().getHiddenColumns()
-              .adjustForHiddenColumns(endx);
-    }
+    int yPos = ypos + charHeight;
+    int startX = startx;
+    int endX = endx;
 
-    int maxwidth = av.getAlignment().getWidth();
     if (av.hasHiddenColumns())
     {
-      maxwidth = av.getAlignment().getHiddenColumns()
-              .findColumnPosition(maxwidth) - 1;
+      HiddenColumns hiddenColumns = av.getAlignment().getHiddenColumns();
+      startX = hiddenColumns.adjustForHiddenColumns(startx);
+      endX = hiddenColumns.adjustForHiddenColumns(endx);
     }
+    FontMetrics fm = getFontMetrics(av.getFont());
 
-    // WEST SCALE
     for (int i = 0; i < av.getAlignment().getHeight(); i++)
     {
       SequenceI seq = av.getAlignment().getSequenceAt(i);
-      int index = startx;
-      int value = -1;
 
-      while (index < endx)
+      /*
+       * find sequence position of first non-gapped position -
+       * to the right if scale left, to the left if scale right
+       */
+      int index = left ? startX : endX;
+      int value = -1;
+      while (index >= startX && index <= endX)
       {
-        if (jalview.util.Comparison.isGap(seq.getCharAt(index)))
+        if (!Comparison.isGap(seq.getCharAt(index)))
+        {
+          value = seq.findPosition(index);
+          break;
+        }
+        if (left)
         {
           index++;
-
-          continue;
         }
-
-        value = av.getAlignment().getSequenceAt(i).findPosition(index);
-
-        break;
+        else
+        {
+          index--;
+        }
       }
 
+      /*
+       * white fill the space for the scale
+       */
+      g.setColor(Color.white);
+      int y = (yPos + (i * charHeight)) - (charHeight / 5);
+      // fillRect origin is top left of rectangle
+      g.fillRect(0, y - charHeight, left ? labelWidthWest : labelWidthEast,
+              charHeight + 1);
+
       if (value != -1)
       {
-        int x = LABEL_WEST - fm.stringWidth(String.valueOf(value))
-                - charWidth / 2;
-        g.drawString(value + "", x, (ypos + (i * charHeight))
-                - (charHeight / 5));
+        /*
+         * draw scale value, right justified within its width less half a
+         * character width padding on the right
+         */
+        int labelSpace = left ? labelWidthWest : labelWidthEast;
+        labelSpace -= charWidth / 2; // leave space to the right
+        String valueAsString = String.valueOf(value);
+        int labelLength = fm.stringWidth(valueAsString);
+        int xOffset = labelSpace - labelLength;
+        g.setColor(Color.black);
+        g.drawString(valueAsString, xOffset, y);
       }
     }
   }
 
   /**
-   * DOCUMENT ME!
+   * Does a fast paint of an alignment in response to a scroll. Most of the
+   * visible region is simply copied and shifted, and then any newly visible
+   * columns or rows are drawn. The scroll may be horizontal or vertical, but
+   * not both at once. Scrolling may be the result of
+   * <ul>
+   * <li>dragging a scroll bar</li>
+   * <li>clicking in the scroll bar</li>
+   * <li>scrolling by trackpad, middle mouse button, or other device</li>
+   * <li>by moving the box in the Overview window</li>
+   * <li>programmatically to make a highlighted position visible</li>
+   * </ul>
    * 
-   * @param g
-   *          DOCUMENT ME!
-   * @param startx
-   *          DOCUMENT ME!
-   * @param endx
-   *          DOCUMENT ME!
-   * @param ypos
-   *          DOCUMENT ME!
+   * @param horizontal
+   *          columns to shift right (positive) or left (negative)
+   * @param vertical
+   *          rows to shift down (positive) or up (negative)
    */
-  void drawEastScale(Graphics g, int startx, int endx, int ypos)
+  public void fastPaint(int horizontal, int vertical)
   {
-    ypos += charHeight;
-
-    if (av.hasHiddenColumns())
+    if (fastpainting || gg == null || img == null)
     {
-      endx = av.getAlignment().getHiddenColumns()
-              .adjustForHiddenColumns(endx);
+      return;
     }
+    fastpainting = true;
+    fastPaint = true;
 
-    SequenceI seq;
-    // EAST SCALE
-    for (int i = 0; i < av.getAlignment().getHeight(); i++)
+    try
     {
-      seq = av.getAlignment().getSequenceAt(i);
-      int index = endx;
-      int value = -1;
+      int charHeight = av.getCharHeight();
+      int charWidth = av.getCharWidth();
+    
+      ViewportRanges ranges = av.getRanges();
+      int startRes = ranges.getStartRes();
+      int endRes = ranges.getEndRes();
+      int startSeq = ranges.getStartSeq();
+      int endSeq = ranges.getEndSeq();
+      int transX = 0;
+      int transY = 0;
+
+      gg.copyArea(horizontal * charWidth, vertical * charHeight,
+              img.getWidth(), img.getHeight(), -horizontal * charWidth,
+              -vertical * charHeight);
+
+      if (horizontal > 0) // scrollbar pulled right, image to the left
+      {
+        transX = (endRes - startRes - horizontal) * charWidth;
+        startRes = endRes - horizontal;
+      }
+      else if (horizontal < 0)
+      {
+        endRes = startRes - horizontal;
+      }
 
-      while (index > startx)
+      if (vertical > 0) // scroll down
       {
-        if (jalview.util.Comparison.isGap(seq.getCharAt(index)))
-        {
-          index--;
+        startSeq = endSeq - vertical;
 
-          continue;
+        if (startSeq < ranges.getStartSeq())
+        { // ie scrolling too fast, more than a page at a time
+          startSeq = ranges.getStartSeq();
+        }
+        else
+        {
+          transY = img.getHeight() - ((vertical + 1) * charHeight);
         }
-
-        value = seq.findPosition(index);
-
-        break;
       }
-
-      if (value != -1)
+      else if (vertical < 0)
       {
-        g.drawString(String.valueOf(value), 0, (ypos + (i * charHeight))
-                - (charHeight / 5));
+        endSeq = startSeq - vertical;
+
+        if (endSeq > ranges.getEndSeq())
+        {
+          endSeq = ranges.getEndSeq();
+        }
       }
-    }
-  }
 
-  boolean fastpainting = false;
+      gg.translate(transX, transY);
+      drawPanel(gg, startRes, endRes, startSeq, endSeq, 0);
+      gg.translate(-transX, -transY);
 
-  /**
-   * need to make this thread safe move alignment rendering in response to
-   * slider adjustment
-   * 
-   * @param horizontal
-   *          shift along
-   * @param vertical
-   *          shift up or down in repaint
-   */
-  public void fastPaint(int horizontal, int vertical)
-  {
-    if (fastpainting || gg == null)
+      repaint();
+    } finally
     {
-      return;
+      fastpainting = false;
     }
-    fastpainting = true;
-    fastPaint = true;
-    updateViewport();
+  }
+
+  @Override
+  public void paintComponent(Graphics g)
+  {
+    super.paintComponent(g);    
+    
+    int charHeight = av.getCharHeight();
+    int charWidth = av.getCharWidth();
 
     ViewportRanges ranges = av.getRanges();
-    int sr = ranges.getStartRes();
-    int er = ranges.getEndRes();
-    int ss = ranges.getStartSeq();
-    int es = ranges.getEndSeq();
-    int transX = 0;
-    int transY = 0;
 
-    gg.copyArea(horizontal * charWidth, vertical * charHeight, imgWidth,
-            imgHeight, -horizontal * charWidth, -vertical * charHeight);
+    int width = getWidth();
+    int height = getHeight();
 
-    if (horizontal > 0) // scrollbar pulled right, image to the left
-    {
-      transX = (er - sr - horizontal) * charWidth;
-      sr = er - horizontal;
-    }
-    else if (horizontal < 0)
+    width -= (width % charWidth);
+    height -= (height % charHeight);
+
+    // selectImage is the selection group outline image
+    BufferedImage selectImage = drawSelectionGroup(
+            ranges.getStartRes(), ranges.getEndRes(),
+            ranges.getStartSeq(), ranges.getEndSeq());
+
+    if ((img != null) && (fastPaint
+            || (getVisibleRect().width != g.getClipBounds().width)
+            || (getVisibleRect().height != g.getClipBounds().height)))
     {
-      er = sr - horizontal;
+      BufferedImage lcimg = buildLocalImage(selectImage);
+      g.drawImage(lcimg, 0, 0, this);
+      fastPaint = false;
     }
-    else if (vertical > 0) // scroll down
+    else if ((width > 0) && (height > 0))
     {
-      ss = es - vertical;
-
-      if (ss < ranges.getStartSeq())
-      { // ie scrolling too fast, more than a page at a time
-        ss = ranges.getStartSeq();
+      // img is a cached version of the last view we drew, if any
+      // if we have no img or the size has changed, make a new one
+      if (img == null || width != img.getWidth()
+              || height != img.getHeight())
+      {
+        img = setupImage();
+        if (img == null)
+        {
+          return;
+        }
+        gg = (Graphics2D) img.getGraphics();
+        gg.setFont(av.getFont());
       }
-      else
+
+      if (av.antiAlias)
       {
-        transY = imgHeight - ((vertical + 1) * charHeight);
+        gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+                RenderingHints.VALUE_ANTIALIAS_ON);
       }
-    }
-    else if (vertical < 0)
-    {
-      es = ss - vertical;
 
-      if (es > ranges.getEndSeq())
+      gg.setColor(Color.white);
+      gg.fillRect(0, 0, img.getWidth(), img.getHeight());
+
+      if (av.getWrapAlignment())
       {
-        es = ranges.getEndSeq();
+        drawWrappedPanel(gg, getWidth(), getHeight(), ranges.getStartRes());
+      }
+      else
+      {
+        drawPanel(gg, ranges.getStartRes(), ranges.getEndRes(),
+                ranges.getStartSeq(), ranges.getEndSeq(), 0);
       }
-    }
 
-    gg.translate(transX, transY);
-    drawPanel(gg, sr, er, ss, es, 0);
-    gg.translate(-transX, -transY);
+      // lcimg is a local *copy* of img which we'll draw selectImage on top of
+      BufferedImage lcimg = buildLocalImage(selectImage);
+      g.drawImage(lcimg, 0, 0, this);
 
-    repaint();
-    fastpainting = false;
-  }
+    }
 
+    if (av.cursorMode)
+    {
+      drawCursor(g, ranges.getStartRes(), ranges.getEndRes(),
+              ranges.getStartSeq(), ranges.getEndSeq());
+    }
+  }
+  
   /**
-   * Definitions of startx and endx (hopefully): SMJS This is what I'm working
-   * towards! startx is the first residue (starting at 0) to display. endx is
-   * the last residue to display (starting at 0). starty is the first sequence
-   * to display (starting at 0). endy is the last sequence to display (starting
-   * at 0). NOTE 1: The av limits are set in setFont in this class and in the
-   * adjustment listener in SeqPanel when the scrollbars move.
+   * Draw an alignment panel for printing
+   * 
+   * @param g1
+   *          Graphics object to draw with
+   * @param startRes
+   *          start residue of print area
+   * @param endRes
+   *          end residue of print area
+   * @param startSeq
+   *          start sequence of print area
+   * @param endSeq
+   *          end sequence of print area
    */
-
-  // Set this to false to force a full panel paint
-  @Override
-  public void paintComponent(Graphics g)
+  public void drawPanelForPrinting(Graphics g1, int startRes, int endRes,
+          int startSeq, int endSeq)
   {
-    updateViewport();
-    BufferedImage lcimg = img; // take reference since other threads may null
-    // img and call later.
-    super.paintComponent(g);
+    drawPanel(g1, startRes, endRes, startSeq, endSeq, 0);
 
-    if (lcimg != null
-            && (fastPaint
-                    || (getVisibleRect().width != g.getClipBounds().width) || (getVisibleRect().height != g
-                    .getClipBounds().height)))
+    BufferedImage selectImage = drawSelectionGroup(startRes, endRes,
+            startSeq, endSeq);
+    if (selectImage != null)
     {
-      g.drawImage(lcimg, 0, 0, this);
-      fastPaint = false;
-      return;
+      ((Graphics2D) g1).setComposite(AlphaComposite
+              .getInstance(AlphaComposite.SRC_OVER));
+      g1.drawImage(selectImage, 0, 0, this);
     }
+  }
 
-    // this draws the whole of the alignment
-    imgWidth = getWidth();
-    imgHeight = getHeight();
-
-    imgWidth -= (imgWidth % charWidth);
-    imgHeight -= (imgHeight % charHeight);
+  /**
+   * Draw a wrapped alignment panel for printing
+   * 
+   * @param g
+   *          Graphics object to draw with
+   * @param canvasWidth
+   *          width of drawing area
+   * @param canvasHeight
+   *          height of drawing area
+   * @param startRes
+   *          start residue of print area
+   */
+  public void drawWrappedPanelForPrinting(Graphics g, int canvasWidth,
+          int canvasHeight, int startRes)
+  {
+    SequenceGroup group = av.getSelectionGroup();
 
-    if ((imgWidth < 1) || (imgHeight < 1))
-    {
-      return;
-    }
+    drawWrappedPanel(g, canvasWidth, canvasHeight, startRes);
 
-    if (lcimg == null || imgWidth != lcimg.getWidth()
-            || imgHeight != lcimg.getHeight())
+    if (group != null)
     {
+      BufferedImage selectImage = null;
       try
       {
-        lcimg = img = new BufferedImage(imgWidth, imgHeight,
-                BufferedImage.TYPE_INT_RGB);
-        gg = (Graphics2D) img.getGraphics();
-        gg.setFont(av.getFont());
+        selectImage = new BufferedImage(canvasWidth, canvasHeight,
+                BufferedImage.TYPE_INT_ARGB); // ARGB so alpha compositing works
       } catch (OutOfMemoryError er)
       {
         System.gc();
-        System.err.println("SeqCanvas OutOfMemory Redraw Error.\n" + er);
-        new OOMWarning("Creating alignment image for display", er);
-
-        return;
+        System.err.println("Print image OutOfMemory Error.\n" + er);
+        new OOMWarning("Creating wrapped alignment image for printing", er);
+      }
+      if (selectImage != null)
+      {
+        Graphics2D g2 = selectImage.createGraphics();
+        setupSelectionGroup(g2, selectImage);
+        drawWrappedSelection(g2, group, canvasWidth, canvasHeight,
+                startRes);
+
+        g2.setComposite(
+                AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
+        g.drawImage(selectImage, 0, 0, this);
+        g2.dispose();
       }
     }
+  }
 
-    if (av.antiAlias)
+  /*
+   * Make a local image by combining the cached image img
+   * with any selection
+   */
+  private BufferedImage buildLocalImage(BufferedImage selectImage)
+  {
+    // clone the cached image
+    BufferedImage lcimg = new BufferedImage(img.getWidth(), img.getHeight(),
+            img.getType());
+    Graphics2D g2d = lcimg.createGraphics();
+    g2d.drawImage(img, 0, 0, null);
+
+    // overlay selection group on lcimg
+    if (selectImage != null)
     {
-      gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
-              RenderingHints.VALUE_ANTIALIAS_ON);
+      g2d.setComposite(
+              AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
+      g2d.drawImage(selectImage, 0, 0, this);
     }
 
-    gg.setColor(Color.white);
-    gg.fillRect(0, 0, imgWidth, imgHeight);
+    g2d.dispose();
 
-    ViewportRanges ranges = av.getRanges();
-    if (av.getWrapAlignment())
+    return lcimg;
+  }
+
+  /*
+   * Set up a buffered image of the correct height and size for the sequence canvas
+   */
+  private BufferedImage setupImage()
+  {
+    BufferedImage lcimg = null;
+
+    int charWidth = av.getCharWidth();
+    int charHeight = av.getCharHeight();
+    
+    int width = getWidth();
+    int height = getHeight();
+
+    width -= (width % charWidth);
+    height -= (height % charHeight);
+
+    if ((width < 1) || (height < 1))
     {
-      drawWrappedPanel(gg, getWidth(), getHeight(), ranges.getStartRes());
+      return null;
     }
-    else
+
+    try
     {
-      drawPanel(gg, ranges.getStartRes(), ranges.getEndRes(),
-              ranges.getStartSeq(), ranges.getEndSeq(), 0);
-    }
+      lcimg = new BufferedImage(width, height,
+              BufferedImage.TYPE_INT_ARGB); // ARGB so alpha compositing works
+    } catch (OutOfMemoryError er)
+    {
+      System.gc();
+      System.err.println(
+              "Group image OutOfMemory Redraw Error.\n" + er);
+      new OOMWarning("Creating alignment image for display", er);
 
-    g.drawImage(lcimg, 0, 0, this);
+      return null;
+    }
 
+    return lcimg;
   }
 
   /**
-   * DOCUMENT ME!
+   * Returns the visible width of the canvas in residues, after allowing for
+   * East or West scales (if shown)
    * 
-   * @param cwidth
-   *          DOCUMENT ME!
+   * @param canvasWidth
+   *          the width in pixels (possibly including scales)
    * 
-   * @return DOCUMENT ME!
+   * @return
    */
-  public int getWrappedCanvasWidth(int cwidth)
+  public int getWrappedCanvasWidth(int canvasWidth)
   {
-    FontMetrics fm = getFontMetrics(av.getFont());
+    int charWidth = av.getCharWidth();
 
-    LABEL_EAST = 0;
-    LABEL_WEST = 0;
+    FontMetrics fm = getFontMetrics(av.getFont());
 
-    if (av.getScaleRightWrapped())
+    int labelWidth = 0;
+    
+    if (av.getScaleRightWrapped() || av.getScaleLeftWrapped())
     {
-      LABEL_EAST = fm.stringWidth(getMask());
+      labelWidth = getLabelWidth(fm);
     }
 
-    if (av.getScaleLeftWrapped())
-    {
-      LABEL_WEST = fm.stringWidth(getMask());
-    }
+    labelWidthEast = av.getScaleRightWrapped() ? labelWidth : 0;
+
+    labelWidthWest = av.getScaleLeftWrapped() ? labelWidth : 0;
 
-    return (cwidth - LABEL_EAST - LABEL_WEST) / charWidth;
+    return (canvasWidth - labelWidthEast - labelWidthWest) / charWidth;
   }
 
   /**
-   * Generates a string of zeroes.
+   * Returns a pixel width sufficient to show the largest sequence coordinate
+   * (end position) in the alignment, calculated as the FontMetrics width of
+   * zeroes "0000000" limited to the number of decimal digits to be shown (3 for
+   * 1-10, 4 for 11-99 etc). One character width is added to this, to allow for
+   * half a character width space on either side.
    * 
-   * @return String
+   * @param fm
+   * @return
    */
-  String getMask()
+  protected int getLabelWidth(FontMetrics fm)
   {
-    String mask = "00";
+    /*
+     * find the biggest sequence end position we need to show
+     * (note this is not necessarily the sequence length)
+     */
     int maxWidth = 0;
-    int tmp;
-    for (int i = 0; i < av.getAlignment().getHeight(); i++)
+    AlignmentI alignment = av.getAlignment();
+    for (int i = 0; i < alignment.getHeight(); i++)
     {
-      tmp = av.getAlignment().getSequenceAt(i).getEnd();
-      if (tmp > maxWidth)
-      {
-        maxWidth = tmp;
-      }
+      maxWidth = Math.max(maxWidth, alignment.getSequenceAt(i).getEnd());
     }
 
+    int length = 0;
     for (int i = maxWidth; i > 0; i /= 10)
     {
-      mask += "0";
+      length++;
     }
-    return mask;
+
+    return fm.stringWidth(ZEROS.substring(0, length)) + av.getCharWidth();
   }
 
   /**
-   * DOCUMENT ME!
+   * Draws as many widths of a wrapped alignment as can fit in the visible
+   * window
    * 
    * @param g
-   *          DOCUMENT ME!
    * @param canvasWidth
-   *          DOCUMENT ME!
+   *          available width in pixels
    * @param canvasHeight
-   *          DOCUMENT ME!
-   * @param startRes
-   *          DOCUMENT ME!
+   *          available height in pixels
+   * @param startColumn
+   *          the first column (0...) of the alignment to draw
    */
   public void drawWrappedPanel(Graphics g, int canvasWidth,
-          int canvasHeight, int startRes)
+          int canvasHeight, final int startColumn)
   {
-    updateViewport();
-    AlignmentI al = av.getAlignment();
+    int wrappedWidthInResidues = calculateWrappedGeometry(canvasWidth,
+            canvasHeight);
 
-    FontMetrics fm = getFontMetrics(av.getFont());
-
-    LABEL_EAST = 0;
-    LABEL_WEST = 0;
+    av.setWrappedWidth(wrappedWidthInResidues);
 
-    if (av.getScaleRightWrapped())
+    ViewportRanges ranges = av.getRanges();
+    ranges.setViewportStartAndWidth(startColumn, wrappedWidthInResidues);
+
+    /*
+     * draw one width at a time (including any scales or annotation shown),
+     * until we have run out of either alignment or vertical space available
+     */
+    int ypos = wrappedSpaceAboveAlignment;
+    int maxWidth = ranges.getVisibleAlignmentWidth();
+
+    int start = startColumn;
+    int currentWidth = 0;
+    while ((currentWidth < wrappedVisibleWidths) && (start < maxWidth))
     {
-      LABEL_EAST = fm.stringWidth(getMask());
+      int endColumn = Math
+              .min(maxWidth, start + wrappedWidthInResidues - 1);
+      drawWrappedWidth(g, ypos, start, endColumn, canvasHeight);
+      ypos += wrappedRepeatHeightPx;
+      start += wrappedWidthInResidues;
+      currentWidth++;
     }
 
-    if (av.getScaleLeftWrapped())
+    drawWrappedDecorators(g, startColumn);
+  }
+
+  /**
+   * Calculates and saves values needed when rendering a wrapped alignment.
+   * These depend on many factors, including
+   * <ul>
+   * <li>canvas width and height</li>
+   * <li>number of visible sequences, and height of annotations if shown</li>
+   * <li>font and character width</li>
+   * <li>whether scales are shown left, right or above the alignment</li>
+   * </ul>
+   * 
+   * @param canvasWidth
+   * @param canvasHeight
+   * @return the number of residue columns in each width
+   */
+  protected int calculateWrappedGeometry(int canvasWidth, int canvasHeight)
+  {
+    int charHeight = av.getCharHeight();
+
+    /*
+     * vertical space in pixels between wrapped widths of alignment
+     * - one character height, or two if scale above is drawn
+     */
+    wrappedSpaceAboveAlignment = charHeight
+            * (av.getScaleAboveWrapped() ? 2 : 1);
+
+    /*
+     * height in pixels of the wrapped widths
+     */
+    wrappedRepeatHeightPx = wrappedSpaceAboveAlignment;
+    // add sequences
+    wrappedRepeatHeightPx += av.getRanges().getViewportHeight()
+            * charHeight;
+    // add annotations panel height if shown
+    wrappedRepeatHeightPx += getAnnotationHeight();
+
+    /*
+     * number of visible widths (the last one may be part height),
+     * ensuring a part height includes at least one sequence
+     */
+    ViewportRanges ranges = av.getRanges();
+    wrappedVisibleWidths = canvasHeight / wrappedRepeatHeightPx;
+    int remainder = canvasHeight % wrappedRepeatHeightPx;
+    if (remainder >= (wrappedSpaceAboveAlignment + charHeight))
     {
-      LABEL_WEST = fm.stringWidth(getMask());
+      wrappedVisibleWidths++;
     }
 
-    int hgap = charHeight;
-    if (av.getScaleAboveWrapped())
+    /*
+     * compute width in residues; this also sets East and West label widths
+     */
+    int wrappedWidthInResidues = getWrappedCanvasWidth(canvasWidth);
+
+    /*
+     *  limit visibleWidths to not exceed width of alignment
+     */
+    int xMax = ranges.getVisibleAlignmentWidth();
+    int startToEnd = xMax - ranges.getStartRes();
+    int maxWidths = startToEnd / wrappedWidthInResidues;
+    if (startToEnd % wrappedWidthInResidues > 0)
     {
-      hgap += charHeight;
+      maxWidths++;
     }
+    wrappedVisibleWidths = Math.min(wrappedVisibleWidths, maxWidths);
 
-    int cWidth = (canvasWidth - LABEL_EAST - LABEL_WEST) / charWidth;
-    int cHeight = av.getAlignment().getHeight() * charHeight;
+    return wrappedWidthInResidues;
+  }
 
-    av.setWrappedWidth(cWidth);
+  /**
+   * Draws one width of a wrapped alignment, including sequences and
+   * annnotations, if shown, but not scales or hidden column markers
+   * 
+   * @param g
+   * @param ypos
+   * @param startColumn
+   * @param endColumn
+   * @param canvasHeight
+   */
+  protected void drawWrappedWidth(Graphics g, int ypos, int startColumn,
+          int endColumn, int canvasHeight)
+  {
+    ViewportRanges ranges = av.getRanges();
+    int viewportWidth = ranges.getViewportWidth();
+
+    int endx = Math.min(startColumn + viewportWidth - 1, endColumn);
+
+    /*
+     * move right before drawing by the width of the scale left (if any)
+     * plus column offset from left margin (usually zero, but may be non-zero
+     * when fast painting is drawing just a few columns)
+     */
+    int charWidth = av.getCharWidth();
+    int xOffset = labelWidthWest
+            + ((startColumn - ranges.getStartRes()) % viewportWidth)
+            * charWidth;
+    g.translate(xOffset, 0);
+
+    // When printing we have an extra clipped region,
+    // the Printable page which we need to account for here
+    Shape clip = g.getClip();
+
+    if (clip == null)
+    {
+      g.setClip(0, 0, viewportWidth * charWidth, canvasHeight);
+    }
+    else
+    {
+      g.setClip(0, (int) clip.getBounds().getY(),
+              viewportWidth * charWidth, (int) clip.getBounds().getHeight());
+    }
 
-    av.getRanges().setViewportStartAndWidth(startRes, cWidth);
+    /*
+     * white fill the region to be drawn (so incremental fast paint doesn't
+     * scribble over an existing image)
+     */
+    g.setColor(Color.white);
+    g.fillRect(0, ypos, (endx - startColumn + 1) * charWidth,
+            wrappedRepeatHeightPx);
 
-    int endx;
-    int ypos = hgap;
-    int maxwidth = av.getAlignment().getWidth();
+    drawPanel(g, startColumn, endx, 0, av.getAlignment().getHeight() - 1,
+            ypos);
 
-    if (av.hasHiddenColumns())
-    {
-      maxwidth = av.getAlignment().getHiddenColumns()
-              .findColumnPosition(maxwidth);
-    }
+    int cHeight = av.getAlignment().getHeight() * av.getCharHeight();
 
-    while ((ypos <= canvasHeight) && (startRes < maxwidth))
+    if (av.isShowAnnotation())
     {
-      endx = startRes + cWidth - 1;
-
-      if (endx > maxwidth)
+      g.translate(0, cHeight + ypos + 3);
+      if (annotations == null)
       {
-        endx = maxwidth;
+        annotations = new AnnotationPanel(av);
       }
 
-      g.setFont(av.getFont());
-      g.setColor(Color.black);
+      annotations.renderer.drawComponent(annotations, av, g, -1,
+              startColumn, endx + 1);
+      g.translate(0, -cHeight - ypos - 3);
+    }
+    g.setClip(clip);
+    g.translate(-xOffset, 0);
+  }
+
+  /**
+   * Draws scales left, right and above (if shown), and any hidden column
+   * markers, on all widths of the wrapped alignment
+   * 
+   * @param g
+   * @param startColumn
+   */
+  protected void drawWrappedDecorators(Graphics g, final int startColumn)
+  {
+    int charWidth = av.getCharWidth();
+
+    g.setFont(av.getFont());
+    g.setColor(Color.black);
+
+    int ypos = wrappedSpaceAboveAlignment;
+    ViewportRanges ranges = av.getRanges();
+    int viewportWidth = ranges.getViewportWidth();
+    int maxWidth = ranges.getVisibleAlignmentWidth();
+    int widthsDrawn = 0;
+    int startCol = startColumn;
+
+    while (widthsDrawn < wrappedVisibleWidths)
+    {
+      int endColumn = Math.min(maxWidth, startCol + viewportWidth - 1);
 
       if (av.getScaleLeftWrapped())
       {
-        drawWestScale(g, startRes, endx, ypos);
+        drawVerticalScale(g, startCol, endColumn - 1, ypos, true);
       }
 
       if (av.getScaleRightWrapped())
       {
-        g.translate(canvasWidth - LABEL_EAST, 0);
-        drawEastScale(g, startRes, endx, ypos);
-        g.translate(-(canvasWidth - LABEL_EAST), 0);
+        int x = labelWidthWest + viewportWidth * charWidth;
+        g.translate(x, 0);
+        drawVerticalScale(g, startCol, endColumn, ypos, false);
+        g.translate(-x, 0);
       }
 
-      g.translate(LABEL_WEST, 0);
+      /*
+       * white fill region of scale above and hidden column markers
+       * (to support incremental fast paint of image)
+       */
+      g.translate(labelWidthWest, 0);
+      g.setColor(Color.white);
+      g.fillRect(0, ypos - wrappedSpaceAboveAlignment, viewportWidth
+              * charWidth + labelWidthWest, wrappedSpaceAboveAlignment);
+      g.setColor(Color.black);
+      g.translate(-labelWidthWest, 0);
+
+      g.translate(labelWidthWest, 0);
 
       if (av.getScaleAboveWrapped())
       {
-        drawNorthScale(g, startRes, endx, ypos);
+        drawNorthScale(g, startCol, endColumn, ypos);
       }
 
       if (av.hasHiddenColumns() && av.getShowHiddenMarkers())
       {
-        g.setColor(Color.blue);
-        int res;
-        HiddenColumns hidden = av.getAlignment().getHiddenColumns();
-        List<Integer> positions = hidden.findHiddenRegionPositions();
-        for (int pos : positions)
-        {
-          res = pos - startRes;
+        drawHiddenColumnMarkers(g, ypos, startCol, endColumn);
+      }
 
-          if (res < 0 || res > endx - startRes)
-          {
-            continue;
-          }
+      g.translate(-labelWidthWest, 0);
 
-          gg.fillPolygon(
-                  new int[] { res * charWidth - charHeight / 4,
-                      res * charWidth + charHeight / 4, res * charWidth },
-                  new int[] { ypos - (charHeight / 2),
-                      ypos - (charHeight / 2), ypos - (charHeight / 2) + 8 },
-                  3);
+      ypos += wrappedRepeatHeightPx;
+      startCol += viewportWidth;
+      widthsDrawn++;
+    }
+  }
 
-        }
-      }
+  /**
+   * Draws markers (triangles) above hidden column positions between startColumn
+   * and endColumn.
+   * 
+   * @param g
+   * @param ypos
+   * @param startColumn
+   * @param endColumn
+   */
+  protected void drawHiddenColumnMarkers(Graphics g, int ypos,
+          int startColumn, int endColumn)
+  {
+    int charHeight = av.getCharHeight();
+    int charWidth = av.getCharWidth();
 
-      // When printing we have an extra clipped region,
-      // the Printable page which we need to account for here
-      Shape clip = g.getClip();
+    g.setColor(Color.blue);
+    HiddenColumns hidden = av.getAlignment().getHiddenColumns();
+    List<Integer> positions = hidden.findHiddenRegionPositions();
+    for (int pos : positions)
+    {
+      int res = pos - startColumn;
 
-      if (clip == null)
+      if (res < 0 || res > endColumn - startColumn + 1)
       {
-        g.setClip(0, 0, cWidth * charWidth, canvasHeight);
-      }
-      else
-      {
-        g.setClip(0, (int) clip.getBounds().getY(), cWidth * charWidth,
-                (int) clip.getBounds().getHeight());
+        continue;
       }
 
-      drawPanel(g, startRes, endx, 0, al.getHeight() - 1, ypos);
+      /*
+       * draw a downward-pointing triangle at the hidden columns location
+       * (before the following visible column)
+       */
+      int xMiddle = res * charWidth;
+      int[] xPoints = new int[] { xMiddle - charHeight / 4,
+          xMiddle + charHeight / 4, xMiddle };
+      int yTop = ypos - (charHeight / 2);
+      int[] yPoints = new int[] { yTop, yTop, yTop + 8 };
+      g.fillPolygon(xPoints, yPoints, 3);
+    }
+  }
 
-      if (av.isShowAnnotation())
-      {
-        g.translate(0, cHeight + ypos + 3);
-        if (annotations == null)
-        {
-          annotations = new AnnotationPanel(av);
-        }
+  /*
+   * Draw a selection group over a wrapped alignment
+   */
+  private void drawWrappedSelection(Graphics2D g, SequenceGroup group,
+          int canvasWidth,
+          int canvasHeight, int startRes)
+  {
+    int charHeight = av.getCharHeight();
+    int charWidth = av.getCharWidth();
+      
+    // height gap above each panel
+    int hgap = charHeight;
+    if (av.getScaleAboveWrapped())
+    {
+      hgap += charHeight;
+    }
+
+    int cWidth = (canvasWidth - labelWidthEast - labelWidthWest)
+            / charWidth;
+    int cHeight = av.getAlignment().getHeight() * charHeight;
+
+    int startx = startRes;
+    int endx;
+    int ypos = hgap; // vertical offset
+    int maxwidth = av.getAlignment().getWidth();
 
-        annotations.renderer.drawComponent(annotations, av, g, -1,
-                startRes, endx + 1);
-        g.translate(0, -cHeight - ypos - 3);
+    if (av.hasHiddenColumns())
+    {
+      maxwidth = av.getAlignment().getHiddenColumns()
+              .findColumnPosition(maxwidth);
+    }
+
+    // chop the wrapped alignment extent up into panel-sized blocks and treat
+    // each block as if it were a block from an unwrapped alignment
+    while ((ypos <= canvasHeight) && (startx < maxwidth))
+    {
+      // set end value to be start + width, or maxwidth, whichever is smaller
+      endx = startx + cWidth - 1;
+
+      if (endx > maxwidth)
+      {
+        endx = maxwidth;
       }
-      g.setClip(clip);
-      g.translate(-LABEL_WEST, 0);
 
+      g.translate(labelWidthWest, 0);
+
+      drawUnwrappedSelection(g, group, startx, endx, 0,
+              av.getAlignment().getHeight() - 1,
+              ypos);
+
+      g.translate(-labelWidthWest, 0);
+
+      // update vertical offset
       ypos += cHeight + getAnnotationHeight() + hgap;
 
-      startRes += cWidth;
+      // update horizontal offset
+      startx += cWidth;
     }
   }
 
-  AnnotationPanel annotations;
-
   int getAnnotationHeight()
   {
     if (!av.isShowAnnotation())
@@ -642,32 +990,38 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
   }
 
   /**
-   * DOCUMENT ME!
+   * Draws the visible region of the alignment on the graphics context. If there
+   * are hidden column markers in the visible region, then each sub-region
+   * between the markers is drawn separately, followed by the hidden column
+   * marker.
    * 
    * @param g1
-   *          DOCUMENT ME!
+   *          the graphics context, positioned at the first residue to be drawn
    * @param startRes
-   *          DOCUMENT ME!
+   *          offset of the first column to draw (0..)
    * @param endRes
-   *          DOCUMENT ME!
+   *          offset of the last column to draw (0..)
    * @param startSeq
-   *          DOCUMENT ME!
+   *          offset of the first sequence to draw (0..)
    * @param endSeq
-   *          DOCUMENT ME!
-   * @param offset
-   *          DOCUMENT ME!
+   *          offset of the last sequence to draw (0..)
+   * @param yOffset
+   *          vertical offset at which to draw (for wrapped alignments)
    */
-  public void drawPanel(Graphics g1, int startRes, int endRes,
-          int startSeq, int endSeq, int offset)
+  public void drawPanel(Graphics g1, final int startRes, final int endRes,
+          final int startSeq, final int endSeq, final int yOffset)
   {
-    updateViewport();
+    int charHeight = av.getCharHeight();
+    int charWidth = av.getCharWidth();
+
     if (!av.hasHiddenColumns())
     {
-      draw(g1, startRes, endRes, startSeq, endSeq, offset);
+      draw(g1, startRes, endRes, startSeq, endSeq, yOffset);
     }
     else
     {
       int screenY = 0;
+      final int screenYMax = endRes - startRes;
       int blockStart = startRes;
       int blockEnd = endRes;
 
@@ -683,38 +1037,47 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
           continue;
         }
 
-        blockEnd = hideStart - 1;
+        /*
+         * draw up to just before the next hidden region, or the end of
+         * the visible region, whichever comes first
+         */
+        blockEnd = Math.min(hideStart - 1, blockStart + screenYMax
+                - screenY);
 
         g1.translate(screenY * charWidth, 0);
 
-        draw(g1, blockStart, blockEnd, startSeq, endSeq, offset);
+        draw(g1, blockStart, blockEnd, startSeq, endSeq, yOffset);
 
-        if (av.getShowHiddenMarkers())
+        /*
+         * draw the downline of the hidden column marker (ScalePanel draws the
+         * triangle on top) if we reached it
+         */
+        if (av.getShowHiddenMarkers() && blockEnd == hideStart - 1)
         {
           g1.setColor(Color.blue);
 
           g1.drawLine((blockEnd - blockStart + 1) * charWidth - 1,
-                  0 + offset, (blockEnd - blockStart + 1) * charWidth - 1,
-                  (endSeq - startSeq + 1) * charHeight + offset);
+                  0 + yOffset, (blockEnd - blockStart + 1) * charWidth - 1,
+                  (endSeq - startSeq + 1) * charHeight + yOffset);
         }
 
         g1.translate(-screenY * charWidth, 0);
         screenY += blockEnd - blockStart + 1;
         blockStart = hideEnd + 1;
 
-        if (screenY > (endRes - startRes))
+        if (screenY > screenYMax)
         {
           // already rendered last block
           return;
         }
       }
 
-      if (screenY <= (endRes - startRes))
+      if (screenY <= screenYMax)
       {
         // remaining visible region to render
-        blockEnd = blockStart + (endRes - startRes) - screenY;
+        blockEnd = blockStart + screenYMax - screenY;
         g1.translate(screenY * charWidth, 0);
-        draw(g1, blockStart, blockEnd, startSeq, endSeq, offset);
+        draw(g1, blockStart, blockEnd, startSeq, endSeq, yOffset);
 
         g1.translate(-screenY * charWidth, 0);
       }
@@ -722,13 +1085,29 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
 
   }
 
-  // int startRes, int endRes, int startSeq, int endSeq, int x, int y,
-  // int x1, int x2, int y1, int y2, int startx, int starty,
+  /**
+   * Draws a region of the visible alignment
+   * 
+   * @param g1
+   * @param startRes
+   *          offset of the first column in the visible region (0..)
+   * @param endRes
+   *          offset of the last column in the visible region (0..)
+   * @param startSeq
+   *          offset of the first sequence in the visible region (0..)
+   * @param endSeq
+   *          offset of the last sequence in the visible region (0..)
+   * @param yOffset
+   *          vertical offset at which to draw (for wrapped alignments)
+   */
   private void draw(Graphics g, int startRes, int endRes, int startSeq,
           int endSeq, int offset)
   {
+    int charHeight = av.getCharHeight();
+    int charWidth = av.getCharWidth();
+
     g.setFont(av.getFont());
-    sr.prepare(g, av.isRenderGaps());
+    seqRdr.prepare(g, av.isRenderGaps());
 
     SequenceI nextSeq;
 
@@ -743,39 +1122,34 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
         // empty
         continue;
       }
-      sr.drawSequence(nextSeq, av.getAlignment().findAllGroups(nextSeq),
+      seqRdr.drawSequence(nextSeq, av.getAlignment().findAllGroups(nextSeq),
               startRes, endRes, offset + ((i - startSeq) * charHeight));
 
       if (av.isShowSequenceFeatures())
       {
-        fr.drawSequence(g, nextSeq, startRes, endRes, offset
-                + ((i - startSeq) * charHeight), false);
+        fr.drawSequence(g, nextSeq, startRes, endRes,
+                offset + ((i - startSeq) * charHeight), false);
       }
 
-      // / Highlight search Results once all sequences have been drawn
-      // ////////////////////////////////////////////////////////
+      /*
+       * highlight search Results once sequence has been drawn
+       */
       if (av.hasSearchResults())
       {
-        int[] visibleResults = av.getSearchResults().getResults(nextSeq,
+        SearchResultsI searchResults = av.getSearchResults();
+        int[] visibleResults = searchResults.getResults(nextSeq,
                 startRes, endRes);
         if (visibleResults != null)
         {
           for (int r = 0; r < visibleResults.length; r += 2)
           {
-            sr.drawHighlightedText(nextSeq, visibleResults[r],
+            seqRdr.drawHighlightedText(nextSeq, visibleResults[r],
                     visibleResults[r + 1], (visibleResults[r] - startRes)
                             * charWidth, offset
                             + ((i - startSeq) * charHeight));
           }
         }
       }
-
-      if (av.cursorMode && cursorY == i && cursorX >= startRes
-              && cursorX <= endRes)
-      {
-        sr.drawCursor(nextSeq, cursorX, (cursorX - startRes) * charWidth,
-                offset + ((i - startSeq) * charHeight));
-      }
     }
 
     if (av.getSelectionGroup() != null
@@ -794,15 +1168,11 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
     // ///////////////////////////////////
     // Now outline any areas if necessary
     // ///////////////////////////////////
-    SequenceGroup group = av.getSelectionGroup();
 
-    int sx = -1;
-    int sy = -1;
-    int ex = -1;
+    SequenceGroup group = null;
     int groupIndex = -1;
-    int visWidth = (endRes - startRes + 1) * charWidth;
 
-    if ((group == null) && (av.getAlignment().getGroups().size() > 0))
+    if (av.getAlignment().getGroups().size() > 0)
     {
       group = av.getAlignment().getGroups().get(0);
       groupIndex = 0;
@@ -810,182 +1180,563 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
 
     if (group != null)
     {
+      g.setStroke(new BasicStroke());
+      g.setColor(group.getOutlineColour());
+      
       do
       {
-        int oldY = -1;
-        int i = 0;
-        boolean inGroup = false;
-        int top = -1;
-        int bottom = -1;
+        drawPartialGroupOutline(g, group, startRes, endRes, startSeq,
+                endSeq, offset);
+
+        groupIndex++;
 
-        for (i = startSeq; i <= endSeq; i++)
+        g.setStroke(new BasicStroke());
+
+        if (groupIndex >= av.getAlignment().getGroups().size())
         {
-          sx = (group.getStartRes() - startRes) * charWidth;
-          sy = offset + ((i - startSeq) * charHeight);
-          ex = (((group.getEndRes() + 1) - group.getStartRes()) * charWidth) - 1;
+          break;
+        }
 
-          if (sx + ex < 0 || sx > visWidth)
-          {
-            continue;
-          }
+        group = av.getAlignment().getGroups().get(groupIndex);
 
-          if ((sx <= (endRes - startRes) * charWidth)
-                  && group.getSequences(null).contains(
-                          av.getAlignment().getSequenceAt(i)))
-          {
-            if ((bottom == -1)
-                    && !group.getSequences(null).contains(
-                            av.getAlignment().getSequenceAt(i + 1)))
-            {
-              bottom = sy + charHeight;
-            }
+      } while (groupIndex < av.getAlignment().getGroups().size());
 
-            if (!inGroup)
-            {
-              if (((top == -1) && (i == 0))
-                      || !group.getSequences(null).contains(
-                              av.getAlignment().getSequenceAt(i - 1)))
-              {
-                top = sy;
-              }
+    }
 
-              oldY = sy;
-              inGroup = true;
+  }
 
-              if (group == av.getSelectionGroup())
-              {
-                g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT,
-                        BasicStroke.JOIN_ROUND, 3f, new float[] { 5f, 3f },
-                        0f));
-                g.setColor(Color.RED);
-              }
-              else
-              {
-                g.setStroke(new BasicStroke());
-                g.setColor(group.getOutlineColour());
-              }
-            }
-          }
-          else
-          {
-            if (inGroup)
-            {
-              if (sx >= 0 && sx < visWidth)
-              {
-                g.drawLine(sx, oldY, sx, sy);
-              }
 
-              if (sx + ex < visWidth)
-              {
-                g.drawLine(sx + ex, oldY, sx + ex, sy);
-              }
+  /*
+   * Draw the selection group as a separate image and overlay
+   */
+  private BufferedImage drawSelectionGroup(int startRes, int endRes,
+          int startSeq, int endSeq)
+  {
+    // get a new image of the correct size
+    BufferedImage selectionImage = setupImage();
 
-              if (sx < 0)
-              {
-                ex += sx;
-                sx = 0;
-              }
+    if (selectionImage == null)
+    {
+      return null;
+    }
 
-              if (sx + ex > visWidth)
-              {
-                ex = visWidth;
-              }
+    SequenceGroup group = av.getSelectionGroup();
+    if (group == null)
+    {
+      // nothing to draw
+      return null;
+    }
 
-              else if (sx + ex >= (endRes - startRes + 1) * charWidth)
-              {
-                ex = (endRes - startRes + 1) * charWidth;
-              }
+    // set up drawing colour
+    Graphics2D g = (Graphics2D) selectionImage.getGraphics();
 
-              if (top != -1)
-              {
-                g.drawLine(sx, top, sx + ex, top);
-                top = -1;
-              }
+    setupSelectionGroup(g, selectionImage);
 
-              if (bottom != -1)
-              {
-                g.drawLine(sx, bottom, sx + ex, bottom);
-                bottom = -1;
-              }
+    if (!av.getWrapAlignment())
+    {
+      drawUnwrappedSelection(g, group, startRes, endRes, startSeq, endSeq,
+              0);
+    }
+    else
+    {
+      drawWrappedSelection(g, group, getWidth(), getHeight(),
+              av.getRanges().getStartRes());
+    }
 
-              inGroup = false;
-            }
-          }
-        }
+    g.dispose();
+    return selectionImage;
+  }
 
-        if (inGroup)
+  /**
+   * Draw the cursor as a separate image and overlay
+   * 
+   * @param startRes
+   *          start residue of area to draw cursor in
+   * @param endRes
+   *          end residue of area to draw cursor in
+   * @param startSeq
+   *          start sequence of area to draw cursor in
+   * @param endSeq
+   *          end sequence of are to draw cursor in
+   * @return a transparent image of the same size as the sequence canvas, with
+   *         the cursor drawn on it, if any
+   */
+  private void drawCursor(Graphics g, int startRes, int endRes,
+          int startSeq,
+          int endSeq)
+  {
+    // convert the cursorY into a position on the visible alignment
+    int cursor_ypos = cursorY;
+
+    // don't do work unless we have to
+    if (cursor_ypos >= startSeq && cursor_ypos <= endSeq)
+    {
+      int yoffset = 0;
+      int xoffset = 0;
+      int startx = startRes;
+      int endx = endRes;
+
+      // convert the cursorX into a position on the visible alignment
+      int cursor_xpos = av.getAlignment().getHiddenColumns()
+              .findColumnPosition(cursorX);
+
+      if (av.getAlignment().getHiddenColumns().isVisible(cursorX))
+      {
+
+        if (av.getWrapAlignment())
         {
-          sy = offset + ((i - startSeq) * charHeight);
-          if (sx >= 0 && sx < visWidth)
+          // work out the correct offsets for the cursor
+          int charHeight = av.getCharHeight();
+          int charWidth = av.getCharWidth();
+          int canvasWidth = getWidth();
+          int canvasHeight = getHeight();
+
+          // height gap above each panel
+          int hgap = charHeight;
+          if (av.getScaleAboveWrapped())
           {
-            g.drawLine(sx, oldY, sx, sy);
+            hgap += charHeight;
           }
 
-          if (sx + ex < visWidth)
-          {
-            g.drawLine(sx + ex, oldY, sx + ex, sy);
-          }
+          int cWidth = (canvasWidth - labelWidthEast - labelWidthWest)
+                  / charWidth;
+          int cHeight = av.getAlignment().getHeight() * charHeight;
 
-          if (sx < 0)
-          {
-            ex += sx;
-            sx = 0;
-          }
+          endx = startx + cWidth - 1;
+          int ypos = hgap; // vertical offset
 
-          if (sx + ex > visWidth)
-          {
-            ex = visWidth;
-          }
-          else if (sx + ex >= (endRes - startRes + 1) * charWidth)
+          // iterate down the wrapped panels
+          while ((ypos <= canvasHeight) && (endx < cursor_xpos))
           {
-            ex = (endRes - startRes + 1) * charWidth;
+            // update vertical offset
+            ypos += cHeight + getAnnotationHeight() + hgap;
+
+            // update horizontal offset
+            startx += cWidth;
+            endx = startx + cWidth - 1;
           }
+          yoffset = ypos;
+          xoffset = labelWidthWest;
+        }
+
+        // now check if cursor is within range for x values
+        if (cursor_xpos >= startx && cursor_xpos <= endx)
+        {
+          // get the character the cursor is drawn at
+          SequenceI seq = av.getAlignment().getSequenceAt(cursorY);
+          char s = seq.getCharAt(cursorX);
+
+          seqRdr.drawCursor(g, s,
+                  xoffset + (cursor_xpos - startx) * av.getCharWidth(),
+                  yoffset + (cursor_ypos - startSeq) * av.getCharHeight());
+        }
+      }
+    }
+  }
+
+
+  /*
+   * Set up graphics for selection group
+   */
+  private void setupSelectionGroup(Graphics2D g,
+          BufferedImage selectionImage)
+  {
+    // set background to transparent
+    g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f));
+    g.fillRect(0, 0, selectionImage.getWidth(), selectionImage.getHeight());
+
+    // set up foreground to draw red dashed line
+    g.setComposite(AlphaComposite.Src);
+    g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT,
+            BasicStroke.JOIN_ROUND, 3f, new float[]
+    { 5f, 3f }, 0f));
+    g.setColor(Color.RED);
+  }
+
+  /*
+   * Draw a selection group over an unwrapped alignment
+   * @param g graphics object to draw with
+   * @param group selection group
+   * @param startRes start residue of area to draw
+   * @param endRes end residue of area to draw
+   * @param startSeq start sequence of area to draw
+   * @param endSeq end sequence of area to draw
+   * @param offset vertical offset (used when called from wrapped alignment code)
+   */
+  private void drawUnwrappedSelection(Graphics2D g, SequenceGroup group,
+          int startRes, int endRes, int startSeq, int endSeq, int offset)
+  {
+    int charWidth = av.getCharWidth();
+          
+    if (!av.hasHiddenColumns())
+    {
+      drawPartialGroupOutline(g, group, startRes, endRes, startSeq, endSeq,
+              offset);
+    }
+    else
+    {
+      // package into blocks of visible columns
+      int screenY = 0;
+      int blockStart = startRes;
+      int blockEnd = endRes;
+
+      for (int[] region : av.getAlignment().getHiddenColumns()
+              .getHiddenColumnsCopy())
+      {
+        int hideStart = region[0];
+        int hideEnd = region[1];
+
+        if (hideStart <= blockStart)
+        {
+          blockStart += (hideEnd - hideStart) + 1;
+          continue;
+        }
+
+        blockEnd = hideStart - 1;
+
+        g.translate(screenY * charWidth, 0);
+        drawPartialGroupOutline(g, group,
+                blockStart, blockEnd, startSeq, endSeq, offset);
+
+        g.translate(-screenY * charWidth, 0);
+        screenY += blockEnd - blockStart + 1;
+        blockStart = hideEnd + 1;
+
+        if (screenY > (endRes - startRes))
+        {
+          // already rendered last block
+          break;
+        }
+      }
+
+      if (screenY <= (endRes - startRes))
+      {
+        // remaining visible region to render
+        blockEnd = blockStart + (endRes - startRes) - screenY;
+        g.translate(screenY * charWidth, 0);
+        drawPartialGroupOutline(g, group,
+                blockStart, blockEnd, startSeq, endSeq, offset);
+        
+        g.translate(-screenY * charWidth, 0);
+      }
+    }
+  }
+
+  /*
+   * Draw the selection group as a separate image and overlay
+   */
+  private void drawPartialGroupOutline(Graphics2D g, SequenceGroup group,
+          int startRes, int endRes, int startSeq, int endSeq,
+          int verticalOffset)
+  {
+    int charHeight = av.getCharHeight();
+    int charWidth = av.getCharWidth();
+    int visWidth = (endRes - startRes + 1) * charWidth;
+
+    int oldY = -1;
+    int i = 0;
+    boolean inGroup = false;
+    int top = -1;
+    int bottom = -1;
+    int sy = -1;
+
+    List<SequenceI> seqs = group.getSequences(null);
+
+    // position of start residue of group relative to startRes, in pixels
+    int sx = (group.getStartRes() - startRes) * charWidth;
+
+    // width of group in pixels
+    int xwidth = (((group.getEndRes() + 1) - group.getStartRes())
+            * charWidth) - 1;
+
+    if (!(sx + xwidth < 0 || sx > visWidth))
+    {
+      for (i = startSeq; i <= endSeq; i++)
+      {
+        sy = verticalOffset + (i - startSeq) * charHeight;
 
-          if (top != -1)
+        if ((sx <= (endRes - startRes) * charWidth)
+                && seqs.contains(av.getAlignment().getSequenceAt(i)))
+        {
+          if ((bottom == -1)
+                  && !seqs.contains(av.getAlignment().getSequenceAt(i + 1)))
           {
-            g.drawLine(sx, top, sx + ex, top);
-            top = -1;
+            bottom = sy + charHeight;
           }
 
-          if (bottom != -1)
+          if (!inGroup)
           {
-            g.drawLine(sx, bottom - 1, sx + ex, bottom - 1);
-            bottom = -1;
+            if (((top == -1) && (i == 0)) || !seqs
+                    .contains(av.getAlignment().getSequenceAt(i - 1)))
+            {
+              top = sy;
+            }
+
+            oldY = sy;
+            inGroup = true;
           }
+        }
+        else if (inGroup)
+        {
+          drawVerticals(g, sx, xwidth, visWidth, oldY, sy);
+          drawHorizontals(g, sx, xwidth, visWidth, top, bottom);
 
+          // reset top and bottom
+          top = -1;
+          bottom = -1;
           inGroup = false;
         }
+      }
+      if (inGroup)
+      {
+        sy = verticalOffset + ((i - startSeq) * charHeight);
+        drawVerticals(g, sx, xwidth, visWidth, oldY, sy);
+        drawHorizontals(g, sx, xwidth, visWidth, top, bottom);
+      }
+    }
+  }
 
-        groupIndex++;
+  /**
+   * Draw horizontal selection group boundaries at top and bottom positions
+   * 
+   * @param g
+   *          graphics object to draw on
+   * @param sx
+   *          start x position
+   * @param xwidth
+   *          width of gap
+   * @param visWidth
+   *          visWidth maximum available width
+   * @param top
+   *          position to draw top of group at
+   * @param bottom
+   *          position to draw bottom of group at
+   */
+  private void drawHorizontals(Graphics2D g, int sx, int xwidth,
+          int visWidth, int top, int bottom)
+  {
+    int width = xwidth;
+    int startx = sx;
+    if (startx < 0)
+    {
+      width += startx;
+      startx = 0;
+    }
 
-        g.setStroke(new BasicStroke());
+    // don't let width extend beyond current block, or group extent
+    // fixes JAL-2672
+    if (startx + width >= visWidth)
+    {
+      width = visWidth - startx;
+    }
 
-        if (groupIndex >= av.getAlignment().getGroups().size())
-        {
-          break;
-        }
+    if (top != -1)
+    {
+      g.drawLine(startx, top, startx + width, top);
+    }
 
-        group = av.getAlignment().getGroups().get(groupIndex);
+    if (bottom != -1)
+    {
+      g.drawLine(startx, bottom - 1, startx + width, bottom - 1);
+    }
+  }
 
-      } while (groupIndex < av.getAlignment().getGroups().size());
+  /**
+   * Draw vertical lines at sx and sx+xwidth providing they lie within
+   * [0,visWidth)
+   * 
+   * @param g
+   *          graphics object to draw on
+   * @param sx
+   *          start x position
+   * @param xwidth
+   *          width of gap
+   * @param visWidth
+   *          visWidth maximum available width
+   * @param oldY
+   *          top y value
+   * @param sy
+   *          bottom y value
+   */
+  private void drawVerticals(Graphics2D g, int sx, int xwidth, int visWidth,
+          int oldY, int sy)
+  {
+    // if start position is visible, draw vertical line to left of
+    // group
+    if (sx >= 0 && sx < visWidth)
+    {
+      g.drawLine(sx, oldY, sx, sy);
+    }
 
+    // if end position is visible, draw vertical line to right of
+    // group
+    if (sx + xwidth < visWidth)
+    {
+      g.drawLine(sx + xwidth, oldY, sx + xwidth, sy);
+    }
+  }
+  
+  /**
+   * Highlights search results in the visible region by rendering as white text
+   * on a black background. Any previous highlighting is removed. Answers true
+   * if any highlight was left on the visible alignment (so status bar should be
+   * set to match), else false.
+   * <p>
+   * Currently fastPaint is not implemented for wrapped alignments. If a wrapped
+   * alignment had to be scrolled to show the highlighted region, then it should
+   * be fully redrawn, otherwise a fast paint can be performed. This argument
+   * could be removed if fast paint of scrolled wrapped alignment is coded in
+   * future (JAL-2609).
+   * 
+   * @param results
+   * @param noFastPaint
+   * @return
+   */
+  public boolean highlightSearchResults(SearchResultsI results,
+          boolean noFastPaint)
+  {
+    if (fastpainting)
+    {
+      return false;
     }
+    boolean wrapped = av.getWrapAlignment();
+    try
+    {
+      fastPaint = !noFastPaint;
+      fastpainting = fastPaint;
+
+      /*
+       * to avoid redrawing the whole visible region, we instead
+       * redraw just the minimal regions to remove previous highlights
+       * and add new ones
+       */
+      SearchResultsI previous = av.getSearchResults();
+      av.setSearchResults(results);
+      boolean redrawn = false;
+      boolean drawn = false;
+      if (wrapped)
+      {
+        redrawn = drawMappedPositionsWrapped(previous);
+        drawn = drawMappedPositionsWrapped(results);
+        redrawn |= drawn;
+      }
+      else
+      {
+        redrawn = drawMappedPositions(previous);
+        drawn = drawMappedPositions(results);
+        redrawn |= drawn;
+      }
 
+      /*
+       * if highlights were either removed or added, repaint
+       */
+      if (redrawn)
+      {
+        repaint();
+      }
+
+      /*
+       * return true only if highlights were added
+       */
+      return drawn;
+
+    } finally
+    {
+      fastpainting = false;
+    }
   }
 
   /**
-   * DOCUMENT ME!
+   * Redraws the minimal rectangle in the visible region (if any) that includes
+   * mapped positions of the given search results. Whether or not positions are
+   * highlighted depends on the SearchResults set on the Viewport. This allows
+   * this method to be called to either clear or set highlighting. Answers true
+   * if any positions were drawn (in which case a repaint is still required),
+   * else false.
    * 
    * @param results
-   *          DOCUMENT ME!
+   * @return
    */
-  public void highlightSearchResults(SearchResultsI results)
+  protected boolean drawMappedPositions(SearchResultsI results)
   {
-    img = null;
+    if ((results == null) || (gg == null)) // JAL-2784 check gg is not null
+    {
+      return false;
+    }
+
+    /*
+     * calculate the minimal rectangle to redraw that 
+     * includes both new and existing search results
+     */
+    int firstSeq = Integer.MAX_VALUE;
+    int lastSeq = -1;
+    int firstCol = Integer.MAX_VALUE;
+    int lastCol = -1;
+    boolean matchFound = false;
+
+    ViewportRanges ranges = av.getRanges();
+    int firstVisibleColumn = ranges.getStartRes();
+    int lastVisibleColumn = ranges.getEndRes();
+    AlignmentI alignment = av.getAlignment();
+    if (av.hasHiddenColumns())
+    {
+      firstVisibleColumn = alignment.getHiddenColumns()
+              .adjustForHiddenColumns(firstVisibleColumn);
+      lastVisibleColumn = alignment.getHiddenColumns()
+              .adjustForHiddenColumns(lastVisibleColumn);
+    }
+
+    for (int seqNo = ranges.getStartSeq(); seqNo <= ranges
+            .getEndSeq(); seqNo++)
+    {
+      SequenceI seq = alignment.getSequenceAt(seqNo);
+
+      int[] visibleResults = results.getResults(seq, firstVisibleColumn,
+              lastVisibleColumn);
+      if (visibleResults != null)
+      {
+        for (int i = 0; i < visibleResults.length - 1; i += 2)
+        {
+          int firstMatchedColumn = visibleResults[i];
+          int lastMatchedColumn = visibleResults[i + 1];
+          if (firstMatchedColumn <= lastVisibleColumn
+                  && lastMatchedColumn >= firstVisibleColumn)
+          {
+            /*
+             * found a search results match in the visible region - 
+             * remember the first and last sequence matched, and the first
+             * and last visible columns in the matched positions
+             */
+            matchFound = true;
+            firstSeq = Math.min(firstSeq, seqNo);
+            lastSeq = Math.max(lastSeq, seqNo);
+            firstMatchedColumn = Math.max(firstMatchedColumn,
+                    firstVisibleColumn);
+            lastMatchedColumn = Math.min(lastMatchedColumn,
+                    lastVisibleColumn);
+            firstCol = Math.min(firstCol, firstMatchedColumn);
+            lastCol = Math.max(lastCol, lastMatchedColumn);
+          }
+        }
+      }
+    }
 
-    av.setSearchResults(results);
+    if (matchFound)
+    {
+      if (av.hasHiddenColumns())
+      {
+        firstCol = alignment.getHiddenColumns()
+                .findColumnPosition(firstCol);
+        lastCol = alignment.getHiddenColumns().findColumnPosition(lastCol);
+      }
+      int transX = (firstCol - ranges.getStartRes()) * av.getCharWidth();
+      int transY = (firstSeq - ranges.getStartSeq()) * av.getCharHeight();
+      gg.translate(transX, transY);
+      drawPanel(gg, firstCol, lastCol, firstSeq, lastSeq, 0);
+      gg.translate(-transX, -transY);
+    }
 
-    repaint();
+    return matchFound;
   }
 
   @Override
@@ -993,48 +1744,464 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
   {
     String eventName = evt.getPropertyName();
 
-    if (av.getWrapAlignment())
+    if (eventName.equals(SequenceGroup.SEQ_GROUP_CHANGED))
     {
-      if (eventName.equals(ViewportRanges.STARTRES))
-      {
-        repaint();
-      }
+      fastPaint = true;
+      repaint();
+      return;
     }
-    else
+    else if (eventName.equals(ViewportRanges.MOVE_VIEWPORT))
+    {
+      fastPaint = false;
+      repaint();
+      return;
+    }
+
+    int scrollX = 0;
+    if (eventName.equals(ViewportRanges.STARTRES)
+            || eventName.equals(ViewportRanges.STARTRESANDSEQ))
     {
-      int scrollX = 0;
+      // Make sure we're not trying to draw a panel
+      // larger than the visible window
       if (eventName.equals(ViewportRanges.STARTRES))
       {
-        // Make sure we're not trying to draw a panel
-        // larger than the visible window
-        ViewportRanges vpRanges = av.getRanges();
         scrollX = (int) evt.getNewValue() - (int) evt.getOldValue();
-        int range = vpRanges.getEndRes() - vpRanges.getStartRes();
-        if (scrollX > range)
+      }
+      else
+      {
+        scrollX = ((int[]) evt.getNewValue())[0]
+                - ((int[]) evt.getOldValue())[0];
+      }
+      ViewportRanges vpRanges = av.getRanges();
+
+      int range = vpRanges.getEndRes() - vpRanges.getStartRes();
+      if (scrollX > range)
+      {
+        scrollX = range;
+      }
+      else if (scrollX < -range)
+      {
+        scrollX = -range;
+      }
+    }
+    // Both scrolling and resizing change viewport ranges: scrolling changes
+    // both start and end points, but resize only changes end values.
+    // Here we only want to fastpaint on a scroll, with resize using a normal
+    // paint, so scroll events are identified as changes to the horizontal or
+    // vertical start value.
+    if (eventName.equals(ViewportRanges.STARTRES))
+    {
+      if (av.getWrapAlignment())
         {
-          scrollX = range;
+          fastPaintWrapped(scrollX);
         }
-        else if (scrollX < -range)
+        else
         {
-          scrollX = -range;
+          fastPaint(scrollX, 0);
         }
+    }
+    else if (eventName.equals(ViewportRanges.STARTSEQ))
+    {
+      // scroll
+      fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue());
+    }
+    else if (eventName.equals(ViewportRanges.STARTRESANDSEQ))
+    {
+      if (av.getWrapAlignment())
+      {
+        fastPaintWrapped(scrollX);
       }
-
-      // Both scrolling and resizing change viewport ranges: scrolling changes
-      // both start and end points, but resize only changes end values.
-      // Here we only want to fastpaint on a scroll, with resize using a normal
-      // paint, so scroll events are identified as changes to the horizontal or
-      // vertical start value.
-      if (eventName.equals(ViewportRanges.STARTRES))
+      else
       {
-        // scroll - startres and endres both change
         fastPaint(scrollX, 0);
       }
-      else if (eventName.equals(ViewportRanges.STARTSEQ))
+      // bizarrely, we only need to scroll on the x value here as fastpaint
+      // copies the full height of the image anyway. Passing in the y value
+      // causes nasty repaint artefacts, which only disappear on a full
+      // repaint.
+    }
+  }
+
+  /**
+   * Does a minimal update of the image for a scroll movement. This method
+   * handles scroll movements of up to one width of the wrapped alignment (one
+   * click in the vertical scrollbar). Larger movements (for example after a
+   * scroll to highlight a mapped position) trigger a full redraw instead.
+   * 
+   * @param scrollX
+   *          number of positions scrolled (right if positive, left if negative)
+   */
+  protected void fastPaintWrapped(int scrollX)
+  {
+    ViewportRanges ranges = av.getRanges();
+
+    // if (Math.abs(scrollX) > ranges.getViewportWidth())
+    // JAL-2836, 2836 temporarily removed wrapped fastpaint for release 2.10.3
+    if (true)
+    {
+      /*
+       * shift of more than one view width is 
+       * overcomplicated to handle in this method
+       */
+      fastPaint = false;
+      repaint();
+      return;
+    }
+
+    if (fastpainting || gg == null)
+    {
+      return;
+    }
+
+    fastPaint = true;
+    fastpainting = true;
+
+    try
+    {
+      calculateWrappedGeometry(getWidth(), getHeight());
+
+      /*
+       * relocate the regions of the alignment that are still visible
+       */
+      shiftWrappedAlignment(-scrollX);
+
+      /*
+       * add new columns (sequence, annotation)
+       * - at top left if scrollX < 0 
+       * - at right of last two widths if scrollX > 0
+       */
+      if (scrollX < 0)
+      {
+        int startRes = ranges.getStartRes();
+        drawWrappedWidth(gg, wrappedSpaceAboveAlignment, startRes, startRes
+                - scrollX - 1, getHeight());
+      }
+      else
+      {
+        fastPaintWrappedAddRight(scrollX);
+      }
+
+      /*
+       * draw all scales (if  shown) and hidden column markers
+       */
+      drawWrappedDecorators(gg, ranges.getStartRes());
+
+      repaint();
+    } finally
+    {
+      fastpainting = false;
+    }
+  }
+
+  /**
+   * Draws the specified number of columns at the 'end' (bottom right) of a
+   * wrapped alignment view, including sequences and annotations if shown, but
+   * not scales. Also draws the same number of columns at the right hand end of
+   * the second last width shown, if the last width is not full height (so
+   * cannot simply be copied from the graphics image).
+   * 
+   * @param columns
+   */
+  protected void fastPaintWrappedAddRight(int columns)
+  {
+    if (columns == 0)
+    {
+      return;
+    }
+
+    ViewportRanges ranges = av.getRanges();
+    int viewportWidth = ranges.getViewportWidth();
+    int charWidth = av.getCharWidth();
+
+    /**
+     * draw full height alignment in the second last row, last columns, if the
+     * last row was not full height
+     */
+    int visibleWidths = wrappedVisibleWidths;
+    int canvasHeight = getHeight();
+    boolean lastWidthPartHeight = (wrappedVisibleWidths * wrappedRepeatHeightPx) > canvasHeight;
+
+    if (lastWidthPartHeight)
+    {
+      int widthsAbove = Math.max(0, visibleWidths - 2);
+      int ypos = wrappedRepeatHeightPx * widthsAbove
+              + wrappedSpaceAboveAlignment;
+      int endRes = ranges.getEndRes();
+      endRes += widthsAbove * viewportWidth;
+      int startRes = endRes - columns;
+      int xOffset = ((startRes - ranges.getStartRes()) % viewportWidth)
+              * charWidth;
+
+      /*
+       * white fill first to erase annotations
+       */
+      gg.translate(xOffset, 0);
+      gg.setColor(Color.white);
+      gg.fillRect(labelWidthWest, ypos,
+              (endRes - startRes + 1) * charWidth, wrappedRepeatHeightPx);
+      gg.translate(-xOffset, 0);
+
+      drawWrappedWidth(gg, ypos, startRes, endRes, canvasHeight);
+    }
+
+    /*
+     * draw newly visible columns in last wrapped width (none if we
+     * have reached the end of the alignment)
+     * y-offset for drawing last width is height of widths above,
+     * plus one gap row
+     */
+    int widthsAbove = visibleWidths - 1;
+    int ypos = wrappedRepeatHeightPx * widthsAbove
+            + wrappedSpaceAboveAlignment;
+    int endRes = ranges.getEndRes();
+    endRes += widthsAbove * viewportWidth;
+    int startRes = endRes - columns + 1;
+
+    /*
+     * white fill first to erase annotations
+     */
+    int xOffset = ((startRes - ranges.getStartRes()) % viewportWidth)
+            * charWidth;
+    gg.translate(xOffset, 0);
+    gg.setColor(Color.white);
+    int width = viewportWidth * charWidth - xOffset;
+    gg.fillRect(labelWidthWest, ypos, width, wrappedRepeatHeightPx);
+    gg.translate(-xOffset, 0);
+
+    gg.setFont(av.getFont());
+    gg.setColor(Color.black);
+
+    if (startRes < ranges.getVisibleAlignmentWidth())
+    {
+      drawWrappedWidth(gg, ypos, startRes, endRes, canvasHeight);
+    }
+
+    /*
+     * and finally, white fill any space below the visible alignment
+     */
+    int heightBelow = canvasHeight - visibleWidths * wrappedRepeatHeightPx;
+    if (heightBelow > 0)
+    {
+      gg.setColor(Color.white);
+      gg.fillRect(0, canvasHeight - heightBelow, getWidth(), heightBelow);
+    }
+  }
+
+  /**
+   * Shifts the visible alignment by the specified number of columns - left if
+   * negative, right if positive. Copies and moves sequences and annotations (if
+   * shown). Scales, hidden column markers and any newly visible columns must be
+   * drawn separately.
+   * 
+   * @param positions
+   */
+  protected void shiftWrappedAlignment(int positions)
+  {
+    if (positions == 0)
+    {
+      return;
+    }
+    int charWidth = av.getCharWidth();
+
+    int canvasHeight = getHeight();
+    ViewportRanges ranges = av.getRanges();
+    int viewportWidth = ranges.getViewportWidth();
+    int widthToCopy = (ranges.getViewportWidth() - Math.abs(positions))
+            * charWidth;
+    int heightToCopy = wrappedRepeatHeightPx - wrappedSpaceAboveAlignment;
+    int xMax = ranges.getVisibleAlignmentWidth();
+
+    if (positions > 0)
+    {
+      /*
+       * shift right (after scroll left)
+       * for each wrapped width (starting with the last), copy (width-positions) 
+       * columns from the left margin to the right margin, and copy positions 
+       * columns from the right margin of the row above (if any) to the 
+       * left margin of the current row
+       */
+
+      /*
+       * get y-offset of last wrapped width, first row of sequences
+       */
+      int y = canvasHeight / wrappedRepeatHeightPx * wrappedRepeatHeightPx;
+      y += wrappedSpaceAboveAlignment;
+      int copyFromLeftStart = labelWidthWest;
+      int copyFromRightStart = copyFromLeftStart + widthToCopy;
+
+      while (y >= 0)
+      {
+        gg.copyArea(copyFromLeftStart, y, widthToCopy, heightToCopy,
+                positions * charWidth, 0);
+        if (y > 0)
+        {
+          gg.copyArea(copyFromRightStart, y - wrappedRepeatHeightPx,
+                  positions * charWidth, heightToCopy, -widthToCopy,
+                  wrappedRepeatHeightPx);
+        }
+
+        y -= wrappedRepeatHeightPx;
+      }
+    }
+    else
+    {
+      /*
+       * shift left (after scroll right)
+       * for each wrapped width (starting with the first), copy (width-positions) 
+       * columns from the right margin to the left margin, and copy positions 
+       * columns from the left margin of the row below (if any) to the 
+       * right margin of the current row
+       */
+      int xpos = av.getRanges().getStartRes();
+      int y = wrappedSpaceAboveAlignment;
+      int copyFromRightStart = labelWidthWest - positions * charWidth;
+
+      while (y < canvasHeight)
+      {
+        gg.copyArea(copyFromRightStart, y, widthToCopy, heightToCopy,
+                positions * charWidth, 0);
+        if (y + wrappedRepeatHeightPx < canvasHeight - wrappedRepeatHeightPx
+                && (xpos + viewportWidth <= xMax))
+        {
+          gg.copyArea(labelWidthWest, y + wrappedRepeatHeightPx, -positions
+                  * charWidth, heightToCopy, widthToCopy,
+                  -wrappedRepeatHeightPx);
+        }
+
+        y += wrappedRepeatHeightPx;
+        xpos += viewportWidth;
+      }
+    }
+  }
+
+  
+  /**
+   * Redraws any positions in the search results in the visible region of a
+   * wrapped alignment. Any highlights are drawn depending on the search results
+   * set on the Viewport, not the <code>results</code> argument. This allows
+   * this method to be called either to clear highlights (passing the previous
+   * search results), or to draw new highlights.
+   * 
+   * @param results
+   * @return
+   */
+  protected boolean drawMappedPositionsWrapped(SearchResultsI results)
+  {
+    if ((results == null) || (gg == null)) // JAL-2784 check gg is not null
+    {
+      return false;
+    }
+    int charHeight = av.getCharHeight();
+
+    boolean matchFound = false;
+
+    calculateWrappedGeometry(getWidth(), getHeight());
+    int wrappedWidth = av.getWrappedWidth();
+    int wrappedHeight = wrappedRepeatHeightPx;
+
+    ViewportRanges ranges = av.getRanges();
+    int canvasHeight = getHeight();
+    int repeats = canvasHeight / wrappedHeight;
+    if (canvasHeight / wrappedHeight > 0)
+    {
+      repeats++;
+    }
+
+    int firstVisibleColumn = ranges.getStartRes();
+    int lastVisibleColumn = ranges.getStartRes() + repeats
+            * ranges.getViewportWidth() - 1;
+
+    AlignmentI alignment = av.getAlignment();
+    if (av.hasHiddenColumns())
+    {
+      firstVisibleColumn = alignment.getHiddenColumns()
+              .adjustForHiddenColumns(firstVisibleColumn);
+      lastVisibleColumn = alignment.getHiddenColumns()
+              .adjustForHiddenColumns(lastVisibleColumn);
+    }
+
+    int gapHeight = charHeight * (av.getScaleAboveWrapped() ? 2 : 1);
+
+    for (int seqNo = ranges.getStartSeq(); seqNo <= ranges
+            .getEndSeq(); seqNo++)
+    {
+      SequenceI seq = alignment.getSequenceAt(seqNo);
+
+      int[] visibleResults = results.getResults(seq, firstVisibleColumn,
+              lastVisibleColumn);
+      if (visibleResults != null)
       {
-        // scroll
-        fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue());
+        for (int i = 0; i < visibleResults.length - 1; i += 2)
+        {
+          int firstMatchedColumn = visibleResults[i];
+          int lastMatchedColumn = visibleResults[i + 1];
+          if (firstMatchedColumn <= lastVisibleColumn
+                  && lastMatchedColumn >= firstVisibleColumn)
+          {
+            /*
+             * found a search results match in the visible region
+             */
+            firstMatchedColumn = Math.max(firstMatchedColumn,
+                    firstVisibleColumn);
+            lastMatchedColumn = Math.min(lastMatchedColumn,
+                    lastVisibleColumn);
+
+            /*
+             * draw each mapped position separately (as contiguous positions may
+             * wrap across lines)
+             */
+            for (int mappedPos = firstMatchedColumn; mappedPos <= lastMatchedColumn; mappedPos++)
+            {
+              int displayColumn = mappedPos;
+              if (av.hasHiddenColumns())
+              {
+                displayColumn = alignment.getHiddenColumns()
+                        .findColumnPosition(displayColumn);
+              }
+
+              /*
+               * transX: offset from left edge of canvas to residue position
+               */
+              int transX = labelWidthWest
+                      + ((displayColumn - ranges.getStartRes()) % wrappedWidth)
+                      * av.getCharWidth();
+
+              /*
+               * transY: offset from top edge of canvas to residue position
+               */
+              int transY = gapHeight;
+              transY += (displayColumn - ranges.getStartRes())
+                      / wrappedWidth * wrappedHeight;
+              transY += (seqNo - ranges.getStartSeq()) * av.getCharHeight();
+
+              /*
+               * yOffset is from graphics origin to start of visible region
+               */
+              int yOffset = 0;// (displayColumn / wrappedWidth) * wrappedHeight;
+              if (transY < getHeight())
+              {
+                matchFound = true;
+                gg.translate(transX, transY);
+                drawPanel(gg, displayColumn, displayColumn, seqNo, seqNo,
+                        yOffset);
+                gg.translate(-transX, -transY);
+              }
+            }
+          }
+        }
       }
     }
+  
+    return matchFound;
+  }
+
+  /**
+   * Answers the width in pixels of the left scale labels (0 if not shown)
+   * 
+   * @return
+   */
+  int getLabelWidthWest()
+  {
+    return labelWidthWest;
   }
 }
index 26096e6..61cac46 100644 (file)
@@ -62,7 +62,6 @@ import java.awt.event.MouseWheelListener;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import java.util.ListIterator;
 
 import javax.swing.JPanel;
 import javax.swing.SwingUtilities;
@@ -74,9 +73,9 @@ import javax.swing.ToolTipManager;
  * @author $author$
  * @version $Revision: 1.130 $
  */
-public class SeqPanel extends JPanel implements MouseListener,
-        MouseMotionListener, MouseWheelListener, SequenceListener,
-        SelectionListener
+public class SeqPanel extends JPanel
+        implements MouseListener, MouseMotionListener, MouseWheelListener,
+        SequenceListener, SelectionListener
 
 {
   /** DOCUMENT ME!! */
@@ -85,6 +84,16 @@ public class SeqPanel extends JPanel implements MouseListener,
   /** DOCUMENT ME!! */
   public AlignmentPanel ap;
 
+  /*
+   * last column position for mouseMoved event
+   */
+  private int lastMouseColumn;
+
+  /*
+   * last sequence offset for mouseMoved event
+   */
+  private int lastMouseSeq;
+
   protected int lastres;
 
   protected int startseq;
@@ -171,6 +180,9 @@ public class SeqPanel extends JPanel implements MouseListener,
       ssm.addStructureViewerListener(this);
       ssm.addSelectionListener(this);
     }
+
+    lastMouseColumn = -1;
+    lastMouseSeq = -1;
   }
 
   int startWrapBlock = -1;
@@ -203,8 +215,8 @@ public class SeqPanel extends JPanel implements MouseListener,
               + hgap + seqCanvas.getAnnotationHeight();
 
       int y = evt.getY();
-      y -= hgap;
-      x = Math.max(0, x - seqCanvas.LABEL_WEST);
+      y = Math.max(0, y - hgap);
+      x = Math.max(0, x - seqCanvas.getLabelWidthWest());
 
       int cwidth = seqCanvas.getWrappedCanvasWidth(this.getWidth());
       if (cwidth < 1)
@@ -263,15 +275,14 @@ public class SeqPanel extends JPanel implements MouseListener,
 
       y -= hgap;
 
-      seq = Math.min((y % cHeight) / av.getCharHeight(), av.getAlignment()
-              .getHeight() - 1);
+      seq = Math.min((y % cHeight) / av.getCharHeight(),
+              av.getAlignment().getHeight() - 1);
     }
     else
     {
-      seq = Math.min((y / av.getCharHeight())
-              + av.getRanges().getStartSeq(),
-              av
-              .getAlignment().getHeight() - 1);
+      seq = Math.min(
+              (y / av.getCharHeight()) + av.getRanges().getStartSeq(),
+              av.getAlignment().getHeight() - 1);
     }
 
     return seq;
@@ -288,8 +299,8 @@ public class SeqPanel extends JPanel implements MouseListener,
       if (editCommand != null && editCommand.getSize() > 0)
       {
         ap.alignFrame.addHistoryItem(editCommand);
-        av.firePropertyChange("alignment", null, av.getAlignment()
-                .getSequences());
+        av.firePropertyChange("alignment", null,
+                av.getAlignment().getSequences());
       }
     } finally
     {
@@ -309,13 +320,13 @@ public class SeqPanel extends JPanel implements MouseListener,
   void setCursorRow()
   {
     seqCanvas.cursorY = getKeyboardNo1() - 1;
-    scrollToVisible();
+    scrollToVisible(true);
   }
 
   void setCursorColumn()
   {
     seqCanvas.cursorX = getKeyboardNo1() - 1;
-    scrollToVisible();
+    scrollToVisible(true);
   }
 
   void setCursorRowAndColumn()
@@ -328,7 +339,7 @@ public class SeqPanel extends JPanel implements MouseListener,
     {
       seqCanvas.cursorX = getKeyboardNo1() - 1;
       seqCanvas.cursorY = getKeyboardNo2() - 1;
-      scrollToVisible();
+      scrollToVisible(true);
     }
   }
 
@@ -337,7 +348,7 @@ public class SeqPanel extends JPanel implements MouseListener,
     SequenceI sequence = av.getAlignment().getSequenceAt(seqCanvas.cursorY);
 
     seqCanvas.cursorX = sequence.findIndex(getKeyboardNo1()) - 1;
-    scrollToVisible();
+    scrollToVisible(true);
   }
 
   void moveCursor(int dx, int dy)
@@ -347,14 +358,16 @@ public class SeqPanel extends JPanel implements MouseListener,
 
     HiddenColumns hidden = av.getAlignment().getHiddenColumns();
 
-    if (av.hasHiddenColumns()
- && !hidden.isVisible(seqCanvas.cursorX))
+    if (av.hasHiddenColumns() && !hidden.isVisible(seqCanvas.cursorX))
     {
       int original = seqCanvas.cursorX - dx;
       int maxWidth = av.getAlignment().getWidth();
 
+      // TODO: once JAL-2759 is ready, change this loop to something more
+      // efficient
       while (!hidden.isVisible(seqCanvas.cursorX)
-              && seqCanvas.cursorX < maxWidth && seqCanvas.cursorX > 0)
+              && seqCanvas.cursorX < maxWidth && seqCanvas.cursorX > 0
+              && dx != 0)
       {
         seqCanvas.cursorX += dx;
       }
@@ -366,10 +379,16 @@ public class SeqPanel extends JPanel implements MouseListener,
       }
     }
 
-    scrollToVisible();
+    scrollToVisible(false);
   }
 
-  void scrollToVisible()
+  /**
+   * Scroll to make the cursor visible in the viewport.
+   * 
+   * @param jump
+   *          just jump to the location rather than scrolling
+   */
+  void scrollToVisible(boolean jump)
   {
     if (seqCanvas.cursorX < 0)
     {
@@ -390,20 +409,44 @@ public class SeqPanel extends JPanel implements MouseListener,
     }
 
     endEditing();
-    if (av.getWrapAlignment())
+
+    boolean repaintNeeded = true;
+    if (jump)
     {
-      av.getRanges().scrollToWrappedVisible(seqCanvas.cursorX);
+      // only need to repaint if the viewport did not move, as otherwise it will
+      // get a repaint
+      repaintNeeded = !av.getRanges().setViewportLocation(seqCanvas.cursorX,
+              seqCanvas.cursorY);
     }
     else
     {
-      av.getRanges().scrollToVisible(seqCanvas.cursorX, seqCanvas.cursorY);
+      if (av.getWrapAlignment())
+      {
+        // scrollToWrappedVisible expects x-value to have hidden cols subtracted
+        int x = av.getAlignment().getHiddenColumns()
+                .findColumnPosition(seqCanvas.cursorX);
+        av.getRanges().scrollToWrappedVisible(x);
+      }
+      else
+      {
+        av.getRanges().scrollToVisible(seqCanvas.cursorX,
+                seqCanvas.cursorY);
+      }
     }
-    setStatusMessage(av.getAlignment().getSequenceAt(seqCanvas.cursorY),
+
+    if (av.getAlignment().getHiddenColumns().isVisible(seqCanvas.cursorX))
+    {
+      setStatusMessage(av.getAlignment().getSequenceAt(seqCanvas.cursorY),
             seqCanvas.cursorX, seqCanvas.cursorY);
+    }
 
-    seqCanvas.repaint();
+    if (repaintNeeded)
+    {
+      seqCanvas.repaint();
+    }
   }
 
+
   void setSelectionAreaAtCursor(boolean topLeft)
   {
     SequenceI sequence = av.getAlignment().getSequenceAt(seqCanvas.cursorY);
@@ -474,7 +517,7 @@ public class SeqPanel extends JPanel implements MouseListener,
       av.setSelectionGroup(sg);
     }
 
-    ap.paintAlignment(false);
+    ap.paintAlignment(false, false);
     av.sendSelection();
   }
 
@@ -671,6 +714,8 @@ public class SeqPanel extends JPanel implements MouseListener,
     }
     lastSearchResults = results;
 
+    boolean wasScrolled = false;
+
     if (av.isFollowHighlight())
     {
       // don't allow highlight of protein/cDNA to also scroll a complementary
@@ -678,14 +723,19 @@ public class SeqPanel extends JPanel implements MouseListener,
       // over residue to change abruptly, causing highlighted residue in panel 2
       // to change, causing a scroll in panel 1 etc)
       ap.setToScrollComplementPanel(false);
-      if (ap.scrollToPosition(results, false))
+      wasScrolled = ap.scrollToPosition(results, false);
+      if (wasScrolled)
       {
         seqCanvas.revalidate();
       }
       ap.setToScrollComplementPanel(true);
     }
-    setStatusMessage(results);
-    seqCanvas.highlightSearchResults(results);
+
+    boolean noFastPaint = wasScrolled && av.getWrapAlignment();
+    if (seqCanvas.highlightSearchResults(results, noFastPaint))
+    {
+      setStatusMessage(results);
+    }
   }
 
   @Override
@@ -702,10 +752,12 @@ public class SeqPanel extends JPanel implements MouseListener,
   }
 
   /**
-   * DOCUMENT ME!
+   * Action on mouse movement is to update the status bar to show the current
+   * sequence position, and (if features are shown) to show any features at the
+   * position in a tooltip. Does nothing if the mouse move does not change
+   * residue position.
    * 
    * @param evt
-   *          DOCUMENT ME!
    */
   @Override
   public void mouseMoved(MouseEvent evt)
@@ -718,11 +770,22 @@ public class SeqPanel extends JPanel implements MouseListener,
     }
 
     final int column = findColumn(evt);
-    int seq = findSeq(evt);
+    final int seq = findSeq(evt);
+
     if (column < 0 || seq < 0 || seq >= av.getAlignment().getHeight())
     {
+      lastMouseSeq = -1;
+      return;
+    }
+    if (column == lastMouseColumn && seq == lastMouseSeq)
+    {
+      /*
+       * just a pixel move without change of residue
+       */
       return;
     }
+    lastMouseColumn = column;
+    lastMouseSeq = seq;
 
     SequenceI sequence = av.getAlignment().getSequenceAt(seq);
 
@@ -773,11 +836,7 @@ public class SeqPanel extends JPanel implements MouseListener,
     if (av.isShowSequenceFeatures())
     {
       List<SequenceFeature> features = ap.getFeatureRenderer()
-              .findFeaturesAtRes(sequence.getDatasetSequence(), pos);
-      if (isGapped)
-      {
-        removeAdjacentFeatures(features, column + 1, sequence);
-      }
+              .findFeaturesAtColumn(sequence, column + 1);
       seqARep.appendFeatures(tooltipText, pos, features,
               this.ap.getSeqPanel().seqCanvas.fr.getMinMax());
     }
@@ -788,45 +847,13 @@ public class SeqPanel extends JPanel implements MouseListener,
     }
     else
     {
-      if (lastTooltip == null
-              || !lastTooltip.equals(tooltipText.toString()))
+      String textString = tooltipText.toString();
+      if (lastTooltip == null || !lastTooltip.equals(textString))
       {
-        String formatedTooltipText = JvSwingUtils.wrapTooltip(true,
-                tooltipText.toString());
-        // String formatedTooltipText = tooltipText.toString();
-        setToolTipText(formatedTooltipText);
-        lastTooltip = tooltipText.toString();
-      }
-
-    }
-
-  }
-
-  /**
-   * Removes from the list of features any that start after, or end before, the
-   * given column position. This allows us to retain only those features
-   * adjacent to a gapped position that straddle the position. Contact features
-   * that 'straddle' the position are also removed, since they are not 'at' the
-   * position.
-   * 
-   * @param features
-   * @param column
-   *          alignment column (1..)
-   * @param sequence
-   */
-  protected void removeAdjacentFeatures(List<SequenceFeature> features,
-          final int column, SequenceI sequence)
-  {
-    // TODO should this be an AlignViewController method (and reused by applet)?
-    ListIterator<SequenceFeature> it = features.listIterator();
-    while (it.hasNext())
-    {
-      SequenceFeature sf = it.next();
-      if (sf.isContactFeature()
-              || sequence.findIndex(sf.getBegin()) > column
-              || sequence.findIndex(sf.getEnd()) < column)
-      {
-        it.remove();
+        String formattedTooltipText = JvSwingUtils.wrapTooltip(true,
+                textString);
+        setToolTipText(formattedTooltipText);
+        lastTooltip = textString;
       }
     }
   }
@@ -847,8 +874,9 @@ public class SeqPanel extends JPanel implements MouseListener,
     Point p = lastp;
     if (!event.isShiftDown() || p == null)
     {
-      p = (tooltipText != null && tooltipText.length() > 6) ? new Point(
-              event.getX() + wdth, event.getY() - 20) : null;
+      p = (tooltipText != null && tooltipText.length() > 6)
+              ? new Point(event.getX() + wdth, event.getY() - 20)
+              : null;
     }
     /*
      * TODO: try to modify position region is not obcured by tooltip
@@ -860,11 +888,12 @@ public class SeqPanel extends JPanel implements MouseListener,
 
   /**
    * set when the current UI interaction has resulted in a change that requires
-   * overview shading to be recalculated. this could be changed to something
-   * more expressive that indicates what actually has changed, so selective
-   * redraws can be applied
+   * shading in overviews and structures to be recalculated. this could be
+   * changed to a something more expressive that indicates what actually has
+   * changed, so selective redraws can be applied (ie. only structures, only
+   * overview, etc)
    */
-  private boolean needOverviewUpdate = false; // TODO: refactor to avcontroller
+  private boolean updateOverviewAndStructs = false; // TODO: refactor to avcontroller
 
   /**
    * set if av.getSelectionGroup() refers to a group that is defined on the
@@ -884,19 +913,48 @@ public class SeqPanel extends JPanel implements MouseListener,
    *          aligned sequence object
    * @param column
    *          alignment column
-   * @param seq
+   * @param seqIndex
    *          index of sequence in alignment
    * @return sequence position of residue at column, or adjacent residue if at a
    *         gap
    */
-  int setStatusMessage(SequenceI sequence, final int column, int seq)
+  int setStatusMessage(SequenceI sequence, final int column, int seqIndex)
+  {
+    char sequenceChar = sequence.getCharAt(column);
+    int pos = sequence.findPosition(column);
+    setStatusMessage(sequence, seqIndex, sequenceChar, pos);
+
+    return pos;
+  }
+
+  /**
+   * Builds the status message for the current cursor location and writes it to
+   * the status bar, for example
+   * 
+   * <pre>
+   * Sequence 3 ID: FER1_SOLLC
+   * Sequence 5 ID: FER1_PEA Residue: THR (4)
+   * Sequence 5 ID: FER1_PEA Residue: B (3)
+   * Sequence 6 ID: O.niloticus.3 Nucleotide: Uracil (2)
+   * </pre>
+   * 
+   * @param sequence
+   * @param seqIndex
+   *          sequence position in the alignment (1..)
+   * @param sequenceChar
+   *          the character under the cursor
+   * @param residuePos
+   *          the sequence residue position (if not over a gap)
+   */
+  protected void setStatusMessage(SequenceI sequence, int seqIndex,
+          char sequenceChar, int residuePos)
   {
     StringBuilder text = new StringBuilder(32);
 
     /*
      * Sequence number (if known), and sequence name.
      */
-    String seqno = seq == -1 ? "" : " " + (seq + 1);
+    String seqno = seqIndex == -1 ? "" : " " + (seqIndex + 1);
     text.append("Sequence").append(seqno).append(" ID: ")
             .append(sequence.getName());
 
@@ -905,31 +963,28 @@ public class SeqPanel extends JPanel implements MouseListener,
     /*
      * Try to translate the display character to residue name (null for gap).
      */
-    final String displayChar = String.valueOf(sequence.getCharAt(column));
-    boolean isGapped = Comparison.isGap(sequence.getCharAt(column));
-    int pos = sequence.findPosition(column);
+    boolean isGapped = Comparison.isGap(sequenceChar);
 
     if (!isGapped)
     {
       boolean nucleotide = av.getAlignment().isNucleotide();
+      String displayChar = String.valueOf(sequenceChar);
       if (nucleotide)
       {
         residue = ResidueProperties.nucleotideName.get(displayChar);
       }
       else
       {
-        residue = "X".equalsIgnoreCase(displayChar) ? "X" : ("*"
-                .equals(displayChar) ? "STOP"
-                : ResidueProperties.aa2Triplet.get(displayChar));
+        residue = "X".equalsIgnoreCase(displayChar) ? "X"
+                : ("*".equals(displayChar) ? "STOP"
+                        : ResidueProperties.aa2Triplet.get(displayChar));
       }
       text.append(" ").append(nucleotide ? "Nucleotide" : "Residue")
               .append(": ").append(residue == null ? displayChar : residue);
 
-      text.append(" (").append(Integer.toString(pos)).append(")");
+      text.append(" (").append(Integer.toString(residuePos)).append(")");
     }
     ap.alignFrame.statusBar.setText(text.toString());
-
-    return pos;
   }
 
   /**
@@ -957,12 +1012,9 @@ public class SeqPanel extends JPanel implements MouseListener,
 
       if (seq == ds)
       {
-        /*
-         * Convert position in sequence (base 1) to sequence character array
-         * index (base 0)
-         */
-        int start = m.getStart() - m.getSequence().getStart();
-        setStatusMessage(seq, start, sequenceIndex);
+        int start = m.getStart();
+        setStatusMessage(seq, sequenceIndex, seq.getCharAt(start - 1),
+                start);
         return;
       }
     }
@@ -982,8 +1034,8 @@ public class SeqPanel extends JPanel implements MouseListener,
       int oldWidth = av.getCharWidth();
 
       // Which is bigger, left-right or up-down?
-      if (Math.abs(evt.getY() - lastMousePress.getY()) > Math.abs(evt
-              .getX() - lastMousePress.getX()))
+      if (Math.abs(evt.getY() - lastMousePress.getY()) > Math
+              .abs(evt.getX() - lastMousePress.getX()))
       {
         /*
          * on drag up or down, decrement or increment font size
@@ -1042,7 +1094,7 @@ public class SeqPanel extends JPanel implements MouseListener,
         }
         if (newWidth > 0)
         {
-          ap.paintAlignment(false);
+          ap.paintAlignment(false, false);
           if (copyChanges)
           {
             /*
@@ -1096,7 +1148,7 @@ public class SeqPanel extends JPanel implements MouseListener,
     }
 
     mouseDragging = true;
-    if (scrollThread != null)
+    if ((scrollThread != null) && (scrollThread.isRunning()))
     {
       scrollThread.setEvent(evt);
     }
@@ -1143,8 +1195,9 @@ public class SeqPanel extends JPanel implements MouseListener,
       }
       if (editCommand == null)
       {
-        editCommand = new EditCommand(MessageManager.formatMessage(
-                "label.edit_params", new String[] { label }));
+        editCommand = new EditCommand(MessageManager
+                .formatMessage("label.edit_params", new String[]
+                { label }));
       }
     }
 
@@ -1161,9 +1214,8 @@ public class SeqPanel extends JPanel implements MouseListener,
     ap.alignFrame.statusBar.setText(message.toString());
 
     // Are we editing within a selection group?
-    if (groupEditing
-            || (sg != null && sg.getSequences(av.getHiddenRepSequences())
-                    .contains(seq)))
+    if (groupEditing || (sg != null
+            && sg.getSequences(av.getHiddenRepSequences()).contains(seq)))
     {
       fixedColumns = true;
 
@@ -1259,7 +1311,7 @@ public class SeqPanel extends JPanel implements MouseListener,
         // Find the next gap before the end
         // of the visible region boundary
         boolean blank = false;
-        for (fixedRight = fixedRight; fixedRight > lastres; fixedRight--)
+        for (; fixedRight > lastres; fixedRight--)
         {
           blank = true;
 
@@ -1351,8 +1403,8 @@ public class SeqPanel extends JPanel implements MouseListener,
         }
         else
         {
-          appendEdit(Action.INSERT_GAP, groupSeqs, startres, startres
-                  - lastres);
+          appendEdit(Action.INSERT_GAP, groupSeqs, startres,
+                  startres - lastres);
         }
       }
       else
@@ -1367,8 +1419,8 @@ public class SeqPanel extends JPanel implements MouseListener,
         }
         else
         {
-          appendEdit(Action.DELETE_GAP, groupSeqs, startres, lastres
-                  - startres);
+          appendEdit(Action.DELETE_GAP, groupSeqs, startres,
+                  lastres - startres);
         }
 
       }
@@ -1522,9 +1574,9 @@ public class SeqPanel extends JPanel implements MouseListener,
       oldSeq = 0;
     }
 
-    if (scrollThread != null)
+    if ((scrollThread != null) && (scrollThread.isRunning()))
     {
-      scrollThread.running = false;
+      scrollThread.stopScrolling();
       scrollThread = null;
     }
   }
@@ -1543,7 +1595,7 @@ public class SeqPanel extends JPanel implements MouseListener,
       return;
     }
 
-    if (mouseDragging)
+    if (mouseDragging && scrollThread == null)
     {
       scrollThread = new ScrollThread();
     }
@@ -1569,19 +1621,13 @@ public class SeqPanel extends JPanel implements MouseListener,
       }
 
       int column = findColumn(evt);
-      boolean isGapped = Comparison.isGap(sequence.getCharAt(column));
 
       /*
        * find features at the position (if not gapped), or straddling
        * the position (if at a gap)
        */
       List<SequenceFeature> features = seqCanvas.getFeatureRenderer()
-              .findFeaturesAtRes(sequence.getDatasetSequence(),
-                      sequence.findPosition(column));
-      if (isGapped)
-      {
-        removeAdjacentFeatures(features, column, sequence);
-      }
+              .findFeaturesAtColumn(sequence, column + 1);
 
       if (!features.isEmpty())
       {
@@ -1591,7 +1637,7 @@ public class SeqPanel extends JPanel implements MouseListener,
         SearchResultsI highlight = new SearchResults();
         highlight.addResult(sequence, features.get(0).getBegin(), features
                 .get(0).getEnd());
-        seqCanvas.highlightSearchResults(highlight);
+        seqCanvas.highlightSearchResults(highlight, false);
 
         /*
          * open the Amend Features dialog; clear highlighting afterwards,
@@ -1600,7 +1646,8 @@ public class SeqPanel extends JPanel implements MouseListener,
         List<SequenceI> seqs = Collections.singletonList(sequence);
         seqCanvas.getFeatureRenderer().amendFeatures(seqs, features, false,
                 ap);
-        seqCanvas.highlightSearchResults(null);
+        av.setSearchResults(null); // clear highlighting
+        seqCanvas.repaint(); // draw new/amended features
       }
     }
   }
@@ -1616,7 +1663,7 @@ public class SeqPanel extends JPanel implements MouseListener,
         av.getRanges().scrollRight(true);
 
       }
-      else if (!av.getWrapAlignment())
+      else
       {
         av.getRanges().scrollUp(false);
       }
@@ -1627,12 +1674,18 @@ public class SeqPanel extends JPanel implements MouseListener,
       {
         av.getRanges().scrollRight(false);
       }
-      else if (!av.getWrapAlignment())
+      else
       {
         av.getRanges().scrollUp(true);
       }
     }
-    // TODO Update tooltip for new position.
+
+    /*
+     * update status bar and tooltip for new position
+     * (need to synthesize a mouse movement to refresh tooltip)
+     */
+    mouseMoved(e);
+    ToolTipManager.sharedInstance().mouseMoved(e);
   }
 
   /**
@@ -1646,14 +1699,15 @@ public class SeqPanel extends JPanel implements MouseListener,
     final int res = findColumn(evt);
     final int seq = findSeq(evt);
     oldSeq = seq;
-    needOverviewUpdate = false;
+    updateOverviewAndStructs = false;
 
     startWrapBlock = wrappedBlock;
 
     if (av.getWrapAlignment() && seq > av.getAlignment().getHeight())
     {
-      JvOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager
-              .getString("label.cannot_edit_annotations_in_wrapped_view"),
+      JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+              MessageManager.getString(
+                      "label.cannot_edit_annotations_in_wrapped_view"),
               MessageManager.getString("label.wrapped_view_no_edit"),
               JvOptionPane.WARNING_MESSAGE);
       return;
@@ -1710,43 +1764,53 @@ public class SeqPanel extends JPanel implements MouseListener,
 
     if (stretchGroup == null)
     {
-      // Only if left mouse button do we want to change group sizes
+      createStretchGroup(res, sequence);
+    }
 
-      // define a new group here
-      SequenceGroup sg = new SequenceGroup();
-      sg.setStartRes(res);
-      sg.setEndRes(res);
-      sg.addSequence(sequence, false);
-      av.setSelectionGroup(sg);
-      stretchGroup = sg;
+    if (stretchGroup != null)
+    {
+      stretchGroup.addPropertyChangeListener(seqCanvas);
+    }
 
-      if (av.getConservationSelected())
-      {
-        SliderPanel.setConservationSlider(ap, av.getResidueShading(),
-                ap.getViewName());
-      }
+    seqCanvas.repaint();
+  }
 
-      if (av.getAbovePIDThreshold())
-      {
-        SliderPanel.setPIDSliderSource(ap, av.getResidueShading(),
-                ap.getViewName());
-      }
-      // TODO: stretchGroup will always be not null. Is this a merge error ?
-      if ((stretchGroup != null) && (stretchGroup.getEndRes() == res))
-      {
-        // Edit end res position of selected group
-        changeEndRes = true;
-      }
-      else if ((stretchGroup != null)
-              && (stretchGroup.getStartRes() == res))
-      {
-        // Edit end res position of selected group
-        changeStartRes = true;
-      }
-      stretchGroup.getWidth();
+  private void createStretchGroup(int res, SequenceI sequence)
+  {
+    // Only if left mouse button do we want to change group sizes
+    // define a new group here
+    SequenceGroup sg = new SequenceGroup();
+    sg.setStartRes(res);
+    sg.setEndRes(res);
+    sg.addSequence(sequence, false);
+    av.setSelectionGroup(sg);
+    stretchGroup = sg;
+
+    if (av.getConservationSelected())
+    {
+      SliderPanel.setConservationSlider(ap, av.getResidueShading(),
+              ap.getViewName());
     }
 
-    seqCanvas.repaint();
+    if (av.getAbovePIDThreshold())
+    {
+      SliderPanel.setPIDSliderSource(ap, av.getResidueShading(),
+              ap.getViewName());
+    }
+    // TODO: stretchGroup will always be not null. Is this a merge error ?
+    // or is there a threading issue here?
+    if ((stretchGroup != null) && (stretchGroup.getEndRes() == res))
+    {
+      // Edit end res position of selected group
+      changeEndRes = true;
+    }
+    else if ((stretchGroup != null) && (stretchGroup.getStartRes() == res))
+    {
+      // Edit end res position of selected group
+      changeStartRes = true;
+    }
+    stretchGroup.getWidth();
+
   }
 
   /**
@@ -1758,12 +1822,11 @@ public class SeqPanel extends JPanel implements MouseListener,
    */
   void showPopupMenu(MouseEvent evt)
   {
-    final int res = findColumn(evt);
+    final int column = findColumn(evt);
     final int seq = findSeq(evt);
     SequenceI sequence = av.getAlignment().getSequenceAt(seq);
     List<SequenceFeature> allFeatures = ap.getFeatureRenderer()
-            .findFeaturesAtRes(sequence.getDatasetSequence(),
-                    sequence.findPosition(res));
+            .findFeaturesAtColumn(sequence, column + 1);
     List<String> links = new ArrayList<>();
     for (SequenceFeature sf : allFeatures)
     {
@@ -1795,17 +1858,21 @@ public class SeqPanel extends JPanel implements MouseListener,
     {
       return;
     }
+
+    stretchGroup.removePropertyChangeListener(seqCanvas);
+
     // always do this - annotation has own state
     // but defer colourscheme update until hidden sequences are passed in
     boolean vischange = stretchGroup.recalcConservation(true);
-    needOverviewUpdate |= vischange && av.isSelectionDefinedGroup()
+    updateOverviewAndStructs |= vischange && av.isSelectionDefinedGroup()
             && afterDrag;
     if (stretchGroup.cs != null)
     {
       stretchGroup.cs.alignmentChanged(stretchGroup,
               av.getHiddenRepSequences());
 
-      ResidueShaderI groupColourScheme = stretchGroup.getGroupColourScheme();
+      ResidueShaderI groupColourScheme = stretchGroup
+              .getGroupColourScheme();
       String name = stretchGroup.getName();
       if (stretchGroup.cs.conservationApplied())
       {
@@ -1817,8 +1884,10 @@ public class SeqPanel extends JPanel implements MouseListener,
       }
     }
     PaintRefresher.Refresh(this, av.getSequenceSetId());
-    ap.paintAlignment(needOverviewUpdate);
-    needOverviewUpdate = false;
+    // TODO: structure colours only need updating if stretchGroup used to or now
+    // does contain sequences with structure views
+    ap.paintAlignment(updateOverviewAndStructs, updateOverviewAndStructs);
+    updateOverviewAndStructs = false;
     changeEndRes = false;
     changeStartRes = false;
     stretchGroup = null;
@@ -1872,7 +1941,7 @@ public class SeqPanel extends JPanel implements MouseListener,
       if (res > (stretchGroup.getStartRes() - 1))
       {
         stretchGroup.setEndRes(res);
-        needOverviewUpdate |= av.isSelectionDefinedGroup();
+        updateOverviewAndStructs |= av.isSelectionDefinedGroup();
       }
     }
     else if (changeStartRes)
@@ -1880,7 +1949,7 @@ public class SeqPanel extends JPanel implements MouseListener,
       if (res < (stretchGroup.getEndRes() + 1))
       {
         stretchGroup.setStartRes(res);
-        needOverviewUpdate |= av.isSelectionDefinedGroup();
+        updateOverviewAndStructs |= av.isSelectionDefinedGroup();
       }
     }
 
@@ -1914,7 +1983,7 @@ public class SeqPanel extends JPanel implements MouseListener,
       if (stretchGroup.getSequences(null).contains(nextSeq))
       {
         stretchGroup.deleteSequence(seq, false);
-        needOverviewUpdate |= av.isSelectionDefinedGroup();
+        updateOverviewAndStructs |= av.isSelectionDefinedGroup();
       }
       else
       {
@@ -1924,7 +1993,7 @@ public class SeqPanel extends JPanel implements MouseListener,
         }
 
         stretchGroup.addSequence(nextSeq, false);
-        needOverviewUpdate |= av.isSelectionDefinedGroup();
+        updateOverviewAndStructs |= av.isSelectionDefinedGroup();
       }
     }
 
@@ -1935,21 +2004,19 @@ public class SeqPanel extends JPanel implements MouseListener,
 
     mouseDragging = true;
 
-    if (scrollThread != null)
+    if ((scrollThread != null) && (scrollThread.isRunning()))
     {
       scrollThread.setEvent(evt);
     }
-
-    seqCanvas.repaint();
   }
 
   void scrollCanvas(MouseEvent evt)
   {
     if (evt == null)
     {
-      if (scrollThread != null)
+      if ((scrollThread != null) && (scrollThread.isRunning()))
       {
-        scrollThread.running = false;
+        scrollThread.stopScrolling();
         scrollThread = null;
       }
       mouseDragging = false;
@@ -1972,7 +2039,7 @@ public class SeqPanel extends JPanel implements MouseListener,
   {
     MouseEvent evt;
 
-    boolean running = false;
+    private volatile boolean threadRunning = true;
 
     public ScrollThread()
     {
@@ -1986,38 +2053,40 @@ public class SeqPanel extends JPanel implements MouseListener,
 
     public void stopScrolling()
     {
-      running = false;
+      threadRunning = false;
+    }
+
+    public boolean isRunning()
+    {
+      return threadRunning;
     }
 
     @Override
     public void run()
     {
-      running = true;
-
-      while (running)
+      while (threadRunning)
       {
         if (evt != null)
         {
           if (mouseDragging && (evt.getY() < 0)
                   && (av.getRanges().getStartSeq() > 0))
           {
-            running = av.getRanges().scrollUp(true);
+            av.getRanges().scrollUp(true);
           }
 
-          if (mouseDragging && (evt.getY() >= getHeight())
-                  && (av.getAlignment().getHeight() > av.getRanges()
-                          .getEndSeq()))
+          if (mouseDragging && (evt.getY() >= getHeight()) && (av
+                  .getAlignment().getHeight() > av.getRanges().getEndSeq()))
           {
-            running = av.getRanges().scrollUp(false);
+            av.getRanges().scrollUp(false);
           }
 
           if (mouseDragging && (evt.getX() < 0))
           {
-            running = av.getRanges().scrollRight(false);
+            av.getRanges().scrollRight(false);
           }
           else if (mouseDragging && (evt.getX() >= getWidth()))
           {
-            running = av.getRanges().scrollRight(true);
+            av.getRanges().scrollRight(true);
           }
         }
 
@@ -2042,8 +2111,10 @@ public class SeqPanel extends JPanel implements MouseListener,
     // handles selection messages...
     // TODO: extend config options to allow user to control if selections may be
     // shared between viewports.
-    boolean iSentTheSelection = (av == source || (source instanceof AlignViewport && ((AlignmentViewport) source)
-            .getSequenceSetId().equals(av.getSequenceSetId())));
+    boolean iSentTheSelection = (av == source
+            || (source instanceof AlignViewport
+                    && ((AlignmentViewport) source).getSequenceSetId()
+                            .equals(av.getSequenceSetId())));
 
     if (iSentTheSelection)
     {
@@ -2145,8 +2216,7 @@ public class SeqPanel extends JPanel implements MouseListener,
       repaint = true;
     }
 
-    if (copycolsel
-            && av.hasHiddenColumns()
+    if (copycolsel && av.hasHiddenColumns()
             && (av.getAlignment().getHiddenColumns() == null))
     {
       System.err.println("Bad things");
index bf0ab70..8d46792 100755 (executable)
@@ -26,6 +26,7 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
+import jalview.fts.core.GFTSPanel;
 import jalview.fts.service.pdb.PDBFTSPanel;
 import jalview.fts.service.uniprot.UniprotFTSPanel;
 import jalview.io.FileFormatI;
@@ -78,6 +79,8 @@ public class SequenceFetcher extends JPanel implements Runnable
 
   JButton close = new JButton();
 
+  JButton back = new JButton();
+
   JPanel jPanel1 = new JPanel();
 
   JTextArea textArea = new JTextArea();
@@ -136,11 +139,10 @@ public class SequenceFetcher extends JPanel implements Runnable
     {
       if (guiWindow != null)
       {
-        guiWindow
-                .setProgressBar(
-                        MessageManager
-                                .getString("status.waiting_sequence_database_fetchers_init"),
-                        Thread.currentThread().hashCode());
+        guiWindow.setProgressBar(
+                MessageManager.getString(
+                        "status.waiting_sequence_database_fetchers_init"),
+                Thread.currentThread().hashCode());
       }
       // initting happening on another thread - so wait around to see if it
       // finishes.
@@ -157,18 +159,17 @@ public class SequenceFetcher extends JPanel implements Runnable
       }
       if (guiWindow != null)
       {
-        guiWindow
-                .setProgressBar(
-                        MessageManager
-                                .getString("status.waiting_sequence_database_fetchers_init"),
-                        Thread.currentThread().hashCode());
+        guiWindow.setProgressBar(
+                MessageManager.getString(
+                        "status.waiting_sequence_database_fetchers_init"),
+                Thread.currentThread().hashCode());
       }
     }
-    if (sfetch == null
-            || dasRegistry != Cache.getDasSourceRegistry()
+    if (sfetch == null || dasRegistry != Cache.getDasSourceRegistry()
             || lastDasSourceRegistry != (Cache.getDasSourceRegistry()
-                    .getDasRegistryURL() + Cache.getDasSourceRegistry()
-                    .getLocalSourceString()).hashCode())
+                    .getDasRegistryURL()
+                    + Cache.getDasSourceRegistry().getLocalSourceString())
+                            .hashCode())
     {
       _initingFetcher = true;
       initingThread = Thread.currentThread();
@@ -177,8 +178,9 @@ public class SequenceFetcher extends JPanel implements Runnable
        */
       if (guiWindow != null)
       {
-        guiWindow.setProgressBar(MessageManager
-                .getString("status.init_sequence_database_fetchers"),
+        guiWindow.setProgressBar(
+                MessageManager.getString(
+                        "status.init_sequence_database_fetchers"),
                 Thread.currentThread().hashCode());
       }
       dasRegistry = Cache.getDasSourceRegistry();
@@ -189,8 +191,8 @@ public class SequenceFetcher extends JPanel implements Runnable
       {
         guiWindow.setProgressBar(null, Thread.currentThread().hashCode());
       }
-      lastDasSourceRegistry = (dasRegistry.getDasRegistryURL() + dasRegistry
-              .getLocalSourceString()).hashCode();
+      lastDasSourceRegistry = (dasRegistry.getDasRegistryURL()
+              + dasRegistry.getLocalSourceString()).hashCode();
       sfetch = sf;
       _initingFetcher = false;
       initingThread = null;
@@ -234,14 +236,12 @@ public class SequenceFetcher extends JPanel implements Runnable
             @Override
             public void run()
             {
-              JvOptionPane
-                      .showInternalMessageDialog(
-                              Desktop.desktop,
-                              MessageManager
-                                      .getString("warn.couldnt_create_sequence_fetcher_client"),
-                              MessageManager
-                                      .getString("label.couldnt_create_sequence_fetcher"),
-                              JvOptionPane.ERROR_MESSAGE);
+              JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                      MessageManager.getString(
+                              "warn.couldnt_create_sequence_fetcher_client"),
+                      MessageManager.getString(
+                              "label.couldnt_create_sequence_fetcher"),
+                      JvOptionPane.ERROR_MESSAGE);
             }
           });
 
@@ -311,14 +311,15 @@ public class SequenceFetcher extends JPanel implements Runnable
         if (sourcep.getTier() == 0)
         {
           database.selection = Arrays
-                  .asList(new DbSourceProxy[] { sourcep });
+                  .asList(new DbSourceProxy[]
+                  { sourcep });
           break;
         }
       }
       if (database.selection == null || database.selection.size() == 0)
       {
-        System.err.println("Ignoring fetch parameter db='" + selectedDb
-                + "'");
+        System.err.println(
+                "Ignoring fetch parameter db='" + selectedDb + "'");
         return false;
       }
       textArea.setText(queryString);
@@ -379,11 +380,21 @@ public class SequenceFetcher extends JPanel implements Runnable
 
   private String getFrameTitle()
   {
-    return ((alignFrame == null) ? MessageManager
-            .getString("label.new_sequence_fetcher") : MessageManager
-            .getString("label.additional_sequence_fetcher"));
+    return ((alignFrame == null)
+            ? MessageManager.getString("label.new_sequence_fetcher")
+            : MessageManager
+                    .getString("label.additional_sequence_fetcher"));
   }
 
+  GFTSPanel parentFTSframe = null;
+  /**
+   * change the buttons so they fit with the FTS panel.
+   */
+  public void embedWithFTSPanel(GFTSPanel toClose)
+  {
+    back.setVisible(true);
+    parentFTSframe = toClose;
+  }
   private void jbInit() throws Exception
   {
     this.setLayout(borderLayout2);
@@ -398,8 +409,8 @@ public class SequenceFetcher extends JPanel implements Runnable
     replacePunctuation.setHorizontalAlignment(SwingConstants.CENTER);
     replacePunctuation
             .setFont(new java.awt.Font("Verdana", Font.ITALIC, 11));
-    replacePunctuation.setText(MessageManager
-            .getString("label.replace_commas_semicolons"));
+    replacePunctuation.setText(
+            MessageManager.getString("label.replace_commas_semicolons"));
     ok.setText(MessageManager.getString("action.ok"));
     ok.addActionListener(new ActionListener()
     {
@@ -428,7 +439,7 @@ public class SequenceFetcher extends JPanel implements Runnable
         example_actionPerformed();
       }
     });
-    close.setText(MessageManager.getString("action.close"));
+    close.setText(MessageManager.getString("action.cancel"));
     close.addActionListener(new ActionListener()
     {
       @Override
@@ -437,6 +448,17 @@ public class SequenceFetcher extends JPanel implements Runnable
         close_actionPerformed(e);
       }
     });
+    back.setText(MessageManager.getString("action.back"));
+    back.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        parentFTSframe.btn_back_ActionPerformed();
+      }
+    });
+    // back not visible unless embedded
+    back.setVisible(false);
     textArea.setFont(JvSwingUtils.getLabelFont());
     textArea.setLineWrap(true);
     textArea.addKeyListener(new KeyAdapter()
@@ -452,9 +474,10 @@ public class SequenceFetcher extends JPanel implements Runnable
     });
     jPanel3.setLayout(borderLayout1);
     borderLayout1.setVgap(5);
-    jPanel1.add(ok);
+    jPanel1.add(back);
     jPanel1.add(example);
     jPanel1.add(clear);
+    jPanel1.add(ok);
     jPanel1.add(close);
     jPanel2.setLayout(borderLayout3);
     databaseButt = /*database.getDatabaseSelectorButton();
@@ -538,8 +561,9 @@ public class SequenceFetcher extends JPanel implements Runnable
                       + database.getSelectedSources().size() + " others)"
                       : ""));
       String eq = database.getExampleQueries();
-      dbeg.setText(MessageManager.formatMessage(
-              "label.example_query_param", new String[] { eq }));
+      dbeg.setText(MessageManager.formatMessage("label.example_query_param",
+              new String[]
+              { eq }));
       boolean enablePunct = !(eq != null && eq.indexOf(",") > -1);
       for (DbSourceProxy dbs : database.getSelectedSources())
       {
@@ -582,6 +606,10 @@ public class SequenceFetcher extends JPanel implements Runnable
     try
     {
       frame.setClosed(true);
+      if (parentFTSframe!=null)
+      {
+        parentFTSframe.btn_cancel_ActionPerformed();
+      }
     } catch (Exception ex)
     {
     }
@@ -594,7 +622,7 @@ public class SequenceFetcher extends JPanel implements Runnable
     textArea.setEnabled(false);
     ok.setEnabled(false);
     close.setEnabled(false);
-
+    back.setEnabled(false);
     Thread worker = new Thread(this);
     worker.start();
   }
@@ -606,6 +634,7 @@ public class SequenceFetcher extends JPanel implements Runnable
     textArea.setEnabled(true);
     ok.setEnabled(true);
     close.setEnabled(true);
+    back.setEnabled(parentFTSframe != null);
   }
 
   @Override
@@ -621,7 +650,7 @@ public class SequenceFetcher extends JPanel implements Runnable
     if (replacePunctuation.isEnabled() && replacePunctuation.isSelected())
     {
       empty = new com.stevesoft.pat.Regex(
-      // replace commas and spaces with a semicolon
+              // replace commas and spaces with a semicolon
               "(\\s|[,; ])+", ";");
     }
     else
@@ -631,8 +660,8 @@ public class SequenceFetcher extends JPanel implements Runnable
     }
     textArea.setText(empty.replaceAll(textArea.getText()));
     // see if there's anthing to search with
-    if (!new com.stevesoft.pat.Regex("[A-Za-z0-9_.]").search(textArea
-            .getText()))
+    if (!new com.stevesoft.pat.Regex("[A-Za-z0-9_.]")
+            .search(textArea.getText()))
     {
       error += "Please enter a (semi-colon separated list of) database id(s)";
     }
@@ -652,8 +681,8 @@ public class SequenceFetcher extends JPanel implements Runnable
     Iterator<DbSourceProxy> proxies = database.getSelectedSources()
             .iterator();
     String[] qries;
-    List<String> nextFetch = Arrays.asList(qries = textArea.getText()
-            .split(";"));
+    List<String> nextFetch = Arrays
+            .asList(qries = textArea.getText().split(";"));
     Iterator<String> en = Arrays.asList(new String[0]).iterator();
     int nqueries = qries.length;
 
@@ -673,13 +702,11 @@ public class SequenceFetcher extends JPanel implements Runnable
       try
       {
         // update status
-        guiWindow
-                .setProgressBar(MessageManager.formatMessage(
-                        "status.fetching_sequence_queries_from",
-                        new String[] {
-                            Integer.valueOf(nqueries).toString(),
-                            proxy.getDbName() }), Thread.currentThread()
-                        .hashCode());
+        guiWindow.setProgressBar(MessageManager.formatMessage(
+                "status.fetching_sequence_queries_from", new String[]
+                { Integer.valueOf(nqueries).toString(),
+                    proxy.getDbName() }),
+                Thread.currentThread().hashCode());
         if (proxy.getMaximumQueryCount() == 1)
         {
           /*
@@ -703,8 +730,8 @@ public class SequenceFetcher extends JPanel implements Runnable
         }
       } catch (Exception e)
       {
-        showErrorMessage("Error retrieving " + textArea.getText()
-                + " from " + database.getSelectedItem());
+        showErrorMessage("Error retrieving " + textArea.getText() + " from "
+                + database.getSelectedItem());
         // error
         // +="Couldn't retrieve sequences from "+database.getSelectedItem();
         System.err.println("Retrieval failed for source ='"
@@ -714,9 +741,7 @@ public class SequenceFetcher extends JPanel implements Runnable
       } catch (OutOfMemoryError e)
       {
         showErrorMessage("Out of Memory when retrieving "
-                + textArea.getText()
-                + " from "
-                + database.getSelectedItem()
+                + textArea.getText() + " from " + database.getSelectedItem()
                 + "\nPlease see the Jalview FAQ for instructions for increasing the memory available to Jalview.\n");
         e.printStackTrace();
       } catch (Error e)
@@ -744,8 +769,8 @@ public class SequenceFetcher extends JPanel implements Runnable
           while (aresult.size() > 0)
           {
             presult.add(aresult.remove(0));
-            presultTitle.add(aresultq.remove(0) + " "
-                    + getDefaultRetrievalTitle());
+            presultTitle.add(
+                    aresultq.remove(0) + " " + getDefaultRetrievalTitle());
           }
         }
         else
@@ -773,15 +798,17 @@ public class SequenceFetcher extends JPanel implements Runnable
           presultTitle.add(titl);
         }
       }
-      guiWindow.setProgressBar(MessageManager
-              .getString("status.finshed_querying"), Thread.currentThread()
-              .hashCode());
+      guiWindow.setProgressBar(
+              MessageManager.getString("status.finshed_querying"),
+              Thread.currentThread().hashCode());
     }
-    guiWindow.setProgressBar(
-            (presult.size() > 0) ? MessageManager
-                    .getString("status.parsing_results") : MessageManager
-                    .getString("status.processing"), Thread.currentThread()
-                    .hashCode());
+    guiWindow
+            .setProgressBar(
+                    (presult.size() > 0)
+                            ? MessageManager
+                                    .getString("status.parsing_results")
+                            : MessageManager.getString("status.processing"),
+                    Thread.currentThread().hashCode());
     // process results
     while (presult.size() > 0)
     {
@@ -794,8 +821,9 @@ public class SequenceFetcher extends JPanel implements Runnable
     {
       StringBuffer sb = new StringBuffer();
       sb.append("Didn't retrieve the following "
-              + (nextFetch.size() == 1 ? "query" : nextFetch.size()
-                      + " queries") + ": \n");
+              + (nextFetch.size() == 1 ? "query"
+                      : nextFetch.size() + " queries")
+              + ": \n");
       int l = sb.length(), lr = 0;
       for (String s : nextFetch)
       {
@@ -830,8 +858,7 @@ public class SequenceFetcher extends JPanel implements Runnable
    */
   void fetchMultipleAccessions(DbSourceProxy proxy,
           Iterator<String> accessions, List<String> aresultq,
-          List<AlignmentI> aresult, List<String> nextFetch)
-          throws Exception
+          List<AlignmentI> aresult, List<String> nextFetch) throws Exception
   {
     StringBuilder multiacc = new StringBuilder();
     List<String> tosend = new ArrayList<String>();
@@ -906,8 +933,9 @@ public class SequenceFetcher extends JPanel implements Runnable
         indres = proxy.getSequenceRecords(accession);
       } catch (OutOfMemoryError oome)
       {
-        new OOMWarning("fetching " + accession + " from "
-                + proxy.getDbName(), oome, this);
+        new OOMWarning(
+                "fetching " + accession + " from " + proxy.getDbName(),
+                oome, this);
       }
       if (indres != null)
       {
@@ -917,9 +945,8 @@ public class SequenceFetcher extends JPanel implements Runnable
       }
     } catch (Exception e)
     {
-      Cache.log.info(
-              "Error retrieving " + accession + " from "
-                      + proxy.getDbName(), e);
+      Cache.log.info("Error retrieving " + accession + " from "
+              + proxy.getDbName(), e);
     }
     return success;
   }
@@ -1006,15 +1033,11 @@ public class SequenceFetcher extends JPanel implements Runnable
         {
           for (SequenceI sq : alsqs)
           {
-            if ((sfs = sq.getSequenceFeatures()) != null)
+            if (sq.getFeatures().hasFeatures())
             {
-              if (sfs.length > 0)
-              {
-                af.setShowSeqFeatures(true);
-                break;
-              }
+              af.setShowSeqFeatures(true);
+              break;
             }
-
           }
         }
 
@@ -1093,4 +1116,9 @@ public class SequenceFetcher extends JPanel implements Runnable
   {
     frame.setVisible(false);
   }
+
+  public void setDatabaseChooserVisible(boolean b)
+  {
+    databaseButt.setVisible(b);
+  }
 }
index 36825ea..81b394b 100755 (executable)
@@ -23,9 +23,8 @@ package jalview.gui;
 import jalview.api.AlignViewportI;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
-import jalview.renderer.ResidueShaderI;
+import jalview.renderer.ResidueColourFinder;
 import jalview.renderer.seqfeatures.FeatureColourFinder;
-import jalview.util.Comparison;
 
 import java.awt.Color;
 import java.awt.FontMetrics;
@@ -41,17 +40,15 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
 
   boolean renderGaps = true;
 
-  SequenceGroup currentSequenceGroup = null;
-
   SequenceGroup[] allGroups = null;
 
-  Color resBoxColour;
+  // Color resBoxColour;
 
   Graphics graphics;
 
   boolean monospacedFont;
 
-  boolean forOverview = false;
+  ResidueColourFinder resColourFinder;
 
   /**
    * Creates a new SequenceRenderer object
@@ -61,6 +58,7 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
   public SequenceRenderer(AlignViewportI viewport)
   {
     this.av = viewport;
+    resColourFinder = new ResidueColourFinder();
   }
 
   /**
@@ -77,32 +75,12 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
     // If EPS graphics, stringWidth will be a double, not an int
     double dwidth = fm.getStringBounds("M", g).getWidth();
 
-    monospacedFont = (dwidth == fm.getStringBounds("|", g).getWidth() && av
-            .getCharWidth() == dwidth);
+    monospacedFont = (dwidth == fm.getStringBounds("|", g).getWidth()
+            && av.getCharWidth() == dwidth);
 
     this.renderGaps = renderGaps;
   }
 
-  protected Color getResidueBoxColour(SequenceI seq, int i)
-  {
-    // rate limiting step when rendering overview for lots of groups
-    allGroups = av.getAlignment().findAllGroups(seq);
-
-    if (inCurrentSequenceGroup(i))
-    {
-      if (currentSequenceGroup.getDisplayBoxes())
-      {
-        getBoxColour(currentSequenceGroup.getGroupColourScheme(), seq, i);
-      }
-    }
-    else if (av.getShowBoxes())
-    {
-      getBoxColour(av.getResidueShading(), seq, i);
-    }
-
-    return resBoxColour;
-  }
-
   /**
    * Get the residue colour at the given sequence position - as determined by
    * the sequence group colour (if any), else the colour scheme, possibly
@@ -117,40 +95,11 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
   public Color getResidueColour(final SequenceI seq, int position,
           FeatureColourFinder finder)
   {
-    Color col = getResidueBoxColour(seq, position);
-
-    if (finder != null)
-    {
-      col = finder.findFeatureColour(col, seq, position);
-    }
-    return col;
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param shader
-   *          DOCUMENT ME!
-   * @param seq
-   *          DOCUMENT ME!
-   * @param i
-   *          DOCUMENT ME!
-   */
-  void getBoxColour(ResidueShaderI shader, SequenceI seq, int i)
-  {
-    if (shader.getColourScheme() != null)
-    {
-      resBoxColour = shader.findColour(seq.getCharAt(i),
-              i, seq);
-    }
-    else if (forOverview && !Comparison.isGap(seq.getCharAt(i)))
-    {
-      resBoxColour = Color.lightGray;
-    }
-    else
-    {
-      resBoxColour = Color.white;
-    }
+    allGroups = av.getAlignment().findAllGroups(seq);
+    return resColourFinder.getResidueColour(av.getShowBoxes(),
+            av.getResidueShading(),
+            allGroups, seq, position,
+            finder);
   }
 
   /**
@@ -209,6 +158,8 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
   public synchronized void drawBoxes(SequenceI seq, int start, int end,
           int y1)
   {
+    Color resBoxColour = Color.white;
+
     if (seq == null)
     {
       return; // fix for racecondition
@@ -217,8 +168,8 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
     int length = seq.getLength();
 
     int curStart = -1;
-    int curWidth = av.getCharWidth(), avWidth = av.getCharWidth(), avHeight = av
-            .getCharHeight();
+    int curWidth = av.getCharWidth(), avWidth = av.getCharWidth(),
+            avHeight = av.getCharHeight();
 
     Color tempColour = null;
 
@@ -228,17 +179,22 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
 
       if (i < length)
       {
-        if (inCurrentSequenceGroup(i))
+        SequenceGroup currentSequenceGroup = resColourFinder
+                .getCurrentSequenceGroup(
+                allGroups, i);
+        if (currentSequenceGroup != null)
         {
           if (currentSequenceGroup.getDisplayBoxes())
           {
-            getBoxColour(currentSequenceGroup.getGroupColourScheme(), seq,
+            resBoxColour = resColourFinder.getBoxColour(
+                    currentSequenceGroup.getGroupColourScheme(), seq,
                     i);
           }
         }
         else if (av.getShowBoxes())
         {
-          getBoxColour(av.getResidueShading(), seq, i);
+          resBoxColour = resColourFinder
+                  .getBoxColour(av.getResidueShading(), seq, i);
         }
       }
 
@@ -308,8 +264,9 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
       else
       {
         char gap = av.getGapCharacter();
-        graphics.drawString(seq.getSequenceAsString(start, end + 1)
-                .replace(gap, ' '), 0, y1);
+        graphics.drawString(
+                seq.getSequenceAsString(start, end + 1).replace(gap, ' '),
+                0, y1);
       }
     }
     else
@@ -317,9 +274,8 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
       boolean srep = av.isDisplayReferenceSeq();
       boolean getboxColour = false;
       boolean isarep = av.getAlignment().getSeqrep() == seq;
-      boolean isgrep = currentSequenceGroup != null ? currentSequenceGroup
-              .getSeqrep() == seq : false;
-      char sr_c;
+      Color resBoxColour = Color.white;
+
       for (int i = start; i <= end; i++)
       {
 
@@ -332,7 +288,10 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
           continue;
         }
 
-        if (inCurrentSequenceGroup(i))
+        SequenceGroup currentSequenceGroup = resColourFinder
+                .getCurrentSequenceGroup(
+                allGroups, i);
+        if (currentSequenceGroup != null)
         {
           if (!currentSequenceGroup.getDisplayText())
           {
@@ -343,7 +302,8 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
                   || currentSequenceGroup.getColourText())
           {
             getboxColour = true;
-            getBoxColour(currentSequenceGroup.getGroupColourScheme(), seq,
+            resBoxColour = resColourFinder.getBoxColour(
+                    currentSequenceGroup.getGroupColourScheme(), seq,
                     i);
 
             if (currentSequenceGroup.getColourText())
@@ -354,7 +314,8 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
             if (currentSequenceGroup.thresholdTextColour > 0)
             {
               if (resBoxColour.getRed() + resBoxColour.getBlue()
-                      + resBoxColour.getGreen() < currentSequenceGroup.thresholdTextColour)
+                      + resBoxColour
+                              .getGreen() < currentSequenceGroup.thresholdTextColour)
               {
                 graphics.setColor(currentSequenceGroup.textColour2);
               }
@@ -364,6 +325,8 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
           {
             graphics.setColor(currentSequenceGroup.textColour);
           }
+          boolean isgrep = currentSequenceGroup != null
+                  ? currentSequenceGroup.getSeqrep() == seq : false;
           if (!isarep && !isgrep
                   && currentSequenceGroup.getShowNonconserved()) // todo
                                                                  // optimize
@@ -384,7 +347,8 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
           if (av.getColourText())
           {
             getboxColour = true;
-            getBoxColour(av.getResidueShading(), seq, i);
+            resBoxColour = resColourFinder
+                    .getBoxColour(av.getResidueShading(), seq, i);
 
             if (av.getShowBoxes())
             {
@@ -400,7 +364,8 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
           {
             if (!getboxColour)
             {
-              getBoxColour(av.getResidueShading(), seq, i);
+              resBoxColour = resColourFinder
+                      .getBoxColour(av.getResidueShading(), seq, i);
             }
 
             if (resBoxColour.getRed() + resBoxColour.getBlue()
@@ -443,21 +408,25 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
     // currentSequenceGroup.getConsensus()
     char conschar = (usesrep) ? (currentGroup == null
             || position < currentGroup.getStartRes()
-            || position > currentGroup.getEndRes() ? av.getAlignment()
-            .getSeqrep().getCharAt(position)
-            : (currentGroup.getSeqrep() != null ? currentGroup.getSeqrep()
-                    .getCharAt(position) : av.getAlignment().getSeqrep()
-                    .getCharAt(position)))
+            || position > currentGroup.getEndRes()
+                    ? av.getAlignment().getSeqrep().getCharAt(position)
+                    : (currentGroup.getSeqrep() != null
+                            ? currentGroup.getSeqrep().getCharAt(position)
+                            : av.getAlignment().getSeqrep()
+                                    .getCharAt(position)))
             : (currentGroup != null && currentGroup.getConsensus() != null
                     && position >= currentGroup.getStartRes()
-                    && position <= currentGroup.getEndRes() && currentGroup
-                    .getConsensus().annotations.length > position) ? currentGroup
-                    .getConsensus().annotations[position].displayCharacter
-                    .charAt(0)
-                    : av.getAlignmentConsensusAnnotation().annotations[position].displayCharacter
-                            .charAt(0);
+                    && position <= currentGroup.getEndRes()
+                    && currentGroup
+                            .getConsensus().annotations.length > position)
+                                    ? currentGroup
+                                            .getConsensus().annotations[position].displayCharacter
+                                                    .charAt(0)
+                                    : av.getAlignmentConsensusAnnotation().annotations[position].displayCharacter
+                                            .charAt(0);
     if (!jalview.util.Comparison.isGap(conschar)
-            && (sequenceChar == conschar || sequenceChar + CHAR_TO_UPPER == conschar))
+            && (sequenceChar == conschar
+                    || sequenceChar + CHAR_TO_UPPER == conschar))
     {
       sequenceChar = conservedChar;
     }
@@ -467,35 +436,6 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
   /**
    * DOCUMENT ME!
    * 
-   * @param res
-   *          DOCUMENT ME!
-   * 
-   * @return DOCUMENT ME!
-   */
-  boolean inCurrentSequenceGroup(int res)
-  {
-    if (allGroups == null)
-    {
-      return false;
-    }
-
-    for (int i = 0; i < allGroups.length; i++)
-    {
-      if ((allGroups[i].getStartRes() <= res)
-              && (allGroups[i].getEndRes() >= res))
-      {
-        currentSequenceGroup = allGroups[i];
-
-        return true;
-      }
-    }
-
-    return false;
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
    * @param seq
    *          DOCUMENT ME!
    * @param start
@@ -511,8 +451,8 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
    * @param height
    *          DOCUMENT ME!
    */
-  public void drawHighlightedText(SequenceI seq, int start, int end,
-          int x1, int y1)
+  public void drawHighlightedText(SequenceI seq, int start, int end, int x1,
+          int y1)
   {
     int pady = av.getCharHeight() / 5;
     int charOffset = 0;
@@ -541,21 +481,30 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
     }
   }
 
-  public void drawCursor(SequenceI seq, int res, int x1, int y1)
+  /**
+   * Draw a sequence canvas cursor
+   * 
+   * @param g
+   *          graphics context to draw on
+   * @param s
+   *          character to draw at cursor
+   * @param x1
+   *          x position of cursor in graphics context
+   * @param y1
+   *          y position of cursor in graphics context
+   */
+  public void drawCursor(Graphics g, char s, int x1, int y1)
   {
     int pady = av.getCharHeight() / 5;
     int charOffset = 0;
-    graphics.setColor(Color.black);
-    graphics.fillRect(x1, y1, av.getCharWidth(), av.getCharHeight());
+    g.setColor(Color.black);
+    g.fillRect(x1, y1, av.getCharWidth(), av.getCharHeight());
 
     if (av.isValidCharWidth())
     {
-      graphics.setColor(Color.white);
-
-      char s = seq.getCharAt(res);
-
+      g.setColor(Color.white);
       charOffset = (av.getCharWidth() - fm.charWidth(s)) / 2;
-      graphics.drawString(String.valueOf(s), charOffset + x1,
+      g.drawString(String.valueOf(s), charOffset + x1,
               (y1 + av.getCharHeight()) - pady);
     }
 
index 2176719..93a2457 100755 (executable)
@@ -99,15 +99,15 @@ public class SliderPanel extends GSliderPanel
 
     if (forConservation)
     {
-      label.setText(MessageManager
-              .getString("label.enter_value_increase_conservation_visibility"));
+      label.setText(MessageManager.getString(
+              "label.enter_value_increase_conservation_visibility"));
       slider.setMinimum(0);
       slider.setMaximum(100);
     }
     else
     {
-      label.setText(MessageManager
-              .getString("label.enter_percentage_identity_above_which_colour_residues"));
+      label.setText(MessageManager.getString(
+              "label.enter_percentage_identity_above_which_colour_residues"));
       slider.setMinimum(0);
       slider.setMaximum(100);
     }
@@ -127,7 +127,7 @@ public class SliderPanel extends GSliderPanel
       @Override
       public void mouseReleased(MouseEvent evt)
       {
-        ap.paintAlignment(true);
+        ap.paintAlignment(true, true);
       }
     });
 
@@ -162,15 +162,16 @@ public class SliderPanel extends GSliderPanel
     else
     {
       sliderPanel = (SliderPanel) conservationSlider.getContentPane();
-      sliderPanel.valueField.setText(String.valueOf(rs.getConservationInc()));
+      sliderPanel.valueField
+              .setText(String.valueOf(rs.getConservationInc()));
       sliderPanel.cs = rs;
       sliderPanel.ap = ap;
       sliderPanel.slider.setValue(rs.getConservationInc());
     }
 
     conservationSlider.setTitle(MessageManager.formatMessage(
-            "label.conservation_colour_increment",
-            new String[] { source == null ? BACKGROUND : source }));
+            "label.conservation_colour_increment", new String[]
+            { source == null ? BACKGROUND : source }));
 
     List<SequenceGroup> groups = ap.av.getAlignment().getGroups();
     if (groups != null && !groups.isEmpty())
@@ -230,15 +231,14 @@ public class SliderPanel extends GSliderPanel
     {
       Desktop.addInternalFrame(conservationSlider,
               conservationSlider.getTitle(), 420, 90, false);
-      conservationSlider
-              .addInternalFrameListener(new InternalFrameAdapter()
-              {
-                @Override
-                public void internalFrameClosed(InternalFrameEvent e)
-                {
-                  conservationSlider = null;
-                }
-              });
+      conservationSlider.addInternalFrameListener(new InternalFrameAdapter()
+      {
+        @Override
+        public void internalFrameClosed(InternalFrameEvent e)
+        {
+          conservationSlider = null;
+        }
+      });
       conservationSlider.setLayer(JLayeredPane.PALETTE_LAYER);
     }
   }
@@ -255,8 +255,8 @@ public class SliderPanel extends GSliderPanel
    * 
    * @return
    */
-  public static int setPIDSliderSource(AlignmentPanel ap,
-          ResidueShaderI rs, String source)
+  public static int setPIDSliderSource(AlignmentPanel ap, ResidueShaderI rs,
+          String source)
   {
     int threshold = rs.getThreshold();
 
@@ -279,8 +279,8 @@ public class SliderPanel extends GSliderPanel
     }
 
     PIDSlider.setTitle(MessageManager.formatMessage(
-            "label.percentage_identity_threshold",
-            new String[] { source == null ? BACKGROUND : source }));
+            "label.percentage_identity_threshold", new String[]
+            { source == null ? BACKGROUND : source }));
 
     if (ap.av.getAlignment().getGroups() != null)
     {
@@ -455,8 +455,8 @@ public class SliderPanel extends GSliderPanel
 
   static int getValue(JInternalFrame slider)
   {
-    return slider == null ? 0 : ((SliderPanel) slider.getContentPane())
-            .getValue();
+    return slider == null ? 0
+            : ((SliderPanel) slider.getContentPane()).getValue();
   }
 
   public static int getPIDValue()
index 16ec9d9..22b697e 100755 (executable)
@@ -43,8 +43,8 @@ import javax.swing.event.HyperlinkListener;
  * @author $author$
  * @version $Revision$
  */
-public class SplashScreen extends JPanel implements Runnable,
-        HyperlinkListener
+public class SplashScreen extends JPanel
+        implements Runnable, HyperlinkListener
 {
   boolean visible = true;
 
@@ -111,14 +111,14 @@ public class SplashScreen extends JPanel implements Runnable,
     try
     {
       java.net.URL url = getClass().getResource("/images/Jalview_Logo.png");
-      java.net.URL urllogo = getClass().getResource(
-              "/images/Jalview_Logo_small.png");
+      java.net.URL urllogo = getClass()
+              .getResource("/images/Jalview_Logo_small.png");
 
       if (url != null)
       {
         image = java.awt.Toolkit.getDefaultToolkit().createImage(url);
-        Image logo = java.awt.Toolkit.getDefaultToolkit().createImage(
-                urllogo);
+        Image logo = java.awt.Toolkit.getDefaultToolkit()
+                .createImage(urllogo);
         MediaTracker mt = new MediaTracker(this);
         mt.addImage(image, 0);
         mt.addImage(logo, 1);
index 1d929e6..5bff407 100644 (file)
@@ -131,8 +131,8 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI
   {
     // allow about 65 pixels for Desktop decorators on Windows
 
-    int newHeight = Math.min(height, Desktop.instance.getHeight()
-            - DESKTOP_DECORATORS_HEIGHT);
+    int newHeight = Math.min(height,
+            Desktop.instance.getHeight() - DESKTOP_DECORATORS_HEIGHT);
     if (newHeight != height)
     {
       int oldDividerLocation = getDividerLocation();
@@ -194,15 +194,29 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI
   }
 
   /**
-   * Adjust the divider for a sensible split of the real estate (for example,
+   * Adjusts the divider for a sensible split of the real estate (for example,
    * when many transcripts are shown with a single protein). This should only be
    * called after the split pane has been laid out (made visible) so it has a
-   * height.
+   * height. The aim is to avoid unnecessary vertical scroll bars, while
+   * ensuring that at least 2 sequences are visible in each panel.
+   * <p>
+   * Once laid out, the user may choose to customise as they wish, so this
+   * method is not called again after the initial layout.
    */
-  protected void adjustDivider()
+  protected void adjustInitialLayout()
   {
-    final AlignViewport topViewport = ((AlignFrame) getTopFrame()).viewport;
-    final AlignViewport bottomViewport = ((AlignFrame) getBottomFrame()).viewport;
+    AlignFrame topFrame = (AlignFrame) getTopFrame();
+    AlignFrame bottomFrame = (AlignFrame) getBottomFrame();
+
+    /*
+     * recompute layout of top and bottom panels to reflect their
+     * actual (rather than requested) height
+     */
+    topFrame.alignPanel.adjustAnnotationHeight();
+    bottomFrame.alignPanel.adjustAnnotationHeight();
+
+    final AlignViewport topViewport = topFrame.viewport;
+    final AlignViewport bottomViewport = bottomFrame.viewport;
     final AlignmentI topAlignment = topViewport.getAlignment();
     final AlignmentI bottomAlignment = bottomViewport.getAlignment();
     boolean topAnnotations = topViewport.isShowAnnotation();
@@ -214,6 +228,29 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI
     int bottomCharHeight = bottomViewport.getViewStyle().getCharHeight();
 
     /*
+     * calculate the minimum ratio that leaves at least the height 
+     * of two sequences (after rounding) visible in the top panel
+     */
+    int topPanelHeight = topFrame.getHeight();
+    int bottomPanelHeight = bottomFrame.getHeight();
+    int topSequencesHeight = topFrame.alignPanel.getSeqPanel().seqCanvas
+            .getHeight();
+    int topPanelMinHeight = topPanelHeight
+            - Math.max(0, topSequencesHeight - 3 * topCharHeight);
+    double totalHeight = (double) topPanelHeight + bottomPanelHeight;
+    double minRatio = topPanelMinHeight / totalHeight;
+
+    /*
+     * calculate the maximum ratio that leaves at least the height 
+     * of two sequences (after rounding) visible in the bottom panel
+     */
+    int bottomSequencesHeight = bottomFrame.alignPanel.getSeqPanel().seqCanvas
+            .getHeight();
+    int bottomPanelMinHeight = bottomPanelHeight
+            - Math.max(0, bottomSequencesHeight - 3 * bottomCharHeight);
+    double maxRatio = (totalHeight - bottomPanelMinHeight) / totalHeight;
+
+    /*
      * estimate ratio of (topFrameContent / bottomFrameContent)
      */
     int insets = Platform.isAMac() ? MAC_INSETS_HEIGHT
@@ -223,13 +260,14 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI
             + (topAnnotations ? topViewport.calcPanelHeight() : 0);
     int bottomHeight = insets + (3 + bottomCount) * bottomCharHeight
             + (bottomAnnotations ? bottomViewport.calcPanelHeight() : 0);
-    double ratio = ((double) topHeight) / (topHeight + bottomHeight);
+    double ratio = ((double) topHeight)
+            / (double) (topHeight + bottomHeight);
 
     /*
-     * limit to 0.2 <= ratio <= 0.8 to avoid concealing all sequences
+     * limit ratio to avoid concealing all sequences
      */
-    ratio = Math.min(ratio, 0.8d);
-    ratio = Math.max(ratio, 0.2d);
+    ratio = Math.min(ratio, maxRatio);
+    ratio = Math.max(ratio, minRatio);
     setRelativeDividerLocation(ratio);
   }
 
@@ -373,8 +411,8 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI
     /*
      * Ctrl-W / Cmd-W - close view or window
      */
-    KeyStroke key_cmdW = KeyStroke.getKeyStroke(KeyEvent.VK_W, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+    KeyStroke key_cmdW = KeyStroke.getKeyStroke(KeyEvent.VK_W,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
     action = new AbstractAction()
     {
       @Override
@@ -394,8 +432,8 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI
     /*
      * Ctrl-T / Cmd-T open new view
      */
-    KeyStroke key_cmdT = KeyStroke.getKeyStroke(KeyEvent.VK_T, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+    KeyStroke key_cmdT = KeyStroke.getKeyStroke(KeyEvent.VK_T,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
     AbstractAction action = new AbstractAction()
     {
       @Override
@@ -448,8 +486,8 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI
         Component c = getFrameAtMouse();
         if (c != null && c instanceof AlignFrame)
         {
-          for (ActionListener a : ((AlignFrame) c).getAccelerators()
-                  .get(ks).getActionListeners())
+          for (ActionListener a : ((AlignFrame) c).getAccelerators().get(ks)
+                  .getActionListeners())
           {
             a.actionPerformed(null);
           }
@@ -719,8 +757,9 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI
    */
   public List<AlignFrame> getAlignFrames()
   {
-    return Arrays.asList(new AlignFrame[] { (AlignFrame) getTopFrame(),
-        (AlignFrame) getBottomFrame() });
+    return Arrays
+            .asList(new AlignFrame[]
+            { (AlignFrame) getTopFrame(), (AlignFrame) getBottomFrame() });
   }
 
   /**
@@ -733,8 +772,8 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI
     /*
      * Ctrl-F / Cmd-F open Finder dialog, 'focused' on the right alignment
      */
-    KeyStroke key_cmdF = KeyStroke.getKeyStroke(KeyEvent.VK_F, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+    KeyStroke key_cmdF = KeyStroke.getKeyStroke(KeyEvent.VK_F,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
     AbstractAction action = new AbstractAction()
     {
       @Override
index 3e516a6..7c386f1 100644 (file)
@@ -62,8 +62,8 @@ import javax.swing.table.AbstractTableModel;
  *
  */
 @SuppressWarnings("serial")
-public class StructureChooser extends GStructureChooser implements
-        IProgressIndicator
+public class StructureChooser extends GStructureChooser
+        implements IProgressIndicator
 {
   private static int MAX_QLENGTH = 7820;
 
@@ -117,9 +117,8 @@ public class StructureChooser extends GStructureChooser implements
                 .getString("status.loading_cached_pdb_entries"), startTime);
         loadLocalCachedPDBEntries();
         updateProgressIndicator(null, startTime);
-        updateProgressIndicator(MessageManager
-                .getString("status.searching_for_pdb_structures"),
-                startTime);
+        updateProgressIndicator(MessageManager.getString(
+                "status.searching_for_pdb_structures"), startTime);
         fetchStructuresMetaData();
         // revise filter options if no results were found
         populateFilterComboBox(isStructuresDiscovered(), cachedPDBExists);
@@ -158,8 +157,8 @@ public class StructureChooser extends GStructureChooser implements
     Collection<FTSDataColumnI> wantedFields = pdbDocFieldPrefs
             .getStructureSummaryFields();
 
-    discoveredStructuresSet = new LinkedHashSet<FTSData>();
-    HashSet<String> errors = new HashSet<String>();
+    discoveredStructuresSet = new LinkedHashSet<>();
+    HashSet<String> errors = new HashSet<>();
     for (SequenceI seq : selectedSequences)
     {
       FTSRestRequest pdbRequest = new FTSRestRequest();
@@ -197,9 +196,8 @@ public class StructureChooser extends GStructureChooser implements
     if (discoveredStructuresSet != null
             && !discoveredStructuresSet.isEmpty())
     {
-      getResultTable().setModel(
-              FTSRestResponse.getTableModel(lastPdbRequest,
-                      discoveredStructuresSet));
+      getResultTable().setModel(FTSRestResponse
+              .getTableModel(lastPdbRequest, discoveredStructuresSet));
       noOfStructuresFound = discoveredStructuresSet.size();
       mainFrame.setTitle(MessageManager.formatMessage(
               "label.structure_chooser_no_of_structures",
@@ -225,7 +223,7 @@ public class StructureChooser extends GStructureChooser implements
 
   public void loadLocalCachedPDBEntries()
   {
-    ArrayList<CachedPDB> entries = new ArrayList<CachedPDB>();
+    ArrayList<CachedPDB> entries = new ArrayList<>();
     for (SequenceI seq : selectedSequences)
     {
       if (seq.getDatasetSequence() != null
@@ -259,7 +257,7 @@ public class StructureChooser extends GStructureChooser implements
     boolean isPDBRefsFound = false;
     boolean isUniProtRefsFound = false;
     StringBuilder queryBuilder = new StringBuilder();
-    Set<String> seqRefs = new LinkedHashSet<String>();
+    Set<String> seqRefs = new LinkedHashSet<>();
 
     if (seq.getAllPDBEntries() != null
             && queryBuilder.length() < MAX_QLENGTH)
@@ -268,8 +266,8 @@ public class StructureChooser extends GStructureChooser implements
       {
         if (isValidSeqName(entry.getId()))
         {
-          queryBuilder.append("pdb_id:")
-                  .append(entry.getId().toLowerCase()).append(" OR ");
+          queryBuilder.append("pdb_id:").append(entry.getId().toLowerCase())
+                  .append(" OR ");
           isPDBRefsFound = true;
         }
       }
@@ -403,8 +401,8 @@ public class StructureChooser extends GStructureChooser implements
         lbl_loading.setVisible(true);
         Collection<FTSDataColumnI> wantedFields = pdbDocFieldPrefs
                 .getStructureSummaryFields();
-        Collection<FTSData> filteredResponse = new HashSet<FTSData>();
-        HashSet<String> errors = new HashSet<String>();
+        Collection<FTSData> filteredResponse = new HashSet<>();
+        HashSet<String> errors = new HashSet<>();
 
         for (SequenceI seq : selectedSequences)
         {
@@ -455,12 +453,11 @@ public class StructureChooser extends GStructureChooser implements
         if (!filteredResponse.isEmpty())
         {
           final int filterResponseCount = filteredResponse.size();
-          Collection<FTSData> reorderedStructuresSet = new LinkedHashSet<FTSData>();
+          Collection<FTSData> reorderedStructuresSet = new LinkedHashSet<>();
           reorderedStructuresSet.addAll(filteredResponse);
           reorderedStructuresSet.addAll(discoveredStructuresSet);
-          getResultTable().setModel(
-                  FTSRestResponse.getTableModel(lastPdbRequest,
-                          reorderedStructuresSet));
+          getResultTable().setModel(FTSRestResponse
+                  .getTableModel(lastPdbRequest, reorderedStructuresSet));
 
           FTSRestResponse.configureTableColumn(getResultTable(),
                   wantedFields, tempUserPrefs);
@@ -484,9 +481,7 @@ public class StructureChooser extends GStructureChooser implements
             {
               errorMsg.append(error).append("\n");
             }
-            JvOptionPane.showMessageDialog(
-                    null,
-                    errorMsg.toString(),
+            JvOptionPane.showMessageDialog(null, errorMsg.toString(),
                     MessageManager.getString("label.pdb_web-service_error"),
                     JvOptionPane.ERROR_MESSAGE);
           }
@@ -509,9 +504,9 @@ public class StructureChooser extends GStructureChooser implements
     jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(
             jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
     chooser.setFileView(new jalview.io.JalviewFileView());
-    chooser.setDialogTitle(MessageManager.formatMessage(
-            "label.select_pdb_file_for",
-            selectedSequence.getDisplayId(false)));
+    chooser.setDialogTitle(
+            MessageManager.formatMessage("label.select_pdb_file_for",
+                    selectedSequence.getDisplayId(false)));
     chooser.setToolTipText(MessageManager.formatMessage(
             "label.load_pdb_file_associate_with_sequence",
             selectedSequence.getDisplayId(false)));
@@ -551,14 +546,14 @@ public class StructureChooser extends GStructureChooser implements
       cmb_filterOption.addItem(new FilterOption("Most Polymer Residues",
               "number_of_polymer_residues", VIEWS_FILTER, true));
     }
-    cmb_filterOption.addItem(new FilterOption("Enter PDB Id", "-",
-            VIEWS_ENTER_ID, false));
-    cmb_filterOption.addItem(new FilterOption("From File", "-",
-            VIEWS_FROM_FILE, false));
+    cmb_filterOption.addItem(
+            new FilterOption("Enter PDB Id", "-", VIEWS_ENTER_ID, false));
+    cmb_filterOption.addItem(
+            new FilterOption("From File", "-", VIEWS_FROM_FILE, false));
 
     if (cachedPDBExists)
     {
-      FilterOption cachedOption = new FilterOption("Cached PDB Entries",
+      FilterOption cachedOption = new FilterOption("Cached Structures",
               "-", VIEWS_LOCAL_PDB, false);
       cmb_filterOption.addItem(cachedOption);
       cmb_filterOption.setSelectedItem(cachedOption);
@@ -642,22 +637,20 @@ public class StructureChooser extends GStructureChooser implements
     lbl_pdbManualFetchStatus.setToolTipText("");
     if (txt_search.getText().length() > 0)
     {
-      lbl_pdbManualFetchStatus
-              .setToolTipText(JvSwingUtils.wrapTooltip(true, MessageManager
-                      .formatMessage("info.no_pdb_entry_found_for",
-                              txt_search.getText())));
+      lbl_pdbManualFetchStatus.setToolTipText(JvSwingUtils.wrapTooltip(true,
+              MessageManager.formatMessage("info.no_pdb_entry_found_for",
+                      txt_search.getText())));
     }
 
     if (errorWarning.length() > 0)
     {
       lbl_pdbManualFetchStatus.setIcon(warningImage);
-      lbl_pdbManualFetchStatus.setToolTipText(JvSwingUtils.wrapTooltip(
-              true, errorWarning.toString()));
+      lbl_pdbManualFetchStatus.setToolTipText(
+              JvSwingUtils.wrapTooltip(true, errorWarning.toString()));
     }
 
-    if (selectedSequences.length == 1
-            || !assSeqOpt.getName().equalsIgnoreCase(
-                    "-Select Associated Seq-"))
+    if (selectedSequences.length == 1 || !assSeqOpt.getName()
+            .equalsIgnoreCase("-Select Associated Seq-"))
     {
       txt_search.setEnabled(true);
       if (isValidPBDEntry)
@@ -682,9 +675,8 @@ public class StructureChooser extends GStructureChooser implements
     AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
             .getCmb_assSeq().getSelectedItem();
     lbl_fromFileStatus.setIcon(errorImage);
-    if (selectedSequences.length == 1
-            || (assSeqOpt != null && !assSeqOpt.getName().equalsIgnoreCase(
-                    "-Select Associated Seq-")))
+    if (selectedSequences.length == 1 || (assSeqOpt != null && !assSeqOpt
+            .getName().equalsIgnoreCase("-Select Associated Seq-")))
     {
       btn_pdbFromFile.setEnabled(true);
       if (selectedPdbFileName != null && selectedPdbFileName.length() > 0)
@@ -733,11 +725,10 @@ public class StructureChooser extends GStructureChooser implements
   @Override
   public void ok_ActionPerformed()
   {
-    final long progressSessionId = System.currentTimeMillis();
     final StructureSelectionManager ssm = ap.getStructureSelectionManager();
+
     final int preferredHeight = pnl_filter.getHeight();
-    ssm.setProgressIndicator(this);
-    ssm.setProgressSessionId(progressSessionId);
+
     new Thread(new Runnable()
     {
       @Override
@@ -755,11 +746,11 @@ public class StructureChooser extends GStructureChooser implements
           int[] selectedRows = getResultTable().getSelectedRows();
           PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
           int count = 0;
-          List<SequenceI> selectedSeqsToView = new ArrayList<SequenceI>();
+          List<SequenceI> selectedSeqsToView = new ArrayList<>();
           for (int row : selectedRows)
           {
-            String pdbIdStr = getResultTable().getValueAt(row,
-                    pdbIdColIndex).toString();
+            String pdbIdStr = getResultTable()
+                    .getValueAt(row, pdbIdColIndex).toString();
             SequenceI selectedSeq = (SequenceI) getResultTable()
                     .getValueAt(row, refSeqColIndex);
             selectedSeqsToView.add(selectedSeq);
@@ -769,6 +760,7 @@ public class StructureChooser extends GStructureChooser implements
               pdbEntry = getFindEntry(pdbIdStr,
                       selectedSeq.getAllPDBEntries());
             }
+
             if (pdbEntry == null)
             {
               pdbEntry = new PDBEntry();
@@ -791,14 +783,14 @@ public class StructureChooser extends GStructureChooser implements
                   .getModelIndex();
           int refSeqColIndex = tbl_local_pdb.getColumn("Ref Sequence")
                   .getModelIndex();
-          List<SequenceI> selectedSeqsToView = new ArrayList<SequenceI>();
+          List<SequenceI> selectedSeqsToView = new ArrayList<>();
           for (int row : selectedRows)
           {
             PDBEntry pdbEntry = (PDBEntry) tbl_local_pdb.getValueAt(row,
                     pdbIdColIndex);
             pdbEntriesToView[count++] = pdbEntry;
-            SequenceI selectedSeq = (SequenceI) tbl_local_pdb.getValueAt(
-                    row, refSeqColIndex);
+            SequenceI selectedSeq = (SequenceI) tbl_local_pdb
+                    .getValueAt(row, refSeqColIndex);
             selectedSeqsToView.add(selectedSeq);
           }
           SequenceI[] selectedSeqs = selectedSeqsToView
@@ -813,7 +805,6 @@ public class StructureChooser extends GStructureChooser implements
           {
             selectedSequence = userSelectedSeq;
           }
-
           String pdbIdStr = txt_search.getText();
           PDBEntry pdbEntry = selectedSequence.getPDBEntry(pdbIdStr);
           if (pdbEntry == null)
@@ -834,25 +825,28 @@ public class StructureChooser extends GStructureChooser implements
 
           PDBEntry[] pdbEntriesToView = new PDBEntry[] { pdbEntry };
           launchStructureViewer(ssm, pdbEntriesToView, ap,
-                  new SequenceI[] { selectedSequence });
-    }
-    else if (currentView == VIEWS_FROM_FILE)
-    {
-      SequenceI userSelectedSeq = ((AssociateSeqOptions) fileChooserAssSeqPanel
-              .getCmb_assSeq().getSelectedItem()).getSequence();
-      if (userSelectedSeq != null)
-      {
-        selectedSequence = userSelectedSeq;
-      }
-      PDBEntry fileEntry = new AssociatePdbFileWithSeq()
-              .associatePdbWithSeq(selectedPdbFileName,
-                          DataSourceType.FILE,
-                      selectedSequence, true, Desktop.instance);
+                  new SequenceI[]
+                  { selectedSequence });
+        }
+        else if (currentView == VIEWS_FROM_FILE)
+        {
+          SequenceI userSelectedSeq = ((AssociateSeqOptions) fileChooserAssSeqPanel
+                  .getCmb_assSeq().getSelectedItem()).getSequence();
+          if (userSelectedSeq != null)
+          {
+            selectedSequence = userSelectedSeq;
+          }
+          PDBEntry fileEntry = new AssociatePdbFileWithSeq()
+                  .associatePdbWithSeq(selectedPdbFileName,
+                          DataSourceType.FILE, selectedSequence, true,
+                          Desktop.instance);
 
           launchStructureViewer(ssm, new PDBEntry[] { fileEntry }, ap,
-                  new SequenceI[] { selectedSequence });
+                  new SequenceI[]
+                  { selectedSequence });
         }
         closeAction(preferredHeight);
+        mainFrame.dispose();
       }
     }).start();
   }
@@ -876,13 +870,15 @@ public class StructureChooser extends GStructureChooser implements
           final PDBEntry[] pdbEntriesToView,
           final AlignmentPanel alignPanel, SequenceI[] sequences)
   {
-    ssm.setProgressBar(MessageManager
-            .getString("status.launching_3d_structure_viewer"));
+    long progressId = sequences.hashCode();
+    setProgressBar(MessageManager
+            .getString("status.launching_3d_structure_viewer"), progressId);
     final StructureViewer sViewer = new StructureViewer(ssm);
+    setProgressBar(null, progressId);
 
     if (SiftsSettings.isMapWithSifts())
     {
-      List<SequenceI> seqsWithoutSourceDBRef = new ArrayList<SequenceI>();
+      List<SequenceI> seqsWithoutSourceDBRef = new ArrayList<>();
       int p = 0;
       // TODO: skip PDBEntry:Sequence pairs where PDBEntry doesn't look like a
       // real PDB ID. For moment, we can also safely do this if there is already
@@ -913,41 +909,37 @@ public class StructureChooser extends GStructureChooser implements
       if (!seqsWithoutSourceDBRef.isEmpty())
       {
         int y = seqsWithoutSourceDBRef.size();
-        ssm.setProgressBar(null);
-        ssm.setProgressBar(MessageManager.formatMessage(
+        setProgressBar(MessageManager.formatMessage(
                 "status.fetching_dbrefs_for_sequences_without_valid_refs",
-                y));
+                y), progressId);
         SequenceI[] seqWithoutSrcDBRef = new SequenceI[y];
         int x = 0;
         for (SequenceI fSeq : seqsWithoutSourceDBRef)
         {
           seqWithoutSrcDBRef[x++] = fSeq;
         }
+
         DBRefFetcher dbRefFetcher = new DBRefFetcher(seqWithoutSrcDBRef);
         dbRefFetcher.fetchDBRefs(true);
+
+        setProgressBar("Fetch complete.", progressId); // todo i18n
       }
     }
     if (pdbEntriesToView.length > 1)
     {
-      ArrayList<SequenceI[]> seqsMap = new ArrayList<SequenceI[]>();
-      for (SequenceI seq : sequences)
-      {
-        seqsMap.add(new SequenceI[] { seq });
-      }
-      SequenceI[][] collatedSeqs = seqsMap.toArray(new SequenceI[0][0]);
-      ssm.setProgressBar(null);
-      ssm.setProgressBar(MessageManager
-              .getString("status.fetching_3d_structures_for_selected_entries"));
-      sViewer.viewStructures(pdbEntriesToView, collatedSeqs, alignPanel);
+      setProgressBar(MessageManager.getString(
+              "status.fetching_3d_structures_for_selected_entries"),
+              progressId);
+      sViewer.viewStructures(pdbEntriesToView, sequences, alignPanel);
     }
     else
     {
-      ssm.setProgressBar(null);
-      ssm.setProgressBar(MessageManager.formatMessage(
+      setProgressBar(MessageManager.formatMessage(
               "status.fetching_3d_structures_for",
-              pdbEntriesToView[0].getId()));
+              pdbEntriesToView[0].getId()),progressId);
       sViewer.viewStructures(pdbEntriesToView[0], sequences, alignPanel);
     }
+    setProgressBar(null, progressId);
   }
 
   /**
@@ -956,11 +948,12 @@ public class StructureChooser extends GStructureChooser implements
    */
   @Override
   public void populateCmbAssociateSeqOptions(
-          JComboBox<AssociateSeqOptions> cmb_assSeq, JLabel lbl_associateSeq)
+          JComboBox<AssociateSeqOptions> cmb_assSeq,
+          JLabel lbl_associateSeq)
   {
     cmb_assSeq.removeAllItems();
-    cmb_assSeq.addItem(new AssociateSeqOptions("-Select Associated Seq-",
-            null));
+    cmb_assSeq.addItem(
+            new AssociateSeqOptions("-Select Associated Seq-", null));
     lbl_associateSeq.setVisible(false);
     if (selectedSequences.length > 1)
     {
@@ -1005,7 +998,7 @@ public class StructureChooser extends GStructureChooser implements
           String searchTerm = txt_search.getText().toLowerCase();
           searchTerm = searchTerm.split(":")[0];
           // System.out.println(">>>>> search term : " + searchTerm);
-          List<FTSDataColumnI> wantedFields = new ArrayList<FTSDataColumnI>();
+          List<FTSDataColumnI> wantedFields = new ArrayList<>();
           FTSRestRequest pdbRequest = new FTSRestRequest();
           pdbRequest.setAllowEmptySeq(false);
           pdbRequest.setResponseSize(1);
@@ -1049,8 +1042,9 @@ public class StructureChooser extends GStructureChooser implements
         public void run()
         {
           fetchStructuresMetaData();
-          filterResultSet(((FilterOption) cmb_filterOption
-                  .getSelectedItem()).getValue());
+          filterResultSet(
+                  ((FilterOption) cmb_filterOption.getSelectedItem())
+                          .getValue());
         }
       });
       refreshThread.start();
@@ -1059,13 +1053,14 @@ public class StructureChooser extends GStructureChooser implements
 
   public class PDBEntryTableModel extends AbstractTableModel
   {
-    String[] columns = { "Ref Sequence", "PDB Id", "Chain", "Type", "File" };
+    String[] columns = { "Ref Sequence", "PDB Id", "Chain", "Type",
+        "File" };
 
     private List<CachedPDB> pdbEntries;
 
     public PDBEntryTableModel(List<CachedPDB> pdbEntries)
     {
-      this.pdbEntries = new ArrayList<CachedPDB>(pdbEntries);
+      this.pdbEntries = new ArrayList<>(pdbEntries);
     }
 
     @Override
@@ -1106,8 +1101,8 @@ public class StructureChooser extends GStructureChooser implements
         value = entry.getPdbEntry();
         break;
       case 2:
-        value = entry.getPdbEntry().getChainCode() == null ? "_" : entry
-                .getPdbEntry().getChainCode();
+        value = entry.getPdbEntry().getChainCode() == null ? "_"
+                : entry.getPdbEntry().getChainCode();
         break;
       case 3:
         value = entry.getPdbEntry().getType();
index 189d490..fb37b77 100644 (file)
@@ -29,19 +29,24 @@ import jalview.structure.StructureSelectionManager;
 
 import java.awt.Rectangle;
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 
 /**
- * proxy for handling structure viewers.
- * 
- * this allows new views to be created with the currently configured viewer, the
- * preferred viewer to be set/read and existing views created previously with a
- * particular viewer to be recovered
+ * A proxy for handling structure viewers, that orchestrates adding selected
+ * structures, associated with sequences in Jalview, to an existing viewer, or
+ * opening a new one. Currently supports either Jmol or Chimera as the structure
+ * viewer.
  * 
  * @author jprocter
  */
 public class StructureViewer
 {
+  private static final String UNKNOWN_VIEWER_TYPE = "Unknown structure viewer type ";
+
   StructureSelectionManager ssm;
 
   public enum ViewerType
@@ -49,6 +54,16 @@ public class StructureViewer
     JMOL, CHIMERA
   };
 
+  /**
+   * Constructor
+   * 
+   * @param structureSelectionManager
+   */
+  public StructureViewer(StructureSelectionManager structureSelectionManager)
+  {
+    ssm = structureSelectionManager;
+  }
+
   public ViewerType getViewerType()
   {
     String viewType = Cache.getDefault(Preferences.STRUCTURE_DISPLAY,
@@ -61,133 +76,161 @@ public class StructureViewer
     Cache.setProperty(Preferences.STRUCTURE_DISPLAY, type.name());
   }
 
-  public StructureViewer(StructureSelectionManager structureSelectionManager)
-  {
-    ssm = structureSelectionManager;
-  }
-
   /**
    * View multiple PDB entries, each with associated sequences
    * 
    * @param pdbs
-   * @param seqsForPdbs
+   * @param seqs
    * @param ap
    * @return
    */
   public JalviewStructureDisplayI viewStructures(PDBEntry[] pdbs,
-          SequenceI[][] seqsForPdbs, AlignmentPanel ap)
+          SequenceI[] seqs, AlignmentPanel ap)
   {
-    JalviewStructureDisplayI viewer = onlyOnePdb(pdbs, seqsForPdbs, ap);
+    JalviewStructureDisplayI viewer = onlyOnePdb(pdbs, seqs, ap);
     if (viewer != null)
     {
+      /*
+       * user added structure to an existing viewer - all done
+       */
       return viewer;
     }
-    return viewStructures(getViewerType(), pdbs, seqsForPdbs, ap);
+
+    ViewerType viewerType = getViewerType();
+
+    Map<PDBEntry, SequenceI[]> seqsForPdbs = getSequencesForPdbs(pdbs,
+            seqs);
+    PDBEntry[] pdbsForFile = seqsForPdbs.keySet().toArray(
+            new PDBEntry[seqsForPdbs.size()]);
+    SequenceI[][] theSeqs = seqsForPdbs.values().toArray(
+            new SequenceI[seqsForPdbs.size()][]);
+    JalviewStructureDisplayI sview = null;
+    if (viewerType.equals(ViewerType.JMOL))
+    {
+      sview = new AppJmol(ap, pdbsForFile, theSeqs);
+    }
+    else if (viewerType.equals(ViewerType.CHIMERA))
+    {
+      sview = new ChimeraViewFrame(pdbsForFile, theSeqs, ap);
+    }
+    else
+    {
+      Cache.log.error(UNKNOWN_VIEWER_TYPE + getViewerType().toString());
+    }
+    return sview;
   }
 
   /**
-   * A strictly temporary method pending JAL-1761 refactoring. Determines if all
-   * the passed PDB entries are the same (this is the case if selected sequences
-   * to view structure for are chains of the same structure). If so, calls the
-   * single-pdb version of viewStructures and returns the viewer, else returns
-   * null.
+   * Converts the list of selected PDB entries (possibly including duplicates
+   * for multiple chains), and corresponding sequences, into a map of sequences
+   * for each distinct PDB file. Returns null if either argument is null, or
+   * their lengths do not match.
    * 
    * @param pdbs
-   * @param seqsForPdbs
-   * @param ap
+   * @param seqs
    * @return
    */
-  private JalviewStructureDisplayI onlyOnePdb(PDBEntry[] pdbs,
-          SequenceI[][] seqsForPdbs, AlignmentPanel ap)
+  Map<PDBEntry, SequenceI[]> getSequencesForPdbs(PDBEntry[] pdbs,
+          SequenceI[] seqs)
   {
-    List<SequenceI> seqs = new ArrayList<SequenceI>();
-    if (pdbs == null || pdbs.length == 0)
+    if (pdbs == null || seqs == null || pdbs.length != seqs.length)
     {
       return null;
     }
-    int i = 0;
-    String firstFile = pdbs[0].getFile();
-    for (PDBEntry pdb : pdbs)
+
+    /*
+     * we want only one 'representative' PDBEntry per distinct file name
+     * (there may be entries for distinct chains)
+     */
+    Map<String, PDBEntry> pdbsSeen = new HashMap<>();
+
+    /*
+     * LinkedHashMap preserves order of PDB entries (significant if they
+     * will get superimposed to the first structure)
+     */
+    Map<PDBEntry, List<SequenceI>> pdbSeqs = new LinkedHashMap<>();
+    for (int i = 0; i < pdbs.length; i++)
     {
+      PDBEntry pdb = pdbs[i];
+      SequenceI seq = seqs[i];
       String pdbFile = pdb.getFile();
-      if (pdbFile == null || !pdbFile.equals(firstFile))
+      if (pdbFile == null || pdbFile.length() == 0)
       {
-        return null;
+        pdbFile = pdb.getId();
       }
-      SequenceI[] pdbseqs = seqsForPdbs[i++];
-      if (pdbseqs != null)
+      if (!pdbsSeen.containsKey(pdbFile))
       {
-        for (SequenceI sq : pdbseqs)
-        {
-          seqs.add(sq);
-        }
+        pdbsSeen.put(pdbFile, pdb);
+        pdbSeqs.put(pdb, new ArrayList<SequenceI>());
+      }
+      else
+      {
+        pdb = pdbsSeen.get(pdbFile);
+      }
+      List<SequenceI> seqsForPdb = pdbSeqs.get(pdb);
+      if (!seqsForPdb.contains(seq))
+      {
+        seqsForPdb.add(seq);
       }
     }
-    return viewStructures(pdbs[0],
-            seqs.toArray(new SequenceI[seqs.size()]), ap);
-  }
 
-  public JalviewStructureDisplayI viewStructures(PDBEntry pdb,
-          SequenceI[] seqsForPdb, AlignmentPanel ap)
-  {
-    return viewStructures(getViewerType(), pdb, seqsForPdb, ap);
-  }
-
-  protected JalviewStructureDisplayI viewStructures(ViewerType viewerType,
-          PDBEntry[] pdbs, SequenceI[][] seqsForPdbs, AlignmentPanel ap)
-  {
-    PDBEntry[] pdbsForFile = getUniquePdbFiles(pdbs);
-    JalviewStructureDisplayI sview = null;
-    if (viewerType.equals(ViewerType.JMOL))
-    {
-      sview = new AppJmol(ap, pdbsForFile, ap.av.collateForPDB(pdbsForFile));
-    }
-    else if (viewerType.equals(ViewerType.CHIMERA))
-    {
-      sview = new ChimeraViewFrame(pdbsForFile,
-              ap.av.collateForPDB(pdbsForFile), ap);
-    }
-    else
+    /*
+     * convert to Map<PDBEntry, SequenceI[]>
+     */
+    Map<PDBEntry, SequenceI[]> result = new LinkedHashMap<>();
+    for (Entry<PDBEntry, List<SequenceI>> entry : pdbSeqs.entrySet())
     {
-      Cache.log.error("Unknown structure viewer type "
-              + getViewerType().toString());
+      List<SequenceI> theSeqs = entry.getValue();
+      result.put(entry.getKey(),
+              theSeqs.toArray(new SequenceI[theSeqs.size()]));
     }
-    return sview;
+
+    return result;
   }
 
   /**
-   * Convert the array of PDBEntry into an array with no filename repeated
+   * A strictly temporary method pending JAL-1761 refactoring. Determines if all
+   * the passed PDB entries are the same (this is the case if selected sequences
+   * to view structure for are chains of the same structure). If so, calls the
+   * single-pdb version of viewStructures and returns the viewer, else returns
+   * null.
    * 
    * @param pdbs
+   * @param seqsForPdbs
+   * @param ap
    * @return
    */
-  static PDBEntry[] getUniquePdbFiles(PDBEntry[] pdbs)
+  private JalviewStructureDisplayI onlyOnePdb(PDBEntry[] pdbs,
+          SequenceI[] seqsForPdbs, AlignmentPanel ap)
   {
-    if (pdbs == null)
+    List<SequenceI> seqs = new ArrayList<SequenceI>();
+    if (pdbs == null || pdbs.length == 0)
     {
       return null;
     }
-    List<PDBEntry> uniques = new ArrayList<PDBEntry>();
-    List<String> filesSeen = new ArrayList<String>();
-    for (PDBEntry entry : pdbs)
+    int i = 0;
+    String firstFile = pdbs[0].getFile();
+    for (PDBEntry pdb : pdbs)
     {
-      String file = entry.getFile();
-      if (file == null)
+      String pdbFile = pdb.getFile();
+      if (pdbFile == null || !pdbFile.equals(firstFile))
       {
-        uniques.add(entry);
+        return null;
       }
-      else if (!filesSeen.contains(file))
+      SequenceI pdbseq = seqsForPdbs[i++];
+      if (pdbseq != null)
       {
-        uniques.add(entry);
-        filesSeen.add(file);
+        seqs.add(pdbseq);
       }
     }
-    return uniques.toArray(new PDBEntry[uniques.size()]);
+    return viewStructures(pdbs[0], seqs.toArray(new SequenceI[seqs.size()]),
+            ap);
   }
 
-  protected JalviewStructureDisplayI viewStructures(ViewerType viewerType,
-          PDBEntry pdb, SequenceI[] seqsForPdb, AlignmentPanel ap)
+  public JalviewStructureDisplayI viewStructures(PDBEntry pdb,
+          SequenceI[] seqsForPdb, AlignmentPanel ap)
   {
+    ViewerType viewerType = getViewerType();
     JalviewStructureDisplayI sview = null;
     if (viewerType.equals(ViewerType.JMOL))
     {
@@ -199,8 +242,7 @@ public class StructureViewer
     }
     else
     {
-      Cache.log.error("Unknown structure viewer type "
-              + getViewerType().toString());
+      Cache.log.error(UNKNOWN_VIEWER_TYPE + getViewerType().toString());
     }
     return sview;
   }
@@ -219,10 +261,10 @@ public class StructureViewer
    * @param vid
    * @return
    */
-  public JalviewStructureDisplayI createView(ViewerType type,
-          String[] pdbf, String[] id, SequenceI[][] sq,
-          AlignmentPanel alignPanel, StructureViewerModel viewerData,
-          String fileloc, Rectangle rect, String vid)
+  public JalviewStructureDisplayI createView(ViewerType type, String[] pdbf,
+          String[] id, SequenceI[][] sq, AlignmentPanel alignPanel,
+          StructureViewerModel viewerData, String fileloc, Rectangle rect,
+          String vid)
   {
     final boolean useinViewerSuperpos = viewerData.isAlignWithPanel();
     final boolean usetoColourbyseq = viewerData.isColourWithAlignPanel();
@@ -236,11 +278,11 @@ public class StructureViewer
               useinViewerSuperpos, viewerColouring, fileloc, rect, vid);
       break;
     case CHIMERA:
-      Cache.log.error("Unsupported structure viewer type "
-              + type.toString());
+      Cache.log.error(
+              "Unsupported structure viewer type " + type.toString());
       break;
     default:
-      Cache.log.error("Unknown structure viewer type " + type.toString());
+      Cache.log.error(UNKNOWN_VIEWER_TYPE + type.toString());
     }
     return sview;
   }
index e73ce07..31c20ed 100644 (file)
@@ -83,18 +83,18 @@ public abstract class StructureViewerBase extends GStructureViewer
   /**
    * list of sequenceSet ids associated with the view
    */
-  protected List<String> _aps = new ArrayList<String>();
+  protected List<String> _aps = new ArrayList<>();
 
   /**
    * list of alignment panels to use for superposition
    */
-  protected Vector<AlignmentPanel> _alignwith = new Vector<AlignmentPanel>();
+  protected Vector<AlignmentPanel> _alignwith = new Vector<>();
 
   /**
    * list of alignment panels that are used for colouring structures by aligned
    * sequences
    */
-  protected Vector<AlignmentPanel> _colourwith = new Vector<AlignmentPanel>();
+  protected Vector<AlignmentPanel> _colourwith = new Vector<>();
 
   private String viewId = null;
 
@@ -119,6 +119,7 @@ public abstract class StructureViewerBase extends GStructureViewer
   {
     super();
   }
+
   /**
    * 
    * @param ap2
@@ -169,7 +170,7 @@ public abstract class StructureViewerBase extends GStructureViewer
   {
     if (_alignwith == null)
     {
-      _alignwith = new Vector<AlignmentPanel>();
+      _alignwith = new Vector<>();
     }
     if (_alignwith.size() == 0 && ap != null)
     {
@@ -309,6 +310,8 @@ public abstract class StructureViewerBase extends GStructureViewer
 
   public abstract ViewerType getViewerType();
 
+  protected abstract IProgressIndicator getIProgressIndicator();
+
   /**
    * add a new structure (with associated sequences and chains) to this viewer,
    * retrieving it if necessary first.
@@ -355,7 +358,8 @@ public abstract class StructureViewerBase extends GStructureViewer
     }
     // otherwise, start adding the structure.
     getBinding().addSequenceAndChain(new PDBEntry[] { pdbentry },
-            new SequenceI[][] { seqs }, new String[][] { chains });
+            new SequenceI[][]
+            { seqs }, new String[][] { chains });
     addingStructures = true;
     _started = false;
     alignAddedStructures = align;
@@ -377,7 +381,8 @@ public abstract class StructureViewerBase extends GStructureViewer
   {
     int option = JvOptionPane.showInternalConfirmDialog(Desktop.desktop,
             MessageManager.formatMessage("label.add_pdbentry_to_view",
-                    new Object[] { pdbId, view.getTitle() }),
+                    new Object[]
+                    { pdbId, view.getTitle() }),
             MessageManager
                     .getString("label.align_to_existing_structure_view"),
             JvOptionPane.YES_NO_CANCEL_OPTION);
@@ -457,7 +462,7 @@ public abstract class StructureViewerBase extends GStructureViewer
      * create the mappings
      */
     apanel.getStructureSelectionManager().setMapping(seq, chains,
-            pdbFilename, DataSourceType.FILE);
+            pdbFilename, DataSourceType.FILE, getIProgressIndicator());
 
     /*
      * alert the FeatureRenderer to show new (PDB RESNUM) features
@@ -465,7 +470,9 @@ public abstract class StructureViewerBase extends GStructureViewer
     if (apanel.getSeqPanel().seqCanvas.fr != null)
     {
       apanel.getSeqPanel().seqCanvas.fr.featuresAdded();
-      apanel.paintAlignment(true);
+      // note - we don't do a refresh for structure here because we do it
+      // explicitly for all panels later on
+      apanel.paintAlignment(true, false);
     }
 
     /*
@@ -488,8 +495,8 @@ public abstract class StructureViewerBase extends GStructureViewer
            */
           viewer.useAlignmentPanelForColourbyseq(apanel);
           viewer.buildActionMenu();
-          apanel.getStructureSelectionManager().sequenceColoursChanged(
-                  apanel);
+          apanel.getStructureSelectionManager()
+                  .sequenceColoursChanged(apanel);
           break;
         }
       }
@@ -520,11 +527,11 @@ public abstract class StructureViewerBase extends GStructureViewer
        */
       int option = JvOptionPane.showInternalConfirmDialog(Desktop.desktop,
               MessageManager.formatMessage(
-                      "label.pdb_entry_is_already_displayed",
-                      new Object[] { pdbId }), MessageManager
-                      .formatMessage(
-                              "label.map_sequences_to_visible_window",
-                              new Object[] { pdbId }),
+                      "label.pdb_entry_is_already_displayed", new Object[]
+                      { pdbId }),
+              MessageManager.formatMessage(
+                      "label.map_sequences_to_visible_window", new Object[]
+                      { pdbId }),
               JvOptionPane.YES_NO_CANCEL_OPTION);
       if (option == JvOptionPane.CANCEL_OPTION)
       {
@@ -596,8 +603,8 @@ public abstract class StructureViewerBase extends GStructureViewer
   public void changeColour_actionPerformed(String colourSchemeName)
   {
     AlignmentI al = getAlignmentPanel().av.getAlignment();
-    ColourSchemeI cs = ColourSchemes.getInstance().getColourScheme(
-            colourSchemeName, al, null);
+    ColourSchemeI cs = ColourSchemes.getInstance()
+            .getColourScheme(colourSchemeName, al, null);
     getBinding().setJalviewColourScheme(cs);
   }
 
@@ -714,11 +721,11 @@ public abstract class StructureViewerBase extends GStructureViewer
 
     if (_colourwith == null)
     {
-      _colourwith = new Vector<AlignmentPanel>();
+      _colourwith = new Vector<>();
     }
     if (_alignwith == null)
     {
-      _alignwith = new Vector<AlignmentPanel>();
+      _alignwith = new Vector<>();
     }
 
     ViewSelectionMenu seqColourBy = new ViewSelectionMenu(
@@ -780,7 +787,8 @@ public abstract class StructureViewerBase extends GStructureViewer
   }
 
   @Override
-  public void setJalviewColourScheme(ColourSchemeI cs) {
+  public void setJalviewColourScheme(ColourSchemeI cs)
+  {
     getBinding().setJalviewColourScheme(cs);
   }
 
@@ -790,8 +798,7 @@ public abstract class StructureViewerBase extends GStructureViewer
    * the operation.
    */
   @Override
-  protected String alignStructs_actionPerformed(
-          ActionEvent actionEvent)
+  protected String alignStructs_actionPerformed(ActionEvent actionEvent)
   {
     return alignStructs_withAllAlignPanels();
   }
@@ -802,12 +809,12 @@ public abstract class StructureViewerBase extends GStructureViewer
     {
       return null;
     }
-  
+
     if (_alignwith.size() == 0)
     {
       _alignwith.add(getAlignmentPanel());
     }
-  
+
     String reply = null;
     try
     {
@@ -815,7 +822,7 @@ public abstract class StructureViewerBase extends GStructureViewer
       HiddenColumns[] alc = new HiddenColumns[_alignwith.size()];
       int[] alm = new int[_alignwith.size()];
       int a = 0;
-  
+
       for (AlignmentPanel ap : _alignwith)
       {
         als[a] = ap.av.getAlignment();
@@ -825,8 +832,8 @@ public abstract class StructureViewerBase extends GStructureViewer
       reply = getBinding().superposeStructures(als, alm, alc);
       if (reply != null)
       {
-        String text = MessageManager.formatMessage(
-                "error.superposition_failed", reply);
+        String text = MessageManager
+                .formatMessage("error.superposition_failed", reply);
         statusBar.setText(text);
       }
     } catch (Exception e)
@@ -853,6 +860,7 @@ public abstract class StructureViewerBase extends GStructureViewer
       getBinding().setBackgroundColour(col);
     }
   }
+
   @Override
   public void viewerColour_actionPerformed(ActionEvent actionEvent)
   {
@@ -862,18 +870,21 @@ public abstract class StructureViewerBase extends GStructureViewer
       getBinding().setColourBySequence(false);
     }
   }
+
   @Override
   public void chainColour_actionPerformed(ActionEvent actionEvent)
   {
     chainColour.setSelected(true);
     getBinding().colourByChain();
   }
+
   @Override
   public void chargeColour_actionPerformed(ActionEvent actionEvent)
   {
     chargeColour.setSelected(true);
     getBinding().colourByCharge();
   }
+
   @Override
   public void seqColour_actionPerformed(ActionEvent actionEvent)
   {
@@ -881,7 +892,7 @@ public abstract class StructureViewerBase extends GStructureViewer
     binding.setColourBySequence(seqColour.isSelected());
     if (_colourwith == null)
     {
-      _colourwith = new Vector<AlignmentPanel>();
+      _colourwith = new Vector<>();
     }
     if (binding.isColourBySequence())
     {
@@ -900,18 +911,19 @@ public abstract class StructureViewerBase extends GStructureViewer
       }
     }
   }
+
   @Override
   public void pdbFile_actionPerformed(ActionEvent actionEvent)
   {
     JalviewFileChooser chooser = new JalviewFileChooser(
             Cache.getProperty("LAST_DIRECTORY"));
-  
+
     chooser.setFileView(new JalviewFileView());
     chooser.setDialogTitle(MessageManager.getString("label.save_pdb_file"));
     chooser.setToolTipText(MessageManager.getString("action.save"));
-  
+
     int value = chooser.showSaveDialog(this);
-  
+
     if (value == JalviewFileChooser.APPROVE_OPTION)
     {
       BufferedReader in = null;
@@ -921,7 +933,7 @@ public abstract class StructureViewerBase extends GStructureViewer
         in = new BufferedReader(
                 new FileReader(getBinding().getStructureFiles()[0]));
         File outFile = chooser.getSelectedFile();
-  
+
         PrintWriter out = new PrintWriter(new FileOutputStream(outFile));
         String data;
         while ((data = in.readLine()) != null)
@@ -950,6 +962,7 @@ public abstract class StructureViewerBase extends GStructureViewer
       }
     }
   }
+
   @Override
   public void viewMapping_actionPerformed(ActionEvent actionEvent)
   {
@@ -984,7 +997,7 @@ public abstract class StructureViewerBase extends GStructureViewer
       return;
     }
     setChainMenuItems(binding.getChainNames());
-  
+
     this.setTitle(binding.getViewerTitle(getViewerName(), true));
 
     /*
index 91e05c6..53e2dee 100644 (file)
@@ -64,7 +64,8 @@ public class TextColourChooser
    * @param sequenceGroup
    *          the SequenceGroup context (only for group pop-menu option)
    */
-  public void chooseColour(AlignmentPanel alignPanel, SequenceGroup sequenceGroup)
+  public void chooseColour(AlignmentPanel alignPanel,
+          SequenceGroup sequenceGroup)
   {
     this.ap = alignPanel;
     this.sg = sequenceGroup;
@@ -86,11 +87,11 @@ public class TextColourChooser
     JPanel panel = new JPanel();
     bigpanel.add(panel, BorderLayout.CENTER);
     bigpanel.add(
-            new JLabel(
-                    "<html>"
-                            + MessageManager
-                                    .getString("label.select_dark_light_set_threshold")
-                            + "</html>"), BorderLayout.NORTH);
+            new JLabel("<html>"
+                    + MessageManager.getString(
+                            "label.select_dark_light_set_threshold")
+                    + "</html>"),
+            BorderLayout.NORTH);
     panel.add(col1);
     panel.add(slider);
     panel.add(col2);
@@ -136,14 +137,11 @@ public class TextColourChooser
       }
     });
 
-    int reply = JvOptionPane
-            .showInternalOptionDialog(
-                    alignPanel,
-                    bigpanel,
-                    MessageManager
-                            .getString("label.adjunst_foreground_text_colour_threshold"),
-                    JvOptionPane.OK_CANCEL_OPTION,
-                    JvOptionPane.QUESTION_MESSAGE, null, null, null);
+    int reply = JvOptionPane.showInternalOptionDialog(alignPanel, bigpanel,
+            MessageManager.getString(
+                    "label.adjunst_foreground_text_colour_threshold"),
+            JvOptionPane.OK_CANCEL_OPTION, JvOptionPane.QUESTION_MESSAGE,
+            null, null, null);
 
     if (reply == JvOptionPane.CANCEL_OPTION)
     {
@@ -186,9 +184,9 @@ public class TextColourChooser
    */
   protected void saveInitialSettings()
   {
-    groupColour1 = new HashMap<SequenceGroup, Color>();
-    groupColour2 = new HashMap<SequenceGroup, Color>();
-    groupThreshold = new HashMap<SequenceGroup, Integer>();
+    groupColour1 = new HashMap<>();
+    groupColour2 = new HashMap<>();
+    groupThreshold = new HashMap<>();
 
     if (sg == null)
     {
@@ -239,7 +237,7 @@ public class TextColourChooser
       sg.textColour = col;
     }
 
-    ap.paintAlignment(true);
+    ap.paintAlignment(false, false);
   }
 
   void colour2Changed(Color col)
@@ -257,7 +255,7 @@ public class TextColourChooser
       sg.textColour2 = col;
     }
 
-    ap.paintAlignment(true);
+    ap.paintAlignment(false, false);
   }
 
   void thresholdChanged(int value)
@@ -275,7 +273,7 @@ public class TextColourChooser
       sg.thresholdTextColour = value;
     }
 
-    ap.paintAlignment(true);
+    ap.paintAlignment(false, false);
   }
 
   void setGroupTextColour()
index e60ac8e..7dc1a99 100755 (executable)
@@ -279,8 +279,9 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
         g.drawString(nodeLabel, xstart + 2, ypos - 2);
       }
 
-      String name = (markPlaceholders && node.isPlaceholder()) ? (PLACEHOLDER + node
-              .getName()) : node.getName();
+      String name = (markPlaceholders && node.isPlaceholder())
+              ? (PLACEHOLDER + node.getName())
+              : node.getName();
 
       int charWidth = fm.stringWidth(name) + 3;
       int charHeight = font.getSize();
@@ -332,10 +333,10 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
         g.fillRect(xend - 2, ypos - 2, 4, 4);
       }
 
-      int ystart = (node.left() == null ? 0 : (int) (((SequenceNode) node
-              .left()).ycount * chunk)) + offy;
-      int yend = (node.right() == null ? 0 : (int) (((SequenceNode) node
-              .right()).ycount * chunk))
+      int ystart = (node.left() == null ? 0
+              : (int) (((SequenceNode) node.left()).ycount * chunk)) + offy;
+      int yend = (node.right() == null ? 0
+              : (int) (((SequenceNode) node.right()).ycount * chunk))
               + offy;
 
       Rectangle pos = new Rectangle(xend - 2, ypos - 2, 5, 5);
@@ -424,8 +425,7 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
 
     SequenceNode top = tree.getTopNode();
 
-    double wscale = ((width * .8) - (offx * 2))
-            / tree.getMaxHeight();
+    double wscale = ((width * .8) - (offx * 2)) / tree.getMaxHeight();
 
     if (top.count == 0)
     {
@@ -654,8 +654,9 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
 
     if (tree == null)
     {
-      g.drawString(MessageManager.getString("label.calculating_tree")
-              + "....", 20, getHeight() / 2);
+      g.drawString(
+              MessageManager.getString("label.calculating_tree") + "....",
+              20, getHeight() / 2);
     }
     else
     {
@@ -666,9 +667,8 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
         repaint();
       }
 
-      if (fitToWindow
-              || (!fitToWindow && (scrollPane.getHeight() > ((fm
-                      .getHeight() * nameHash.size()) + offy))))
+      if (fitToWindow || (!fitToWindow && (scrollPane
+              .getHeight() > ((fm.getHeight() * nameHash.size()) + offy))))
       {
         draw(g, scrollPane.getWidth(), scrollPane.getHeight());
         setPreferredSize(null);
@@ -752,7 +752,8 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
         g2.setColor(Color.gray);
       }
 
-      int x = (int) ((threshold * (getWidth() - labelLength - (2 * offx))) + offx);
+      int x = (int) ((threshold * (getWidth() - labelLength - (2 * offx)))
+              + offx);
 
       g2.drawLine(x, 0, x, getHeight());
     }
@@ -861,8 +862,8 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
     if (ob instanceof SequenceNode)
     {
       highlightNode = (SequenceNode) ob;
-      this.setToolTipText("<html>"
-              + MessageManager.getString("label.highlightnode"));
+      this.setToolTipText(
+              "<html>" + MessageManager.getString("label.highlightnode"));
       repaint();
 
     }
@@ -1007,9 +1008,8 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
         }
         else
         {
-          cs = ColourSchemeProperty.getColourScheme(sg,
-                  ColourSchemeProperty.getColourName(av
-                          .getGlobalColourScheme()));
+          cs = ColourSchemeProperty.getColourScheme(sg, ColourSchemeProperty
+                  .getColourName(av.getGlobalColourScheme()));
         }
         // cs is null if shading is an annotationColourGradient
         // if (cs != null)
@@ -1029,8 +1029,7 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
       for (int a = 0; a < aps.length; a++)
       {
         if (aps[a].av.getGlobalColourScheme() != null
-                && aps[a].av.getResidueShading()
-                        .conservationApplied())
+                && aps[a].av.getResidueShading().conservationApplied())
         {
           Conservation c = new Conservation("Group", sg.getSequences(null),
                   sg.getStartRes(), sg.getEndRes());
index 35998eb..2727db1 100755 (executable)
@@ -55,6 +55,7 @@ import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.image.BufferedImage;
 import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
 import java.io.FileOutputStream;
 import java.util.ArrayList;
 import java.util.List;
@@ -63,6 +64,8 @@ import javax.imageio.ImageIO;
 import javax.swing.ButtonGroup;
 import javax.swing.JMenuItem;
 import javax.swing.JRadioButtonMenuItem;
+import javax.swing.event.InternalFrameAdapter;
+import javax.swing.event.InternalFrameEvent;
 
 import org.jibble.epsgraphics.EpsGraphics2D;
 
@@ -141,7 +144,35 @@ public class TreePanel extends GTreePanel
 
     buildAssociatedViewMenu();
 
-    av.addPropertyChangeListener(new java.beans.PropertyChangeListener()
+    final PropertyChangeListener listener = addAlignmentListener();
+
+    /*
+     * remove listener when window is closed, so that this
+     * panel can be garbage collected
+     */
+    addInternalFrameListener(new InternalFrameAdapter()
+    {
+      @Override
+      public void internalFrameClosed(InternalFrameEvent evt)
+      {
+        if (av != null)
+        {
+          av.removePropertyChangeListener(listener);
+        }
+      }
+    });
+
+    TreeLoader tl = new TreeLoader(newTree, inputData);
+    tl.start();
+
+  }
+
+  /**
+   * @return
+   */
+  protected PropertyChangeListener addAlignmentListener()
+  {
+    final PropertyChangeListener listener = new PropertyChangeListener()
     {
       @Override
       public void propertyChange(PropertyChangeEvent evt)
@@ -158,8 +189,8 @@ public class TreePanel extends GTreePanel
           }
           if (evt.getNewValue() == null)
           {
-            System.out
-                    .println("new alignment sequences vector value is null");
+            System.out.println(
+                    "new alignment sequences vector value is null");
           }
 
           tree.updatePlaceHolders((List<SequenceI>) evt.getNewValue());
@@ -168,11 +199,9 @@ public class TreePanel extends GTreePanel
           repaint();
         }
       }
-    });
-
-    TreeLoader tl = new TreeLoader(newTree, inputData);
-    tl.start();
-
+    };
+    av.addPropertyChangeListener(listener);
+    return listener;
   }
 
   @Override
@@ -183,8 +212,8 @@ public class TreePanel extends GTreePanel
 
   void buildAssociatedViewMenu()
   {
-    AlignmentPanel[] aps = PaintRefresher.getAssociatedPanels(av
-            .getSequenceSetId());
+    AlignmentPanel[] aps = PaintRefresher
+            .getAssociatedPanels(av.getSequenceSetId());
     if (aps.length == 1 && treeCanvas.ap == aps[0])
     {
       associateLeavesMenu.setVisible(false);
@@ -193,7 +222,8 @@ public class TreePanel extends GTreePanel
 
     associateLeavesMenu.setVisible(true);
 
-    if ((viewMenu.getItem(viewMenu.getItemCount() - 2) instanceof JMenuItem))
+    if ((viewMenu
+            .getItem(viewMenu.getItemCount() - 2) instanceof JMenuItem))
     {
       viewMenu.insertSeparator(viewMenu.getItemCount() - 1);
     }
@@ -275,11 +305,11 @@ public class TreePanel extends GTreePanel
       }
       else
       {
-        ScoreModelI sm = ScoreModels.getInstance().getScoreModel(
-                scoreModelName, treeCanvas.ap);
-        TreeBuilder njtree = treeType.equals(TreeBuilder.NEIGHBOUR_JOINING) ? new NJTree(
-                av, sm, similarityParams) : new AverageDistanceTree(av, sm,
-                similarityParams);
+        ScoreModelI sm = ScoreModels.getInstance()
+                .getScoreModel(scoreModelName, treeCanvas.ap);
+        TreeBuilder njtree = treeType.equals(TreeBuilder.NEIGHBOUR_JOINING)
+                ? new NJTree(av, sm, similarityParams)
+                : new AverageDistanceTree(av, sm, similarityParams);
         tree = new TreeModel(njtree);
         showDistances(true);
       }
@@ -363,8 +393,8 @@ public class TreePanel extends GTreePanel
     JalviewFileChooser chooser = new JalviewFileChooser(
             jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
     chooser.setFileView(new JalviewFileView());
-    chooser.setDialogTitle(MessageManager
-            .getString("label.save_tree_as_newick"));
+    chooser.setDialogTitle(
+            MessageManager.getString("label.save_tree_as_newick"));
     chooser.setToolTipText(MessageManager.getString("action.save"));
 
     int value = chooser.showSaveDialog(null);
@@ -372,15 +402,15 @@ public class TreePanel extends GTreePanel
     if (value == JalviewFileChooser.APPROVE_OPTION)
     {
       String choice = chooser.getSelectedFile().getPath();
-      jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
-              .getSelectedFile().getParent());
+      jalview.bin.Cache.setProperty("LAST_DIRECTORY",
+              chooser.getSelectedFile().getParent());
 
       try
       {
         jalview.io.NewickFile fout = new jalview.io.NewickFile(
                 tree.getTopNode());
-        String output = fout.print(tree.hasBootstrap(),
-                tree.hasDistances(), tree.hasRootDistance());
+        String output = fout.print(tree.hasBootstrap(), tree.hasDistances(),
+                tree.hasRootDistance());
         java.io.PrintWriter out = new java.io.PrintWriter(
                 new java.io.FileWriter(choice));
         out.println(output);
@@ -411,8 +441,8 @@ public class TreePanel extends GTreePanel
     AlignmentView originalData = tree.getOriginalData();
     if (originalData == null)
     {
-      jalview.bin.Cache.log
-              .info("Unexpected call to originalSeqData_actionPerformed - should have hidden this menu action.");
+      jalview.bin.Cache.log.info(
+              "Unexpected call to originalSeqData_actionPerformed - should have hidden this menu action.");
       return;
     }
     // decide if av alignment is sufficiently different to original data to
@@ -439,8 +469,9 @@ public class TreePanel extends GTreePanel
       // AlignmentOrder origorder = new AlignmentOrder(alAndColsel[0]);
 
       AlignmentI al = new Alignment((SequenceI[]) alAndColsel[0]);
-      AlignmentI dataset = (av != null && av.getAlignment() != null) ? av
-              .getAlignment().getDataset() : null;
+      AlignmentI dataset = (av != null && av.getAlignment() != null)
+              ? av.getAlignment().getDataset()
+              : null;
       if (dataset != null)
       {
         al.setDataset(dataset);
@@ -450,8 +481,7 @@ public class TreePanel extends GTreePanel
       {
         // make a new frame!
         AlignFrame af = new AlignFrame(al, (HiddenColumns) alAndColsel[1],
-                AlignFrame.DEFAULT_WIDTH,
-                AlignFrame.DEFAULT_HEIGHT);
+                AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
 
         // >>>This is a fix for the moment, until a better solution is
         // found!!<<<
@@ -461,8 +491,8 @@ public class TreePanel extends GTreePanel
         // msaorder);
 
         Desktop.addInternalFrame(af, MessageManager.formatMessage(
-                "label.original_data_for_params",
-                new Object[] { this.title }), AlignFrame.DEFAULT_WIDTH,
+                "label.original_data_for_params", new Object[]
+                { this.title }), AlignFrame.DEFAULT_WIDTH,
                 AlignFrame.DEFAULT_HEIGHT);
       }
     }
@@ -492,9 +522,9 @@ public class TreePanel extends GTreePanel
 
     if (treeCanvas.applyToAllViews)
     {
-      final ArrayList<CommandI> commands = new ArrayList<CommandI>();
-      for (AlignmentPanel ap : PaintRefresher.getAssociatedPanels(av
-              .getSequenceSetId()))
+      final ArrayList<CommandI> commands = new ArrayList<>();
+      for (AlignmentPanel ap : PaintRefresher
+              .getAssociatedPanels(av.getSequenceSetId()))
       {
         commands.add(sortAlignmentIn(ap.av.getAlignPanel()));
       }
@@ -532,8 +562,8 @@ public class TreePanel extends GTreePanel
           }
         }
       });
-      for (AlignmentPanel ap : PaintRefresher.getAssociatedPanels(av
-              .getSequenceSetId()))
+      for (AlignmentPanel ap : PaintRefresher
+              .getAssociatedPanels(av.getSequenceSetId()))
       {
         // ensure all the alignFrames refresh their GI after adding an undo item
         ap.alignFrame.updateEditMenuBar();
@@ -549,13 +579,14 @@ public class TreePanel extends GTreePanel
 
   public CommandI sortAlignmentIn(AlignmentPanel ap)
   {
+    // TODO: move to alignment view controller
     AlignmentViewport viewport = ap.av;
     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
     AlignmentSorter.sortByTree(viewport.getAlignment(), tree);
     CommandI undo;
     undo = new OrderCommand("Tree Sort", oldOrder, viewport.getAlignment());
 
-    ap.paintAlignment(true);
+    ap.paintAlignment(true, false);
     return undo;
   }
 
@@ -668,8 +699,8 @@ public class TreePanel extends GTreePanel
       JalviewFileChooser chooser = new JalviewFileChooser(
               ImageMaker.EPS_EXTENSION, ImageMaker.EPS_EXTENSION);
       chooser.setFileView(new JalviewFileView());
-      chooser.setDialogTitle(MessageManager
-              .getString("label.create_eps_from_tree"));
+      chooser.setDialogTitle(
+              MessageManager.getString("label.create_eps_from_tree"));
       chooser.setToolTipText(MessageManager.getString("action.save"));
 
       int value = chooser.showSaveDialog(this);
@@ -679,11 +710,13 @@ public class TreePanel extends GTreePanel
         return;
       }
 
-      Cache.setProperty("LAST_DIRECTORY", chooser.getSelectedFile()
-              .getParent());
+      Cache.setProperty("LAST_DIRECTORY",
+              chooser.getSelectedFile().getParent());
 
-      FileOutputStream out = new FileOutputStream(chooser.getSelectedFile());
-      EpsGraphics2D pg = new EpsGraphics2D("Tree", out, 0, 0, width, height);
+      FileOutputStream out = new FileOutputStream(
+              chooser.getSelectedFile());
+      EpsGraphics2D pg = new EpsGraphics2D("Tree", out, 0, 0, width,
+              height);
 
       pg.setAccurateTextMode(accurateText);
 
@@ -715,8 +748,8 @@ public class TreePanel extends GTreePanel
               ImageMaker.PNG_EXTENSION, ImageMaker.PNG_DESCRIPTION);
 
       chooser.setFileView(new jalview.io.JalviewFileView());
-      chooser.setDialogTitle(MessageManager
-              .getString("label.create_png_from_tree"));
+      chooser.setDialogTitle(
+              MessageManager.getString("label.create_png_from_tree"));
       chooser.setToolTipText(MessageManager.getString("action.save"));
 
       int value = chooser.showSaveDialog(this);
@@ -726,10 +759,11 @@ public class TreePanel extends GTreePanel
         return;
       }
 
-      jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
-              .getSelectedFile().getParent());
+      jalview.bin.Cache.setProperty("LAST_DIRECTORY",
+              chooser.getSelectedFile().getParent());
 
-      FileOutputStream out = new FileOutputStream(chooser.getSelectedFile());
+      FileOutputStream out = new FileOutputStream(
+              chooser.getSelectedFile());
 
       BufferedImage bi = new BufferedImage(width, height,
               BufferedImage.TYPE_INT_RGB);
@@ -770,9 +804,9 @@ public class TreePanel extends GTreePanel
           if (sq != null)
           {
             // search dbrefs, features and annotation
-            DBRefEntry[] refs = jalview.util.DBRefUtils.selectRefs(
-                    sq.getDBRefs(),
-                    new String[] { labelClass.toUpperCase() });
+            DBRefEntry[] refs = jalview.util.DBRefUtils
+                    .selectRefs(sq.getDBRefs(), new String[]
+                    { labelClass.toUpperCase() });
             if (refs != null)
             {
               for (int i = 0; i < refs.length; i++)
@@ -789,19 +823,17 @@ public class TreePanel extends GTreePanel
             }
             if (newname == null)
             {
-              SequenceFeature sf[] = sq.getSequenceFeatures();
-              for (int i = 0; sf != null && i < sf.length; i++)
+              List<SequenceFeature> features = sq.getFeatures()
+                      .getPositionalFeatures(labelClass);
+              for (SequenceFeature feature : features)
               {
-                if (sf[i].getType().equals(labelClass))
+                if (newname == null)
                 {
-                  if (newname == null)
-                  {
-                    newname = new String(sf[i].getDescription());
-                  }
-                  else
-                  {
-                    newname = newname + "; " + sf[i].getDescription();
-                  }
+                  newname = feature.getDescription();
+                }
+                else
+                {
+                  newname = newname + "; " + feature.getDescription();
                 }
               }
             }
@@ -823,6 +855,7 @@ public class TreePanel extends GTreePanel
    * Neighbour Joining Using BLOSUM62
    * <p>
    * For a tree loaded from file, just uses the file name
+   * 
    * @return
    */
   public String getPanelTitle()
@@ -835,8 +868,8 @@ public class TreePanel extends GTreePanel
     /*
      * i18n description of Neighbour Joining or Average Distance method
      */
-    String treecalcnm = MessageManager.getString("label.tree_calc_"
-            + treeType.toLowerCase());
+    String treecalcnm = MessageManager
+            .getString("label.tree_calc_" + treeType.toLowerCase());
 
     /*
      * short score model name (long description can be too long)
index f75a0a3..3290500 100755 (executable)
@@ -59,11 +59,11 @@ import javax.swing.event.ChangeListener;
  * @author Andrew Waterhouse
  * @author Mungo Carstairs
  */
-public class UserDefinedColours extends GUserDefinedColours implements
-        ChangeListener
+public class UserDefinedColours extends GUserDefinedColours
+        implements ChangeListener
 {
-  private static final Font VERDANA_BOLD_10 = new Font("Verdana",
-          Font.BOLD, 10);
+  private static final Font VERDANA_BOLD_10 = new Font("Verdana", Font.BOLD,
+          10);
 
   public static final String USER_DEFINED_COLOURS = "USER_DEFINED_COLOURS";
 
@@ -113,7 +113,8 @@ public class UserDefinedColours extends GUserDefinedColours implements
     if (oldColourScheme instanceof UserColourScheme)
     {
       schemeName.setText(oldColourScheme.getSchemeName());
-      if (((UserColourScheme) oldColourScheme).getLowerCaseColours() != null)
+      if (((UserColourScheme) oldColourScheme)
+              .getLowerCaseColours() != null)
       {
         caseSensitive.setSelected(true);
         lcaseColour.setEnabled(true);
@@ -135,7 +136,7 @@ public class UserDefinedColours extends GUserDefinedColours implements
   UserDefinedColours()
   {
     super();
-    selectedButtons = new ArrayList<JButton>();
+    selectedButtons = new ArrayList<>();
   }
 
   void showFrame()
@@ -162,7 +163,7 @@ public class UserDefinedColours extends GUserDefinedColours implements
 
     if (upperCaseButtons == null)
     {
-      upperCaseButtons = new ArrayList<JButton>();
+      upperCaseButtons = new ArrayList<>();
     }
 
     for (int i = 0; i < 20; i++)
@@ -193,7 +194,7 @@ public class UserDefinedColours extends GUserDefinedColours implements
 
       if (lowerCaseButtons == null)
       {
-        lowerCaseButtons = new ArrayList<JButton>();
+        lowerCaseButtons = new ArrayList<>();
       }
 
       for (int i = 0; i < 20; i++)
@@ -249,7 +250,8 @@ public class UserDefinedColours extends GUserDefinedColours implements
       {
         button = lowerCaseButtons.get(i);
         button.setBackground(newColour);
-        button.setForeground(ColorUtils.brighterThan(button.getBackground()));
+        button.setForeground(
+                ColorUtils.brighterThan(button.getBackground()));
       }
     }
     for (int i = 0; i < selectedButtons.size(); i++)
@@ -321,8 +323,8 @@ public class UserDefinedColours extends GUserDefinedColours implements
         JButton button = (JButton) buttonPanel.getComponent(b);
         if (!selectedButtons.contains(button))
         {
-          button.setForeground(ColorUtils.brighterThan(button
-                  .getBackground()));
+          button.setForeground(
+                  ColorUtils.brighterThan(button.getBackground()));
           selectedButtons.add(button);
         }
       }
@@ -335,7 +337,8 @@ public class UserDefinedColours extends GUserDefinedColours implements
         button.setForeground(ColorUtils.darkerThan(button.getBackground()));
       }
       selectedButtons.clear();
-      pressed.setForeground(ColorUtils.brighterThan(pressed.getBackground()));
+      pressed.setForeground(
+              ColorUtils.brighterThan(pressed.getBackground()));
       selectedButtons.add(pressed);
 
     }
@@ -343,13 +346,14 @@ public class UserDefinedColours extends GUserDefinedColours implements
     {
       if (selectedButtons.contains(pressed))
       {
-        pressed.setForeground(ColorUtils.darkerThan(pressed.getBackground()));
+        pressed.setForeground(
+                ColorUtils.darkerThan(pressed.getBackground()));
         selectedButtons.remove(pressed);
       }
       else
       {
-        pressed.setForeground(ColorUtils.brighterThan(pressed
-                .getBackground()));
+        pressed.setForeground(
+                ColorUtils.brighterThan(pressed.getBackground()));
         selectedButtons.add(pressed);
       }
     }
@@ -440,8 +444,9 @@ public class UserDefinedColours extends GUserDefinedColours implements
   {
     if (isNoSelectionMade())
     {
-      JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
-              .getString("label.no_colour_selection_in_scheme"),
+      JvOptionPane.showMessageDialog(Desktop.desktop,
+              MessageManager
+                      .getString("label.no_colour_selection_in_scheme"),
               MessageManager.getString("label.no_colour_selection_warn"),
               JvOptionPane.WARNING_MESSAGE);
     }
@@ -543,8 +548,9 @@ public class UserDefinedColours extends GUserDefinedColours implements
   {
     if (isNoSelectionMade())
     {
-      JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
-              .getString("label.no_colour_selection_in_scheme"),
+      JvOptionPane.showMessageDialog(Desktop.desktop,
+              MessageManager
+                      .getString("label.no_colour_selection_in_scheme"),
               MessageManager.getString("label.no_colour_selection_warn"),
               JvOptionPane.WARNING_MESSAGE);
 
@@ -625,14 +631,14 @@ public class UserDefinedColours extends GUserDefinedColours implements
   @Override
   protected void loadbutton_actionPerformed()
   {
-    upperCaseButtons = new ArrayList<JButton>();
-    lowerCaseButtons = new ArrayList<JButton>();
+    upperCaseButtons = new ArrayList<>();
+    lowerCaseButtons = new ArrayList<>();
 
     JalviewFileChooser chooser = new JalviewFileChooser("jc",
             "Jalview User Colours");
     chooser.setFileView(new JalviewFileView());
-    chooser.setDialogTitle(MessageManager
-            .getString("label.load_colour_scheme"));
+    chooser.setDialogTitle(
+            MessageManager.getString("label.load_colour_scheme"));
     chooser.setToolTipText(MessageManager.getString("action.load"));
 
     int value = chooser.showOpenDialog(this);
@@ -644,8 +650,8 @@ public class UserDefinedColours extends GUserDefinedColours implements
     File choice = chooser.getSelectedFile();
     Cache.setProperty(LAST_DIRECTORY, choice.getParent());
 
-    UserColourScheme ucs = ColourSchemeLoader.loadColourScheme(choice
-            .getAbsolutePath());
+    UserColourScheme ucs = ColourSchemeLoader
+            .loadColourScheme(choice.getAbsolutePath());
     Color[] colors = ucs.getColours();
     schemeName.setText(ucs.getSchemeName());
 
@@ -712,7 +718,8 @@ public class UserDefinedColours extends GUserDefinedColours implements
    * name if overwriting</li>
    * <li>Do the standard file chooser thing to write with extension .jc</li>
    * <li>If saving changes (possibly not yet applied) to the currently selected
-   * colour scheme, then apply the changes, as it is too late to back out now</li>
+   * colour scheme, then apply the changes, as it is too late to back out
+   * now</li>
    * <li>Don't apply the changes if the currently selected scheme is different,
    * to allow a new scheme to be configured and saved but not applied</li>
    * </ul>
@@ -726,8 +733,9 @@ public class UserDefinedColours extends GUserDefinedColours implements
     String name = schemeName.getText().trim();
     if (name.length() < 1)
     {
-      JvOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager
-              .getString("label.user_colour_scheme_must_have_name"),
+      JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+              MessageManager
+                      .getString("label.user_colour_scheme_must_have_name"),
               MessageManager.getString("label.no_name_colour_scheme"),
               JvOptionPane.WARNING_MESSAGE);
       return false;
@@ -737,8 +745,8 @@ public class UserDefinedColours extends GUserDefinedColours implements
     {
       int reply = JvOptionPane.showInternalConfirmDialog(Desktop.desktop,
               MessageManager.formatMessage(
-                      "label.colour_scheme_exists_overwrite", new Object[] {
-                          name, name }),
+                      "label.colour_scheme_exists_overwrite", new Object[]
+                      { name, name }),
               MessageManager.getString("label.duplicate_scheme_name"),
               JvOptionPane.YES_NO_OPTION);
       if (reply != JvOptionPane.YES_OPTION)
@@ -751,8 +759,8 @@ public class UserDefinedColours extends GUserDefinedColours implements
 
     JalviewFileView fileView = new JalviewFileView();
     chooser.setFileView(fileView);
-    chooser.setDialogTitle(MessageManager
-            .getString("label.save_colour_scheme"));
+    chooser.setDialogTitle(
+            MessageManager.getString("label.save_colour_scheme"));
     chooser.setToolTipText(MessageManager.getString("action.save"));
 
     int value = chooser.showSaveDialog(this);
@@ -796,8 +804,8 @@ public class UserDefinedColours extends GUserDefinedColours implements
      * update the delimited list of user defined colour files in
      * Jalview property USER_DEFINED_COLOURS
      */
-    String defaultColours = Cache
-            .getDefault(USER_DEFINED_COLOURS, filePath);
+    String defaultColours = Cache.getDefault(USER_DEFINED_COLOURS,
+            filePath);
     if (defaultColours.indexOf(filePath) == -1)
     {
       if (defaultColours.length() > 0)
@@ -868,7 +876,7 @@ public class UserDefinedColours extends GUserDefinedColours implements
   protected void cancelButton_actionPerformed()
   {
     ap.alignFrame.changeColour(oldColourScheme);
-    ap.paintAlignment(true);
+    ap.paintAlignment(true, true);
 
     try
     {
index 5e5d965..ef86756 100644 (file)
@@ -42,11 +42,9 @@ public class UserQuestionnaireCheck implements Runnable
   {
     if (url.indexOf("questionnaire.pl") == -1)
     {
-      jalview.bin.Cache.log
-              .error("'"
-                      + url
-                      + "' is an Invalid URL for the checkForQuestionnaire() method.\n"
-                      + "This argument is only for questionnaires derived from jalview's questionnaire.pl cgi interface.");
+      jalview.bin.Cache.log.error("'" + url
+              + "' is an Invalid URL for the checkForQuestionnaire() method.\n"
+              + "This argument is only for questionnaires derived from jalview's questionnaire.pl cgi interface.");
     }
     else
     {
@@ -62,8 +60,8 @@ public class UserQuestionnaireCheck implements Runnable
     boolean prompt = false;
     // see if we have already responsed to this questionnaire or get a new
     // qid/rid pair
-    BufferedReader br = new BufferedReader(new InputStreamReader(
-            qurl.openStream()));
+    BufferedReader br = new BufferedReader(
+            new InputStreamReader(qurl.openStream()));
     String qresp;
     while ((qresp = br.readLine()) != null)
     {
@@ -114,8 +112,9 @@ public class UserQuestionnaireCheck implements Runnable
         String qurl = url + (url.indexOf('?') > -1 ? "&" : "?")
                 + "checkresponse=1";
         // query the server with the old qid/id pair
-        String qqid = lastq.indexOf(':') > -1 ? lastq.substring(0,
-                lastq.indexOf(':')) : null;
+        String qqid = lastq.indexOf(':') > -1
+                ? lastq.substring(0, lastq.indexOf(':'))
+                : null;
         if (qqid != null && qqid != "null" && qqid.length() > 0)
         {
           qurl += "&qid=" + qqid;
@@ -140,15 +139,12 @@ public class UserQuestionnaireCheck implements Runnable
       {
         String qurl = url + (url.indexOf('?') > -1 ? "&" : "?") + "qid="
                 + qid + "&rid=" + rid;
-        jalview.bin.Cache.log.info("Prompting user for questionnaire at "
-                + qurl);
-        int reply = JvOptionPane
-                .showInternalConfirmDialog(Desktop.desktop, MessageManager
-                        .getString("label.jalview_new_questionnaire"),
-                        MessageManager
-                                .getString("label.jalview_user_survey"),
-                        JvOptionPane.YES_NO_OPTION,
-                        JvOptionPane.QUESTION_MESSAGE);
+        jalview.bin.Cache.log
+                .info("Prompting user for questionnaire at " + qurl);
+        int reply = JvOptionPane.showInternalConfirmDialog(Desktop.desktop,
+                MessageManager.getString("label.jalview_new_questionnaire"),
+                MessageManager.getString("label.jalview_user_survey"),
+                JvOptionPane.YES_NO_OPTION, JvOptionPane.QUESTION_MESSAGE);
 
         if (reply == JvOptionPane.YES_OPTION)
         {
@@ -158,8 +154,8 @@ public class UserQuestionnaireCheck implements Runnable
       }
     } catch (Exception e)
     {
-      jalview.bin.Cache.log.warn("When trying to access questionnaire URL "
-              + url, e);
+      jalview.bin.Cache.log
+              .warn("When trying to access questionnaire URL " + url, e);
     }
   }
 
index d58cb5a..d2086e0 100644 (file)
@@ -156,9 +156,8 @@ public class VamsasApplication implements SelectionSource, VamsasSource
       {
         if (sess != null)
         {
-          throw new Error(
-                  MessageManager
-                          .getString("error.implementation_error_cannot_import_vamsas_doc"));
+          throw new Error(MessageManager.getString(
+                  "error.implementation_error_cannot_import_vamsas_doc"));
         }
         try
         {
@@ -174,15 +173,13 @@ public class VamsasApplication implements SelectionSource, VamsasSource
           }
         } catch (InvalidSessionDocumentException e)
         {
-          JvOptionPane
-                  .showInternalMessageDialog(
-                          Desktop.desktop,
+          JvOptionPane.showInternalMessageDialog(Desktop.desktop,
 
-                          MessageManager
-                                  .getString("label.vamsas_doc_couldnt_be_opened_as_new_session"),
-                          MessageManager
-                                  .getString("label.vamsas_document_import_failed"),
-                          JvOptionPane.ERROR_MESSAGE);
+                  MessageManager.getString(
+                          "label.vamsas_doc_couldnt_be_opened_as_new_session"),
+                  MessageManager
+                          .getString("label.vamsas_document_import_failed"),
+                  JvOptionPane.ERROR_MESSAGE);
 
         }
       }
@@ -204,8 +201,8 @@ public class VamsasApplication implements SelectionSource, VamsasSource
 
     } catch (Exception e)
     {
-      jalview.bin.Cache.log
-              .error("Couldn't instantiate vamsas client !", e);
+      jalview.bin.Cache.log.error("Couldn't instantiate vamsas client !",
+              e);
       return false;
     }
     return true;
@@ -228,14 +225,14 @@ public class VamsasApplication implements SelectionSource, VamsasSource
       }
     } catch (Error e)
     {
-      Cache.log
-              .warn("Probable SERIOUS VAMSAS client incompatibility - carrying on regardless",
-                      e);
+      Cache.log.warn(
+              "Probable SERIOUS VAMSAS client incompatibility - carrying on regardless",
+              e);
     } catch (Exception e)
     {
-      Cache.log
-              .warn("Probable VAMSAS client incompatibility - carrying on regardless",
-                      e);
+      Cache.log.warn(
+              "Probable VAMSAS client incompatibility - carrying on regardless",
+              e);
     }
   }
 
@@ -267,16 +264,15 @@ public class VamsasApplication implements SelectionSource, VamsasSource
   {
     if (!inSession())
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_error_vamsas_operation_not_init"));
+      throw new Error(MessageManager.getString(
+              "error.implementation_error_vamsas_operation_not_init"));
     }
     addDocumentUpdateHandler();
     addStoreDocumentHandler();
     startSession();
     inInitialUpdate = true;
-    Cache.log
-            .debug("Jalview loading the Vamsas Session for the first time.");
+    Cache.log.debug(
+            "Jalview loading the Vamsas Session for the first time.");
     dealWithDocumentUpdate(false); // we don't push an update out to the
     inInitialUpdate = false;
     // document yet.
@@ -310,9 +306,9 @@ public class VamsasApplication implements SelectionSource, VamsasSource
       }
     } catch (Exception e)
     {
-      Cache.log
-              .warn("Exception whilst refreshing jalview windows after a vamsas document update.",
-                      e);
+      Cache.log.warn(
+              "Exception whilst refreshing jalview windows after a vamsas document update.",
+              e);
     }
   }
 
@@ -355,9 +351,8 @@ public class VamsasApplication implements SelectionSource, VamsasSource
   {
     if (!inSession())
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.jalview_no_connected_vamsas_session"));
+      throw new Error(MessageManager
+              .getString("error.jalview_no_connected_vamsas_session"));
     }
     Cache.log.info("Jalview disconnecting from the Vamsas Session.");
     try
@@ -372,8 +367,8 @@ public class VamsasApplication implements SelectionSource, VamsasSource
       }
       else
       {
-        Cache.log
-                .warn("JV Client leaving a session that's its not joined yet.");
+        Cache.log.warn(
+                "JV Client leaving a session that's its not joined yet.");
       }
       joinedSession = false;
       vclient = null;
@@ -487,11 +482,10 @@ public class VamsasApplication implements SelectionSource, VamsasSource
             } catch (Exception e)
             {
               errorsDuringUpdate = true;
-              Cache.log.error("Exception synchronizing "
-                      + af.getTitle()
+              Cache.log.error("Exception synchronizing " + af.getTitle()
                       + " "
-                      + (af.getViewport().viewName == null ? "" : " view "
-                              + af.getViewport().viewName)
+                      + (af.getViewport().viewName == null ? ""
+                              : " view " + af.getViewport().viewName)
                       + " to document.", e);
               stored = false;
             }
@@ -588,8 +582,8 @@ public class VamsasApplication implements SelectionSource, VamsasSource
         storedviews += updateVamsasDocument(cdoc);
         if (Cache.log.isDebugEnabled())
         {
-          Cache.log
-                  .debug("Time taken to update Vamsas Document from jalview\t= "
+          Cache.log.debug(
+                  "Time taken to update Vamsas Document from jalview\t= "
                           + (System.currentTimeMillis() - time));
           time = System.currentTimeMillis();
         }
@@ -606,8 +600,8 @@ public class VamsasApplication implements SelectionSource, VamsasSource
         updateJalview(cdoc);
         if (Cache.log.isDebugEnabled())
         {
-          Cache.log
-                  .debug("Time taken to update Jalview from vamsas document Roots\t= "
+          Cache.log.debug(
+                  "Time taken to update Jalview from vamsas document Roots\t= "
                           + (System.currentTimeMillis() - time));
           time = System.currentTimeMillis();
         }
@@ -663,15 +657,14 @@ public class VamsasApplication implements SelectionSource, VamsasSource
               {
                 if (client.promptUser)
                 {
-                  Cache.log
-                          .debug("Asking user if the vamsas session should be stored.");
-                  int reply = JvOptionPane
-                          .showInternalConfirmDialog(
-                                  Desktop.desktop,
-                                  "The current VAMSAS session has unsaved data - do you want to save it ?",
-                                  "VAMSAS Session Shutdown",
-                                  JvOptionPane.YES_NO_OPTION,
-                                  JvOptionPane.QUESTION_MESSAGE);
+                  Cache.log.debug(
+                          "Asking user if the vamsas session should be stored.");
+                  int reply = JvOptionPane.showInternalConfirmDialog(
+                          Desktop.desktop,
+                          "The current VAMSAS session has unsaved data - do you want to save it ?",
+                          "VAMSAS Session Shutdown",
+                          JvOptionPane.YES_NO_OPTION,
+                          JvOptionPane.QUESTION_MESSAGE);
 
                   if (reply == JvOptionPane.YES_OPTION)
                   {
@@ -680,13 +673,13 @@ public class VamsasApplication implements SelectionSource, VamsasSource
                     Cache.log
                             .debug("Finished attempt at storing document.");
                   }
-                  Cache.log
-                          .debug("finished dealing with REQUESTTOCLOSE event.");
+                  Cache.log.debug(
+                          "finished dealing with REQUESTTOCLOSE event.");
                 }
                 else
                 {
-                  Cache.log
-                          .debug("Ignoring store document request (promptUser==false)");
+                  Cache.log.debug(
+                          "Ignoring store document request (promptUser==false)");
                 }
               }
             });
@@ -728,9 +721,8 @@ public class VamsasApplication implements SelectionSource, VamsasSource
         return;
       }
 
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_error_cannot_recover_vamsas_object_mappings"));
+      throw new Error(MessageManager.getString(
+              "error.implementation_error_cannot_recover_vamsas_object_mappings"));
     }
     jv2vobj.clear();
     Iterator el = _backup_jv2vobj.entrySet().iterator();
@@ -937,8 +929,8 @@ public class VamsasApplication implements SelectionSource, VamsasSource
                       {
                         jselection.setStartRes(prange[p + l] - 1);
                       }
-                      if (jselection.getEndRes() <= maxWidth
-                              && prange[p + u] == (jselection.getEndRes() + 2))
+                      if (jselection.getEndRes() <= maxWidth && prange[p
+                              + u] == (jselection.getEndRes() + 2))
                       {
                         jselection.setEndRes(prange[p + u] - 1);
                       }
@@ -1009,8 +1001,8 @@ public class VamsasApplication implements SelectionSource, VamsasSource
           {
             if (vobj2jv == null)
             {
-              Cache.log
-                      .warn("Selection listener still active for dead session.");
+              Cache.log.warn(
+                      "Selection listener still active for dead session.");
               // not in a session.
               return;
             }
@@ -1023,15 +1015,17 @@ public class VamsasApplication implements SelectionSource, VamsasSource
               }
               SelectionMessage sm = null;
               if ((seqsel == null || seqsel.getSize() == 0)
-                      && (colsel == null || colsel.getSelected() == null || colsel
-                              .getSelected().size() == 0))
+                      && (colsel == null || colsel.getSelected() == null
+                              || colsel.getSelected().size() == 0))
               {
                 if (source instanceof AlignViewport)
                 {
                   // the empty selection.
                   sm = new SelectionMessage("jalview",
-                          new String[] { ((AlignmentViewport) source)
-                                  .getSequenceSetId() }, null, true);
+                          new String[]
+                          { ((AlignmentViewport) source)
+                                  .getSequenceSetId() },
+                          null, true);
                 }
                 else
                 {
index f1e2467..2a7743a 100644 (file)
@@ -60,15 +60,6 @@ public class ViewSelectionMenu extends JMenu
 
   private ItemListener _handler;
 
-  @Override
-  protected void finalize() throws Throwable
-  {
-    _selectedviews = null;
-    _handler = null;
-    _allviews = null;
-    super.finalize();
-  }
-
   /**
    * create a new view selection menu. This menu has some standard entries
    * (select all, invert selection), and a checkbox for every view. Mousing over
@@ -152,8 +143,8 @@ public class ViewSelectionMenu extends JMenu
       append = append || _selectedviews.size() > 1;
       toggleview = new JCheckBoxMenuItem(
               MessageManager.getString("label.select_many_views"), append);
-      toggleview.setToolTipText(MessageManager
-              .getString("label.toggle_enabled_views"));
+      toggleview.setToolTipText(
+              MessageManager.getString("label.toggle_enabled_views"));
       toggleview.addItemListener(new ItemListener()
       {
 
@@ -219,8 +210,9 @@ public class ViewSelectionMenu extends JMenu
     }
     for (final AlignmentPanel ap : allviews)
     {
-      String nm = ((ap.getViewName() == null || ap.getViewName().length() == 0) ? ""
-              : ap.getViewName() + " for ")
+      String nm = ((ap.getViewName() == null
+              || ap.getViewName().length() == 0) ? ""
+                      : ap.getViewName() + " for ")
               + ap.alignFrame.getTitle();
       final JCheckBoxMenuItem checkBox = new JCheckBoxMenuItem(nm,
               _selectedviews.contains(ap));
index f650807..2fc08e1 100644 (file)
@@ -56,8 +56,8 @@ import javax.swing.text.html.StyleSheet;
  * @author $author$
  * @version $Revision$
  */
-public class WebserviceInfo extends GWebserviceInfo implements
-        HyperlinkListener, IProgressIndicator
+public class WebserviceInfo extends GWebserviceInfo
+        implements HyperlinkListener, IProgressIndicator
 {
 
   /** Job is Queued */
@@ -328,8 +328,8 @@ public class WebserviceInfo extends GWebserviceInfo implements
     this.title = title;
     setInfoText(info);
 
-    java.net.URL url = getClass().getResource(
-            "/images/Jalview_Logo_small.png");
+    java.net.URL url = getClass()
+            .getResource("/images/Jalview_Logo_small.png");
     image = java.awt.Toolkit.getDefaultToolkit().createImage(url);
 
     MediaTracker mt = new MediaTracker(this);
@@ -348,19 +348,20 @@ public class WebserviceInfo extends GWebserviceInfo implements
     Thread thread = new Thread(ap);
     thread.start();
     final WebserviceInfo thisinfo = this;
-    frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
-    {
-      public void internalFrameClosed(
-              javax.swing.event.InternalFrameEvent evt)
-      {
-        // System.out.println("Shutting down webservice client");
-        WSClientI service = thisinfo.getthisService();
-        if (service != null && service.isCancellable())
-        {
-          service.cancelJob();
-        }
-      };
-    });
+    frame.addInternalFrameListener(
+            new javax.swing.event.InternalFrameAdapter()
+            {
+              public void internalFrameClosed(
+                      javax.swing.event.InternalFrameEvent evt)
+              {
+                // System.out.println("Shutting down webservice client");
+                WSClientI service = thisinfo.getthisService();
+                if (service != null && service.isCancellable())
+                {
+                  service.cancelJob();
+                }
+              };
+            });
     frame.validate();
 
   }
@@ -387,8 +388,8 @@ public class WebserviceInfo extends GWebserviceInfo implements
     if (jobpane < 0 || jobpane >= jobPanes.size())
     {
       throw new Error(MessageManager.formatMessage(
-              "error.setstatus_called_non_existent_job_pane",
-              new String[] { Integer.valueOf(jobpane).toString() }));
+              "error.setstatus_called_non_existent_job_pane", new String[]
+              { Integer.valueOf(jobpane).toString() }));
     }
     switch (status)
     {
@@ -515,8 +516,8 @@ public class WebserviceInfo extends GWebserviceInfo implements
     int htmlpos = leaveFirst ? -1 : lowertxt.indexOf("<body");
 
     int htmlend = leaveLast ? -1 : lowertxt.indexOf("</body");
-    int htmlpose = lowertxt.indexOf(">", htmlpos), htmlende = lowertxt
-            .indexOf(">", htmlend);
+    int htmlpose = lowertxt.indexOf(">", htmlpos),
+            htmlende = lowertxt.indexOf(">", htmlend);
     if (htmlend == -1 && htmlpos == -1)
     {
       return text;
@@ -563,8 +564,8 @@ public class WebserviceInfo extends GWebserviceInfo implements
     }
     if (text.indexOf("<meta") > -1)
     {
-      System.err.println("HTML COntent: \n" + text
-              + "<< END HTML CONTENT\n");
+      System.err
+              .println("HTML COntent: \n" + text + "<< END HTML CONTENT\n");
 
     }
     return text;
@@ -586,11 +587,12 @@ public class WebserviceInfo extends GWebserviceInfo implements
     {
       String txt = getHtmlFragment(
               ((JEditorPane) ((JScrollPane) jobPanes.get(which))
-                      .getViewport().getComponent(0)).getText(), true,
-              false);
+                      .getViewport().getComponent(0)).getText(),
+              true, false);
       ((JEditorPane) ((JScrollPane) jobPanes.get(which)).getViewport()
-              .getComponent(0)).setText(ensureHtmlTagged(txt
-              + getHtmlFragment(text, false, true)));
+              .getComponent(0))
+                      .setText(ensureHtmlTagged(
+                              txt + getHtmlFragment(text, false, true)));
     }
     else
     {
@@ -683,8 +685,8 @@ public class WebserviceInfo extends GWebserviceInfo implements
       // JBPNote : TODO: Instead of a warning, we should have an optional 'Are
       // you sure?' prompt
       warnUser(
-              MessageManager
-                      .getString("warn.job_cannot_be_cancelled_close_window"),
+              MessageManager.getString(
+                      "warn.job_cannot_be_cancelled_close_window"),
               MessageManager.getString("action.cancel_job"));
     }
     else
@@ -764,7 +766,8 @@ public class WebserviceInfo extends GWebserviceInfo implements
         {
           Thread.sleep(50);
 
-          int units = (int) ((System.currentTimeMillis() - startTime) / 10f);
+          int units = (int) ((System.currentTimeMillis() - startTime)
+                  / 10f);
           angle += units;
           angle %= 360;
           startTime = System.currentTimeMillis();
@@ -828,8 +831,8 @@ public class WebserviceInfo extends GWebserviceInfo implements
 
       case STATE_CANCELLED_OK:
         g.drawString(
-                title.concat(" - ").concat(
-                        MessageManager
+                title.concat(" - ")
+                        .concat(MessageManager
                                 .getString("label.state_job_cancelled")),
                 60, 30);
 
@@ -845,8 +848,8 @@ public class WebserviceInfo extends GWebserviceInfo implements
 
       case STATE_STOPPED_SERVERERROR:
         g.drawString(
-                title.concat(" - ").concat(
-                        MessageManager
+                title.concat(" - ")
+                        .concat(MessageManager
                                 .getString("label.server_error_try_later")),
                 60, 30);
 
index 17c0760..10798f6 100644 (file)
@@ -186,7 +186,8 @@ public class WsJobParameters extends JPanel implements ItemListener,
    * @param jobArgset
    */
   public WsJobParameters(JFrame parent, ParamDatastoreI paramStorei,
-          Jws2Instance service, WsParamSetI preset, List<Argument> jobArgset)
+          Jws2Instance service, WsParamSetI preset,
+          List<Argument> jobArgset)
   {
     super();
     jbInit();
@@ -218,13 +219,14 @@ public class WsJobParameters extends JPanel implements ItemListener,
     frame = new JDialog(Desktop.instance, true);
 
     frame.setTitle(MessageManager.formatMessage("label.edit_params_for",
-            new String[] { service.getActionText() }));
+            new String[]
+            { service.getActionText() }));
     Rectangle deskr = Desktop.instance.getBounds();
     Dimension pref = this.getPreferredSize();
-    frame.setBounds(new Rectangle(
-            (int) (deskr.getCenterX() - pref.width / 2), (int) (deskr
-                    .getCenterY() - pref.height / 2), pref.width,
-            pref.height));
+    frame.setBounds(
+            new Rectangle((int) (deskr.getCenterX() - pref.width / 2),
+                    (int) (deskr.getCenterY() - pref.height / 2),
+                    pref.width, pref.height));
     frame.setContentPane(this);
 
     // should perhaps recover defaults from user prefs.
@@ -302,9 +304,10 @@ public class WsJobParameters extends JPanel implements ItemListener,
                 create_actionPerformed(e);
               }
             });
-    revertpref = JvSwingUtils.makeButton(MessageManager
-            .getString("action.revert"), MessageManager
-            .getString("label.revert_changes_user_parameter_set"),
+    revertpref = JvSwingUtils.makeButton(
+            MessageManager.getString("action.revert"),
+            MessageManager
+                    .getString("label.revert_changes_user_parameter_set"),
             new ActionListener()
             {
 
@@ -337,8 +340,8 @@ public class WsJobParameters extends JPanel implements ItemListener,
               }
             });
 
-    setDetails.setBorder(new TitledBorder(MessageManager
-            .getString("label.details")));
+    setDetails.setBorder(
+            new TitledBorder(MessageManager.getString("label.details")));
     setDetails.setLayout(new BorderLayout());
     setDescr.setColumns(40);
     setDescr.setWrapStyleWord(true);
@@ -346,8 +349,8 @@ public class WsJobParameters extends JPanel implements ItemListener,
     setDescr.setBackground(getBackground());
     setDescr.setEditable(true);
     setDescr.getDocument().addDocumentListener(this);
-    setDescr.setToolTipText(MessageManager
-            .getString("label.edit_notes_parameter_set"));
+    setDescr.setToolTipText(
+            MessageManager.getString("label.edit_notes_parameter_set"));
     JScrollPane setDescrView = new JScrollPane();
     setDescrView.getViewport().setView(setDescr);
     setName.setEditable(true);
@@ -397,14 +400,14 @@ public class WsJobParameters extends JPanel implements ItemListener,
 
     // paramPane.setPreferredSize(new Dimension(360, 400));
     // paramPane.setPreferredSize(null);
-    jobOptions.setBorder(new TitledBorder(MessageManager
-            .getString("label.options")));
+    jobOptions.setBorder(
+            new TitledBorder(MessageManager.getString("label.options")));
     jobOptions.setOpaque(true);
-    paramList.setBorder(new TitledBorder(MessageManager
-            .getString("label.parameters")));
+    paramList.setBorder(
+            new TitledBorder(MessageManager.getString("label.parameters")));
     paramList.setOpaque(true);
-    JPanel bjo = new JPanel(new BorderLayout()), bjp = new JPanel(
-            new BorderLayout());
+    JPanel bjo = new JPanel(new BorderLayout()),
+            bjp = new JPanel(new BorderLayout());
     bjo.add(jobOptions, BorderLayout.CENTER);
     bjp.add(paramList, BorderLayout.CENTER);
     bjp.setOpaque(true);
@@ -532,8 +535,8 @@ public class WsJobParameters extends JPanel implements ItemListener,
     List<ArgumentI> jobArgset = null;
     settingDialog = true;
     { // instantiate the abstract proxy for Jaba objects
-      jobArgset = jabajobArgset == null ? null : JabaParamStore
-              .getJwsArgsfromJaba(jabajobArgset);
+      jobArgset = jabajobArgset == null ? null
+              : JabaParamStore.getJwsArgsfromJaba(jabajobArgset);
       p = jabap; // (jabap != null) ? paramStore.getPreset(jabap.getName()) :
                  // null;
     }
@@ -716,7 +719,8 @@ public class WsJobParameters extends JPanel implements ItemListener,
 
   private void updateButtonDisplay()
   {
-    boolean _update = false, _create = false, _delete = false, _revert = false;
+    boolean _update = false, _create = false, _delete = false,
+            _revert = false;
     if (modifiedElements.size() > 0)
     {
       // set modified
@@ -787,8 +791,8 @@ public class WsJobParameters extends JPanel implements ItemListener,
     boolean stn = settingDialog;
     boolean renamed = false;
     settingDialog = true;
-    String nm = (curSetName != null ? curSetName : (String) setName
-            .getSelectedItem());
+    String nm = (curSetName != null ? curSetName
+            : (String) setName.getSelectedItem());
     // check if the name is reserved - if it is, rename it.
     if (isServicePreset(nm))
     {
@@ -841,10 +845,10 @@ public class WsJobParameters extends JPanel implements ItemListener,
     FlowLayout fl = new FlowLayout(FlowLayout.LEFT);
     int sep = fl.getVgap();
     boolean fh = true;
-    int os = 0, s = jobOptions.getBorder().getBorderInsets(jobOptions).bottom
-            + jobOptions.getBorder().getBorderInsets(jobOptions).top
-            + 2
-            * sep;
+    int os = 0,
+            s = jobOptions.getBorder().getBorderInsets(jobOptions).bottom
+                    + jobOptions.getBorder().getBorderInsets(jobOptions).top
+                    + 2 * sep;
     /**
      * final height for viewport
      */
@@ -853,8 +857,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
             - jobOptions.getBorder().getBorderInsets(jobOptions).left
             + jobOptions.getBorder().getBorderInsets(jobOptions).right;
 
-    int w = 2
-            * fl.getHgap()
+    int w = 2 * fl.getHgap()
             + (MAX_OPTWIDTH > OptsAndParamsPage.PARAM_WIDTH ? MAX_OPTWIDTH
                     : OptsAndParamsPage.PARAM_WIDTH);
     int hgap = fl.getHgap(), cw = hgap;
@@ -1021,8 +1024,8 @@ public class WsJobParameters extends JPanel implements ItemListener,
             }
             {
               System.out.println("Testing opts dupes for "
-                      + lastserv.getUri() + " : "
-                      + lastserv.getActionText() + ":" + pr.getName());
+                      + lastserv.getUri() + " : " + lastserv.getActionText()
+                      + ":" + pr.getName());
               List<Option> rg = lastserv.getRunnerConfig().getOptions();
               for (Option o : rg)
               {
@@ -1076,28 +1079,28 @@ public class WsJobParameters extends JPanel implements ItemListener,
                                 lastserv.getRunnerConfig(), " ");
                 readparam = jalview.ws.jws2.ParameterUtils
                         .writeParameterSet(pset, " ");
-                Iterator<String> o = pr.getOptions().iterator(), s = writeparam
-                        .iterator(), t = readparam.iterator();
+                Iterator<String> o = pr.getOptions().iterator(),
+                        s = writeparam.iterator(), t = readparam.iterator();
                 boolean failed = false;
                 while (s.hasNext() && t.hasNext())
                 {
                   String on = o.next(), sn = s.next(), st = t.next();
                   if (!sn.equals(st))
                   {
-                    System.out.println("Original was " + on
-                            + " Phase 1 wrote " + sn + "\tPhase 2 wrote "
-                            + st);
+                    System.out.println(
+                            "Original was " + on + " Phase 1 wrote " + sn
+                                    + "\tPhase 2 wrote " + st);
                     failed = true;
                   }
                 }
                 if (failed)
                 {
-                  System.out.println("Original parameters:\n"
-                          + pr.getOptions());
-                  System.out.println("Wrote parameters in first set:\n"
-                          + writeparam);
-                  System.out.println("Wrote parameters in second set:\n"
-                          + readparam);
+                  System.out.println(
+                          "Original parameters:\n" + pr.getOptions());
+                  System.out.println(
+                          "Wrote parameters in first set:\n" + writeparam);
+                  System.out.println(
+                          "Wrote parameters in second set:\n" + readparam);
 
                 }
               } catch (Exception e)
@@ -1107,9 +1110,9 @@ public class WsJobParameters extends JPanel implements ItemListener,
             }
             WsJobParameters pgui = new WsJobParameters(lastserv,
                     new JabaPreset(lastserv, pr));
-            JFrame jf = new JFrame(MessageManager.formatMessage(
-                    "label.ws_parameters_for",
-                    new String[] { lastserv.getActionText() }));
+            JFrame jf = new JFrame(MessageManager
+                    .formatMessage("label.ws_parameters_for", new String[]
+                    { lastserv.getActionText() }));
             JPanel cont = new JPanel(new BorderLayout());
             pgui.validate();
             cont.setPreferredSize(pgui.getPreferredSize());
@@ -1191,8 +1194,8 @@ public class WsJobParameters extends JPanel implements ItemListener,
 
   public boolean isServiceDefaults()
   {
-    return (!isModified() && (lastParmSet != null && lastParmSet
-            .equals(SVC_DEF)));
+    return (!isModified()
+            && (lastParmSet != null && lastParmSet.equals(SVC_DEF)));
   }
 
   public List<ArgumentI> getJobParams()
@@ -1372,14 +1375,10 @@ public class WsJobParameters extends JPanel implements ItemListener,
       }
       settingDialog = true;
       System.out.println("Prompting to save " + lsetname);
-      if (JvOptionPane
-              .showConfirmDialog(
-                      this,
-                      "Parameter set '"
-                              + lsetname
-                              + "' is modifed, and your changes will be lost.\nReally change preset ?",
-                      "Warning: Unsaved Changes",
-                      JvOptionPane.OK_CANCEL_OPTION) != JvOptionPane.OK_OPTION)
+      if (JvOptionPane.showConfirmDialog(this, "Parameter set '" + lsetname
+              + "' is modifed, and your changes will be lost.\nReally change preset ?",
+              "Warning: Unsaved Changes",
+              JvOptionPane.OK_CANCEL_OPTION) != JvOptionPane.OK_OPTION)
       {
         // revert the combobox to the current item
         settingDialog = true;
@@ -1455,8 +1454,9 @@ public class WsJobParameters extends JPanel implements ItemListener,
             @Override
             public void run()
             {
-              JvOptionPane.showMessageDialog(ourframe, MessageManager
-                      .getString("label.invalid_name_preset_exists"),
+              JvOptionPane.showMessageDialog(ourframe,
+                      MessageManager.getString(
+                              "label.invalid_name_preset_exists"),
                       MessageManager.getString("label.invalid_name"),
                       JvOptionPane.WARNING_MESSAGE);
             }
@@ -1486,9 +1486,9 @@ public class WsJobParameters extends JPanel implements ItemListener,
     if (!settingDialog)
     {
 
-      argSetModified(
-              setDescr,
-              (lastDescrText == null ? setDescr.getText().trim().length() > 0
+      argSetModified(setDescr,
+              (lastDescrText == null
+                      ? setDescr.getText().trim().length() > 0
                       : !setDescr.getText().equals(lastDescrText)));
 
     }
index 1aa0803..d91775c 100644 (file)
@@ -84,8 +84,8 @@ public class WsParamSetManager implements ParamManager
           {
             add = true;
           }
-          add &= (modifiable == p.isModifiable() || unmodifiable == !p
-                  .isModifiable());
+          add &= (modifiable == p.isModifiable()
+                  || unmodifiable == !p.isModifiable());
           add &= name == null || p.getName().equals(name);
 
           if (add)
@@ -97,11 +97,9 @@ public class WsParamSetManager implements ParamManager
         }
       } catch (IOException e)
       {
-        Cache.log
-                .info("Failed to parse parameter file "
-                        + pfile
-                        + " (Check that all JALVIEW_WSPARAMFILES entries are valid!)",
-                        e);
+        Cache.log.info("Failed to parse parameter file " + pfile
+                + " (Check that all JALVIEW_WSPARAMFILES entries are valid!)",
+                e);
       }
     }
     return params.toArray(new WsParamSetI[0]);
@@ -177,9 +175,8 @@ public class WsParamSetManager implements ParamManager
     }
     if (parser == null)
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_error_cannot_find_marshaller_for_param_set"));
+      throw new Error(MessageManager.getString(
+              "error.implementation_error_cannot_find_marshaller_for_param_set"));
     }
     if (filename == null)
     {
@@ -193,8 +190,8 @@ public class WsParamSetManager implements ParamManager
       if (value == JalviewFileChooser.APPROVE_OPTION)
       {
         outfile = chooser.getSelectedFile();
-        jalview.bin.Cache
-                .setProperty("LAST_DIRECTORY", outfile.getParent());
+        jalview.bin.Cache.setProperty("LAST_DIRECTORY",
+                outfile.getParent());
         filename = outfile.getAbsolutePath();
         if (!filename.endsWith(".wsparams"))
         {
@@ -225,8 +222,8 @@ public class WsParamSetManager implements ParamManager
       paramxml.setVersion("1.0");
       try
       {
-        paramxml.setParameters(parser
-                .generateServiceParameterFile(parameterSet));
+        paramxml.setParameters(
+                parser.generateServiceParameterFile(parameterSet));
         PrintWriter out = new PrintWriter(new OutputStreamWriter(
                 new FileOutputStream(outfile), "UTF-8"));
         paramxml.marshal(out);
@@ -299,9 +296,9 @@ public class WsParamSetManager implements ParamManager
       }
     } catch (Exception e)
     {
-      Cache.log
-              .error("Exception when trying to delete webservice user preset: ",
-                      e);
+      Cache.log.error(
+              "Exception when trying to delete webservice user preset: ",
+              e);
     }
   }
 
index 32671d5..850ef21 100644 (file)
@@ -89,20 +89,20 @@ public class WsPreferences extends GWsPreferences
       rsbsUrls = new Vector<String>();
     }
     updateRsbsList();
-    enableEnfinServices.setSelected(oldEnfin = Cache.getDefault(
-            "SHOW_ENFIN_SERVICES", true));
+    enableEnfinServices.setSelected(
+            oldEnfin = Cache.getDefault("SHOW_ENFIN_SERVICES", true));
     enableEnfinServices.addActionListener(updateAction);
-    enableJws2Services.setSelected(oldJws2 = Cache.getDefault(
-            "SHOW_JWS2_SERVICES", true));
+    enableJws2Services.setSelected(
+            oldJws2 = Cache.getDefault("SHOW_JWS2_SERVICES", true));
     enableJws2Services.addActionListener(updateAction);
-    indexByHost.setSelected(oldIndexByHost = Cache.getDefault(
-            "WSMENU_BYHOST", false));
+    indexByHost.setSelected(
+            oldIndexByHost = Cache.getDefault("WSMENU_BYHOST", false));
     indexByHost.addActionListener(updateAction);
-    indexByType.setSelected(oldIndexByType = Cache.getDefault(
-            "WSMENU_BYTYPE", false));
+    indexByType.setSelected(
+            oldIndexByType = Cache.getDefault("WSMENU_BYTYPE", false));
     indexByType.addActionListener(updateAction);
-    displayWsWarning.setSelected(oldWsWarning = Cache.getDefault(
-            "SHOW_WSDISCOVERY_ERRORS", true));
+    displayWsWarning.setSelected(oldWsWarning = Cache
+            .getDefault("SHOW_WSDISCOVERY_ERRORS", true));
   }
 
   ActionListener updateAction = new ActionListener()
@@ -128,12 +128,12 @@ public class WsPreferences extends GWsPreferences
     }
 
     wsList.setModel(new WsUrlTableModel(tdat));
-    wsList.getColumn(MessageManager.getString("label.status")).setMinWidth(
-            10);
+    wsList.getColumn(MessageManager.getString("label.status"))
+            .setMinWidth(10);
   }
 
-  private class JabaWSStatusRenderer extends JPanel implements
-          TableCellRenderer
+  private class JabaWSStatusRenderer extends JPanel
+          implements TableCellRenderer
   {
     public JabaWSStatusRenderer()
     {
@@ -353,16 +353,14 @@ public class WsPreferences extends GWsPreferences
   {
     if (old)
     {
-      if (oldUrls != wsUrls
-              || (wsUrls != null && oldUrls != null && !wsUrls
-                      .equals(oldUrls)))
+      if (oldUrls != wsUrls || (wsUrls != null && oldUrls != null
+              && !wsUrls.equals(oldUrls)))
       {
         update++;
       }
       wsUrls = (oldUrls == null) ? null : new Vector(oldUrls);
-      if (oldRsbsUrls != rsbsUrls
-              || (rsbsUrls != null && oldRsbsUrls != null && !oldRsbsUrls
-                      .equals(rsbsUrls)))
+      if (oldRsbsUrls != rsbsUrls || (rsbsUrls != null
+              && oldRsbsUrls != null && !oldRsbsUrls.equals(rsbsUrls)))
       {
         update++;
       }
@@ -372,26 +370,21 @@ public class WsPreferences extends GWsPreferences
     {
 
     }
-    Cache.setProperty(
-            "SHOW_ENFIN_SERVICES",
+    Cache.setProperty("SHOW_ENFIN_SERVICES",
             Boolean.valueOf(
                     old ? oldEnfin : enableEnfinServices.isSelected())
                     .toString());
-    Cache.setProperty(
-            "SHOW_JWS2_SERVICES",
+    Cache.setProperty("SHOW_JWS2_SERVICES",
             Boolean.valueOf(old ? oldJws2 : enableJws2Services.isSelected())
                     .toString());
-    Cache.setProperty(
-            "WSMENU_BYHOST",
+    Cache.setProperty("WSMENU_BYHOST",
             Boolean.valueOf(old ? oldIndexByHost : indexByHost.isSelected())
                     .toString());
-    Cache.setProperty(
-            "WSMENU_BYTYPE",
+    Cache.setProperty("WSMENU_BYTYPE",
             Boolean.valueOf(old ? oldIndexByType : indexByType.isSelected())
                     .toString());
 
-    Cache.setProperty(
-            "SHOW_WSDISCOVERY_ERRORS",
+    Cache.setProperty("SHOW_WSDISCOVERY_ERRORS",
             Boolean.valueOf(
                     old ? oldWsWarning : displayWsWarning.isSelected())
                     .toString());
@@ -460,10 +453,9 @@ public class WsPreferences extends GWsPreferences
     panel.add(pane12, BorderLayout.NORTH);
     boolean valid = false;
     int resp = JvOptionPane.CANCEL_OPTION;
-    while (!valid
-            && (resp = JvOptionPane.showInternalConfirmDialog(
-                    Desktop.desktop, panel, title,
-                    JvOptionPane.OK_CANCEL_OPTION)) == JvOptionPane.OK_OPTION)
+    while (!valid && (resp = JvOptionPane.showInternalConfirmDialog(
+            Desktop.desktop, panel, title,
+            JvOptionPane.OK_CANCEL_OPTION)) == JvOptionPane.OK_OPTION)
     {
       try
       {
@@ -499,26 +491,20 @@ public class WsPreferences extends GWsPreferences
         }
         else
         {
-          int opt = JvOptionPane
-                  .showInternalOptionDialog(
-                          Desktop.desktop,
-                          "The Server  '"
-                                  + foo.toString()
-                                  + "' failed validation,\ndo you want to add it anyway? ",
-                          "Server Validation Failed",
-                          JvOptionPane.YES_NO_OPTION,
-                          JvOptionPane.INFORMATION_MESSAGE, null, null, null);
+          int opt = JvOptionPane.showInternalOptionDialog(Desktop.desktop,
+                  "The Server  '" + foo.toString()
+                          + "' failed validation,\ndo you want to add it anyway? ",
+                  "Server Validation Failed", JvOptionPane.YES_NO_OPTION,
+                  JvOptionPane.INFORMATION_MESSAGE, null, null, null);
           if (opt == JvOptionPane.YES_OPTION)
           {
             return foo.toString();
           }
           else
           {
-            JvOptionPane
-                    .showInternalMessageDialog(
-                            Desktop.desktop,
-                            MessageManager
-                                    .getString("warn.server_didnt_pass_validation"));
+            JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                    MessageManager.getString(
+                            "warn.server_didnt_pass_validation"));
           }
 
         }
index ecc8d99..ece2df0 100644 (file)
@@ -74,8 +74,8 @@ public abstract class AbstractRequestHandler extends AbstractHandler
         /*
          * Can't write an HTTP header once any response content has been written
          */
-        System.err
-                .println("Unable to return HTTP 500 as response already committed");
+        System.err.println(
+                "Unable to return HTTP 500 as response already committed");
       }
       else
       {
@@ -143,8 +143,8 @@ public abstract class AbstractRequestHandler extends AbstractHandler
       stop();
     } catch (Exception e)
     {
-      System.err.println("Error stopping " + getName() + ": "
-              + e.getMessage());
+      System.err.println(
+              "Error stopping " + getName() + ": " + e.getMessage());
     }
   }
 
index 134123b..a18d38d 100644 (file)
@@ -156,8 +156,8 @@ public class HttpServer
       contextRoot = server.getURI();
     } catch (Exception e)
     {
-      System.err.println("Error trying to start HttpServer: "
-              + e.getMessage());
+      System.err.println(
+              "Error trying to start HttpServer: " + e.getMessage());
       try
       {
         server.stop();
@@ -267,8 +267,8 @@ public class HttpServer
       ch.start();
     } catch (Exception e)
     {
-      System.err.println("Error starting handler for " + path + ": "
-              + e.getMessage());
+      System.err.println(
+              "Error starting handler for " + path + ": " + e.getMessage());
     }
 
     handler.setUri(this.contextRoot + ch.getContextPath().substring(1));
index 7333075..2340283 100755 (executable)
@@ -40,8 +40,8 @@ import java.util.Vector;
  * @author $author$
  * @version $Revision$
  */
-public abstract class AlignFile extends FileParse implements
-        AlignmentFileReaderI, AlignmentFileWriterI
+public abstract class AlignFile extends FileParse
+        implements AlignmentFileReaderI, AlignmentFileWriterI
 {
   int noSeqs = 0;
 
@@ -118,8 +118,7 @@ public abstract class AlignFile extends FileParse implements
    * @throws IOException
    */
   public AlignFile(boolean parseImmediately, String dataObject,
-          DataSourceType sourceType)
-          throws IOException
+          DataSourceType sourceType) throws IOException
   {
     super(dataObject, sourceType);
     initData();
@@ -175,11 +174,6 @@ public abstract class AlignFile extends FileParse implements
     }
     parseCalled = true;
     parse();
-    // sets the index of each sequence in the alignment
-    for (int i = 0, c = seqs.size(); i < c; i++)
-    {
-      seqs.get(i).setIndex(i);
-    }
   }
 
   /**
@@ -282,9 +276,8 @@ public abstract class AlignFile extends FileParse implements
   {
     if (key == null)
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_error_cannot_have_null_alignment"));
+      throw new Error(MessageManager.getString(
+              "error.implementation_error_cannot_have_null_alignment"));
     }
     if (value == null)
     {
index 77a7643..a471d9b 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.io;
 
 import jalview.api.AlignExportSettingI;
index d8e2dd4..6af4d1e 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.io;
 
 import jalview.api.AlignExportSettingI;
index b669ee5..00476d6 100755 (executable)
@@ -100,7 +100,8 @@ public class AnnotationFile
   public String printAnnotations(AlignmentAnnotation[] annotations,
           List<SequenceGroup> list, Hashtable properties)
   {
-    return printAnnotations(annotations, list, properties, null, null, null);
+    return printAnnotations(annotations, list, properties, null, null,
+            null);
 
   }
 
@@ -119,8 +120,8 @@ public class AnnotationFile
 
     public final Hashtable hiddenRepSeqs;
 
-    public ViewDef(String vname, HiddenSequences hseqs,
-            HiddenColumns hcols, Hashtable hRepSeqs)
+    public ViewDef(String vname, HiddenSequences hseqs, HiddenColumns hcols,
+            Hashtable hRepSeqs)
     {
       this.viewname = vname;
       this.hidseqs = hseqs;
@@ -140,8 +141,7 @@ public class AnnotationFile
    * @return annotation file
    */
   public String printAnnotations(AlignmentAnnotation[] annotations,
-          List<SequenceGroup> list, Hashtable properties,
- HiddenColumns cs,
+          List<SequenceGroup> list, Hashtable properties, HiddenColumns cs,
           AlignmentI al, ViewDef view)
   {
     if (view != null)
@@ -199,10 +199,8 @@ public class AnnotationFile
       {
         row = annotations[i];
 
-        if (!row.visible
-                && !row.hasScore()
-                && !(row.graphGroup > -1 && graphGroupSeen
-                        .get(row.graphGroup)))
+        if (!row.visible && !row.hasScore() && !(row.graphGroup > -1
+                && graphGroupSeen.get(row.graphGroup)))
         {
           continue;
         }
@@ -217,7 +215,8 @@ public class AnnotationFile
         writeGroup_Ref(refGroup, row.groupRef);
         refGroup = row.groupRef;
 
-        boolean hasGlyphs = row.hasIcons, hasLabels = row.hasText, hasValues = row.hasScore, hasText = false;
+        boolean hasGlyphs = row.hasIcons, hasLabels = row.hasText,
+                hasValues = row.hasScore, hasText = false;
         // lookahead to check what the annotation row object actually contains.
         for (int j = 0; row.annotations != null
                 && j < row.annotations.length
@@ -226,14 +225,15 @@ public class AnnotationFile
           if (row.annotations[j] != null)
           {
             hasLabels |= (row.annotations[j].displayCharacter != null
-                    && row.annotations[j].displayCharacter.length() > 0 && !row.annotations[j].displayCharacter
-                    .equals(" "));
-            hasGlyphs |= (row.annotations[j].secondaryStructure != 0 && row.annotations[j].secondaryStructure != ' ');
+                    && row.annotations[j].displayCharacter.length() > 0
+                    && !row.annotations[j].displayCharacter.equals(" "));
+            hasGlyphs |= (row.annotations[j].secondaryStructure != 0
+                    && row.annotations[j].secondaryStructure != ' ');
             hasValues |= (!Float.isNaN(row.annotations[j].value)); // NaNs can't
             // be
             // rendered..
-            hasText |= (row.annotations[j].description != null && row.annotations[j].description
-                    .length() > 0);
+            hasText |= (row.annotations[j].description != null
+                    && row.annotations[j].description.length() > 0);
           }
         }
 
@@ -266,8 +266,8 @@ public class AnnotationFile
             graphLine.append("\t");
             graphLine.append(row.getThreshold().label);
             graphLine.append("\t");
-            graphLine.append(jalview.util.Format.getHexString(row
-                    .getThreshold().colour));
+            graphLine.append(jalview.util.Format
+                    .getHexString(row.getThreshold().colour));
             graphLine.append(newline);
           }
 
@@ -362,11 +362,8 @@ public class AnnotationFile
             if (row.annotations[j].colour != null
                     && row.annotations[j].colour != java.awt.Color.black)
             {
-              text.append(comma
-                      + "["
-                      + jalview.util.Format
-                              .getHexString(row.annotations[j].colour)
-                      + "]");
+              text.append(comma + "[" + jalview.util.Format
+                      .getHexString(row.annotations[j].colour) + "]");
               comma = ",";
             }
           }
@@ -418,8 +415,8 @@ public class AnnotationFile
         for (Map.Entry<Integer, String> combine_statement : graphGroup
                 .entrySet())
         {
-          Object[] seqRefAndGroup = graphGroup_refs.get(combine_statement
-                  .getKey());
+          Object[] seqRefAndGroup = graphGroup_refs
+                  .get(combine_statement.getKey());
 
           writeSequence_Ref(refSeq, (SequenceI) seqRefAndGroup[0]);
           refSeq = (SequenceI) seqRefAndGroup[0];
@@ -570,8 +567,8 @@ public class AnnotationFile
       if (sg.cs != null)
       {
         text.append("colour=");
-        text.append(ColourSchemeProperty.getColourName(sg.cs
-                .getColourScheme()));
+        text.append(ColourSchemeProperty
+                .getColourName(sg.cs.getColourScheme()));
         text.append("\t");
         if (sg.cs.getThreshold() != 0)
         {
@@ -649,8 +646,8 @@ public class AnnotationFile
 
   String refSeqId = null;
 
-  public boolean annotateAlignmentView(AlignViewportI viewport,
-          String file, DataSourceType protocol)
+  public boolean annotateAlignmentView(AlignViewportI viewport, String file,
+          DataSourceType protocol)
   {
     ColumnSelection colSel = viewport.getColumnSelection();
     HiddenColumns hidden = viewport.getAlignment().getHiddenColumns();
@@ -662,8 +659,8 @@ public class AnnotationFile
     {
       hidden = new HiddenColumns();
     }
-    boolean rslt = readAnnotationFile(viewport.getAlignment(), hidden,
-            file, protocol);
+    boolean rslt = readAnnotationFile(viewport.getAlignment(), hidden, file,
+            protocol);
     if (rslt && (colSel.hasSelectedColumns() || hidden.hasHiddenColumns()))
     {
       viewport.setColumnSelection(colSel);
@@ -717,8 +714,8 @@ public class AnnotationFile
       System.out.println("Problem reading annotation file: " + ex);
       if (nlinesread > 0)
       {
-        System.out.println("Last read line " + nlinesread + ": '"
-                + lastread + "' (first 80 chars) ...");
+        System.out.println("Last read line " + nlinesread + ": '" + lastread
+                + "' (first 80 chars) ...");
       }
       return false;
     }
@@ -826,7 +823,8 @@ public class AnnotationFile
         {
           // keep a record of current state and resolve groupRef at end
           combineAnnotation_calls
-                  .add(new Object[] { st, refSeq, groupRef });
+                  .add(new Object[]
+                  { st, refSeq, groupRef });
           modified = true;
           continue;
         }
@@ -839,8 +837,9 @@ public class AnnotationFile
         else if (token.equalsIgnoreCase(GRAPHLINE))
         {
           // resolve at end
-          deferredAnnotation_calls.add(new Object[] { GRAPHLINE, st,
-              refSeq, groupRef });
+          deferredAnnotation_calls
+                  .add(new Object[]
+                  { GRAPHLINE, st, refSeq, groupRef });
           modified = true;
           continue;
         }
@@ -860,8 +859,8 @@ public class AnnotationFile
               if (refSeqIndex < 1)
               {
                 refSeqIndex = 1;
-                System.out
-                        .println("WARNING: SEQUENCE_REF index must be > 0 in AnnotationFile");
+                System.out.println(
+                        "WARNING: SEQUENCE_REF index must be > 0 in AnnotationFile");
               }
             } catch (Exception ex)
             {
@@ -962,8 +961,8 @@ public class AnnotationFile
           {
             if (hidden == null)
             {
-              System.err
-                      .println("Cannot process HIDE_INSERTIONS without an alignment view: Ignoring line: "
+              System.err.println(
+                      "Cannot process HIDE_INSERTIONS without an alignment view: Ignoring line: "
                               + line);
             }
             else
@@ -1046,9 +1045,8 @@ public class AnnotationFile
                 (index == 0) ? null : annotations, 0, 0, graphStyle);
 
         annotation.score = score;
-        if (!overrideAutoAnnot
-                && autoAnnots.containsKey(autoAnnotsKey(annotation, refSeq,
-                        groupRef)))
+        if (!overrideAutoAnnot && autoAnnots
+                .containsKey(autoAnnotsKey(annotation, refSeq, groupRef)))
         {
           // skip - we've already got an automatic annotation of this type.
           continue;
@@ -1066,14 +1064,14 @@ public class AnnotationFile
             // TODO: verify that undo/redo with 1:many sequence associated
             // annotations can be undone correctly
             AlignmentAnnotation ann = new AlignmentAnnotation(annotation);
-            annotation
-                    .createSequenceMapping(referedSeq, refSeqIndex, false);
+            annotation.createSequenceMapping(referedSeq, refSeqIndex,
+                    false);
             annotation.adjustForAlignment();
             referedSeq.addAlignmentAnnotation(annotation);
             al.addAnnotation(annotation);
             al.setAnnotationIndex(annotation,
-                    al.getAlignmentAnnotation().length
-                            - existingAnnotations - 1);
+                    al.getAlignmentAnnotation().length - existingAnnotations
+                            - 1);
             if (groupRef != null)
             {
               ((Vector) groupRefRows.get(groupRef)).addElement(annotation);
@@ -1081,8 +1079,8 @@ public class AnnotationFile
             // and recover our virgin copy to use again if necessary.
             annotation = ann;
 
-          } while (refSeqId != null
-                  && (referedSeq = al.findName(referedSeq, refSeqId, true)) != null);
+          } while (refSeqId != null && (referedSeq = al.findName(referedSeq,
+                  refSeqId, true)) != null);
         }
         else
         {
@@ -1115,8 +1113,8 @@ public class AnnotationFile
             {
               // TODO: specify and implement duplication of alignment annotation
               // for multiple group references.
-              System.err
-                      .println("Ignoring 1:many group reference mappings for group name '"
+              System.err.println(
+                      "Ignoring 1:many group reference mappings for group name '"
                               + groupRef + "'");
             }
             else
@@ -1127,7 +1125,8 @@ public class AnnotationFile
               if (rowset != null && rowset.size() > 0)
               {
                 AlignmentAnnotation alan = null;
-                for (int elm = 0, elmSize = rowset.size(); elm < elmSize; elm++)
+                for (int elm = 0, elmSize = rowset
+                        .size(); elm < elmSize; elm++)
                 {
                   alan = (AlignmentAnnotation) rowset.elementAt(elm);
                   alan.groupRef = theGroup;
@@ -1143,12 +1142,13 @@ public class AnnotationFile
       {
         if (_deferred_args[0] == GRAPHLINE)
         {
-          addLine(al,
-                  (StringTokenizer) _deferred_args[1], // st
+          addLine(al, (StringTokenizer) _deferred_args[1], // st
                   (SequenceI) _deferred_args[2], // refSeq
-                  (_deferred_args[3] == null) ? null : groupRefLookup
-                          .get(_deferred_args[3]) // the reference
-                                                  // group, or null
+                  (_deferred_args[3] == null) ? null
+                          : groupRefLookup.get(_deferred_args[3]) // the
+                                                                  // reference
+                                                                  // group, or
+                                                                  // null
           );
         }
       }
@@ -1162,13 +1162,13 @@ public class AnnotationFile
       int combinecount = 0;
       for (Object[] _combine_args : combineAnnotation_calls)
       {
-        combineAnnotations(al,
-                ++combinecount,
+        combineAnnotations(al, ++combinecount,
                 (StringTokenizer) _combine_args[0], // st
                 (SequenceI) _combine_args[1], // refSeq
-                (_combine_args[2] == null) ? null : groupRefLookup
-                        .get(_combine_args[2]) // the reference group,
-                                               // or null
+                (_combine_args[2] == null) ? null
+                        : groupRefLookup.get(_combine_args[2]) // the reference
+                                                               // group,
+                                                               // or null
         );
       }
     }
@@ -1232,8 +1232,7 @@ public class AnnotationFile
     int j = string.indexOf("]");
     if (i > -1 && j > -1)
     {
-      colour = ColorUtils.parseColourString(string.substring(i + 1,
-              j));
+      colour = ColorUtils.parseColourString(string.substring(i + 1, j));
       if (i > 0 && string.charAt(i - 1) == ',')
       {
         // clip the preceding comma as well
@@ -1286,8 +1285,8 @@ public class AnnotationFile
           displayChar = token;
         }
       }
-      if (hasSymbols
-              && (token.length() == 1 && "()<>[]{}AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"
+      if (hasSymbols && (token.length() == 1
+              && "()<>[]{}AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"
                       .contains(token)))
       {
         // Either this character represents a helix or sheet
@@ -1407,8 +1406,8 @@ public class AnnotationFile
     }
     else
     {
-      System.err
-              .println("Couldn't combine annotations. None are added to alignment yet!");
+      System.err.println(
+              "Couldn't combine annotations. None are added to alignment yet!");
     }
   }
 
@@ -1474,8 +1473,8 @@ public class AnnotationFile
       }
     } catch (Exception e)
     {
-      System.err
-              .println("Couldn't parse Group Start or End Field as '*' or a valid column or sequence index: '"
+      System.err.println(
+              "Couldn't parse Group Start or End Field as '*' or a valid column or sequence index: '"
                       + rng + "' - assuming alignment width for group.");
       // assume group is full width
       sg.setStartRes(0);
@@ -1521,7 +1520,8 @@ public class AnnotationFile
         }
         else
         {
-          sg.addSequence(al.getSequenceAt(Integer.parseInt(tmp) - 1), false);
+          sg.addSequence(al.getSequenceAt(Integer.parseInt(tmp) - 1),
+                  false);
         }
       }
     }
@@ -1617,8 +1617,8 @@ public class AnnotationFile
         }
         else if (key.equalsIgnoreCase("colour"))
         {
-          sg.cs.setColourScheme(ColourSchemeProperty
-                  .getColourScheme(al, value));
+          sg.cs.setColourScheme(
+                  ColourSchemeProperty.getColourScheme(al, value));
         }
         else if (key.equalsIgnoreCase("pidThreshold"))
         {
@@ -1699,8 +1699,8 @@ public class AnnotationFile
     AlignmentAnnotation aa, ala[] = al.getAlignmentAnnotation();
     if (ala == null)
     {
-      System.err
-              .print("Warning - no annotation to set below for sequence associated annotation:");
+      System.err.print(
+              "Warning - no annotation to set below for sequence associated annotation:");
     }
     while (st.hasMoreTokens())
     {
@@ -1779,10 +1779,13 @@ public class AnnotationFile
 
   public String printAnnotationsForView(AlignViewportI viewport)
   {
-    return printAnnotations(viewport.isShowAnnotation() ? viewport
-            .getAlignment().getAlignmentAnnotation() : null, viewport
-            .getAlignment().getGroups(), viewport.getAlignment()
-            .getProperties(), viewport.getAlignment().getHiddenColumns(),
+    return printAnnotations(
+            viewport.isShowAnnotation()
+                    ? viewport.getAlignment().getAlignmentAnnotation()
+                    : null,
+            viewport.getAlignment().getGroups(),
+            viewport.getAlignment().getProperties(),
+            viewport.getAlignment().getHiddenColumns(),
             viewport.getAlignment(), null);
   }
 
index 907ff46..5e209e6 100755 (executable)
@@ -85,8 +85,9 @@ public class AppletFormatAdapter
   public static String getSupportedFormats()
   {
     return "Formats currently supported are\n"
-          + prettyPrint(FileFormats.getInstance().getReadableFormats());
+            + prettyPrint(FileFormats.getInstance().getReadableFormats());
   }
+
   public AppletFormatAdapter()
   {
   }
@@ -154,8 +155,8 @@ public class AppletFormatAdapter
         String structureParser = StructureImportSettings
                 .getDefaultPDBFileParser();
         boolean isParseWithJMOL = structureParser.equalsIgnoreCase(
-                        StructureImportSettings.StructureParser.JMOL_PARSER
-                                .toString());
+                StructureImportSettings.StructureParser.JMOL_PARSER
+                        .toString());
         StructureImportSettings.addSettings(annotFromStructure,
                 localSecondaryStruct, serviceSecondaryStruct);
         if (isParseWithJMOL)
@@ -170,21 +171,20 @@ public class AppletFormatAdapter
                   localSecondaryStruct, serviceSecondaryStruct, inFile,
                   sourceType);
         }
-        ((StructureFile) alignFile).setDbRefType(FileFormat.PDB
-                .equals(fileFormat) ? Type.PDB : Type.MMCIF);
+        ((StructureFile) alignFile).setDbRefType(
+                FileFormat.PDB.equals(fileFormat) ? Type.PDB : Type.MMCIF);
       }
       else
       {
         // alignFile = fileFormat.getAlignmentFile(inFile, sourceType);
-        alignFile = fileFormat.getReader(new FileParse(inFile,
-                sourceType));
+        alignFile = fileFormat.getReader(new FileParse(inFile, sourceType));
       }
       return buildAlignmentFromFile();
     } catch (Exception e)
     {
       e.printStackTrace();
-      System.err.println("Failed to read alignment using the '"
-              + fileFormat + "' reader.\n" + e);
+      System.err.println("Failed to read alignment using the '" + fileFormat
+              + "' reader.\n" + e);
 
       if (e.getMessage() != null
               && e.getMessage().startsWith(INVALID_CHARACTERS))
@@ -333,10 +333,10 @@ public class AppletFormatAdapter
           AlignmentViewPanel ap, boolean selectedOnly)
   {
 
-    AlignmentView selvew = ap.getAlignViewport().getAlignmentView(
-            selectedOnly, false);
-    AlignmentI aselview = selvew.getVisibleAlignment(ap.getAlignViewport()
-            .getGapCharacter());
+    AlignmentView selvew = ap.getAlignViewport()
+            .getAlignmentView(selectedOnly, false);
+    AlignmentI aselview = selvew
+            .getVisibleAlignment(ap.getAlignViewport().getGapCharacter());
     List<AlignmentAnnotation> ala = (ap.getAlignViewport()
             .getVisibleAlignmentAnnotation(selectedOnly));
     if (ala != null)
@@ -399,8 +399,7 @@ public class AppletFormatAdapter
     } catch (Exception e)
     {
       System.err.println("Failed to write alignment as a '"
-              + format.getName()
-              + "' file\n");
+              + format.getName() + "' file\n");
       e.printStackTrace();
     }
 
@@ -446,10 +445,9 @@ public class AppletFormatAdapter
           System.gc();
           long memf = -r.totalMemory() + r.freeMemory();
           long t1 = -System.currentTimeMillis();
-          AlignmentI al = afa
-                  .readFile(args[i], DataSourceType.FILE,
-                          new IdentifyFile().identify(args[i],
-                                  DataSourceType.FILE));
+          AlignmentI al = afa.readFile(args[i], DataSourceType.FILE,
+                  new IdentifyFile().identify(args[i],
+                          DataSourceType.FILE));
           t1 += System.currentTimeMillis();
           System.gc();
           memf += r.totalMemory() - r.freeMemory();
@@ -459,12 +457,12 @@ public class AppletFormatAdapter
                     + " sequences and " + al.getWidth() + " columns.");
             try
             {
-              System.out.println(new AppletFormatAdapter().formatSequences(
-                      FileFormat.Fasta, al, true));
+              System.out.println(new AppletFormatAdapter()
+                      .formatSequences(FileFormat.Fasta, al, true));
             } catch (Exception e)
             {
-              System.err
-                      .println("Couln't format the alignment for output as a FASTA file.");
+              System.err.println(
+                      "Couln't format the alignment for output as a FASTA file.");
               e.printStackTrace(System.err);
             }
           }
@@ -473,8 +471,8 @@ public class AppletFormatAdapter
             System.out.println("Couldn't read alignment");
           }
           System.out.println("Read took " + (t1 / 1000.0) + " seconds.");
-          System.out
-                  .println("Difference between free memory now and before is "
+          System.out.println(
+                  "Difference between free memory now and before is "
                           + (memf / (1024.0 * 1024.0) * 1.0) + " MB");
         } catch (Exception e)
         {
@@ -558,8 +556,8 @@ public class AppletFormatAdapter
     {
       if (debug)
       {
-        System.out.println("Trying to get contents of resource as "
-                + protocol + ":");
+        System.out.println(
+                "Trying to get contents of resource as " + protocol + ":");
       }
       fp = new FileParse(file, protocol);
       if (!fp.isValid())
index 6317e83..1b93892 100755 (executable)
@@ -246,10 +246,7 @@ public class BLCFile extends AlignFile
 
       out.append(newline);
 
-      if (s[i].getSequence().length > max)
-      {
-        max = s[i].getSequence().length;
-      }
+      max = Math.max(max, s[i].getLength());
 
       i++;
     }
index fd9c584..52ce845 100644 (file)
@@ -53,8 +53,7 @@ public class BioJsHTMLOutput extends HTMLOutput
           .getDefault("biojs_template_directory", DEFAULT_DIR);
 
   public static final String BJS_TEMPLATE_GIT_REPO = jalview.bin.Cache
-          .getDefault(
-                  "biojs_template_git_repo",
+          .getDefault("biojs_template_git_repo",
                   "https://raw.githubusercontent.com/jalview/exporter-templates/master/biojs/package.json");
 
   public BioJsHTMLOutput(AlignmentPanel ap)
@@ -80,8 +79,8 @@ public class BioJsHTMLOutput extends HTMLOutput
       return;
     } catch (Exception e)
     {
-      setProgressMessage(MessageManager.formatMessage(
-              "info.error_creating_file", "BioJS MSA"));
+      setProgressMessage(MessageManager
+              .formatMessage("info.error_creating_file", "BioJS MSA"));
       e.printStackTrace();
       return;
     }
@@ -89,8 +88,6 @@ public class BioJsHTMLOutput extends HTMLOutput
 
   }
 
-
-
   public static void refreshVersionInfo(String dirName)
           throws URISyntaxException
   {
@@ -133,7 +130,8 @@ public class BioJsHTMLOutput extends HTMLOutput
       {
         try
         {
-          String gitRepoPkgJson = getURLContentAsString(BJS_TEMPLATE_GIT_REPO);
+          String gitRepoPkgJson = getURLContentAsString(
+                  BJS_TEMPLATE_GIT_REPO);
           if (gitRepoPkgJson != null)
           {
             BioJSRepositoryPojo release = new BioJSRepositoryPojo(
@@ -235,8 +233,8 @@ public class BioJsHTMLOutput extends HTMLOutput
         }
       }
     }
-    return responseStrBuilder == null ? null : responseStrBuilder
-            .toString();
+    return responseStrBuilder == null ? null
+            : responseStrBuilder.toString();
   }
 
   public static File getCurrentBJSTemplateFile()
@@ -289,13 +287,13 @@ public class BioJsHTMLOutput extends HTMLOutput
       String generatedBioJsWithJalviewAlignmentAsJson = bioJSTemplateString
               .replaceAll("#sequenceData#", bioJSON).toString();
 
-      PrintWriter out = new java.io.PrintWriter(new java.io.FileWriter(
-              generatedFile));
+      PrintWriter out = new java.io.PrintWriter(
+              new java.io.FileWriter(generatedFile));
       out.print(generatedBioJsWithJalviewAlignmentAsJson);
       out.flush();
       out.close();
-      setProgressMessage(MessageManager.formatMessage(
-              "status.export_complete", "BioJS"));
+      setProgressMessage(MessageManager
+              .formatMessage("status.export_complete", "BioJS"));
       exportCompleted();
 
     } catch (OutOfMemoryError err)
@@ -305,8 +303,8 @@ public class BioJsHTMLOutput extends HTMLOutput
       new OOMWarning("Creating Image for " + generatedFile, err);
     } catch (Exception e)
     {
-      setProgressMessage(MessageManager.formatMessage(
-              "info.error_creating_file", "HTML"));
+      setProgressMessage(MessageManager
+              .formatMessage("info.error_creating_file", "HTML"));
       e.printStackTrace();
     }
 
index 5d58d42..c21b02c 100755 (executable)
@@ -61,7 +61,8 @@ public class ClustalFile extends AlignFile
     boolean flag = false;
     boolean rna = false;
     boolean top = false;
-    StringBuffer pssecstr = new StringBuffer(), consstr = new StringBuffer();
+    StringBuffer pssecstr = new StringBuffer(),
+            consstr = new StringBuffer();
     Vector headers = new Vector();
     Hashtable seqhash = new Hashtable();
     StringBuffer tempseq;
@@ -158,16 +159,15 @@ public class ClustalFile extends AlignFile
           }
 
           Sequence newSeq = parseId(headers.elementAt(i).toString());
-          newSeq.setSequence(seqhash.get(headers.elementAt(i).toString())
-                  .toString());
+          newSeq.setSequence(
+                  seqhash.get(headers.elementAt(i).toString()).toString());
 
           seqs.addElement(newSeq);
         }
         else
         {
-          System.err
-                  .println("Clustal File Reader: Can't find sequence for "
-                          + headers.elementAt(i));
+          System.err.println("Clustal File Reader: Can't find sequence for "
+                  + headers.elementAt(i));
         }
       }
       AlignmentAnnotation lastssa = null;
@@ -186,9 +186,8 @@ public class ClustalFile extends AlignFile
         AlignmentAnnotation ssa = StockholmFile.parseAnnotationRow(ss,
                 "secondary structure", consstr.toString());
         ssa.label = "Consensus Secondary Structure";
-        if (lastssa == null
-                || !lastssa.getRNAStruc().equals(
-                        ssa.getRNAStruc().replace('-', '.')))
+        if (lastssa == null || !lastssa.getRNAStruc()
+                .equals(ssa.getRNAStruc().replace('-', '.')))
         {
           annotations.addElement(ssa);
         }
@@ -210,10 +209,7 @@ public class ClustalFile extends AlignFile
     {
       String tmp = printId(s[i], jvsuffix);
 
-      if (s[i].getSequence().length > max)
-      {
-        max = s[i].getSequence().length;
-      }
+      max = Math.max(max, s[i].getLength());
 
       if (tmp.length() > maxid)
       {
@@ -239,20 +235,20 @@ public class ClustalFile extends AlignFile
 
       while ((j < s.length) && (s[j] != null))
       {
-        out.append(new Format("%-" + maxid + "s").form(printId(s[j],
-                jvsuffix) + " "));
+        out.append(new Format("%-" + maxid + "s")
+                .form(printId(s[j], jvsuffix) + " "));
 
         int start = i * len;
         int end = start + len;
 
-        if ((end < s[j].getSequence().length)
-                && (start < s[j].getSequence().length))
+        int length = s[j].getLength();
+        if ((end < length) && (start < length))
         {
           out.append(s[j].getSequenceAsString(start, end));
         }
         else
         {
-          if (start < s[j].getSequence().length)
+          if (start < length)
           {
             out.append(s[j].getSequenceAsString().substring(start));
           }
index e2808e8..5d0c462 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.io;
 
 public enum DataSourceType
index da925e4..9acd7da 100755 (executable)
@@ -164,8 +164,8 @@ public class FastaFile extends AlignFile
         anots[i] = new Annotation("" + cn, null, ' ', Float.NaN);
       }
     }
-    AlignmentAnnotation aa = new AlignmentAnnotation(seq.getName()
-            .substring(2), seq.getDescription(), anots);
+    AlignmentAnnotation aa = new AlignmentAnnotation(
+            seq.getName().substring(2), seq.getDescription(), anots);
     return aa;
   }
 
index 48eeee3..d2282b1 100755 (executable)
@@ -44,8 +44,8 @@ import java.awt.Color;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -94,14 +94,14 @@ public class FeaturesFile extends AlignFile implements FeaturesSourceI
   /**
    * Constructor which does not parse the file immediately
    * 
-   * @param inFile
+   * @param file
    * @param paste
    * @throws IOException
    */
-  public FeaturesFile(String inFile, DataSourceType paste)
+  public FeaturesFile(String file, DataSourceType paste)
           throws IOException
   {
-    super(false, inFile, paste);
+    super(false, file, paste);
   }
 
   /**
@@ -117,15 +117,14 @@ public class FeaturesFile extends AlignFile implements FeaturesSourceI
    * Constructor that optionally parses the file immediately
    * 
    * @param parseImmediately
-   * @param inFile
+   * @param file
    * @param type
    * @throws IOException
    */
-  public FeaturesFile(boolean parseImmediately, String inFile,
-          DataSourceType type)
-          throws IOException
+  public FeaturesFile(boolean parseImmediately, String file,
+          DataSourceType type) throws IOException
   {
-    super(parseImmediately, inFile, type);
+    super(parseImmediately, file, type);
   }
 
   /**
@@ -282,7 +281,7 @@ public class FeaturesFile extends AlignFile implements FeaturesSourceI
      */
     for (SequenceI newseq : newseqs)
     {
-      if (newseq.getSequenceFeatures() != null)
+      if (newseq.getFeatures().hasFeatures())
       {
         align.addSequence(newseq);
       }
@@ -305,7 +304,8 @@ public class FeaturesFile extends AlignFile implements FeaturesSourceI
    */
   protected boolean parseJalviewFeature(String line, String[] gffColumns,
           AlignmentI alignment, Map<String, FeatureColourI> featureColours,
-          boolean removeHTML, boolean relaxedIdMatching, String featureGroup)
+          boolean removeHTML, boolean relaxedIdMatching,
+          String featureGroup)
   {
     /*
      * tokens: description seqid seqIndex start end type [score]
@@ -359,20 +359,23 @@ public class FeaturesFile extends AlignFile implements FeaturesSourceI
       Color colour = ColorUtils.createColourFromName(ft);
       featureColours.put(ft, new FeatureColour(colour));
     }
-    SequenceFeature sf = new SequenceFeature(ft, desc, "", startPos,
-            endPos, featureGroup);
+    SequenceFeature sf = null;
     if (gffColumns.length > 6)
     {
       float score = Float.NaN;
       try
       {
         score = new Float(gffColumns[6]).floatValue();
-        // update colourgradient bounds if allowed to
       } catch (NumberFormatException ex)
       {
-        // leave as NaN
+        sf = new SequenceFeature(ft, desc, startPos, endPos, featureGroup);
       }
-      sf.setScore(score);
+      sf = new SequenceFeature(ft, desc, startPos, endPos, score,
+              featureGroup);
+    }
+    else
+    {
+      sf = new SequenceFeature(ft, desc, startPos, endPos, featureGroup);
     }
 
     parseDescriptionHTML(sf, removeHTML);
@@ -472,219 +475,191 @@ public class FeaturesFile extends AlignFile implements FeaturesSourceI
     ParseHtmlBodyAndLinks parsed = new ParseHtmlBodyAndLinks(
             sf.getDescription(), removeHTML, newline);
 
-    sf.description = (removeHTML) ? parsed.getNonHtmlContent()
-            : sf.description;
+    if (removeHTML)
+    {
+      sf.setDescription(parsed.getNonHtmlContent());
+    }
+
     for (String link : parsed.getLinks())
     {
       sf.addLink(link);
     }
-
-  }
-
-  /**
-   * generate a features file for seqs includes non-pos features by default.
-   * 
-   * @param sequences
-   *          source of sequence features
-   * @param visible
-   *          hash of feature types and colours
-   * @return features file contents
-   */
-  public String printJalviewFormat(SequenceI[] sequences,
-          Map<String, FeatureColourI> visible)
-  {
-    return printJalviewFormat(sequences, visible, true, true);
   }
 
   /**
-   * generate a features file for seqs with colours from visible (if any)
+   * Returns contents of a Jalview format features file, for visible features,
+   * as filtered by type and group. Features with a null group are displayed if
+   * their feature type is visible. Non-positional features may optionally be
+   * included (with no check on type or group).
    * 
    * @param sequences
    *          source of features
    * @param visible
-   *          hash of Colours for each feature type
-   * @param visOnly
-   *          when true only feature types in 'visible' will be output
-   * @param nonpos
-   *          indicates if non-positional features should be output (regardless
-   *          of group or type)
-   * @return features file contents
+   *          map of colour for each visible feature type
+   * @param visibleFeatureGroups
+   * @param includeNonPositional
+   *          if true, include non-positional features (regardless of group or
+   *          type)
+   * @return
    */
   public String printJalviewFormat(SequenceI[] sequences,
-          Map<String, FeatureColourI> visible, boolean visOnly,
-          boolean nonpos)
+          Map<String, FeatureColourI> visible,
+          List<String> visibleFeatureGroups, boolean includeNonPositional)
   {
-    StringBuilder out = new StringBuilder(256);
-    boolean featuresGen = false;
-    if (visOnly && !nonpos && (visible == null || visible.size() < 1))
+    if (!includeNonPositional && (visible == null || visible.isEmpty()))
     {
       // no point continuing.
       return "No Features Visible";
     }
 
-    if (visible != null && visOnly)
+    /*
+     * write out feature colours (if we know them)
+     */
+    // TODO: decide if feature links should also be written here ?
+    StringBuilder out = new StringBuilder(256);
+    if (visible != null)
     {
-      // write feature colours only if we're given them and we are generating
-      // viewed features
-      // TODO: decide if feature links should also be written here ?
-      Iterator<String> en = visible.keySet().iterator();
-      while (en.hasNext())
+      for (Entry<String, FeatureColourI> featureColour : visible.entrySet())
       {
-        String featureType = en.next().toString();
-        FeatureColourI colour = visible.get(featureType);
-        out.append(colour.toJalviewFormat(featureType)).append(newline);
+        FeatureColourI colour = featureColour.getValue();
+        out.append(colour.toJalviewFormat(featureColour.getKey())).append(
+                newline);
       }
     }
 
-    // Work out which groups are both present and visible
-    List<String> groups = new ArrayList<String>();
-    int groupIndex = 0;
-    boolean isnonpos = false;
+    String[] types = visible == null ? new String[0] : visible.keySet()
+            .toArray(new String[visible.keySet().size()]);
+
+    /*
+     * sort groups alphabetically, and ensure that features with a
+     * null or empty group are output after those in named groups
+     */
+    List<String> sortedGroups = new ArrayList<String>(visibleFeatureGroups);
+    sortedGroups.remove(null);
+    sortedGroups.remove("");
+    Collections.sort(sortedGroups);
+    sortedGroups.add(null);
+    sortedGroups.add("");
 
-    SequenceFeature[] features;
-    for (int i = 0; i < sequences.length; i++)
+    boolean foundSome = false;
+
+    /*
+     * first output any non-positional features
+     */
+    if (includeNonPositional)
     {
-      features = sequences[i].getSequenceFeatures();
-      if (features != null)
+      for (int i = 0; i < sequences.length; i++)
       {
-        for (int j = 0; j < features.length; j++)
+        String sequenceName = sequences[i].getName();
+        for (SequenceFeature feature : sequences[i].getFeatures()
+                .getNonPositionalFeatures())
         {
-          isnonpos = features[j].begin == 0 && features[j].end == 0;
-          if ((!nonpos && isnonpos)
-                  || (!isnonpos && visOnly && !visible
-                          .containsKey(features[j].type)))
-          {
-            continue;
-          }
-
-          if (features[j].featureGroup != null
-                  && !groups.contains(features[j].featureGroup))
-          {
-            groups.add(features[j].featureGroup);
-          }
+          foundSome = true;
+          out.append(formatJalviewFeature(sequenceName, feature));
         }
       }
     }
 
-    String group = null;
-    do
+    for (String group : sortedGroups)
     {
-      if (groups.size() > 0 && groupIndex < groups.size())
+      boolean isNamedGroup = (group != null && !"".equals(group));
+      if (isNamedGroup)
       {
-        group = groups.get(groupIndex);
         out.append(newline);
         out.append("STARTGROUP").append(TAB);
         out.append(group);
         out.append(newline);
       }
-      else
-      {
-        group = null;
-      }
 
+      /*
+       * output positional features within groups
+       */
       for (int i = 0; i < sequences.length; i++)
       {
-        features = sequences[i].getSequenceFeatures();
-        if (features != null)
+        String sequenceName = sequences[i].getName();
+        List<SequenceFeature> features = new ArrayList<SequenceFeature>();
+        if (types.length > 0)
         {
-          for (SequenceFeature sequenceFeature : features)
-          {
-            isnonpos = sequenceFeature.begin == 0
-                    && sequenceFeature.end == 0;
-            if ((!nonpos && isnonpos)
-                    || (!isnonpos && visOnly && !visible
-                            .containsKey(sequenceFeature.type)))
-            {
-              // skip if feature is nonpos and we ignore them or if we only
-              // output visible and it isn't non-pos and it's not visible
-              continue;
-            }
-
-            if (group != null
-                    && (sequenceFeature.featureGroup == null || !sequenceFeature.featureGroup
-                            .equals(group)))
-            {
-              continue;
-            }
+          features.addAll(sequences[i].getFeatures().getFeaturesForGroup(
+                  true, group, types));
+        }
 
-            if (group == null && sequenceFeature.featureGroup != null)
-            {
-              continue;
-            }
-            // we have features to output
-            featuresGen = true;
-            if (sequenceFeature.description == null
-                    || sequenceFeature.description.equals(""))
-            {
-              out.append(sequenceFeature.type).append(TAB);
-            }
-            else
-            {
-              if (sequenceFeature.links != null
-                      && sequenceFeature.getDescription().indexOf("<html>") == -1)
-              {
-                out.append("<html>");
-              }
-
-              out.append(sequenceFeature.description);
-              if (sequenceFeature.links != null)
-              {
-                for (int l = 0; l < sequenceFeature.links.size(); l++)
-                {
-                  String label = sequenceFeature.links.elementAt(l);
-                  String href = label.substring(label.indexOf("|") + 1);
-                  label = label.substring(0, label.indexOf("|"));
-
-                  if (sequenceFeature.description.indexOf(href) == -1)
-                  {
-                    out.append(" <a href=\"" + href + "\">" + label
-                            + "</a>");
-                  }
-                }
-
-                if (sequenceFeature.getDescription().indexOf("</html>") == -1)
-                {
-                  out.append("</html>");
-                }
-              }
-
-              out.append(TAB);
-            }
-            out.append(sequences[i].getName());
-            out.append("\t-1\t");
-            out.append(sequenceFeature.begin);
-            out.append(TAB);
-            out.append(sequenceFeature.end);
-            out.append(TAB);
-            out.append(sequenceFeature.type);
-            if (!Float.isNaN(sequenceFeature.score))
-            {
-              out.append(TAB);
-              out.append(sequenceFeature.score);
-            }
-            out.append(newline);
-          }
+        for (SequenceFeature sequenceFeature : features)
+        {
+          foundSome = true;
+          out.append(formatJalviewFeature(sequenceName, sequenceFeature));
         }
       }
 
-      if (group != null)
+      if (isNamedGroup)
       {
         out.append("ENDGROUP").append(TAB);
         out.append(group);
         out.append(newline);
-        groupIndex++;
       }
-      else
+    }
+
+    return foundSome ? out.toString() : "No Features Visible";
+  }
+
+  /**
+   * @param out
+   * @param sequenceName
+   * @param sequenceFeature
+   */
+  protected String formatJalviewFeature(
+          String sequenceName, SequenceFeature sequenceFeature)
+  {
+    StringBuilder out = new StringBuilder(64);
+    if (sequenceFeature.description == null
+            || sequenceFeature.description.equals(""))
+    {
+      out.append(sequenceFeature.type).append(TAB);
+    }
+    else
+    {
+      if (sequenceFeature.links != null
+              && sequenceFeature.getDescription().indexOf("<html>") == -1)
       {
-        break;
+        out.append("<html>");
       }
 
-    } while (groupIndex < groups.size() + 1);
+      out.append(sequenceFeature.description);
+      if (sequenceFeature.links != null)
+      {
+        for (int l = 0; l < sequenceFeature.links.size(); l++)
+        {
+          String label = sequenceFeature.links.elementAt(l);
+          String href = label.substring(label.indexOf("|") + 1);
+          label = label.substring(0, label.indexOf("|"));
+
+          if (sequenceFeature.description.indexOf(href) == -1)
+          {
+            out.append(" <a href=\"" + href + "\">" + label + "</a>");
+          }
+        }
+
+        if (sequenceFeature.getDescription().indexOf("</html>") == -1)
+        {
+          out.append("</html>");
+        }
+      }
 
-    if (!featuresGen)
+      out.append(TAB);
+    }
+    out.append(sequenceName);
+    out.append("\t-1\t");
+    out.append(sequenceFeature.begin);
+    out.append(TAB);
+    out.append(sequenceFeature.end);
+    out.append(TAB);
+    out.append(sequenceFeature.type);
+    if (!Float.isNaN(sequenceFeature.score))
     {
-      return "No Features Visible";
+      out.append(TAB);
+      out.append(sequenceFeature.score);
     }
+    out.append(newline);
 
     return out.toString();
   }
@@ -742,102 +717,90 @@ public class FeaturesFile extends AlignFile implements FeaturesSourceI
   }
 
   /**
-   * Returns features output in GFF2 format, including hidden and non-positional
-   * features
-   * 
-   * @param sequences
-   *          the sequences whose features are to be output
-   * @param visible
-   *          a map whose keys are the type names of visible features
-   * @return
-   */
-  public String printGffFormat(SequenceI[] sequences,
-          Map<String, FeatureColourI> visible)
-  {
-    return printGffFormat(sequences, visible, true, true);
-  }
-
-  /**
    * Returns features output in GFF2 format
    * 
    * @param sequences
    *          the sequences whose features are to be output
    * @param visible
    *          a map whose keys are the type names of visible features
-   * @param outputVisibleOnly
+   * @param visibleFeatureGroups
    * @param includeNonPositionalFeatures
    * @return
    */
   public String printGffFormat(SequenceI[] sequences,
-          Map<String, FeatureColourI> visible, boolean outputVisibleOnly,
+          Map<String, FeatureColourI> visible,
+          List<String> visibleFeatureGroups,
           boolean includeNonPositionalFeatures)
   {
     StringBuilder out = new StringBuilder(256);
-    int version = gffVersion == 0 ? 2 : gffVersion;
-    out.append(String.format("%s %d\n", GFF_VERSION, version));
-    String source;
-    boolean isnonpos;
+
+    out.append(String.format("%s %d\n", GFF_VERSION, gffVersion == 0 ? 2 : gffVersion));
+
+    if (!includeNonPositionalFeatures
+            && (visible == null || visible.isEmpty()))
+    {
+      return out.toString();
+    }
+
+    String[] types = visible == null ? new String[0] : visible.keySet()
+            .toArray(
+            new String[visible.keySet().size()]);
+
     for (SequenceI seq : sequences)
     {
-      SequenceFeature[] features = seq.getSequenceFeatures();
-      if (features != null)
+      List<SequenceFeature> features = new ArrayList<SequenceFeature>();
+      if (includeNonPositionalFeatures)
       {
-        for (SequenceFeature sf : features)
-        {
-          isnonpos = sf.begin == 0 && sf.end == 0;
-          if (!includeNonPositionalFeatures && isnonpos)
-          {
-            /*
-             * ignore non-positional features if not wanted
-             */
-            continue;
-          }
-          // TODO why the test !isnonpos here?
-          // what about not visible non-positional features?
-          if (!isnonpos && outputVisibleOnly
-                  && !visible.containsKey(sf.type))
-          {
-            /*
-             * ignore not visible features if not wanted
-             */
-            continue;
-          }
+        features.addAll(seq.getFeatures().getNonPositionalFeatures());
+      }
+      if (visible != null && !visible.isEmpty())
+      {
+        features.addAll(seq.getFeatures().getPositionalFeatures(types));
+      }
 
-          source = sf.featureGroup;
-          if (source == null)
-          {
-            source = sf.getDescription();
-          }
+      for (SequenceFeature sf : features)
+      {
+        String source = sf.featureGroup;
+        if (!sf.isNonPositional() && source != null
+                && !visibleFeatureGroups.contains(source))
+        {
+          // group is not visible
+          continue;
+        }
 
-          out.append(seq.getName());
-          out.append(TAB);
-          out.append(source);
-          out.append(TAB);
-          out.append(sf.type);
-          out.append(TAB);
-          out.append(sf.begin);
-          out.append(TAB);
-          out.append(sf.end);
-          out.append(TAB);
-          out.append(sf.score);
-          out.append(TAB);
-
-          int strand = sf.getStrand();
-          out.append(strand == 1 ? "+" : (strand == -1 ? "-" : "."));
-          out.append(TAB);
-
-          String phase = sf.getPhase();
-          out.append(phase == null ? "." : phase);
-
-          // miscellaneous key-values (GFF column 9)
-          String attributes = sf.getAttributes();
-          if (attributes != null)
-          {
-            out.append(TAB).append(attributes);
-          }
+        if (source == null)
+        {
+          source = sf.getDescription();
+        }
 
-          out.append(newline);
+        out.append(seq.getName());
+        out.append(TAB);
+        out.append(source);
+        out.append(TAB);
+        out.append(sf.type);
+        out.append(TAB);
+        out.append(sf.begin);
+        out.append(TAB);
+        out.append(sf.end);
+        out.append(TAB);
+        out.append(sf.score);
+        out.append(TAB);
+
+        int strand = sf.getStrand();
+        out.append(strand == 1 ? "+" : (strand == -1 ? "-" : "."));
+        out.append(TAB);
+
+        String phase = sf.getPhase();
+        out.append(phase == null ? "." : phase);
+
+        // miscellaneous key-values (GFF column 9)
+        String attributes = sf.getAttributes();
+        if (attributes != null)
+        {
+          out.append(TAB).append(attributes);
         }
+
+        out.append(newline);
       }
     }
 
@@ -899,8 +862,8 @@ public class FeaturesFile extends AlignFile implements FeaturesSourceI
         fromCount = Integer.parseInt(tokens[2]);
       } catch (NumberFormatException nfe)
       {
-        throw new IOException("Invalid number in Align field: "
-                + nfe.getMessage());
+        throw new IOException(
+                "Invalid number in Align field: " + nfe.getMessage());
       }
 
       /*
@@ -1098,10 +1061,11 @@ public class FeaturesFile extends AlignFile implements FeaturesSourceI
 
       // rename sequences if GFF handler requested this
       // TODO a more elegant way e.g. gffHelper.postProcess(newseqs) ?
-      SequenceFeature[] sfs = seq.getSequenceFeatures();
-      if (sfs != null)
+      List<SequenceFeature> sfs = seq.getFeatures().getPositionalFeatures();
+      if (!sfs.isEmpty())
       {
-        String newName = (String) sfs[0].getValue(GffHelperI.RENAME_TOKEN);
+        String newName = (String) sfs.get(0).getValue(
+                GffHelperI.RENAME_TOKEN);
         if (newName != null)
         {
           seq.setName(newName);
@@ -1120,9 +1084,8 @@ public class FeaturesFile extends AlignFile implements FeaturesSourceI
    * @param newseqs
    * @throws IOException
    */
-  protected void processGffPragma(String line,
-          Map<String, String> gffProps, AlignmentI align,
-          List<SequenceI> newseqs) throws IOException
+  protected void processGffPragma(String line, Map<String, String> gffProps,
+          AlignmentI align, List<SequenceI> newseqs) throws IOException
   {
     line = line.trim();
     if ("###".equals(line))
index 3354b88..4b33dbf 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.io;
 
 import jalview.datamodel.AlignmentI;
index c037cf2..0866b1b 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.io;
 
 import java.io.IOException;
index e6f390d..f7b6076 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.io;
 
 import jalview.datamodel.AlignmentI;
index 19a61cf..aadcdb9 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.io;
 
 import java.util.ArrayList;
index 9d5fd93..f26d6da 100755 (executable)
@@ -254,7 +254,8 @@ public class FileLoader implements Runnable
   @Override
   public void run()
   {
-    String title = protocol == DataSourceType.PASTE ? "Copied From Clipboard"
+    String title = protocol == DataSourceType.PASTE
+            ? "Copied From Clipboard"
             : file;
     Runtime rt = Runtime.getRuntime();
     try
@@ -285,8 +286,7 @@ public class FileLoader implements Runnable
                 + "\" has null or unidentifiable data content!");
         if (!Jalview.isHeadlessMode())
         {
-          JvOptionPane.showInternalMessageDialog(
-                  Desktop.desktop,
+          JvOptionPane.showInternalMessageDialog(Desktop.desktop,
                   MessageManager.getString("label.couldnt_read_data")
                           + " in " + file + "\n"
                           + AppletFormatAdapter.getSupportedFormats(),
@@ -313,8 +313,8 @@ public class FileLoader implements Runnable
         if (source != null)
         {
           // Tell the user (developer?) that this is going to cause a problem
-          System.err
-                  .println("IMPLEMENTATION ERROR: Cannot read consecutive Jalview XML projects from a stream.");
+          System.err.println(
+                  "IMPLEMENTATION ERROR: Cannot read consecutive Jalview XML projects from a stream.");
           // We read the data anyway - it might make sense.
         }
         alignFrame = new Jalview2XML(raiseGUI).loadJalviewAlign(file);
@@ -339,9 +339,10 @@ public class FileLoader implements Runnable
             if (downloadStructureFile)
             {
               String structExt = format.getExtensions().split(",")[0];
-              String urlLeafName = file.substring(file.lastIndexOf(System
-                      .getProperty("file.separator")), file
-                      .lastIndexOf("."));
+              String urlLeafName = file.substring(
+                      file.lastIndexOf(
+                              System.getProperty("file.separator")),
+                      file.lastIndexOf("."));
               String tempStructureFileStr = createNamedJvTempFile(
                       urlLeafName, structExt);
               UrlDownloadClient.download(file, tempStructureFileStr);
@@ -376,8 +377,9 @@ public class FileLoader implements Runnable
               {
                 // register PDB entries with desktop's structure selection
                 // manager
-                StructureSelectionManager.getStructureSelectionManager(
-                        Desktop.instance).registerPDBEntry(pdbe);
+                StructureSelectionManager
+                        .getStructureSelectionManager(Desktop.instance)
+                        .registerPDBEntry(pdbe);
               }
             }
           }
@@ -412,8 +414,8 @@ public class FileLoader implements Runnable
               alignFrame.getViewport().setFeaturesDisplayed(fd);
               alignFrame.getViewport().setShowSequenceFeatures(
                       ((ComplexAlignFile) source).isShowSeqFeatures());
-              ColourSchemeI cs = ColourSchemeMapper.getJalviewColourScheme(
-                      colourSchemeName, al);
+              ColourSchemeI cs = ColourSchemeMapper
+                      .getJalviewColourScheme(colourSchemeName, al);
               if (cs != null)
               {
                 alignFrame.changeColour(cs);
@@ -439,8 +441,8 @@ public class FileLoader implements Runnable
                       .applyFeaturesStyle(proxyColourScheme);
             }
             alignFrame.statusBar.setText(MessageManager.formatMessage(
-                    "label.successfully_loaded_file",
-                    new String[] { title }));
+                    "label.successfully_loaded_file", new String[]
+                    { title }));
 
             if (raiseGUI)
             {
@@ -455,8 +457,8 @@ public class FileLoader implements Runnable
 
             try
             {
-              alignFrame.setMaximum(jalview.bin.Cache.getDefault(
-                      "SHOW_FULLSCREEN", false));
+              alignFrame.setMaximum(jalview.bin.Cache
+                      .getDefault("SHOW_FULLSCREEN", false));
             } catch (java.beans.PropertyVetoException ex)
             {
             }
@@ -469,11 +471,8 @@ public class FileLoader implements Runnable
             Desktop.instance.stopLoading();
           }
 
-          final String errorMessage = MessageManager
-                  .getString("label.couldnt_load_file")
-                  + " "
-                  + title
-                  + "\n" + error;
+          final String errorMessage = MessageManager.getString(
+                  "label.couldnt_load_file") + " " + title + "\n" + error;
           // TODO: refactor FileLoader to be independent of Desktop / Applet GUI
           // bits ?
           if (raiseGUI && Desktop.desktop != null)
@@ -484,7 +483,8 @@ public class FileLoader implements Runnable
               public void run()
               {
                 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
-                        errorMessage, MessageManager
+                        errorMessage,
+                        MessageManager
                                 .getString("label.error_loading_file"),
                         JvOptionPane.WARNING_MESSAGE);
               }
@@ -510,11 +510,11 @@ public class FileLoader implements Runnable
           @Override
           public void run()
           {
-            JvOptionPane.showInternalMessageDialog(
-                    Desktop.desktop, MessageManager.formatMessage(
-                            "label.problems_opening_file",
-                            new String[] { file }), MessageManager
-                            .getString("label.file_open_error"),
+            JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                    MessageManager.formatMessage(
+                            "label.problems_opening_file", new String[]
+                            { file }),
+                    MessageManager.getString("label.file_open_error"),
                     JvOptionPane.WARNING_MESSAGE);
           }
         });
@@ -532,11 +532,11 @@ public class FileLoader implements Runnable
           @Override
           public void run()
           {
-            JvOptionPane.showInternalMessageDialog(
-                    Desktop.desktop, MessageManager.formatMessage(
+            JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                    MessageManager.formatMessage(
                             "warn.out_of_memory_loading_file", new String[]
-                            { file }), MessageManager
-                            .getString("label.out_of_memory"),
+                            { file }),
+                    MessageManager.getString("label.out_of_memory"),
                     JvOptionPane.WARNING_MESSAGE);
           }
         });
@@ -600,24 +600,10 @@ public class FileLoader implements Runnable
     String seprator = System.getProperty("file.separator");
     String jvTempDir = System.getProperty("java.io.tmpdir") + "jalview"
             + seprator + System.currentTimeMillis();
-    File tempStructFile = new File(jvTempDir + seprator + fileName + "."
-            + extension);
+    File tempStructFile = new File(
+            jvTempDir + seprator + fileName + "." + extension);
     tempStructFile.mkdirs();
     return tempStructFile.toString();
   }
 
-  /*
-   * (non-Javadoc)
-   * 
-   * @see java.lang.Object#finalize()
-   */
-  @Override
-  protected void finalize() throws Throwable
-  {
-    source = null;
-    alignFrame = null;
-    viewport = null;
-    super.finalize();
-  }
-
 }
index dc0418f..c0328d5 100755 (executable)
@@ -125,9 +125,8 @@ public class FileParse
   {
     if (from == null)
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_error_null_fileparse"));
+      throw new Error(MessageManager
+              .getString("error.implementation_error_null_fileparse"));
     }
     if (from == this)
     {
@@ -204,16 +203,16 @@ public class FileParse
   private BufferedReader tryAsGzipSource(InputStream inputStream)
           throws Exception
   {
-    BufferedReader inData = new BufferedReader(new InputStreamReader(
-            new GZIPInputStream(inputStream)));
+    BufferedReader inData = new BufferedReader(
+            new InputStreamReader(new GZIPInputStream(inputStream)));
     inData.mark(2048);
     inData.read();
     inData.reset();
     return inData;
   }
 
-  private boolean checkURLSource(String fileStr) throws IOException,
-          MalformedURLException
+  private boolean checkURLSource(String fileStr)
+          throws IOException, MalformedURLException
   {
     errormessage = "URL NOT FOUND";
     URL url = new URL(fileStr);
@@ -242,10 +241,8 @@ public class FileParse
     {
       if (e != null)
       {
-        throw new IOException(
-                MessageManager
-                        .getString("exception.failed_to_resolve_gzip_stream"),
-                e);
+        throw new IOException(MessageManager
+                .getString("exception.failed_to_resolve_gzip_stream"), e);
       }
       throw q;
     }
@@ -326,15 +323,15 @@ public class FileParse
           {
             throw new IOException(MessageManager.formatMessage(
                     "exception.problem_opening_file_also_tried",
-                    new String[] { inFile.getName(), suffixLess,
-                        errormessage }));
+                    new String[]
+                    { inFile.getName(), suffixLess, errormessage }));
           }
         }
         else
         {
           throw new IOException(MessageManager.formatMessage(
-                  "exception.problem_opening_file",
-                  new String[] { inFile.getName(), errormessage }));
+                  "exception.problem_opening_file", new String[]
+                  { inFile.getName(), errormessage }));
         }
       }
     }
@@ -414,8 +411,8 @@ public class FileParse
     {
       // pass up the reason why we have no source to read from
       throw new IOException(MessageManager.formatMessage(
-              "exception.failed_to_read_data_from_source",
-              new String[] { errormessage }));
+              "exception.failed_to_read_data_from_source", new String[]
+              { errormessage }));
     }
     error = false;
     dataIn.mark(READAHEAD_LIMIT);
@@ -446,9 +443,9 @@ public class FileParse
     {
       return dataIn.readLine();
     }
-    throw new IOException(MessageManager.formatMessage(
-            "exception.invalid_source_stream",
-            new String[] { errormessage }));
+    throw new IOException(MessageManager
+            .formatMessage("exception.invalid_source_stream", new String[]
+            { errormessage }));
   }
 
   /**
@@ -501,9 +498,8 @@ public class FileParse
     }
     else
     {
-      throw new IOException(
-              MessageManager
-                      .getString("error.implementation_error_reset_called_for_invalid_source"));
+      throw new IOException(MessageManager.getString(
+              "error.implementation_error_reset_called_for_invalid_source"));
     }
   }
 
index f09e8a0..7647a16 100755 (executable)
@@ -116,8 +116,8 @@ public class FormatAdapter extends AppletFormatAdapter
           startIndex = startEnd[0];
           endIndex = startEnd[1];
           // get first non-gaped residue start position
-          while (Comparison.isGap(seqs[i]
-                  .getCharAt(startIndex)) && startIndex < endIndex)
+          while (Comparison.isGap(seqs[i].getCharAt(startIndex))
+                  && startIndex < endIndex)
           {
             startIndex++;
           }
@@ -161,7 +161,8 @@ public class FormatAdapter extends AppletFormatAdapter
 
   public boolean getCacheSuffixDefault(FileFormatI format)
   {
-    return Cache.getDefault(format.getName() + "_JVSUFFIX", true);
+    return Cache.getDefault(format.getName().toUpperCase() + "_JVSUFFIX",
+            true);
   }
 
   public String formatSequences(FileFormatI format, AlignmentI alignment,
old mode 100755 (executable)
new mode 100644 (file)
index 77006db..bebfd28
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.io;
 
 import jalview.api.AlignExportSettingI;
@@ -86,12 +106,12 @@ public abstract class HTMLOutput implements Runnable
       };
     }
     AlignmentExportData exportData = jalview.gui.AlignFrame
-            .getAlignmentForExport(FileFormat.Json,
-                    ap.getAlignViewport(), exportSettings);
+            .getAlignmentForExport(FileFormat.Json, ap.getAlignViewport(),
+                    exportSettings);
     String bioJSON = new FormatAdapter(ap, exportData.getSettings())
             .formatSequences(FileFormat.Json, exportData.getAlignment(),
-                    exportData.getOmitHidden(), exportData
-.getStartEndPostions(), ap.getAlignViewport()
+                    exportData.getOmitHidden(),
+                    exportData.getStartEndPostions(), ap.getAlignViewport()
                             .getAlignment().getHiddenColumns());
     return bioJSON;
   }
@@ -124,7 +144,7 @@ public abstract class HTMLOutput implements Runnable
         {
           sb.append(line).append(lineSeparator);
         }
-  
+
       } catch (Exception ex)
       {
         ex.printStackTrace();
@@ -134,7 +154,7 @@ public abstract class HTMLOutput implements Runnable
         {
           isReader.close();
         }
-  
+
         if (buffReader != null)
         {
           buffReader.close();
@@ -146,89 +166,55 @@ public abstract class HTMLOutput implements Runnable
 
   public static String getImageMapHTML()
   {
-    return new String(
-            "<html>\n"
-                    + "<head>\n"
-                    + "<script language=\"JavaScript\">\n"
-                    + "var ns4 = document.layers;\n"
-                    + "var ns6 = document.getElementById && !document.all;\n"
-                    + "var ie4 = document.all;\n"
-                    + "offsetX = 0;\n"
-                    + "offsetY = 20;\n"
-                    + "var toolTipSTYLE=\"\";\n"
-                    + "function initToolTips()\n"
-                    + "{\n"
-                    + "  if(ns4||ns6||ie4)\n"
-                    + "  {\n"
-                    + "    if(ns4) toolTipSTYLE = document.toolTipLayer;\n"
-                    + "    else if(ns6) toolTipSTYLE = document.getElementById(\"toolTipLayer\").style;\n"
-                    + "    else if(ie4) toolTipSTYLE = document.all.toolTipLayer.style;\n"
-                    + "    if(ns4) document.captureEvents(Event.MOUSEMOVE);\n"
-                    + "    else\n"
-                    + "    {\n"
-                    + "      toolTipSTYLE.visibility = \"visible\";\n"
-                    + "      toolTipSTYLE.display = \"none\";\n"
-                    + "    }\n"
-                    + "    document.onmousemove = moveToMouseLoc;\n"
-                    + "  }\n"
-                    + "}\n"
-                    + "function toolTip(msg, fg, bg)\n"
-                    + "{\n"
-                    + "  if(toolTip.arguments.length < 1) // hide\n"
-                    + "  {\n"
-                    + "    if(ns4) toolTipSTYLE.visibility = \"hidden\";\n"
-                    + "    else toolTipSTYLE.display = \"none\";\n"
-                    + "  }\n"
-                    + "  else // show\n"
-                    + "  {\n"
-                    + "    if(!fg) fg = \"#555555\";\n"
-                    + "    if(!bg) bg = \"#FFFFFF\";\n"
-                    + "    var content =\n"
-                    + "    '<table border=\"0\" cellspacing=\"0\" cellpadding=\"1\" bgcolor=\"' + fg + '\"><td>' +\n"
-                    + "    '<table border=\"0\" cellspacing=\"0\" cellpadding=\"1\" bgcolor=\"' + bg + \n"
-                    + "    '\"><td align=\"center\"><font face=\"sans-serif\" color=\"' + fg +\n"
-                    + "    '\" size=\"-2\">&nbsp;' + msg +\n"
-                    + "    '&nbsp;</font></td></table></td></table>';\n"
-                    + "    if(ns4)\n"
-                    + "    {\n"
-                    + "      toolTipSTYLE.document.write(content);\n"
-                    + "      toolTipSTYLE.document.close();\n"
-                    + "      toolTipSTYLE.visibility = \"visible\";\n"
-                    + "    }\n"
-                    + "    if(ns6)\n"
-                    + "    {\n"
-                    + "      document.getElementById(\"toolTipLayer\").innerHTML = content;\n"
-                    + "      toolTipSTYLE.display='block'\n"
-                    + "    }\n"
-                    + "    if(ie4)\n"
-                    + "    {\n"
-                    + "      document.all(\"toolTipLayer\").innerHTML=content;\n"
-                    + "      toolTipSTYLE.display='block'\n"
-                    + "    }\n"
-                    + "  }\n"
-                    + "}\n"
-                    + "function moveToMouseLoc(e)\n"
-                    + "{\n"
-                    + "  if(ns4||ns6)\n"
-                    + "  {\n"
-                    + "    x = e.pageX;\n"
-                    + "    y = e.pageY;\n"
-                    + "  }\n"
-                    + "  else\n"
-                    + "  {\n"
-                    + "    x = event.x + document.body.scrollLeft;\n"
-                    + "    y = event.y + document.body.scrollTop;\n"
-                    + "  }\n"
-                    + "  toolTipSTYLE.left = x + offsetX;\n"
-                    + "  toolTipSTYLE.top = y + offsetY;\n"
-                    + "  return true;\n"
-                    + "}\n"
-                    + "</script>\n"
-                    + "</head>\n"
-                    + "<body>\n"
-                    + "<div id=\"toolTipLayer\" style=\"position:absolute; visibility: hidden\"></div>\n"
-                    + "<script language=\"JavaScript\"><!--\n"
-                    + "initToolTips(); //--></script>\n");
+    return new String("<html>\n" + "<head>\n"
+            + "<script language=\"JavaScript\">\n"
+            + "var ns4 = document.layers;\n"
+            + "var ns6 = document.getElementById && !document.all;\n"
+            + "var ie4 = document.all;\n" + "offsetX = 0;\n"
+            + "offsetY = 20;\n" + "var toolTipSTYLE=\"\";\n"
+            + "function initToolTips()\n" + "{\n" + "  if(ns4||ns6||ie4)\n"
+            + "  {\n"
+            + "    if(ns4) toolTipSTYLE = document.toolTipLayer;\n"
+            + "    else if(ns6) toolTipSTYLE = document.getElementById(\"toolTipLayer\").style;\n"
+            + "    else if(ie4) toolTipSTYLE = document.all.toolTipLayer.style;\n"
+            + "    if(ns4) document.captureEvents(Event.MOUSEMOVE);\n"
+            + "    else\n" + "    {\n"
+            + "      toolTipSTYLE.visibility = \"visible\";\n"
+            + "      toolTipSTYLE.display = \"none\";\n" + "    }\n"
+            + "    document.onmousemove = moveToMouseLoc;\n" + "  }\n"
+            + "}\n" + "function toolTip(msg, fg, bg)\n" + "{\n"
+            + "  if(toolTip.arguments.length < 1) // hide\n" + "  {\n"
+            + "    if(ns4) toolTipSTYLE.visibility = \"hidden\";\n"
+            + "    else toolTipSTYLE.display = \"none\";\n" + "  }\n"
+            + "  else // show\n" + "  {\n"
+            + "    if(!fg) fg = \"#555555\";\n"
+            + "    if(!bg) bg = \"#FFFFFF\";\n" + "    var content =\n"
+            + "    '<table border=\"0\" cellspacing=\"0\" cellpadding=\"1\" bgcolor=\"' + fg + '\"><td>' +\n"
+            + "    '<table border=\"0\" cellspacing=\"0\" cellpadding=\"1\" bgcolor=\"' + bg + \n"
+            + "    '\"><td align=\"center\"><font face=\"sans-serif\" color=\"' + fg +\n"
+            + "    '\" size=\"-2\">&nbsp;' + msg +\n"
+            + "    '&nbsp;</font></td></table></td></table>';\n"
+            + "    if(ns4)\n" + "    {\n"
+            + "      toolTipSTYLE.document.write(content);\n"
+            + "      toolTipSTYLE.document.close();\n"
+            + "      toolTipSTYLE.visibility = \"visible\";\n" + "    }\n"
+            + "    if(ns6)\n" + "    {\n"
+            + "      document.getElementById(\"toolTipLayer\").innerHTML = content;\n"
+            + "      toolTipSTYLE.display='block'\n" + "    }\n"
+            + "    if(ie4)\n" + "    {\n"
+            + "      document.all(\"toolTipLayer\").innerHTML=content;\n"
+            + "      toolTipSTYLE.display='block'\n" + "    }\n" + "  }\n"
+            + "}\n" + "function moveToMouseLoc(e)\n" + "{\n"
+            + "  if(ns4||ns6)\n" + "  {\n" + "    x = e.pageX;\n"
+            + "    y = e.pageY;\n" + "  }\n" + "  else\n" + "  {\n"
+            + "    x = event.x + document.body.scrollLeft;\n"
+            + "    y = event.y + document.body.scrollTop;\n" + "  }\n"
+            + "  toolTipSTYLE.left = x + offsetX;\n"
+            + "  toolTipSTYLE.top = y + offsetY;\n" + "  return true;\n"
+            + "}\n" + "</script>\n" + "</head>\n" + "<body>\n"
+            + "<div id=\"toolTipLayer\" style=\"position:absolute; visibility: hidden\"></div>\n"
+            + "<script language=\"JavaScript\"><!--\n"
+            + "initToolTips(); //--></script>\n");
 
   }
 
@@ -246,15 +232,15 @@ public abstract class HTMLOutput implements Runnable
             "HTML files");
     jvFileChooser.setFileView(new JalviewFileView());
 
-    jvFileChooser.setDialogTitle(MessageManager
-            .getString("label.save_as_html"));
+    jvFileChooser
+            .setDialogTitle(MessageManager.getString("label.save_as_html"));
     jvFileChooser.setToolTipText(MessageManager.getString("action.save"));
 
     int fileChooserOpt = jvFileChooser.showSaveDialog(null);
     if (fileChooserOpt == JalviewFileChooser.APPROVE_OPTION)
     {
-      jalview.bin.Cache.setProperty("LAST_DIRECTORY", jvFileChooser
-              .getSelectedFile().getParent());
+      jalview.bin.Cache.setProperty("LAST_DIRECTORY",
+              jvFileChooser.getSelectedFile().getParent());
       selectedFile = jvFileChooser.getSelectedFile().getPath();
     }
     else
index 3fb3cf2..948578a 100644 (file)
@@ -39,7 +39,6 @@ import org.jfree.graphics2d.svg.SVGHints;
 public class HtmlSvgOutput extends HTMLOutput
 {
 
-
   public HtmlSvgOutput(AlignmentPanel ap)
   {
     super(ap);
@@ -63,8 +62,8 @@ public class HtmlSvgOutput extends HTMLOutput
       return;
     } catch (Exception e)
     {
-      setProgressMessage(MessageManager.formatMessage(
-              "info.error_creating_file", "HTML"));
+      setProgressMessage(MessageManager
+              .formatMessage("info.error_creating_file", "HTML"));
       e.printStackTrace();
       return;
     }
@@ -92,10 +91,13 @@ public class HtmlSvgOutput extends HTMLOutput
     htmlSvg.append("<html>\n");
     if (jsonData != null)
     {
-      htmlSvg.append("<button onclick=\"javascipt:openJalviewUsingCurrentUrl();\">Launch in Jalview</button> &nbsp;");
-      htmlSvg.append("<input type=\"submit\" value=\"View raw BioJSON Data\" onclick=\"jQuery.facebox({ div:'#seqData' }); return false;\" />");
-      htmlSvg.append("<div style=\"display: none;\" name=\"seqData\" id=\"seqData\" >"
-              + jsonData + "</div>");
+      htmlSvg.append(
+              "<button onclick=\"javascipt:openJalviewUsingCurrentUrl();\">Launch in Jalview</button> &nbsp;");
+      htmlSvg.append(
+              "<input type=\"submit\" value=\"View raw BioJSON Data\" onclick=\"jQuery.facebox({ div:'#seqData' }); return false;\" />");
+      htmlSvg.append(
+              "<div style=\"display: none;\" name=\"seqData\" id=\"seqData\" >"
+                      + jsonData + "</div>");
       htmlSvg.append("<br/>&nbsp;");
     }
     htmlSvg.append("\n<style type=\"text/css\"> "
@@ -108,72 +110,80 @@ public class HtmlSvgOutput extends HTMLOutput
     if (jsonData != null)
     {
       // facebox style sheet for displaying raw BioJSON data
-      htmlSvg.append("#facebox { position: absolute;  top: 0;   left: 0; z-index: 100; text-align: left; }\n"
-              + "#facebox .popup{ position:relative; border:3px solid rgba(0,0,0,0); -webkit-border-radius:5px;"
-              + "-moz-border-radius:5px; border-radius:5px; -webkit-box-shadow:0 0 18px rgba(0,0,0,0.4); -moz-box-shadow:0 0 18px rgba(0,0,0,0.4);"
-              + "box-shadow:0 0 18px rgba(0,0,0,0.4); }\n"
-              + "#facebox .content { display:table; width: 98%; padding: 10px; background: #fff; -webkit-border-radius:4px; -moz-border-radius:4px;"
-              + " border-radius:4px; }\n"
-              + "#facebox .content > p:first-child{ margin-top:0; }\n"
-              + "#facebox .content > p:last-child{ margin-bottom:0; }\n"
-              + "#facebox .close{ position:absolute; top:5px; right:5px; padding:2px; background:#fff; }\n"
-              + "#facebox .close img{ opacity:0.3; }\n"
-              + "#facebox .close:hover img{ opacity:1.0; }\n"
-              + "#facebox .loading { text-align: center; }\n"
-              + "#facebox .image { text-align: center;}\n"
-              + "#facebox img { border: 0;  margin: 0; }\n"
-              + "#facebox_overlay { position: fixed; top: 0px; left: 0px; height:100%; width:100%; }\n"
-              + ".facebox_hide { z-index:-100; }\n"
-              + ".facebox_overlayBG { background-color: #000;  z-index: 99;  }");
+      htmlSvg.append(
+              "#facebox { position: absolute;  top: 0;   left: 0; z-index: 100; text-align: left; }\n"
+                      + "#facebox .popup{ position:relative; border:3px solid rgba(0,0,0,0); -webkit-border-radius:5px;"
+                      + "-moz-border-radius:5px; border-radius:5px; -webkit-box-shadow:0 0 18px rgba(0,0,0,0.4); -moz-box-shadow:0 0 18px rgba(0,0,0,0.4);"
+                      + "box-shadow:0 0 18px rgba(0,0,0,0.4); }\n"
+                      + "#facebox .content { display:table; width: 98%; padding: 10px; background: #fff; -webkit-border-radius:4px; -moz-border-radius:4px;"
+                      + " border-radius:4px; }\n"
+                      + "#facebox .content > p:first-child{ margin-top:0; }\n"
+                      + "#facebox .content > p:last-child{ margin-bottom:0; }\n"
+                      + "#facebox .close{ position:absolute; top:5px; right:5px; padding:2px; background:#fff; }\n"
+                      + "#facebox .close img{ opacity:0.3; }\n"
+                      + "#facebox .close:hover img{ opacity:1.0; }\n"
+                      + "#facebox .loading { text-align: center; }\n"
+                      + "#facebox .image { text-align: center;}\n"
+                      + "#facebox img { border: 0;  margin: 0; }\n"
+                      + "#facebox_overlay { position: fixed; top: 0px; left: 0px; height:100%; width:100%; }\n"
+                      + ".facebox_hide { z-index:-100; }\n"
+                      + ".facebox_overlayBG { background-color: #000;  z-index: 99;  }");
     }
     htmlSvg.append("</style>");
     if (!wrapped)
     {
-    htmlSvg.append("<div class=\"main-container\" \n>");
-    htmlSvg.append("<div class=\"titlex\">\n");
-    htmlSvg.append("<div class=\"sub-category-container\"> \n");
-    htmlSvg.append(titleSvg);
-    htmlSvg.append("</div>");
-    htmlSvg.append("</div>\n\n<!-- ========================================================================================== -->\n\n");
-    htmlSvg.append("<div class=\"align\" >");
-    htmlSvg.append(
-            "<div class=\"sub-category-container\"> <div style=\"overflow-x: scroll;\">")
-            .append(alignmentSvg).append("</div></div>").append("</div>");
-    htmlSvg.append("</div>");
+      htmlSvg.append("<div class=\"main-container\" \n>");
+      htmlSvg.append("<div class=\"titlex\">\n");
+      htmlSvg.append("<div class=\"sub-category-container\"> \n");
+      htmlSvg.append(titleSvg);
+      htmlSvg.append("</div>");
+      htmlSvg.append(
+              "</div>\n\n<!-- ========================================================================================== -->\n\n");
+      htmlSvg.append("<div class=\"align\" >");
+      htmlSvg.append(
+              "<div class=\"sub-category-container\"> <div style=\"overflow-x: scroll;\">")
+              .append(alignmentSvg).append("</div></div>").append("</div>");
+      htmlSvg.append("</div>");
 
-    htmlSvg.append("<script language=\"JavaScript\" type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js\"></script>\n"
-            + "<script language=\"JavaScript\" type=\"text/javascript\"  src=\"http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js\"></script>\n"
-            + "<script>\n"
-            + "var subCatContainer = $(\".sub-category-container\");\n"
-            + "subCatContainer.scroll(\nfunction() {\n"
-            + "subCatContainer.scrollTop($(this).scrollTop());\n});\n");
+      htmlSvg.append(
+              "<script language=\"JavaScript\" type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js\"></script>\n"
+                      + "<script language=\"JavaScript\" type=\"text/javascript\"  src=\"http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js\"></script>\n"
+                      + "<script>\n"
+                      + "var subCatContainer = $(\".sub-category-container\");\n"
+                      + "subCatContainer.scroll(\nfunction() {\n"
+                      + "subCatContainer.scrollTop($(this).scrollTop());\n});\n");
 
-    htmlSvg.append("</script>\n");
+      htmlSvg.append("</script>\n");
     }
     else
     {
-      htmlSvg.append("<div>\n")
-              .append(alignmentSvg).append("</div>");
-      htmlSvg.append("<script language=\"JavaScript\" type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js\"></script>\n"
-              + "<script language=\"JavaScript\" type=\"text/javascript\"  src=\"http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js\"></script>\n");
+      htmlSvg.append("<div>\n").append(alignmentSvg).append("</div>");
+      htmlSvg.append(
+              "<script language=\"JavaScript\" type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js\"></script>\n"
+                      + "<script language=\"JavaScript\" type=\"text/javascript\"  src=\"http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js\"></script>\n");
     }
 
     // javascript for launching file in Jalview
     htmlSvg.append("<script language=\"JavaScript\">\n");
     htmlSvg.append("function openJalviewUsingCurrentUrl(){\n");
-    htmlSvg.append("    var json = JSON.parse(document.getElementById(\"seqData\").innerHTML);\n");
-    htmlSvg.append("    var jalviewVersion = json['appSettings'].version;\n");
+    htmlSvg.append(
+            "    var json = JSON.parse(document.getElementById(\"seqData\").innerHTML);\n");
+    htmlSvg.append(
+            "    var jalviewVersion = json['appSettings'].version;\n");
     htmlSvg.append("    var url = json['appSettings'].webStartUrl;\n");
-    htmlSvg.append("    var myForm = document.createElement(\"form\");\n\n");
+    htmlSvg.append(
+            "    var myForm = document.createElement(\"form\");\n\n");
     htmlSvg.append("    var heap = document.createElement(\"input\");\n");
     htmlSvg.append("    heap.setAttribute(\"name\", \"jvm-max-heap\") ;\n");
     htmlSvg.append("    heap.setAttribute(\"value\", \"2G\");\n\n");
     htmlSvg.append("    var target = document.createElement(\"input\");\n");
     htmlSvg.append("    target.setAttribute(\"name\", \"open\");\n");
     htmlSvg.append("    target.setAttribute(\"value\", document.URL);\n\n");
-    htmlSvg.append("    var jvVersion = document.createElement(\"input\");\n");
+    htmlSvg.append(
+            "    var jvVersion = document.createElement(\"input\");\n");
     htmlSvg.append("    jvVersion.setAttribute(\"name\", \"version\") ;\n");
-    htmlSvg.append("    jvVersion.setAttribute(\"value\", jalviewVersion);\n\n");
+    htmlSvg.append(
+            "    jvVersion.setAttribute(\"value\", jalviewVersion);\n\n");
     htmlSvg.append("    myForm.action = url;\n");
     htmlSvg.append("    myForm.appendChild(heap);\n");
     htmlSvg.append("    myForm.appendChild(target);\n");
@@ -204,8 +214,8 @@ public class HtmlSvgOutput extends HTMLOutput
   @Override
   public boolean isEmbedData()
   {
-    return Boolean.valueOf(jalview.bin.Cache.getDefault(
-            "EXPORT_EMBBED_BIOJSON", "true"));
+    return Boolean.valueOf(
+            jalview.bin.Cache.getDefault("EXPORT_EMBBED_BIOJSON", "true"));
   }
 
   @Override
@@ -273,14 +283,14 @@ public class HtmlSvgOutput extends HTMLOutput
       String idPanelSvgData = idPanelGraphics.getSVGDocument();
       String alignPanelSvgData = alignPanelGraphics.getSVGDocument();
       String jsonData = getBioJSONData();
-      String htmlData = getHtml(idPanelSvgData, alignPanelSvgData,
-              jsonData, ap.av.getWrapAlignment());
+      String htmlData = getHtml(idPanelSvgData, alignPanelSvgData, jsonData,
+              ap.av.getWrapAlignment());
       FileOutputStream out = new FileOutputStream(generatedFile);
       out.write(htmlData.getBytes());
       out.flush();
       out.close();
-      setProgressMessage(MessageManager.formatMessage(
-              "status.export_complete", "HTML"));
+      setProgressMessage(MessageManager
+              .formatMessage("status.export_complete", "HTML"));
       exportCompleted();
     } catch (OutOfMemoryError err)
     {
@@ -290,8 +300,8 @@ public class HtmlSvgOutput extends HTMLOutput
     } catch (Exception e)
     {
       e.printStackTrace();
-      setProgressMessage(MessageManager.formatMessage(
-              "info.error_creating_file", "HTML"));
+      setProgressMessage(MessageManager
+              .formatMessage("info.error_creating_file", "HTML"));
     }
   }
 }
index 035c1fa..ff959b0 100755 (executable)
@@ -72,10 +72,11 @@ public class IdentifyFile
     // preserves original behaviour prior to version 2.3
   }
 
-  public FileFormatI identify(AlignmentFileReaderI file, boolean closeSource)
-          throws IOException
+  public FileFormatI identify(AlignmentFileReaderI file,
+          boolean closeSource) throws IOException
   {
-    FileParse fp = new FileParse(file.getInFile(), file.getDataSourceType());
+    FileParse fp = new FileParse(file.getInFile(),
+            file.getDataSourceType());
     return identify(fp, closeSource);
   }
 
@@ -274,6 +275,11 @@ public class IdentifyFile
           // read as a FASTA (probably)
           break;
         }
+        if (data.indexOf("{\"") > -1)
+        {
+          reply = FileFormat.Json;
+          break;
+        }
         int lessThan = data.indexOf("<");
         if ((lessThan > -1)) // possible Markup Language data i.e HTML,
                              // RNAML, XML
@@ -291,11 +297,6 @@ public class IdentifyFile
           }
         }
 
-        if (data.indexOf("{\"") > -1)
-        {
-          reply = FileFormat.Json;
-          break;
-        }
         if ((data.length() < 1) || (data.indexOf("#") == 0))
         {
           lineswereskipped = true;
@@ -309,9 +310,8 @@ public class IdentifyFile
           break;
         }
 
-        if ((data.indexOf("//") == 0)
-                || ((data.indexOf("!!") > -1) && (data.indexOf("!!") < data
-                        .indexOf("_MULTIPLE_ALIGNMENT "))))
+        if ((data.indexOf("//") == 0) || ((data.indexOf("!!") > -1) && (data
+                .indexOf("!!") < data.indexOf("_MULTIPLE_ALIGNMENT "))))
         {
           reply = FileFormat.MSF;
 
@@ -361,8 +361,8 @@ public class IdentifyFile
     }
     if (trimmedLength == 0)
     {
-      System.err
-              .println("File Identification failed! - Empty file was read.");
+      System.err.println(
+              "File Identification failed! - Empty file was read.");
       throw new FileFormatException("EMPTY DATA FILE");
     }
     System.out.println("File format identified as " + reply.toString());
@@ -428,9 +428,9 @@ public class IdentifyFile
         type = ider.identify(args[i], DataSourceType.FILE);
       } catch (FileFormatException e)
       {
-        System.err.println(String.format(
-                "Error '%s' identifying file type for %s", args[i],
-                e.getMessage()));
+        System.err.println(
+                String.format("Error '%s' identifying file type for %s",
+                        args[i], e.getMessage()));
       }
       System.out.println("Type of " + args[i] + " is " + type);
     }
index d269e97..65ba74a 100644 (file)
@@ -47,11 +47,4 @@ public class InputStreamParser extends FileParse
     error = false;
   }
 
-  @Override
-  protected void finalize() throws Throwable
-  {
-    dataIn = null;
-    super.finalize();
-  }
-
 }
index fd971fd..026c879 100755 (executable)
@@ -219,8 +219,8 @@ public class JPredFile extends AlignFile
 
           for (int j = 0; j < i; j++)
           {
-            scores.setElementAt(
-                    ((Float) scores.elementAt(j)).toString(), j);
+            scores.setElementAt(((Float) scores.elementAt(j)).toString(),
+                    j);
           }
 
           scores.addElement(ascore);
@@ -299,20 +299,20 @@ public class JPredFile extends AlignFile
     {
       // Add all sequence like objects
       Sequence newSeq = new Sequence(ids.elementAt(i).toString(),
-              seq_entries.elementAt(i).toString(), 1, seq_entries
-                      .elementAt(i).toString().length());
+              seq_entries.elementAt(i).toString(), 1,
+              seq_entries.elementAt(i).toString().length());
 
       if (maxLength != seq_entries.elementAt(i).toString().length())
       {
-        throw new IOException(
-                MessageManager
-                        .formatMessage(
-                                "exception.jpredconcide_entry_has_unexpected_number_of_columns",
-                                new String[] { ids.elementAt(i).toString() }));
+        throw new IOException(MessageManager.formatMessage(
+                "exception.jpredconcide_entry_has_unexpected_number_of_columns",
+                new String[]
+                { ids.elementAt(i).toString() }));
       }
 
-      if ((newSeq.getName().startsWith("QUERY") || newSeq.getName()
-              .startsWith("align;")) && (QuerySeqPosition == -1))
+      if ((newSeq.getName().startsWith("QUERY")
+              || newSeq.getName().startsWith("align;"))
+              && (QuerySeqPosition == -1))
       {
         QuerySeqPosition = seqs.size();
       }
@@ -332,11 +332,10 @@ public class JPredFile extends AlignFile
       } catch (Exception e)
       {
         tal = null;
-        IOException ex = new IOException(
-                MessageManager
-                        .formatMessage(
-                                "exception.couldnt_parse_concise_annotation_for_prediction",
-                                new String[] { e.getMessage() }));
+        IOException ex = new IOException(MessageManager.formatMessage(
+                "exception.couldnt_parse_concise_annotation_for_prediction",
+                new String[]
+                { e.getMessage() }));
         e.printStackTrace(); // java 1.1 does not have :
                              // ex.setStackTrace(e.getStackTrace());
         throw ex;
index c293cd4..fda22dc 100644 (file)
@@ -51,6 +51,7 @@ import jalview.schemes.ColourSchemeProperty;
 import jalview.schemes.JalviewColourScheme;
 import jalview.schemes.ResidueColourScheme;
 import jalview.util.ColorUtils;
+import jalview.util.Format;
 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
 
 import java.awt.Color;
@@ -218,9 +219,8 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
         // are not exported
         if (globalColourScheme
                 .equalsIgnoreCase(JalviewColourScheme.RNAHelices.toString())
-                || globalColourScheme
-                        .equalsIgnoreCase(JalviewColourScheme.TCoffee
-                                .toString()))
+                || globalColourScheme.equalsIgnoreCase(
+                        JalviewColourScheme.TCoffee.toString()))
         {
           jsonAlignmentPojo.setGlobalColorScheme(ResidueColourScheme.NONE);
         }
@@ -228,8 +228,7 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
 
       if (exportSettings.isExportFeatures())
       {
-        jsonAlignmentPojo
-                .setSeqFeatures(sequenceFeatureToJsonPojo(sqs, fr));
+        jsonAlignmentPojo.setSeqFeatures(sequenceFeatureToJsonPojo(sqs));
       }
 
       if (exportSettings.isExportGroups() && seqGroups != null
@@ -309,8 +308,8 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
     return hiddenSections;
   }
 
-  public List<SequenceFeaturesPojo> sequenceFeatureToJsonPojo(
-          SequenceI[] sqs, FeatureRenderer fr)
+  protected List<SequenceFeaturesPojo> sequenceFeatureToJsonPojo(
+          SequenceI[] sqs)
   {
     displayedFeatures = (fr == null) ? null : fr.getFeaturesDisplayed();
     List<SequenceFeaturesPojo> sequenceFeaturesPojo = new ArrayList<>();
@@ -321,41 +320,38 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
 
     FeatureColourFinder finder = new FeatureColourFinder(fr);
 
+    String[] visibleFeatureTypes = displayedFeatures == null ? null
+            : displayedFeatures.getVisibleFeatures().toArray(
+                    new String[displayedFeatures.getVisibleFeatureCount()]);
+
     for (SequenceI seq : sqs)
     {
-      SequenceI dataSetSequence = seq.getDatasetSequence();
-      SequenceFeature[] seqFeatures = (dataSetSequence == null) ? null
-              : seq.getDatasetSequence().getSequenceFeatures();
-
-      seqFeatures = (seqFeatures == null) ? seq.getSequenceFeatures()
-              : seqFeatures;
-      if (seqFeatures == null)
-      {
-        continue;
-      }
-
+      /*
+       * get all features currently visible (and any non-positional features)
+       */
+      List<SequenceFeature> seqFeatures = seq.getFeatures().getAllFeatures(
+              visibleFeatureTypes);
       for (SequenceFeature sf : seqFeatures)
       {
-        if (displayedFeatures != null
-                && displayedFeatures.isVisible(sf.getType()))
-        {
-          SequenceFeaturesPojo jsonFeature = new SequenceFeaturesPojo(
-                  String.valueOf(seq.hashCode()));
-
-          String featureColour = (fr == null) ? null : jalview.util.Format
-                  .getHexString(finder.findFeatureColour(Color.white, seq,
-                          seq.findIndex(sf.getBegin())));
-          jsonFeature.setXstart(seq.findIndex(sf.getBegin()) - 1);
-          jsonFeature.setXend(seq.findIndex(sf.getEnd()));
-          jsonFeature.setType(sf.getType());
-          jsonFeature.setDescription(sf.getDescription());
-          jsonFeature.setLinks(sf.links);
-          jsonFeature.setOtherDetails(sf.otherDetails);
-          jsonFeature.setScore(sf.getScore());
-          jsonFeature.setFillColor(featureColour);
-          jsonFeature.setFeatureGroup(sf.getFeatureGroup());
-          sequenceFeaturesPojo.add(jsonFeature);
-        }
+        SequenceFeaturesPojo jsonFeature = new SequenceFeaturesPojo(
+                String.valueOf(seq.hashCode()));
+
+        String featureColour = (fr == null) ? null : Format
+                .getHexString(finder.findFeatureColour(Color.white, seq,
+                        seq.findIndex(sf.getBegin())));
+        int xStart = sf.getBegin() == 0 ? 0
+                : seq.findIndex(sf.getBegin()) - 1;
+        int xEnd = sf.getEnd() == 0 ? 0 : seq.findIndex(sf.getEnd());
+        jsonFeature.setXstart(xStart);
+        jsonFeature.setXend(xEnd);
+        jsonFeature.setType(sf.getType());
+        jsonFeature.setDescription(sf.getDescription());
+        jsonFeature.setLinks(sf.links);
+        jsonFeature.setOtherDetails(sf.otherDetails);
+        jsonFeature.setScore(sf.getScore());
+        jsonFeature.setFillColor(featureColour);
+        jsonFeature.setFeatureGroup(sf.getFeatureGroup());
+        sequenceFeaturesPojo.add(jsonFeature);
       }
     }
     return sequenceFeaturesPojo;
@@ -409,8 +405,8 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
           annotationPojo.setDisplayCharacter(displayChar);
           if (annotation.colour != null)
           {
-            annotationPojo.setColour(jalview.util.Format
-                    .getHexString(annotation.colour));
+            annotationPojo.setColour(
+                    jalview.util.Format.getHexString(annotation.colour));
           }
           alignAnnotPojo.getAnnotations().add(annotationPojo);
         }
@@ -454,8 +450,8 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
       {
         globalColourScheme = (String) jvSettingsJsonObj
                 .get("globalColorScheme");
-        Boolean showFeatures = Boolean.valueOf(jvSettingsJsonObj.get(
-                "showSeqFeatures").toString());
+        Boolean showFeatures = Boolean.valueOf(
+                jvSettingsJsonObj.get("showSeqFeatures").toString());
         setShowSeqFeatures(showFeatures);
         parseHiddenSeqRefsAsList(jvSettingsJsonObj);
         parseHiddenCols(jvSettingsJsonObj);
@@ -463,8 +459,8 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
 
       hiddenSequences = new ArrayList<>();
       seqMap = new Hashtable<>();
-      for (Iterator<JSONObject> sequenceIter = seqJsonArray.iterator(); sequenceIter
-              .hasNext();)
+      for (Iterator<JSONObject> sequenceIter = seqJsonArray
+              .iterator(); sequenceIter.hasNext();)
       {
         JSONObject sequence = sequenceIter.next();
         String sequcenceString = sequence.get("seq").toString();
@@ -484,22 +480,22 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
 
       parseFeatures(jsonSeqArray);
 
-      for (Iterator<JSONObject> seqGrpIter = seqGrpJsonArray.iterator(); seqGrpIter
-              .hasNext();)
+      for (Iterator<JSONObject> seqGrpIter = seqGrpJsonArray
+              .iterator(); seqGrpIter.hasNext();)
       {
         JSONObject seqGrpObj = seqGrpIter.next();
         String grpName = seqGrpObj.get("groupName").toString();
         String colourScheme = seqGrpObj.get("colourScheme").toString();
         String description = (seqGrpObj.get("description") == null) ? null
                 : seqGrpObj.get("description").toString();
-        boolean displayBoxes = Boolean.valueOf(seqGrpObj
-                .get("displayBoxes").toString());
-        boolean displayText = Boolean.valueOf(seqGrpObj.get("displayText")
-                .toString());
-        boolean colourText = Boolean.valueOf(seqGrpObj.get("colourText")
-                .toString());
-        boolean showNonconserved = Boolean.valueOf(seqGrpObj.get(
-                "showNonconserved").toString());
+        boolean displayBoxes = Boolean
+                .valueOf(seqGrpObj.get("displayBoxes").toString());
+        boolean displayText = Boolean
+                .valueOf(seqGrpObj.get("displayText").toString());
+        boolean colourText = Boolean
+                .valueOf(seqGrpObj.get("colourText").toString());
+        boolean showNonconserved = Boolean
+                .valueOf(seqGrpObj.get("showNonconserved").toString());
         int startRes = Integer
                 .valueOf(seqGrpObj.get("startRes").toString());
         int endRes = Integer.valueOf(seqGrpObj.get("endRes").toString());
@@ -521,23 +517,23 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
         }
         SequenceGroup seqGrp = new SequenceGroup(grpSeqs, grpName, null,
                 displayBoxes, displayText, colourText, startRes, endRes);
-        seqGrp.setColourScheme(ColourSchemeMapper.getJalviewColourScheme(
-                colourScheme, seqGrp));
+        seqGrp.setColourScheme(ColourSchemeMapper
+                .getJalviewColourScheme(colourScheme, seqGrp));
         seqGrp.setShowNonconserved(showNonconserved);
         seqGrp.setDescription(description);
         this.seqGroups.add(seqGrp);
 
       }
 
-      for (Iterator<JSONObject> alAnnotIter = alAnnotJsonArray.iterator(); alAnnotIter
-              .hasNext();)
+      for (Iterator<JSONObject> alAnnotIter = alAnnotJsonArray
+              .iterator(); alAnnotIter.hasNext();)
       {
         JSONObject alAnnot = alAnnotIter.next();
         JSONArray annotJsonArray = (JSONArray) alAnnot.get("annotations");
         Annotation[] annotations = new Annotation[annotJsonArray.size()];
         int count = 0;
-        for (Iterator<JSONObject> annotIter = annotJsonArray.iterator(); annotIter
-                .hasNext();)
+        for (Iterator<JSONObject> annotIter = annotJsonArray
+                .iterator(); annotIter.hasNext();)
         {
           JSONObject annot = annotIter.next();
           if (annot == null)
@@ -546,59 +542,64 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
           }
           else
           {
-            float val = annot.get("value") == null ? null : Float
-                    .valueOf(annot.get("value").toString());
-            String desc = annot.get("description") == null ? null : annot
-                    .get("description").toString();
+            float val = annot.get("value") == null ? null
+                    : Float.valueOf(annot.get("value").toString());
+            String desc = annot.get("description") == null ? null
+                    : annot.get("description").toString();
             char ss = annot.get("secondaryStructure") == null
                     || annot.get("secondaryStructure").toString()
-                            .equalsIgnoreCase("u0000") ? ' ' : annot
-                    .get("secondaryStructure").toString().charAt(0);
+                            .equalsIgnoreCase("u0000") ? ' '
+                                    : annot.get("secondaryStructure")
+                                            .toString().charAt(0);
             String displayChar = annot.get("displayCharacter") == null ? ""
                     : annot.get("displayCharacter").toString();
 
             annotations[count] = new Annotation(displayChar, desc, ss, val);
             if (annot.get("colour") != null)
             {
-              Color color = ColorUtils.parseColourString(annot.get(
-                      "colour").toString());
+              Color color = ColorUtils
+                      .parseColourString(annot.get("colour").toString());
               annotations[count].colour = color;
             }
           }
           ++count;
         }
 
-        AlignmentAnnotation alignAnnot = new AlignmentAnnotation(alAnnot
-                .get("label").toString(), alAnnot.get("description")
-                .toString(), annotations);
-        alignAnnot.graph = (alAnnot.get("graphType") == null) ? 0 : Integer
-                .valueOf(alAnnot.get("graphType").toString());
+        AlignmentAnnotation alignAnnot = new AlignmentAnnotation(
+                alAnnot.get("label").toString(),
+                alAnnot.get("description").toString(), annotations);
+        alignAnnot.graph = (alAnnot.get("graphType") == null) ? 0
+                : Integer.valueOf(alAnnot.get("graphType").toString());
 
         JSONObject diplaySettings = (JSONObject) alAnnot
                 .get("annotationSettings");
         if (diplaySettings != null)
         {
 
-          alignAnnot.scaleColLabel = (diplaySettings.get("scaleColLabel") == null) ? false
-                  : Boolean.valueOf(diplaySettings.get("scaleColLabel")
-                          .toString());
+          alignAnnot.scaleColLabel = (diplaySettings
+                  .get("scaleColLabel") == null) ? false
+                          : Boolean.valueOf(diplaySettings
+                                  .get("scaleColLabel").toString());
           alignAnnot.showAllColLabels = (diplaySettings
-                  .get("showAllColLabels") == null) ? true : Boolean
-                  .valueOf(diplaySettings.get("showAllColLabels")
-                          .toString());
+                  .get("showAllColLabels") == null) ? true
+                          : Boolean.valueOf(diplaySettings
+                                  .get("showAllColLabels").toString());
           alignAnnot.centreColLabels = (diplaySettings
                   .get("centreColLabels") == null) ? true
-                  : Boolean.valueOf(diplaySettings.get("centreColLabels")
-                          .toString());
-          alignAnnot.belowAlignment = (diplaySettings.get("belowAlignment") == null) ? false
-                  : Boolean.valueOf(diplaySettings.get("belowAlignment")
-                          .toString());
-          alignAnnot.visible = (diplaySettings.get("visible") == null) ? true
-                  : Boolean.valueOf(diplaySettings.get("visible")
-                          .toString());
-          alignAnnot.hasIcons = (diplaySettings.get("hasIcon") == null) ? true
-                  : Boolean.valueOf(diplaySettings.get("hasIcon")
-                          .toString());
+                          : Boolean.valueOf(diplaySettings
+                                  .get("centreColLabels").toString());
+          alignAnnot.belowAlignment = (diplaySettings
+                  .get("belowAlignment") == null) ? false
+                          : Boolean.valueOf(diplaySettings
+                                  .get("belowAlignment").toString());
+          alignAnnot.visible = (diplaySettings.get("visible") == null)
+                  ? true
+                  : Boolean.valueOf(
+                          diplaySettings.get("visible").toString());
+          alignAnnot.hasIcons = (diplaySettings.get("hasIcon") == null)
+                  ? true
+                  : Boolean.valueOf(
+                          diplaySettings.get("hasIcon").toString());
 
         }
         if (alAnnot.get("score") != null)
@@ -607,11 +608,12 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
                   .valueOf(alAnnot.get("score").toString());
         }
 
-        String calcId = (alAnnot.get("calcId") == null) ? "" : alAnnot.get(
-                "calcId").toString();
+        String calcId = (alAnnot.get("calcId") == null) ? ""
+                : alAnnot.get("calcId").toString();
         alignAnnot.setCalcId(calcId);
-        String seqHash = (alAnnot.get("sequenceRef") != null) ? alAnnot
-                .get("sequenceRef").toString() : null;
+        String seqHash = (alAnnot.get("sequenceRef") != null)
+                ? alAnnot.get("sequenceRef").toString()
+                : null;
 
         Sequence sequence = (seqHash != null) ? seqMap.get(seqHash) : null;
         if (sequence != null)
@@ -673,20 +675,31 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
     if (jsonSeqFeatures != null)
     {
       displayedFeatures = new FeaturesDisplayed();
-      for (Iterator<JSONObject> seqFeatureItr = jsonSeqFeatures.iterator(); seqFeatureItr
-              .hasNext();)
+      for (Iterator<JSONObject> seqFeatureItr = jsonSeqFeatures
+              .iterator(); seqFeatureItr.hasNext();)
       {
         JSONObject jsonFeature = seqFeatureItr.next();
         Long begin = (Long) jsonFeature.get("xStart");
         Long end = (Long) jsonFeature.get("xEnd");
         String type = (String) jsonFeature.get("type");
         String featureGrp = (String) jsonFeature.get("featureGroup");
-        String descripiton = (String) jsonFeature.get("description");
+        String description = (String) jsonFeature.get("description");
         String seqRef = (String) jsonFeature.get("sequenceRef");
         Float score = Float.valueOf(jsonFeature.get("score").toString());
 
         Sequence seq = seqMap.get(seqRef);
-        SequenceFeature sequenceFeature = new SequenceFeature();
+
+        /*
+         * begin/end of 0 is for a non-positional feature
+         */
+        int featureBegin = begin.intValue() == 0 ? 0 : seq
+                .findPosition(begin.intValue());
+        int featureEnd = end.intValue() == 0 ? 0 : seq.findPosition(end
+                .intValue()) - 1;
+
+        SequenceFeature sequenceFeature = new SequenceFeature(type,
+                description, featureBegin, featureEnd, score, featureGrp);
+
         JSONArray linksJsonArray = (JSONArray) jsonFeature.get("links");
         if (linksJsonArray != null && linksJsonArray.size() > 0)
         {
@@ -697,12 +710,7 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
             sequenceFeature.addLink(link);
           }
         }
-        sequenceFeature.setFeatureGroup(featureGrp);
-        sequenceFeature.setScore(score);
-        sequenceFeature.setDescription(descripiton);
-        sequenceFeature.setType(type);
-        sequenceFeature.setBegin(seq.findPosition(begin.intValue()));
-        sequenceFeature.setEnd(seq.findPosition(end.intValue()) - 1);
+
         seq.addSequenceFeature(sequenceFeature);
         displayedFeatures.setVisible(type);
       }
@@ -757,8 +765,8 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
         }
       }
     }
-    globalColourScheme = ColourSchemeProperty.getColourName(viewport
-            .getGlobalColourScheme());
+    globalColourScheme = ColourSchemeProperty
+            .getColourName(viewport.getGlobalColourScheme());
     setDisplayedFeatures(viewport.getFeaturesDisplayed());
     showSeqFeatures = viewport.isShowSequenceFeatures();
 
index 98cd162..c49e34f 100755 (executable)
@@ -65,7 +65,8 @@ public class JalviewFileChooser extends JFileChooser
    * @param selected
    * @return
    */
-  public static JalviewFileChooser forRead(String directory, String selected)
+  public static JalviewFileChooser forRead(String directory,
+          String selected)
   {
     List<String> extensions = new ArrayList<String>();
     List<String> descs = new ArrayList<String>();
@@ -131,7 +132,8 @@ public class JalviewFileChooser extends JFileChooser
   public JalviewFileChooser(String extension, String desc)
   {
     this(Cache.getProperty("LAST_DIRECTORY"), new String[] { extension },
-            new String[] { desc }, desc, true);
+            new String[]
+            { desc }, desc, true);
   }
 
   JalviewFileChooser(String dir, String[] extensions, String[] descs,
@@ -371,8 +373,8 @@ public class JalviewFileChooser extends JFileChooser
         }
       });
 
-      this.setBorder(new javax.swing.border.TitledBorder(MessageManager
-              .getString("label.recently_opened")));
+      this.setBorder(new javax.swing.border.TitledBorder(
+              MessageManager.getString("label.recently_opened")));
 
       final JScrollPane scroller = new JScrollPane(list);
 
@@ -398,8 +400,8 @@ public class JalviewFileChooser extends JFileChooser
         @Override
         public void run()
         {
-          scroller.getHorizontalScrollBar().setValue(
-                  scroller.getHorizontalScrollBar().getMaximum());
+          scroller.getHorizontalScrollBar()
+                  .setValue(scroller.getHorizontalScrollBar().getMaximum());
         }
       });
 
index 6bfb3b9..b2fe587 100755 (executable)
@@ -44,8 +44,8 @@ public class JalviewFileView extends FileView
       String exts = ff.getExtensions();
       for (String ext : exts.split(","))
       {
-        extensions.put(ext.trim().toLowerCase(), desc
-                + ("jar".equals(ext) ? " (old)" : ""));
+        extensions.put(ext.trim().toLowerCase(),
+                desc + ("jar".equals(ext) ? " (old)" : ""));
       }
     }
   }
@@ -136,8 +136,8 @@ public class JalviewFileView extends FileView
         }
         else
         {
-          System.err
-                  .println("JalviewFileView.createImageIcon: Couldn't find file: "
+          System.err.println(
+                  "JalviewFileView.createImageIcon: Couldn't find file: "
                           + filePath);
         }
         icons.put(filePath, icon);
index 3feae5d..c9f1fcf 100755 (executable)
@@ -59,22 +59,19 @@ public class JnetAnnotationMaker
     // in the future we could search for the query
     // sequence in the alignment before calling this function.
     SequenceI seqRef = al.getSequenceAt(firstSeq);
-    int width = preds[0].getSequence().length;
+    int width = preds[0].getLength();
     int[] gapmap = al.getSequenceAt(firstSeq).gapMap();
     if ((delMap != null && delMap.length > width)
             || (delMap == null && gapmap.length != width))
     {
-      throw (new Exception(
-              MessageManager
-                      .formatMessage(
-                              "exception.number_of_residues_in_query_sequence_differ_from_prediction",
-                              new String[] {
-                                  (delMap == null ? "" : MessageManager
-                                          .getString("label.mapped")),
-                                  al.getSequenceAt(firstSeq).getName(),
-                                  al.getSequenceAt(firstSeq)
-                                          .getSequenceAsString(),
-                                  Integer.valueOf(width).toString() })));
+      throw (new Exception(MessageManager.formatMessage(
+              "exception.number_of_residues_in_query_sequence_differ_from_prediction",
+              new String[]
+              { (delMap == null ? ""
+                      : MessageManager.getString("label.mapped")),
+                  al.getSequenceAt(firstSeq).getName(),
+                  al.getSequenceAt(firstSeq).getSequenceAsString(),
+                  Integer.valueOf(width).toString() })));
     }
 
     AlignmentAnnotation annot;
@@ -98,7 +95,8 @@ public class JnetAnnotationMaker
       {
         if (id.startsWith("JNETSOL"))
         {
-          float amnt = (id.endsWith("25") ? 3f : id.endsWith("5") ? 6f : 9f);
+          float amnt = (id.endsWith("25") ? 3f
+                  : id.endsWith("5") ? 6f : 9f);
           for (int spos = 0; spos < width; spos++)
           {
             int sposw = (delMap == null) ? gapmap[spos]
@@ -222,8 +220,7 @@ public class JnetAnnotationMaker
     if (!firstsol)
     {
       // add the solvent accessibility
-      annot = new AlignmentAnnotation(
-              "Jnet Burial",
+      annot = new AlignmentAnnotation("Jnet Burial",
               "<html>Prediction of Solvent Accessibility<br/>levels are<ul><li>0 - Exposed</li><li>3 - 25% or more S.A. accessible</li><li>6 - 5% or more S.A. accessible</li><li>9 - Buried (<5% exposed)</li></ul>",
               sol, 0f, 9f, AlignmentAnnotation.BAR_GRAPH);
 
@@ -234,8 +231,8 @@ public class JnetAnnotationMaker
         seqRef.addAlignmentAnnotation(annot);
       }
       al.addAnnotation(annot);
-      al.setAnnotationIndex(annot, al.getAlignmentAnnotation().length
-              - existingAnnotations - 1);
+      al.setAnnotationIndex(annot,
+              al.getAlignmentAnnotation().length - existingAnnotations - 1);
     }
     // Hashtable scores = prediction.getScores();
 
index f379724..df2bed2 100755 (executable)
@@ -278,10 +278,10 @@ public class MSFfile extends AlignFile
       i++;
     }
 
-    Format maxLenpad = new Format("%" + (new String("" + max)).length()
-            + "d");
-    Format maxChkpad = new Format("%" + (new String("1" + max)).length()
-            + "d");
+    Format maxLenpad = new Format(
+            "%" + (new String("" + max)).length() + "d");
+    Format maxChkpad = new Format(
+            "%" + (new String("1" + max)).length() + "d");
     i = 0;
 
     int bigChecksum = 0;
@@ -294,7 +294,7 @@ public class MSFfile extends AlignFile
     }
 
     long maxNB = 0;
-    out.append("   MSF: " + s[0].getSequence().length + "   Type: "
+    out.append("   MSF: " + s[0].getLength() + "   Type: "
             + (is_NA ? "N" : "P") + "    Check:  " + (bigChecksum % 10000)
             + "   ..");
     out.append(newline);
@@ -310,9 +310,9 @@ public class MSFfile extends AlignFile
 
       nameBlock[i] = new String("  Name: " + printId(s[i], jvSuffix) + " ");
 
-      idBlock[i] = new String("Len: "
-              + maxLenpad.form(s[i].getSequence().length) + "  Check: "
-              + maxChkpad.form(checksums[i]) + "  Weight: 1.00" + newline);
+      idBlock[i] = new String("Len: " + maxLenpad.form(s[i].getLength())
+              + "  Check: " + maxChkpad.form(checksums[i])
+              + "  Weight: 1.00" + newline);
 
       if (s[i].getName().length() > maxid)
       {
@@ -369,8 +369,9 @@ public class MSFfile extends AlignFile
           int start = (i * 50) + (k * 10);
           int end = start + 10;
 
-          if ((end < s[j].getSequence().length)
-                  && (start < s[j].getSequence().length))
+          int length = s[j].getLength();
+          if ((end < length)
+                  && (start < length))
           {
             out.append(s[j].getSequence(start, end));
 
@@ -385,7 +386,7 @@ public class MSFfile extends AlignFile
           }
           else
           {
-            if (start < s[j].getSequence().length)
+            if (start < length)
             {
               out.append(s[j].getSequenceAsString().substring(start));
               out.append(newline);
index 1ab9545..442278d 100755 (executable)
@@ -61,7 +61,8 @@ public class ModellerDescription
    */
   final int Types[] = { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 };
 
-  final char Padding[] = { ' ', ' ', ' ', '.', ' ', '.', '.', '.', '.', '.' };
+  final char Padding[] = { ' ', ' ', ' ', '.', ' ', '.', '.', '.', '.',
+      '.' };
 
   java.util.Hashtable fields = new java.util.Hashtable();
 
@@ -244,15 +245,15 @@ public class ModellerDescription
     {
       // Set start and end before we update the type (in the case of a
       // synthesized field set)
-      if (getStartCode() == null
-              || (getStartNum() != seq.getStart() && getStartCode().val != null))
+      if (getStartCode() == null || (getStartNum() != seq.getStart()
+              && getStartCode().val != null))
       {
         // unset or user updated sequence start position
         setStartCode(seq.getStart());
       }
 
-      if (getEndCode() == null
-              || (getEndNum() != seq.getEnd() && getStartCode() != null && getStartCode().val != null))
+      if (getEndCode() == null || (getEndNum() != seq.getEnd()
+              && getStartCode() != null && getStartCode().val != null))
       {
         setEndCode(seq.getEnd());
       }
index 765ea95..c414145 100755 (executable)
@@ -87,14 +87,14 @@ public class NewickFile extends FileParse
 
   boolean printRootInfo = true;
 
-  private com.stevesoft.pat.Regex[] NodeSafeName = new com.stevesoft.pat.Regex[]
-  { new com.stevesoft.pat.Regex().perlCode("m/[\\[,:'()]/"), // test for
+  private com.stevesoft.pat.Regex[] NodeSafeName = new com.stevesoft.pat.Regex[] {
+      new com.stevesoft.pat.Regex().perlCode("m/[\\[,:'()]/"), // test for
       // requiring
       // quotes
       new com.stevesoft.pat.Regex().perlCode("s/'/''/"), // escaping quote
       // characters
       new com.stevesoft.pat.Regex().perlCode("s/\\/w/_/") // unqoted whitespace
-  // transformation
+      // transformation
   };
 
   char QuoteChar = '\'';
@@ -218,13 +218,10 @@ public class NewickFile extends FileParse
   private String ErrorStringrange(String Error, String Er, int r, int p,
           String s)
   {
-    return ((Error == null) ? "" : Error)
-            + Er
-            + " at position "
-            + p
-            + " ( "
+    return ((Error == null) ? "" : Error) + Er + " at position " + p + " ( "
             + s.substring(((p - r) < 0) ? 0 : (p - r),
-                    ((p + r) > s.length()) ? s.length() : (p + r)) + " )\n";
+                    ((p + r) > s.length()) ? s.length() : (p + r))
+            + " )\n";
   }
 
   // @tree annotations
@@ -363,8 +360,8 @@ public class NewickFile extends FileParse
         if (qnodename.searchFrom(nf, fcp))
         {
           int nl = qnodename.stringMatched().length();
-          nodename = new String(qnodename.stringMatched().substring(1,
-                  nl - 1));
+          nodename = new String(
+                  qnodename.stringMatched().substring(1, nl - 1));
           // unpack any escaped colons
           com.stevesoft.pat.Regex xpandquotes = com.stevesoft.pat.Regex
                   .perlCode("s/''/'/");
@@ -387,8 +384,8 @@ public class NewickFile extends FileParse
         {
           if (d != -1)
           {
-            Error = ErrorStringrange(Error, "Wayward semicolon (depth=" + d
-                    + ")", 7, fcp, nf);
+            Error = ErrorStringrange(Error,
+                    "Wayward semicolon (depth=" + d + ")", 7, fcp, nf);
           }
           // cp advanced at the end of default
         }
@@ -401,7 +398,8 @@ public class NewickFile extends FileParse
            * '"+nf.substring(cp,fcp)+"'"); }
            */
           // verify termination.
-          com.stevesoft.pat.Regex comment = new com.stevesoft.pat.Regex("]");
+          com.stevesoft.pat.Regex comment = new com.stevesoft.pat.Regex(
+                  "]");
           if (comment.searchFrom(nf, fcp))
           {
             // Skip the comment field
@@ -441,8 +439,7 @@ public class NewickFile extends FileParse
         com.stevesoft.pat.Regex ndist = new com.stevesoft.pat.Regex(
                 ":([-0-9Ee.+]+)");
 
-        if (!parsednodename
-                && uqnodename.search(fstring)
+        if (!parsednodename && uqnodename.search(fstring)
                 && ((uqnodename.matchedFrom(1) == 0) || (fstring
                         .charAt(uqnodename.matchedFrom(1) - 1) != ':'))) // JBPNote
         // HACK!
@@ -469,15 +466,14 @@ public class NewickFile extends FileParse
 
         if (nbootstrap.search(fstring))
         {
-          if (nbootstrap.stringMatched(1).equals(
-                  uqnodename.stringMatched(1)))
+          if (nbootstrap.stringMatched(1)
+                  .equals(uqnodename.stringMatched(1)))
           {
             nodename = null; // no nodename here.
           }
-          if (nodename == null
-                  || nodename.length() == 0
-                  || nbootstrap.matchedFrom(1) > (uqnodename.matchedFrom(1) + uqnodename
-                          .stringMatched().length()))
+          if (nodename == null || nodename.length() == 0
+                  || nbootstrap.matchedFrom(1) > (uqnodename.matchedFrom(1)
+                          + uqnodename.stringMatched().length()))
           {
             try
             {
@@ -486,9 +482,8 @@ public class NewickFile extends FileParse
               HasBootstrap = true;
             } catch (Exception e)
             {
-              Error = ErrorStringrange(Error,
-                      "Can't parse bootstrap value", 4,
-                      ncp + nbootstrap.matchedFrom(), nf);
+              Error = ErrorStringrange(Error, "Can't parse bootstrap value",
+                      4, ncp + nbootstrap.matchedFrom(), nf);
             }
           }
         }
@@ -565,8 +560,7 @@ public class NewickFile extends FileParse
 
           if ((d > -1) && (c == null))
           {
-            Error = ErrorStringrange(
-                    Error,
+            Error = ErrorStringrange(Error,
                     "File broke algorithm: Lost place in tree (is there an extra ')' ?)",
                     7, fcp, nf);
           }
@@ -616,14 +610,15 @@ public class NewickFile extends FileParse
 
     if (Error != null)
     {
-      throw (new IOException(MessageManager.formatMessage(
-              "exception.newfile", new String[] { Error.toString() })));
+      throw (new IOException(
+              MessageManager.formatMessage("exception.newfile", new String[]
+              { Error.toString() })));
     }
     if (root == null)
     {
-      throw (new IOException(MessageManager.formatMessage(
-              "exception.newfile", new String[] { MessageManager
-                      .getString("label.no_tree_read_in") })));
+      throw (new IOException(
+              MessageManager.formatMessage("exception.newfile", new String[]
+              { MessageManager.getString("label.no_tree_read_in") })));
     }
     // THe next line is failing for topali trees - not sure why yet. if
     // (root.right()!=null && root.isDummy())
@@ -675,8 +670,8 @@ public class NewickFile extends FileParse
             // more codes here.
           } catch (Exception e)
           {
-            System.err.println("Couldn't parse code '" + code + "' = '"
-                    + value + "'");
+            System.err.println(
+                    "Couldn't parse code '" + code + "' = '" + value + "'");
             e.printStackTrace(System.err);
           }
         }
@@ -847,10 +842,10 @@ public class NewickFile extends FileParse
   private String printNodeField(SequenceNode c)
   {
     return ((c.getName() == null) ? "" : nodeName(c.getName()))
-            + ((HasBootstrap) ? ((c.getBootstrap() > -1) ? ((c.getName() != null ? " "
-                    : "") + c.getBootstrap())
-                    : "")
-                    : "") + ((HasDistances) ? (":" + c.dist) : "");
+            + ((HasBootstrap) ? ((c.getBootstrap() > -1)
+                    ? ((c.getName() != null ? " " : "") + c.getBootstrap())
+                    : "") : "")
+            + ((HasDistances) ? (":" + c.dist) : "");
   }
 
   /**
@@ -863,12 +858,16 @@ public class NewickFile extends FileParse
    */
   private String printRootField(SequenceNode root)
   {
-    return (printRootInfo) ? (((root.getName() == null) ? ""
-            : nodeName(root.getName()))
-            + ((HasBootstrap) ? ((root.getBootstrap() > -1) ? ((root
-                    .getName() != null ? " " : "") + +root.getBootstrap())
-                    : "") : "") + ((RootHasDistance) ? (":" + root.dist)
-            : "")) : "";
+    return (printRootInfo)
+            ? (((root.getName() == null) ? "" : nodeName(root.getName()))
+                    + ((HasBootstrap)
+                            ? ((root.getBootstrap() > -1)
+                                    ? ((root.getName() != null ? " " : "")
+                                            + +root.getBootstrap())
+                                    : "")
+                            : "")
+                    + ((RootHasDistance) ? (":" + root.dist) : ""))
+            : "";
   }
 
   // Non recursive call deals with root node properties
@@ -948,8 +947,8 @@ public class NewickFile extends FileParse
     {
       if (args == null || args.length != 1)
       {
-        System.err
-                .println("Takes one argument - file name of a newick tree file.");
+        System.err.println(
+                "Takes one argument - file name of a newick tree file.");
         System.exit(0);
       }
 
index bc22fae..6b9dc3f 100755 (executable)
@@ -117,8 +117,8 @@ public class PfamFile extends AlignFile
 
     if (noSeqs < 1)
     {
-      throw new IOException(
-              MessageManager.getString("exception.pfam_no_sequences_found"));
+      throw new IOException(MessageManager
+              .getString("exception.pfam_no_sequences_found"));
     }
 
     for (i = 0; i < headers.size(); i++)
@@ -131,8 +131,8 @@ public class PfamFile extends AlignFile
         }
 
         Sequence newSeq = parseId(headers.get(i).toString());
-        newSeq.setSequence(seqhash.get(headers.get(i).toString())
-                .toString());
+        newSeq.setSequence(
+                seqhash.get(headers.get(i).toString()).toString());
         seqs.addElement(newSeq);
       }
       else
@@ -157,10 +157,7 @@ public class PfamFile extends AlignFile
     {
       String tmp = printId(s[i], jvsuffix);
 
-      if (s[i].getSequence().length > max)
-      {
-        max = s[i].getSequence().length;
-      }
+      max = Math.max(max, s[i].getLength());
 
       if (tmp.length() > maxid)
       {
index e8fe7e9..539826f 100644 (file)
@@ -27,9 +27,9 @@ import java.io.IOException;
 
 /**
  * <p>
- * Parser and exporter for PHYLIP file format, as defined <a
- * href="http://evolution.genetics.washington.edu/phylip/doc/main.html">in the
- * documentation</a>. The parser imports PHYLIP files in both sequential and
+ * Parser and exporter for PHYLIP file format, as defined
+ * <a href="http://evolution.genetics.washington.edu/phylip/doc/main.html">in
+ * the documentation</a>. The parser imports PHYLIP files in both sequential and
  * interleaved format, and (currently) exports in interleaved format (using 60
  * characters per matrix for the sequence).
  * <p>
@@ -38,7 +38,8 @@ import java.io.IOException;
  * The following assumptions have been made for input
  * <ul>
  * <li>Sequences are expressed as letters, not real numbers with decimal points
- * separated by blanks (which is a valid option according to the specification)</li>
+ * separated by blanks (which is a valid option according to the
+ * specification)</li>
  * </ul>
  *
  * The following assumptions have been made for output
@@ -112,8 +113,8 @@ public class PhylipFile extends AlignFile
                 "First line must contain the number of specifies and number of characters");
       }
 
-      int numberSpecies = Integer.parseInt(lineElements[0]), numberCharacters = Integer
-              .parseInt(lineElements[1]);
+      int numberSpecies = Integer.parseInt(lineElements[0]),
+              numberCharacters = Integer.parseInt(lineElements[1]);
 
       if (numberSpecies <= 0)
       {
@@ -144,8 +145,8 @@ public class PhylipFile extends AlignFile
         }
         else
         {
-          sequenceElements[i] = parseId(validateName(potentialName
-                  .substring(0, tabIndex)));
+          sequenceElements[i] = parseId(
+                  validateName(potentialName.substring(0, tabIndex)));
           sequences[i] = new StringBuffer(
                   removeWhitespace(line.substring(tabIndex)));
         }
@@ -222,8 +223,8 @@ public class PhylipFile extends AlignFile
     {
       if (name.indexOf(c) > -1)
       {
-        throw new IOException("Species name contains illegal character "
-                + c);
+        throw new IOException(
+                "Species name contains illegal character " + c);
       }
     }
     return name;
@@ -247,7 +248,7 @@ public class PhylipFile extends AlignFile
     sb.append(" ");
     // if there are no sequences, then define the number of characters as 0
     sb.append(
-            (sqs.length > 0) ? Integer.toString(sqs[0].getSequence().length)
+(sqs.length > 0) ? Integer.toString(sqs[0].getLength())
                     : "0")
             .append(newline);
 
@@ -279,13 +280,13 @@ public class PhylipFile extends AlignFile
       // sequential has the entire sequence following the name
       if (sequential)
       {
-        sb.append(s.getSequence());
+        sb.append(s.getSequenceAsString());
       }
       else
       {
         // Jalview ensures all sequences are of same length so no need
         // to keep track of min/max length
-        sequenceLength = s.getSequence().length;
+        sequenceLength = s.getLength();
         // interleaved breaks the sequence into chunks for
         // interleavedColumns characters
         sb.append(s.getSequence(0,
@@ -313,9 +314,8 @@ public class PhylipFile extends AlignFile
         int start = i * numInterleavedColumns;
         for (SequenceI s : sqs)
         {
-          sb.append(
-                  s.getSequence(start, Math.min(start
-                          + numInterleavedColumns, sequenceLength)))
+          sb.append(s.getSequence(start,
+                  Math.min(start + numInterleavedColumns, sequenceLength)))
                   .append(newline);
         }
       }
index 84be72c..f7f718b 100755 (executable)
@@ -92,7 +92,7 @@ public class PileUpfile extends MSFfile
       i++;
     }
 
-    out.append("   MSF: " + s[0].getSequence().length
+    out.append("   MSF: " + s[0].getLength()
             + "   Type: P    Check:  " + bigChecksum % 10000 + "   ..");
     out.append(newline);
     out.append(newline);
@@ -103,8 +103,8 @@ public class PileUpfile extends MSFfile
     {
       String seq = s[i].getSequenceAsString();
       out.append(" Name: " + printId(s[i], jvsuffix) + " oo  Len:  "
-              + seq.length()
-              + "  Check:  " + checksums[i] + "  Weight:  1.00");
+              + seq.length() + "  Check:  " + checksums[i]
+              + "  Weight:  1.00");
       out.append(newline);
 
       if (seq.length() > max)
@@ -151,8 +151,8 @@ public class PileUpfile extends MSFfile
           int start = (i * 50) + (k * 10);
           int end = start + 10;
 
-          if ((end < s[j].getSequence().length)
-                  && (start < s[j].getSequence().length))
+          int length = s[j].getLength();
+          if ((end < length) && (start < length))
           {
             out.append(s[j].getSequence(start, end));
 
@@ -167,7 +167,7 @@ public class PileUpfile extends MSFfile
           }
           else
           {
-            if (start < s[j].getSequence().length)
+            if (start < length)
             {
               out.append(s[j].getSequenceAsString().substring(start));
               out.append(newline);
index eb623d3..4d3ddc1 100644 (file)
@@ -103,35 +103,35 @@ public class RnamlFile extends AlignFile
     } catch (ExceptionPermissionDenied pdx)
     {
       errormessage = MessageManager.formatMessage(
-              "exception.rnaml_couldnt_access_datasource",
-              new String[] { pdx.getMessage() });
+              "exception.rnaml_couldnt_access_datasource", new String[]
+              { pdx.getMessage() });
       throw new IOException(pdx);
     } catch (ExceptionLoadingFailed lf)
     {
       errormessage = MessageManager.formatMessage(
-              "exception.ranml_couldnt_process_data",
-              new String[] { lf.getMessage() });
+              "exception.ranml_couldnt_process_data", new String[]
+              { lf.getMessage() });
       throw new IOException(lf);
     } catch (ExceptionFileFormatOrSyntax iff)
     {
-      errormessage = MessageManager.formatMessage(
-              "exception.ranml_invalid_file",
-              new String[] { iff.getMessage() });
+      errormessage = MessageManager
+              .formatMessage("exception.ranml_invalid_file", new String[]
+              { iff.getMessage() });
       throw new IOException(iff);
     } catch (Exception x)
     {
       error = true;
       errormessage = MessageManager.formatMessage(
-              "exception.ranml_problem_parsing_data",
-              new String[] { x.getMessage() });
+              "exception.ranml_problem_parsing_data", new String[]
+              { x.getMessage() });
       throw new IOException(errormessage, x);
     }
   }
 
   @SuppressWarnings("unchecked")
-  public void _parse() throws FileNotFoundException,
-          ExceptionPermissionDenied, ExceptionLoadingFailed,
-          ExceptionFileFormatOrSyntax
+  public void _parse()
+          throws FileNotFoundException, ExceptionPermissionDenied,
+          ExceptionLoadingFailed, ExceptionFileFormatOrSyntax
   {
 
     result = RNAFactory.loadSecStrRNAML(getReader());
@@ -172,15 +172,16 @@ public class RnamlFile extends AlignFile
       }
       for (int k = 0; k < rna.length(); k++)
       {
-        ann[k] = new Annotation(annot[k], "", Rna.getRNASecStrucState(
-                annot[k]).charAt(0), 0f);
+        ann[k] = new Annotation(annot[k], "",
+                Rna.getRNASecStrucState(annot[k]).charAt(0), 0f);
       }
 
       AlignmentAnnotation align = new AlignmentAnnotation(
               "Secondary Structure",
-              current.getID().trim().length() > 0 ? "Secondary Structure for "
-                      + current.getID()
-                      : "", ann);
+              current.getID().trim().length() > 0
+                      ? "Secondary Structure for " + current.getID()
+                      : "",
+              ann);
 
       sqs[i].addAlignmentAnnotation(align);
       sqs[i].setRNA(result.get(i));
index 6b2f891..0b70dce 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.io;
 
 import jalview.analysis.scoremodels.ScoreMatrix;
@@ -30,8 +50,8 @@ import java.util.StringTokenizer;
  * and the substitution scores
  * </pre>
  */
-public class ScoreMatrixFile extends AlignFile implements
-        AlignmentFileReaderI
+public class ScoreMatrixFile extends AlignFile
+        implements AlignmentFileReaderI
 {
   // first non-comment line identifier - also checked in IdentifyFile
   public static final String SCOREMATRIX = "SCOREMATRIX";
@@ -186,9 +206,9 @@ public class ScoreMatrixFile extends AlignFile implements
      */
     if (row < size)
     {
-      err = String
-              .format("Expected %d rows of score data in score matrix but only found %d",
-                      size, row);
+      err = String.format(
+              "Expected %d rows of score data in score matrix but only found %d",
+              size, row);
       throw new FileFormatException(err);
     }
 
@@ -312,9 +332,9 @@ public class ScoreMatrixFile extends AlignFile implements
       String symbol = scoreLine.nextToken();
       if (symbol.length() > 1 || symbol.charAt(0) != alphabet[row])
       {
-        err = String
-                .format("Error parsing score matrix at line %d, expected '%s' but found '%s'",
-                        lineNo, alphabet[row], symbol);
+        err = String.format(
+                "Error parsing score matrix at line %d, expected '%s' but found '%s'",
+                lineNo, alphabet[row], symbol);
         throw new FileFormatException(err);
       }
       tokenCount = scoreLine.countTokens(); // excluding guide symbol
@@ -328,7 +348,7 @@ public class ScoreMatrixFile extends AlignFile implements
       err = String.format(
               "Expected %d scores at line %d: '%s' but found %d", row + 1,
               lineNo, data, tokenCount);
-        throw new FileFormatException(err);
+      throw new FileFormatException(err);
     }
 
     if (!isLowerDiagonalOnly && tokenCount != size)
@@ -359,9 +379,8 @@ public class ScoreMatrixFile extends AlignFile implements
         col++;
       } catch (NumberFormatException e)
       {
-        err = String.format(
-                "Invalid score value '%s' at line %d column %d", value,
-                lineNo, col);
+        err = String.format("Invalid score value '%s' at line %d column %d",
+                value, lineNo, col);
         throw new FileFormatException(err);
       }
     }
@@ -387,7 +406,7 @@ public class ScoreMatrixFile extends AlignFile implements
   {
     String err = "Unexpected aaIndex score matrix data at line " + lineNo
             + ": " + data;
-    
+
     try
     {
       String[] toks = data.split(",");
index 6c8f40f..f1ebcac 100644 (file)
@@ -57,7 +57,8 @@ public class SequenceAnnotationReport
   final String linkImageURL;
 
   /*
-   * Comparator to order DBRefEntry by Source + accession id (case-insensitive)
+   * Comparator to order DBRefEntry by Source + accession id (case-insensitive),
+   * with 'Primary' sources placed before others
    */
   private static Comparator<DBRefEntry> comparator = new Comparator<DBRefEntry>()
   {
@@ -77,14 +78,14 @@ public class SequenceAnnotationReport
       {
         return 1;
       }
-      int comp = s1 == null ? -1 : (s2 == null ? 1 : s1
-              .compareToIgnoreCase(s2));
+      int comp = s1 == null ? -1
+              : (s2 == null ? 1 : s1.compareToIgnoreCase(s2));
       if (comp == 0)
       {
         String a1 = ref1.getAccessionId();
         String a2 = ref2.getAccessionId();
-        comp = a1 == null ? -1 : (a2 == null ? 1 : a1
-                .compareToIgnoreCase(a2));
+        comp = a1 == null ? -1
+                : (a2 == null ? 1 : a1.compareToIgnoreCase(a2));
       }
       return comp;
     }
@@ -150,8 +151,7 @@ public class SequenceAnnotationReport
           sb.append("<br>");
         }
         sb.append(feature.getType()).append(" ").append(feature.getBegin())
-                .append(":")
-                .append(feature.getEnd());
+                .append(":").append(feature.getEnd());
       }
     }
     else
@@ -223,8 +223,8 @@ public class SequenceAnnotationReport
         // check score should be shown
         if (!Float.isNaN(feature.getScore()))
         {
-          float[][] rng = (minmax == null) ? null : minmax.get(feature
-                  .getType());
+          float[][] rng = (minmax == null) ? null
+                  : minmax.get(feature.getType());
           if (rng != null && rng[0] != null && rng[0][0] != rng[0][1])
           {
             sb.append(" Score=").append(String.valueOf(feature.getScore()));
@@ -268,21 +268,19 @@ public class SequenceAnnotationReport
           {
             for (List<String> urllink : createLinksFrom(null, urlstring))
             {
-              sb.append("<br/> <a href=\""
-                      + urllink.get(3)
-                      + "\" target=\""
-                      + urllink.get(0)
-                      + "\">"
+              sb.append("<br/> <a href=\"" + urllink.get(3) + "\" target=\""
+                      + urllink.get(0) + "\">"
                       + (urllink.get(0).toLowerCase()
-                              .equals(urllink.get(1).toLowerCase()) ? urllink
-                              .get(0) : (urllink.get(0) + ":" + urllink
-                              .get(1)))
+                              .equals(urllink.get(1).toLowerCase())
+                                      ? urllink.get(0)
+                                      : (urllink.get(0) + ":"
+                                              + urllink.get(1)))
                       + "</a></br>");
             }
           } catch (Exception x)
           {
-            System.err.println("problem when creating links from "
-                    + urlstring);
+            System.err.println(
+                    "problem when creating links from " + urlstring);
             x.printStackTrace();
           }
         }
@@ -356,108 +354,129 @@ public class SequenceAnnotationReport
     {
       ds = ds.getDatasetSequence();
     }
+    
+    if (showDbRefs)
+    {
+      maxWidth = Math.max(maxWidth, appendDbRefs(sb, ds, summary));
+    }
+
+    /*
+     * add non-positional features if wanted
+     */
+    if (showNpFeats)
+    {
+      for (SequenceFeature sf : sequence.getFeatures()
+              .getNonPositionalFeatures())
+      {
+        int sz = -sb.length();
+        appendFeature(sb, 0, minmax, sf);
+        sz += sb.length();
+        maxWidth = Math.max(maxWidth, sz);
+      }
+    }
+    sb.append("</i>");
+    return maxWidth;
+  }
+
+  /**
+   * A helper method that appends any DBRefs, returning the maximum line length
+   * added
+   * 
+   * @param sb
+   * @param ds
+   * @param summary
+   * @return
+   */
+  protected int appendDbRefs(final StringBuilder sb, SequenceI ds,
+          boolean summary)
+  {
     DBRefEntry[] dbrefs = ds.getDBRefs();
-    if (showDbRefs && dbrefs != null)
+    if (dbrefs == null)
+    {
+      return 0;
+    }
+
+    // note this sorts the refs held on the sequence!
+    Arrays.sort(dbrefs, comparator);
+    boolean ellipsis = false;
+    String source = null;
+    String lastSource = null;
+    int countForSource = 0;
+    int sourceCount = 0;
+    boolean moreSources = false;
+    int maxLineLength = 0;
+    int lineLength = 0;
+
+    for (DBRefEntry ref : dbrefs)
     {
-      // note this sorts the refs held on the sequence!
-      Arrays.sort(dbrefs, comparator);
-      boolean ellipsis = false;
-      String source = null;
-      String lastSource = null;
-      int countForSource = 0;
-      int sourceCount = 0;
-      boolean moreSources = false;
-      int lineLength = 0;
-
-      for (DBRefEntry ref : dbrefs)
+      source = ref.getSource();
+      if (source == null)
       {
-        source = ref.getSource();
-        if (source == null)
-        {
-          // shouldn't happen
-          continue;
-        }
-        boolean sourceChanged = !source.equals(lastSource);
-        if (sourceChanged)
-        {
-          lineLength = 0;
-          countForSource = 0;
-          sourceCount++;
-        }
-        if (sourceCount > MAX_SOURCES && summary)
-        {
-          ellipsis = true;
-          moreSources = true;
-          break;
-        }
-        lastSource = source;
-        countForSource++;
-        if (countForSource == 1 || !summary)
-        {
-          sb.append("<br>");
-        }
-        if (countForSource <= MAX_REFS_PER_SOURCE || !summary)
-        {
-          String accessionId = ref.getAccessionId();
-          lineLength += accessionId.length() + 1;
-          if (countForSource > 1 && summary)
-          {
-            sb.append(", ").append(accessionId);
-            lineLength++;
-          }
-          else
-          {
-            sb.append(source).append(" ").append(accessionId);
-            lineLength += source.length();
-          }
-          maxWidth = Math.max(maxWidth, lineLength);
-        }
-        if (countForSource == MAX_REFS_PER_SOURCE && summary)
-        {
-          sb.append(COMMA).append(ELLIPSIS);
-          ellipsis = true;
-        }
+        // shouldn't happen
+        continue;
       }
-      if (moreSources)
+      boolean sourceChanged = !source.equals(lastSource);
+      if (sourceChanged)
       {
-        sb.append("<br>").append(ELLIPSIS).append(COMMA).append(source)
-                .append(COMMA).append(ELLIPSIS);
+        lineLength = 0;
+        countForSource = 0;
+        sourceCount++;
       }
-      if (ellipsis)
+      if (sourceCount > MAX_SOURCES && summary)
       {
-        sb.append("<br>(");
-        sb.append(MessageManager.getString("label.output_seq_details"));
-        sb.append(")");
+        ellipsis = true;
+        moreSources = true;
+        break;
       }
-    }
-
-    /*
-     * add non-positional features if wanted
-     */
-    SequenceFeature[] features = sequence.getSequenceFeatures();
-    if (showNpFeats && features != null)
-    {
-      for (int i = 0; i < features.length; i++)
+      lastSource = source;
+      countForSource++;
+      if (countForSource == 1 || !summary)
+      {
+        sb.append("<br>");
+      }
+      if (countForSource <= MAX_REFS_PER_SOURCE || !summary)
       {
-        if (features[i].begin == 0 && features[i].end == 0)
+        String accessionId = ref.getAccessionId();
+        lineLength += accessionId.length() + 1;
+        if (countForSource > 1 && summary)
         {
-          int sz = -sb.length();
-          appendFeature(sb, 0, minmax, features[i]);
-          sz += sb.length();
-          maxWidth = Math.max(maxWidth, sz);
+          sb.append(", ").append(accessionId);
+          lineLength++;
         }
+        else
+        {
+          sb.append(source).append(" ").append(accessionId);
+          lineLength += source.length();
+        }
+        maxLineLength = Math.max(maxLineLength, lineLength);
+      }
+      if (countForSource == MAX_REFS_PER_SOURCE && summary)
+      {
+        sb.append(COMMA).append(ELLIPSIS);
+        ellipsis = true;
       }
     }
-    sb.append("</i>");
-    return maxWidth;
+    if (moreSources)
+    {
+      sb.append("<br>").append(source)
+              .append(COMMA).append(ELLIPSIS);
+    }
+    if (ellipsis)
+    {
+      sb.append("<br>(");
+      sb.append(MessageManager.getString("label.output_seq_details"));
+      sb.append(")");
+    }
+
+    return maxLineLength;
   }
 
   public void createTooltipAnnotationReport(final StringBuilder tip,
           SequenceI sequence, boolean showDbRefs, boolean showNpFeats,
           Map<String, float[][]> minmax)
   {
-    int maxWidth = createSequenceAnnotationReport(tip, sequence,
-            showDbRefs, showNpFeats, minmax, true);
+    int maxWidth = createSequenceAnnotationReport(tip, sequence, showDbRefs,
+            showNpFeats, minmax, true);
 
     if (maxWidth > 60)
     {
index 1b72545..ba6b2f3 100644 (file)
@@ -165,8 +165,8 @@ public class SimpleBlastFile extends AlignFile
               rstart = Long.parseLong(stindx);
             } catch (Exception e)
             {
-              System.err.println("Couldn't parse '" + stindx
-                      + "' as start of row");
+              System.err.println(
+                      "Couldn't parse '" + stindx + "' as start of row");
               // inAlignments = false;
               // warn for this line
             }
@@ -175,8 +175,8 @@ public class SimpleBlastFile extends AlignFile
               rend = Long.parseLong(endindx);
             } catch (Exception e)
             {
-              System.err.println("Couldn't parse '" + endindx
-                      + "' as end of row");
+              System.err.println(
+                      "Couldn't parse '" + endindx + "' as end of row");
               // inAlignments = false;
 
               // warn for this line
@@ -204,7 +204,8 @@ public class SimpleBlastFile extends AlignFile
             {
               padseq = true; // prepend gaps to new sequences in this block
               seqentry = new Object[] { new StringBuffer(),
-                  new long[] { rstart, rend } };
+                  new long[]
+                  { rstart, rend } };
               seqentries.addElement(seqentry);
               seqhash.put(sqid, seqentry);
 
@@ -258,7 +259,7 @@ public class SimpleBlastFile extends AlignFile
         {
           Sequence newseq = new Sequence(idstring,
 
-          ((StringBuffer) seqentry[0]).toString(),
+                  ((StringBuffer) seqentry[0]).toString(),
                   (int) ((long[]) seqentry[1])[0],
                   (int) ((long[]) seqentry[1])[1]);
           if (newseq.getEnd() == 0)
index c2f3683..f5b5177 100644 (file)
@@ -74,6 +74,8 @@ import fr.orsay.lri.varna.models.rna.RNA;
  */
 public class StockholmFile extends AlignFile
 {
+  private static final String ANNOTATION = "annotation";
+
   private static final Regex OPEN_PAREN = new Regex("(<|\\[)", "(");
 
   private static final Regex CLOSE_PAREN = new Regex("(>|\\])", ")");
@@ -163,8 +165,8 @@ public class StockholmFile extends AlignFile
 
       for (int k = 0; k < rna.length(); k++)
       {
-        ann[k] = new Annotation(annot[k], "", Rna.getRNASecStrucState(
-                annot[k]).charAt(0), 0f);
+        ann[k] = new Annotation(annot[k], "",
+                Rna.getRNASecStrucState(annot[k]).charAt(0), 0f);
 
       }
       AlignmentAnnotation align = new AlignmentAnnotation("Sec. str.",
@@ -207,9 +209,8 @@ public class StockholmFile extends AlignFile
     r = new Regex("# STOCKHOLM ([\\d\\.]+)");
     if (!r.search(nextLine()))
     {
-      throw new IOException(
-              MessageManager
-                      .getString("exception.stockholm_invalid_format"));
+      throw new IOException(MessageManager
+              .getString("exception.stockholm_invalid_format"));
     }
     else
     {
@@ -392,7 +393,7 @@ public class StockholmFile extends AlignFile
               while (j.hasMoreElements())
               {
                 String desc = j.nextElement().toString();
-                if ("annotations".equals(desc) && annotsAdded)
+                if (ANNOTATION.equals(desc) && annotsAdded)
                 {
                   // don't add features if we already added an annotation row
                   continue;
@@ -412,7 +413,7 @@ public class StockholmFile extends AlignFile
                     int new_pos = posmap[k]; // look up nearest seqeunce
                     // position to this column
                     SequenceFeature feat = new SequenceFeature(type, desc,
-                            new_pos, new_pos, 0f, null);
+                            new_pos, new_pos, null);
 
                     seqO.addSequenceFeature(feat);
                   }
@@ -439,8 +440,8 @@ public class StockholmFile extends AlignFile
         {
           // logger.error("Could not parse sequence line: " + line);
           throw new IOException(MessageManager.formatMessage(
-                  "exception.couldnt_parse_sequence_line",
-                  new String[] { line }));
+                  "exception.couldnt_parse_sequence_line", new String[]
+                  { line }));
         }
         String ns = seqs.get(x.stringMatched(1));
         if (ns == null)
@@ -635,7 +636,7 @@ public class StockholmFile extends AlignFile
               content = new Hashtable();
               features.put(this.id2type(type), content);
             }
-            String ns = (String) content.get("annotation");
+            String ns = (String) content.get(ANNOTATION);
 
             if (ns == null)
             {
@@ -643,7 +644,7 @@ public class StockholmFile extends AlignFile
             }
             // finally, append the annotation line
             ns += seq;
-            content.put("annotation", ns);
+            content.put(ANNOTATION, ns);
             // // end of wrapped annotation block.
             // // Now a new row is created with the current set of data
 
@@ -671,8 +672,8 @@ public class StockholmFile extends AlignFile
           // }
           else
           {
-            System.err
-                    .println("Warning - couldn't parse sequence annotation row line:\n"
+            System.err.println(
+                    "Warning - couldn't parse sequence annotation row line:\n"
                             + line);
             // throw new IOException("Error parsing " + line);
           }
@@ -680,8 +681,8 @@ public class StockholmFile extends AlignFile
         else
         {
           throw new IOException(MessageManager.formatMessage(
-                  "exception.unknown_annotation_detected", new String[] {
-                      annType, annContent }));
+                  "exception.unknown_annotation_detected", new String[]
+                  { annType, annContent }));
         }
       }
     }
@@ -794,8 +795,10 @@ public class StockholmFile extends AlignFile
     {
       for (DBRefEntry d : dbrs)
       {
-        jalview.util.MapList mp = new jalview.util.MapList(new int[] {
-            seqO.getStart(), seqO.getEnd() }, new int[] { st, en }, 1, 1);
+        jalview.util.MapList mp = new jalview.util.MapList(
+                new int[]
+                { seqO.getStart(), seqO.getEnd() }, new int[] { st, en }, 1,
+                1);
         jalview.datamodel.Mapping mping = new Mapping(mp);
         d.setMap(mping);
       }
@@ -815,8 +818,9 @@ public class StockholmFile extends AlignFile
     String type = label;
     if (label.contains("_cons"))
     {
-      type = (label.indexOf("_cons") == label.length() - 5) ? label
-              .substring(0, label.length() - 5) : label;
+      type = (label.indexOf("_cons") == label.length() - 5)
+              ? label.substring(0, label.length() - 5)
+              : label;
     }
     boolean ss = false, posterior = false;
     type = id2type(type);
@@ -850,14 +854,14 @@ public class StockholmFile extends AlignFile
             ann.secondaryStructure = ResidueProperties.getDssp3state(pos)
                     .charAt(0);
 
-          if (ann.secondaryStructure == pos.charAt(0))
-          {
-            ann.displayCharacter = ""; // null; // " ";
-          }
-          else
-          {
-            ann.displayCharacter = " " + ann.displayCharacter;
-          }
+            if (ann.secondaryStructure == pos.charAt(0))
+            {
+              ann.displayCharacter = ""; // null; // " ";
+            }
+            else
+            {
+              ann.displayCharacter = " " + ann.displayCharacter;
+            }
           }
         }
 
@@ -928,10 +932,7 @@ public class StockholmFile extends AlignFile
     while ((in < s.length) && (s[in] != null))
     {
       String tmp = printId(s[in], jvSuffix);
-      if (s[in].getSequence().length > max)
-      {
-        max = s[in].getSequence().length;
-      }
+      max = Math.max(max, s[in].getLength());
 
       if (tmp.length() > maxid)
       {
@@ -980,8 +981,8 @@ public class StockholmFile extends AlignFile
       {
         Object idd = en.nextElement();
         String type = (String) dataRef.remove(idd);
-        out.append(new Format("%-" + (maxid - 2) + "s").form("#=GS "
-                + idd.toString() + " "));
+        out.append(new Format("%-" + (maxid - 2) + "s")
+                .form("#=GS " + idd.toString() + " "));
         if (type.contains("PFAM") || type.contains("RFAM"))
         {
 
@@ -1021,8 +1022,8 @@ public class StockholmFile extends AlignFile
           }
 
           // out.append("#=GR ");
-          out.append(new Format("%-" + maxid + "s").form("#=GR "
-                  + printId(s[i], jvSuffix) + " " + key + " "));
+          out.append(new Format("%-" + maxid + "s").form(
+                  "#=GR " + printId(s[i], jvSuffix) + " " + key + " "));
           ann = alAnot[j].annotations;
           String seq = "";
           for (int k = 0; k < ann.length; k++)
@@ -1077,8 +1078,8 @@ public class StockholmFile extends AlignFile
         }
         label = label.replace(" ", "_");
 
-        out.append(new Format("%-" + maxid + "s").form("#=GC " + label
-                + " "));
+        out.append(
+                new Format("%-" + maxid + "s").form("#=GC " + label + " "));
         boolean isrna = aa.isValidStruc();
         for (int j = 0; j < aa.annotations.length; j++)
         {
@@ -1110,8 +1111,10 @@ public class StockholmFile extends AlignFile
   {
     char seq = ' ';
     Annotation annot = ann[k];
-    String ch = (annot == null) ? ((sequenceI == null) ? "-" : Character
-            .toString(sequenceI.getCharAt(k))) : annot.displayCharacter;
+    String ch = (annot == null)
+            ? ((sequenceI == null) ? "-"
+                    : Character.toString(sequenceI.getCharAt(k)))
+            : annot.displayCharacter;
     if (key != null && key.equals("SS"))
     {
       if (annot == null)
@@ -1188,8 +1191,8 @@ public class StockholmFile extends AlignFile
     {
       return (String) typeIds.get(id);
     }
-    System.err.println("Warning : Unknown Stockholm annotation type code "
-            + id);
+    System.err.println(
+            "Warning : Unknown Stockholm annotation type code " + id);
     return id;
   }
 
@@ -1210,8 +1213,8 @@ public class StockholmFile extends AlignFile
     {
       return key;
     }
-    System.err.println("Warning : Unknown Stockholm annotation type: "
-            + type);
+    System.err.println(
+            "Warning : Unknown Stockholm annotation type: " + type);
     return key;
   }
 
index ab220f0..3025907 100644 (file)
@@ -191,11 +191,13 @@ public abstract class StructureFile extends AlignFile
       {
         // TODO: use the PDB ID of the structure if one is available, to save
         // bandwidth and avoid uploading the whole structure to the service
-        Object annotate3d = cl.getConstructor(new Class[] {}).newInstance(
-                new Object[] {});
-        AlignmentI al = ((AlignmentI) cl.getMethod("getRNAMLFor",
-                new Class[] { FileParse.class }).invoke(annotate3d,
-                new Object[] { new FileParse(getDataName(), dataSourceType) }));
+        Object annotate3d = cl.getConstructor(new Class[] {})
+                .newInstance(new Object[] {});
+        AlignmentI al = ((AlignmentI) cl
+                .getMethod("getRNAMLFor", new Class[]
+                { FileParse.class })
+                .invoke(annotate3d, new Object[]
+                { new FileParse(getDataName(), dataSourceType) }));
         for (SequenceI sq : al.getSequences())
         {
           if (sq.getDatasetSequence() != null)
@@ -222,8 +224,8 @@ public abstract class StructureFile extends AlignFile
   }
 
   @SuppressWarnings("unchecked")
-  protected void replaceAndUpdateChains(List<SequenceI> prot,
-          AlignmentI al, String pep, boolean b)
+  protected void replaceAndUpdateChains(List<SequenceI> prot, AlignmentI al,
+          String pep, boolean b)
   {
     List<List<? extends Object>> replaced = AlignSeq
             .replaceMatchingSeqsWith(seqs, annotations, prot, al, pep,
@@ -288,8 +290,8 @@ public abstract class StructureFile extends AlignFile
         processWithJmolParser(proteinSequences);
       } catch (Exception x)
       {
-        System.err
-                .println("Exceptions from Jmol when processing data in pdb file");
+        System.err.println(
+                "Exceptions from Jmol when processing data in pdb file");
         x.printStackTrace();
       }
     }
@@ -304,8 +306,11 @@ public abstract class StructureFile extends AlignFile
       Class cl = Class.forName("jalview.ext.jmol.JmolParser");
       if (cl != null)
       {
-        final Constructor constructor = cl.getConstructor(new Class[] {FileParse.class });
-        final Object[] args = new Object[] { new FileParse(getDataName(), dataSourceType) };
+        final Constructor constructor = cl
+                .getConstructor(new Class[]
+                { FileParse.class });
+        final Object[] args = new Object[] {
+            new FileParse(getDataName(), dataSourceType) };
 
         StructureImportSettings.setShowSeqFeatures(false);
         StructureImportSettings.setVisibleChainAnnotation(false);
@@ -314,8 +319,8 @@ public abstract class StructureFile extends AlignFile
         StructureImportSettings
                 .setExternalSecondaryStructure(externalSecondaryStructure);
         Object jmf = constructor.newInstance(args);
-        AlignmentI al = new Alignment((SequenceI[]) cl.getMethod(
-                "getSeqsAsArray", new Class[] {}).invoke(jmf));
+        AlignmentI al = new Alignment((SequenceI[]) cl
+                .getMethod("getSeqsAsArray", new Class[] {}).invoke(jmf));
         cl.getMethod("addAnnotations", new Class[] { AlignmentI.class })
                 .invoke(jmf, al);
         for (SequenceI sq : al.getSequences())
@@ -392,8 +397,10 @@ public abstract class StructureFile extends AlignFile
 
   public static boolean isRNA(SequenceI seq)
   {
-    for (char c : seq.getSequence())
+    int length = seq.getLength();
+    for (int i = 0; i < length; i++)
     {
+      char c = seq.getCharAt(i);
       if ((c != 'A') && (c != 'C') && (c != 'G') && (c != 'U'))
       {
         return false;
@@ -416,7 +423,8 @@ public abstract class StructureFile extends AlignFile
     {
       dataName = dataName.substring(p + 1);
     }
-    if(dataName.indexOf(".") > -1){
+    if (dataName.indexOf(".") > -1)
+    {
       dataName = dataName.substring(0, dataName.lastIndexOf("."));
     }
     return dataName;
index 648954f..fc0c913 100644 (file)
@@ -182,8 +182,9 @@ public class TCoffeeScoreFile extends AlignFile
    */
   public String getScoresFor(String id)
   {
-    return scores != null && scores.containsKey(id) ? scores.get(id)
-            .toString() : "";
+    return scores != null && scores.containsKey(id)
+            ? scores.get(id).toString()
+            : "";
   }
 
   /**
@@ -274,9 +275,9 @@ public class TCoffeeScoreFile extends AlignFile
         if (scoreStringBuilder == null)
         {
           error = true;
-          errormessage = String
-                  .format("Invalid T-Coffee score file: Sequence ID '%s' is not declared in header section",
-                          entry.getKey());
+          errormessage = String.format(
+                  "Invalid T-Coffee score file: Sequence ID '%s' is not declared in header section",
+                  entry.getKey());
           return;
         }
 
@@ -584,9 +585,9 @@ public class TCoffeeScoreFile extends AlignFile
       i++;
       if (s == null && i != scores.size() && !id.getKey().equals("cons"))
       {
-        System.err.println("No "
-                + (matchids ? "match " : " sequences left ")
-                + " for TCoffee score set : " + id.getKey());
+        System.err
+                .println("No " + (matchids ? "match " : " sequences left ")
+                        + " for TCoffee score set : " + id.getKey());
         continue;
       }
       int jSize = al.getWidth() < srow.length ? al.getWidth() : srow.length;
@@ -599,16 +600,16 @@ public class TCoffeeScoreFile extends AlignFile
           annotations[j] = null;
           if (val > 0)
           {
-            System.err
-                    .println("Warning: non-zero value for positional T-COFFEE score for gap at "
+            System.err.println(
+                    "Warning: non-zero value for positional T-COFFEE score for gap at "
                             + j + " in sequence " + s.getName());
           }
         }
         else
         {
           annotations[j] = new Annotation(s == null ? "" + val : null,
-                  s == null ? "" + val : null, '\0', val * 1f, val >= 0
-                          && val < colors.length ? colors[val]
+                  s == null ? "" + val : null, '\0', val * 1f,
+                  val >= 0 && val < colors.length ? colors[val]
                           : Color.white);
         }
       }
index 1cab8ca..d81a6b0 100644 (file)
@@ -182,8 +182,8 @@ public class VamsasAppDatastore
           Vobject obj = getjv2vObj(seqsetidobj);
           if (obj != null && !(obj instanceof Alignment))
           {
-            Cache.log
-                    .warn("IMPLEMENTATION ERROR?: Unexpected mapping for unmapped jalview string object content:"
+            Cache.log.warn(
+                    "IMPLEMENTATION ERROR?: Unexpected mapping for unmapped jalview string object content:"
                             + seqsetidobj + " to object " + obj);
           }
           return obj;
@@ -199,8 +199,8 @@ public class VamsasAppDatastore
 
     if (Cache.log.isDebugEnabled())
     {
-      Cache.log.debug("Returning null VorbaID binding for jalview object "
-              + jvobj);
+      Cache.log.debug(
+              "Returning null VorbaID binding for jalview object " + jvobj);
     }
     return null;
   }
@@ -216,8 +216,8 @@ public class VamsasAppDatastore
     if (id == null)
     {
       id = cdoc.registerObject(vobj);
-      Cache.log
-              .debug("Registering new object and returning null for getvObj2jv");
+      Cache.log.debug(
+              "Registering new object and returning null for getvObj2jv");
       return null;
     }
     if (vobj2jv.containsKey(vobj.getVorbaId()))
@@ -238,27 +238,27 @@ public class VamsasAppDatastore
       {
         Cache.log.error("Failed to get id for "
                 + (vobj.isRegisterable() ? "registerable"
-                        : "unregisterable") + " object " + vobj);
+                        : "unregisterable")
+                + " object " + vobj);
       }
     }
 
     if (vobj2jv.containsKey(vobj.getVorbaId())
             && !((VorbaId) vobj2jv.get(vobj.getVorbaId())).equals(jvobj))
     {
-      Cache.log
-              .debug("Warning? Overwriting existing vamsas id binding for "
+      Cache.log.debug(
+              "Warning? Overwriting existing vamsas id binding for "
                       + vobj.getVorbaId(),
-                      new Exception(
-                              MessageManager
-                                      .getString("exception.overwriting_vamsas_id_binding")));
+              new Exception(MessageManager.getString(
+                      "exception.overwriting_vamsas_id_binding")));
     }
     else if (jv2vobj.containsKey(jvobj)
             && !((VorbaId) jv2vobj.get(jvobj)).equals(vobj.getVorbaId()))
     {
       Cache.log.debug(
               "Warning? Overwriting existing jalview object binding for "
-                      + jvobj, new Exception(
-                      "Overwriting jalview object binding."));
+                      + jvobj,
+              new Exception("Overwriting jalview object binding."));
     }
     /*
      * Cache.log.error("Attempt to make conflicting object binding! "+vobj+" id "
@@ -337,9 +337,8 @@ public class VamsasAppDatastore
                 if (vbound.getV_parent() != null
                         && dataset != vbound.getV_parent())
                 {
-                  throw new Error(
-                          MessageManager
-                                  .getString("error.implementation_error_cannot_map_alignment_sequences"));
+                  throw new Error(MessageManager.getString(
+                          "error.implementation_error_cannot_map_alignment_sequences"));
                   // This occurs because the dataset for the alignment we are
                   // trying to
                 }
@@ -372,7 +371,8 @@ public class VamsasAppDatastore
       // flag.
       // this *will* break when alignment contains both nucleotide and amino
       // acid sequences.
-      String dict = jal.isNucleotide() ? uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA
+      String dict = jal.isNucleotide()
+              ? uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA
               : uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_AA;
       Vector dssmods = new Vector();
       for (int i = 0; i < jal.getHeight(); i++)
@@ -381,8 +381,8 @@ public class VamsasAppDatastore
         // referenced
         // sequences
         // to dataset.
-        Datasetsequence dssync = new jalview.io.vamsas.Datasetsequence(
-                this, sq, dict, dataset);
+        Datasetsequence dssync = new jalview.io.vamsas.Datasetsequence(this,
+                sq, dict, dataset);
         sequence = (Sequence) dssync.getVobj();
         if (dssync.getModified())
         {
@@ -440,8 +440,8 @@ public class VamsasAppDatastore
       else
       {
         // always prepare to clone the alignment
-        boolean alismod = av.isUndoRedoHashModified((long[]) alignRDHash
-                .get(av.getSequenceSetId()));
+        boolean alismod = av.isUndoRedoHashModified(
+                (long[]) alignRDHash.get(av.getSequenceSetId()));
         // todo: verify and update mutable alignment props.
         // TODO: Use isLocked methods
         if (alignment.getModifiable() == null
@@ -461,8 +461,8 @@ public class VamsasAppDatastore
           {
             // removeValignmentSequences(alignment, docseqs);
             docseqs.removeAllElements();
-            System.out
-                    .println("Sequence deletion from alignment is not implemented.");
+            System.out.println(
+                    "Sequence deletion from alignment is not implemented.");
 
           }
           if (modified)
@@ -501,17 +501,18 @@ public class VamsasAppDatastore
           // unbind alignment from view.
           // create new binding and new alignment.
           // mark trail on new alignment as being derived from old ?
-          System.out
-                  .println("update edited alignment to new alignment in document.");
+          System.out.println(
+                  "update edited alignment to new alignment in document.");
         }
       }
       // ////////////////////////////////////////////
       // SAVE Alignment Sequence Features
-      for (int i = 0, iSize = alignment.getAlignmentSequenceCount(); i < iSize; i++)
+      for (int i = 0, iSize = alignment
+              .getAlignmentSequenceCount(); i < iSize; i++)
       {
         AlignmentSequence valseq;
-        SequenceI alseq = (SequenceI) getvObj2jv(valseq = alignment
-                .getAlignmentSequence(i));
+        SequenceI alseq = (SequenceI) getvObj2jv(
+                valseq = alignment.getAlignmentSequence(i));
         if (alseq != null && alseq.getSequenceFeatures() != null)
         {
           /*
@@ -556,8 +557,8 @@ public class VamsasAppDatastore
           if (aa[i].groupRef != null)
           {
             // TODO: store any group associated annotation references
-            Cache.log
-                    .warn("Group associated sequence annotation is not stored in VAMSAS document.");
+            Cache.log.warn(
+                    "Group associated sequence annotation is not stored in VAMSAS document.");
             continue;
           }
           if (aa[i].sequenceRef != null)
@@ -590,7 +591,8 @@ public class VamsasAppDatastore
           else
           {
             // add Alignment Annotation
-            uk.ac.vamsas.objects.core.AlignmentAnnotation an = (uk.ac.vamsas.objects.core.AlignmentAnnotation) getjv2vObj(aa[i]);
+            uk.ac.vamsas.objects.core.AlignmentAnnotation an = (uk.ac.vamsas.objects.core.AlignmentAnnotation) getjv2vObj(
+                    aa[i]);
             if (an == null)
             {
               an = new uk.ac.vamsas.objects.core.AlignmentAnnotation();
@@ -639,8 +641,8 @@ public class VamsasAppDatastore
                 ae = new AnnotationElement();
                 ae.setDescription(aa[i].annotations[a].description);
                 ae.addGlyph(new Glyph());
-                ae.getGlyph(0).setContent(
-                        aa[i].annotations[a].displayCharacter); // assume
+                ae.getGlyph(0)
+                        .setContent(aa[i].annotations[a].displayCharacter); // assume
                 // jax-b
                 // takes
                 // care
@@ -655,9 +657,10 @@ public class VamsasAppDatastore
                 if (aa[i].annotations[a].secondaryStructure != ' ')
                 {
                   Glyph ss = new Glyph();
-                  ss.setDict(uk.ac.vamsas.objects.utils.GlyphDictionary.PROTEIN_SS_3STATE);
-                  ss.setContent(String
-                          .valueOf(aa[i].annotations[a].secondaryStructure));
+                  ss.setDict(
+                          uk.ac.vamsas.objects.utils.GlyphDictionary.PROTEIN_SS_3STATE);
+                  ss.setContent(String.valueOf(
+                          aa[i].annotations[a].secondaryStructure));
                   ae.addGlyph(ss);
                 }
                 an.addAnnotationElement(ae);
@@ -678,12 +681,13 @@ public class VamsasAppDatastore
                 if (aa[i].threshold != null && aa[i].threshold.displayed)
                 {
                   an.addProperty(Properties.newProperty(THRESHOLD,
-                          Properties.FLOATTYPE, "" + aa[i].threshold.value));
+                          Properties.FLOATTYPE,
+                          "" + aa[i].threshold.value));
                   if (aa[i].threshold.label != null)
                   {
-                    an.addProperty(Properties.newProperty(THRESHOLD
-                            + "Name", Properties.STRINGTYPE, ""
-                            + aa[i].threshold.label));
+                    an.addProperty(Properties.newProperty(
+                            THRESHOLD + "Name", Properties.STRINGTYPE,
+                            "" + aa[i].threshold.label));
                   }
                 }
               }
@@ -696,14 +700,14 @@ public class VamsasAppDatastore
               // LOCK METHODS)
               {
                 // verify annotation - update (perhaps)
-                Cache.log
-                        .info("update alignment sequence annotation. not yet implemented.");
+                Cache.log.info(
+                        "update alignment sequence annotation. not yet implemented.");
               }
               else
               {
                 // verify annotation - update (perhaps)
-                Cache.log
-                        .info("updated alignment sequence annotation added.");
+                Cache.log.info(
+                        "updated alignment sequence annotation added.");
               }
             }
           }
@@ -777,18 +781,19 @@ public class VamsasAppDatastore
    * @param alignment
    * @param docseqs
    */
-  private void removeValignmentSequences(Alignment alignment, Vector docseqs)
+  private void removeValignmentSequences(Alignment alignment,
+          Vector docseqs)
   {
     // delete these from document. This really needs to be a generic document
     // API function derived by CASTOR.
     Enumeration en = docseqs.elements();
     while (en.hasMoreElements())
     {
-      alignment.removeAlignmentSequence((AlignmentSequence) en
-              .nextElement());
+      alignment.removeAlignmentSequence(
+              (AlignmentSequence) en.nextElement());
     }
-    Entry pe = addProvenance(alignment.getProvenance(), "Removed "
-            + docseqs.size() + " sequences");
+    Entry pe = addProvenance(alignment.getProvenance(),
+            "Removed " + docseqs.size() + " sequences");
     en = alignment.enumerateAlignmentAnnotation();
     Vector toremove = new Vector();
     while (en.hasMoreElements())
@@ -827,8 +832,8 @@ public class VamsasAppDatastore
     en = toremove.elements();
     while (en.hasMoreElements())
     {
-      alignment
-              .removeAlignmentAnnotation((uk.ac.vamsas.objects.core.AlignmentAnnotation) en
+      alignment.removeAlignmentAnnotation(
+              (uk.ac.vamsas.objects.core.AlignmentAnnotation) en
                       .nextElement());
     }
     // TODO: search through alignment annotations to remove any references to
@@ -877,17 +882,16 @@ public class VamsasAppDatastore
       modal = true;
       alseq.setName(jvalsq.getName());
     }
-    if (jvalsq.getDescription() != null
-            && (alseq.getDescription() == null || !jvalsq.getDescription()
-                    .equals(alseq.getDescription())))
+    if (jvalsq.getDescription() != null && (alseq.getDescription() == null
+            || !jvalsq.getDescription().equals(alseq.getDescription())))
     {
       modal = true;
       alseq.setDescription(jvalsq.getDescription());
     }
     if (getjv2vObj(jvalsq.getDatasetSequence()) == null)
     {
-      Cache.log
-              .warn("Serious Implementation error - Unbound dataset sequence in alignment: "
+      Cache.log.warn(
+              "Serious Implementation error - Unbound dataset sequence in alignment: "
                       + jvalsq.getDatasetSequence());
     }
     alseq.setRefid(getjv2vObj(jvalsq.getDatasetSequence()));
@@ -927,8 +931,8 @@ public class VamsasAppDatastore
               || !valseq.getSequence().equals(alseq.getSequenceAsString()))
       {
         // this might go *horribly* wrong
-        alseq.setSequence(new String(valseq.getSequence()).replace(
-                valGapchar, gapChar));
+        alseq.setSequence(new String(valseq.getSequence())
+                .replace(valGapchar, gapChar));
         alseq.setStart((int) valseq.getStart());
         alseq.setEnd((int) valseq.getEnd());
         modal = true;
@@ -938,23 +942,22 @@ public class VamsasAppDatastore
         modal = true;
         alseq.setName(valseq.getName());
       }
-      if (alseq.getDescription() == null
-              || (valseq.getDescription() != null && !alseq
-                      .getDescription().equals(valseq.getDescription())))
+      if (alseq.getDescription() == null || (valseq.getDescription() != null
+              && !alseq.getDescription().equals(valseq.getDescription())))
       {
         alseq.setDescription(valseq.getDescription());
         modal = true;
       }
       if (modal && Cache.log.isDebugEnabled())
       {
-        Cache.log.debug("Updating apparently edited sequence "
-                + alseq.getName());
+        Cache.log.debug(
+                "Updating apparently edited sequence " + alseq.getName());
       }
     }
     else
     {
-      alseq = new jalview.datamodel.Sequence(valseq.getName(), valseq
-              .getSequence().replace(valGapchar, gapChar),
+      alseq = new jalview.datamodel.Sequence(valseq.getName(),
+              valseq.getSequence().replace(valGapchar, gapChar),
               (int) valseq.getStart(), (int) valseq.getEnd());
 
       Vobject datsetseq = (Vobject) valseq.getRefid();
@@ -970,8 +973,8 @@ public class VamsasAppDatastore
           // inherit description line from dataset.
           if (alseq.getDatasetSequence().getDescription() != null)
           {
-            alseq.setDescription(alseq.getDatasetSequence()
-                    .getDescription());
+            alseq.setDescription(
+                    alseq.getDatasetSequence().getDescription());
           }
         }
         // if
@@ -984,8 +987,8 @@ public class VamsasAppDatastore
       }
       else
       {
-        Cache.log
-                .error("Invalid dataset sequence id (null) for alignment sequence "
+        Cache.log.error(
+                "Invalid dataset sequence id (null) for alignment sequence "
                         + valseq.getVorbaId());
       }
       bindjvvobj(alseq, valseq);
@@ -1055,9 +1058,10 @@ public class VamsasAppDatastore
       {
         // we only write an annotation where it really exists.
         Glyph ss = new Glyph();
-        ss.setDict(uk.ac.vamsas.objects.utils.GlyphDictionary.PROTEIN_SS_3STATE);
-        ss.setContent(String
-                .valueOf(alan.annotations[a].secondaryStructure));
+        ss.setDict(
+                uk.ac.vamsas.objects.utils.GlyphDictionary.PROTEIN_SS_3STATE);
+        ss.setContent(
+                String.valueOf(alan.annotations[a].secondaryStructure));
         ae.addGlyph(ss);
       }
       an.addAnnotationElement(ae);
@@ -1072,7 +1076,8 @@ public class VamsasAppDatastore
     // uk.ac.vamsas.
     // objects.core.AlignmentSequence alsref = (uk.ac.vamsas.
     // objects.core.AlignmentSequence) sref;
-    uk.ac.vamsas.objects.core.DataSetAnnotations an = (uk.ac.vamsas.objects.core.DataSetAnnotations) getjv2vObj(alan);
+    uk.ac.vamsas.objects.core.DataSetAnnotations an = (uk.ac.vamsas.objects.core.DataSetAnnotations) getjv2vObj(
+            alan);
     int[] gapMap = getGapMap(AlSeqMaps, alan);
     if (an == null)
     {
@@ -1116,8 +1121,8 @@ public class VamsasAppDatastore
       else
       {
         // verify existing alignment sequence annotation is up to date
-        System.out
-                .println("make new alignment dataset sequence annotation if modification has happened.");
+        System.out.println(
+                "make new alignment dataset sequence annotation if modification has happened.");
       }
     }
 
@@ -1150,7 +1155,8 @@ public class VamsasAppDatastore
     // uk.ac.vamsas.
     // objects.core.AlignmentSequence alsref = (uk.ac.vamsas.
     // objects.core.AlignmentSequence) sref;
-    uk.ac.vamsas.objects.core.AlignmentSequenceAnnotation an = (uk.ac.vamsas.objects.core.AlignmentSequenceAnnotation) getjv2vObj(alan);
+    uk.ac.vamsas.objects.core.AlignmentSequenceAnnotation an = (uk.ac.vamsas.objects.core.AlignmentSequenceAnnotation) getjv2vObj(
+            alan);
     int[] gapMap = getGapMap(AlSeqMaps, alan);
     if (an == null)
     {
@@ -1184,8 +1190,8 @@ public class VamsasAppDatastore
       else
       {
         // verify existing alignment sequence annotation is up to date
-        System.out
-                .println("make new alignment sequence annotation if modification has happened.");
+        System.out.println(
+                "make new alignment sequence annotation if modification has happened.");
       }
     }
   }
@@ -1326,8 +1332,8 @@ public class VamsasAppDatastore
               @Override
               public JarInputStream getJarInputStream() throws IOException
               {
-                jalview.bin.Cache.log
-                        .debug("Returning client input stream for Jalview from Vamsas Document.");
+                jalview.bin.Cache.log.debug(
+                        "Returning client input stream for Jalview from Vamsas Document.");
                 return new JarInputStream(cappdata.getClientInputStream());
               }
             };
@@ -1374,8 +1380,8 @@ public class VamsasAppDatastore
             @Override
             public JarInputStream getJarInputStream() throws IOException
             {
-              jalview.bin.Cache.log
-                      .debug("Returning user input stream for Jalview from Vamsas Document.");
+              jalview.bin.Cache.log.debug(
+                      "Returning user input stream for Jalview from Vamsas Document.");
               return new JarInputStream(cappdata.getUserInputStream());
             }
           };
@@ -1420,9 +1426,9 @@ public class VamsasAppDatastore
       // TODO implement this : af.getNumberOfViews
       String seqsetidobj = av.getSequenceSetId();
       views = Desktop.getViewports(seqsetidobj);
-      Cache.log.debug("Found "
-              + (views == null ? " no " : "" + views.length)
-              + " views for '" + av.getSequenceSetId() + "'");
+      Cache.log
+              .debug("Found " + (views == null ? " no " : "" + views.length)
+                      + " views for '" + av.getSequenceSetId() + "'");
       if (views.length > 1)
       {
         // we need to close the original document view.
@@ -1505,7 +1511,8 @@ public class VamsasAppDatastore
       // from another client
       throw new Error(MessageManager.formatMessage(
               "error.implementation_error_old_jalview_object_not_bound",
-              new String[] { oldjvobject.toString() }));
+              new String[]
+              { oldjvobject.toString() }));
     }
     if (newjvobject != null)
     {
@@ -1530,22 +1537,22 @@ public class VamsasAppDatastore
         jxml.setSkipList(skipList);
         if (dojvsync)
         {
-          jxml.saveState(new JarOutputStream(cappdata
-                  .getClientOutputStream()));
+          jxml.saveState(
+                  new JarOutputStream(cappdata.getClientOutputStream()));
         }
 
       } catch (Exception e)
       {
         // TODO raise GUI warning if user requests it.
-        jalview.bin.Cache.log
-                .error("Couldn't update jalview client application data. Giving up - local settings probably lost.",
-                        e);
+        jalview.bin.Cache.log.error(
+                "Couldn't update jalview client application data. Giving up - local settings probably lost.",
+                e);
       }
     }
     else
     {
-      jalview.bin.Cache.log
-              .error("Couldn't access client application data for vamsas session. This is probably a vamsas client bug.");
+      jalview.bin.Cache.log.error(
+              "Couldn't access client application data for vamsas session. This is probably a vamsas client bug.");
     }
   }
 
@@ -1605,7 +1612,8 @@ public class VamsasAppDatastore
         DataSet dataset = root.getDataSet(_ds);
         int i, iSize = dataset.getSequenceCount();
         List<SequenceI> dsseqs;
-        jalview.datamodel.Alignment jdataset = (jalview.datamodel.Alignment) getvObj2jv(dataset);
+        jalview.datamodel.Alignment jdataset = (jalview.datamodel.Alignment) getvObj2jv(
+                dataset);
         int jremain = 0;
         if (jdataset == null)
         {
@@ -1662,22 +1670,25 @@ public class VamsasAppDatastore
         // add any new dataset sequence feature annotations
         if (dataset.getDataSetAnnotations() != null)
         {
-          for (int dsa = 0; dsa < dataset.getDataSetAnnotationsCount(); dsa++)
+          for (int dsa = 0; dsa < dataset
+                  .getDataSetAnnotationsCount(); dsa++)
           {
             DataSetAnnotations dseta = dataset.getDataSetAnnotations(dsa);
             // TODO: deal with group annotation on datset sequences.
             if (dseta.getSeqRefCount() == 1)
             {
-              SequenceI dsSeq = (SequenceI) getvObj2jv((Vobject) dseta
-                      .getSeqRef(0)); // TODO: deal with group dataset
+              SequenceI dsSeq = (SequenceI) getvObj2jv(
+                      (Vobject) dseta.getSeqRef(0)); // TODO: deal with group
+                                                     // dataset
               // annotations
               if (dsSeq == null)
               {
-                jalview.bin.Cache.log
-                        .warn("Couldn't resolve jalview sequenceI for dataset object reference "
-                                + ((Vobject) dataset.getDataSetAnnotations(
-                                        dsa).getSeqRef(0)).getVorbaId()
-                                        .getId());
+                jalview.bin.Cache.log.warn(
+                        "Couldn't resolve jalview sequenceI for dataset object reference "
+                                + ((Vobject) dataset
+                                        .getDataSetAnnotations(dsa)
+                                        .getSeqRef(0)).getVorbaId()
+                                                .getId());
               }
               else
               {
@@ -1693,15 +1704,15 @@ public class VamsasAppDatastore
                   // JBPNote: we could just add them to all alignments but
                   // that may complicate cross references in the jalview
                   // datamodel
-                  Cache.log
-                          .warn("Ignoring dataset annotation with annotationElements. Not yet supported in jalview.");
+                  Cache.log.warn(
+                          "Ignoring dataset annotation with annotationElements. Not yet supported in jalview.");
                 }
               }
             }
             else
             {
-              Cache.log
-                      .warn("Ignoring multiply referenced dataset sequence annotation for binding to datsaet sequence features.");
+              Cache.log.warn(
+                      "Ignoring multiply referenced dataset sequence annotation for binding to datsaet sequence features.");
             }
           }
         }
@@ -1709,7 +1720,8 @@ public class VamsasAppDatastore
         {
           // LOAD ALIGNMENTS from DATASET
 
-          for (int al = 0, nal = dataset.getAlignmentCount(); al < nal; al++)
+          for (int al = 0, nal = dataset
+                  .getAlignmentCount(); al < nal; al++)
           {
             uk.ac.vamsas.objects.core.Alignment alignment = dataset
                     .getAlignment(al);
@@ -1722,8 +1734,8 @@ public class VamsasAppDatastore
               // TODO check that correct alignment object is retrieved when
               // hidden seqs exist.
               jal = (av.hasHiddenRows()) ? av.getAlignment()
-                      .getHiddenSequences().getFullAlignment() : av
-                      .getAlignment();
+                      .getHiddenSequences().getFullAlignment()
+                      : av.getAlignment();
             }
             iSize = alignment.getAlignmentSequenceCount();
             boolean refreshal = false;
@@ -1743,7 +1755,8 @@ public class VamsasAppDatastore
             for (i = 0; i < iSize; i++)
             {
               AlignmentSequence valseq = alignment.getAlignmentSequence(i);
-              jalview.datamodel.Sequence alseq = (jalview.datamodel.Sequence) getvObj2jv(valseq);
+              jalview.datamodel.Sequence alseq = (jalview.datamodel.Sequence) getvObj2jv(
+                      valseq);
               if (syncFromAlignmentSequence(valseq, valGapchar, gapChar,
                       dsseqs) && alseq != null)
               {
@@ -1758,7 +1771,8 @@ public class VamsasAppDatastore
                         .getAlignmentSequenceAnnotation();
                 for (int a = 0; a < vasannot.length; a++)
                 {
-                  jalview.datamodel.AlignmentAnnotation asa = (jalview.datamodel.AlignmentAnnotation) getvObj2jv(vasannot[a]); // TODO:
+                  jalview.datamodel.AlignmentAnnotation asa = (jalview.datamodel.AlignmentAnnotation) getvObj2jv(
+                          vasannot[a]); // TODO:
                   // 1:many
                   // jalview
                   // alignment
@@ -1793,8 +1807,8 @@ public class VamsasAppDatastore
                     // OBJECT LOCK
                     // METHODS)
                     {
-                      Cache.log
-                              .info("UNIMPLEMENTED: not recovering user modifiable sequence alignment annotation");
+                      Cache.log.info(
+                              "UNIMPLEMENTED: not recovering user modifiable sequence alignment annotation");
                       // TODO: should at least replace with new one - otherwise
                       // things will break
                       // basically do this:
@@ -1824,10 +1838,11 @@ public class VamsasAppDatastore
             if (newasAnnots != null && newasAnnots.size() > 0)
             {
               // Add the new sequence annotations in to the alignment.
-              for (int an = 0, anSize = newasAnnots.size(); an < anSize; an++)
+              for (int an = 0, anSize = newasAnnots
+                      .size(); an < anSize; an++)
               {
-                jal.addAnnotation((AlignmentAnnotation) newasAnnots
-                        .elementAt(an));
+                jal.addAnnotation(
+                        (AlignmentAnnotation) newasAnnots.elementAt(an));
                 // TODO: check if anything has to be done - like calling
                 // adjustForAlignment or something.
                 newasAnnots.setElementAt(null, an);
@@ -1844,7 +1859,8 @@ public class VamsasAppDatastore
 
               for (int j = 0; j < an.length; j++)
               {
-                jalview.datamodel.AlignmentAnnotation jan = (jalview.datamodel.AlignmentAnnotation) getvObj2jv(an[j]);
+                jalview.datamodel.AlignmentAnnotation jan = (jalview.datamodel.AlignmentAnnotation) getvObj2jv(
+                        an[j]);
                 if (jan != null)
                 {
                   // update or stay the same.
@@ -1854,16 +1870,16 @@ public class VamsasAppDatastore
                   // jan.update(getjAlignmentAnnotation(jal, an[a])); // update
                   // from another annotation object in place.
 
-                  Cache.log
-                          .debug("update from vamsas alignment annotation to existing jalview alignment annotation.");
+                  Cache.log.debug(
+                          "update from vamsas alignment annotation to existing jalview alignment annotation.");
                   if (an[j].getModifiable() == null) // TODO: USE VAMSAS
                   // LIBRARY OBJECT LOCK
                   // METHODS)
                   {
                     // TODO: user defined annotation is totally mutable... - so
                     // load it up or throw away if locally edited.
-                    Cache.log
-                            .info("NOT IMPLEMENTED - Recovering user-modifiable annotation - yet...");
+                    Cache.log.info(
+                            "NOT IMPLEMENTED - Recovering user-modifiable annotation - yet...");
                   }
                   // TODO: compare annotation element rows
                   // TODO: compare props.
@@ -1887,18 +1903,18 @@ public class VamsasAppDatastore
               // ///////////////////////////////
               // construct alignment view
               alignFrame = new AlignFrame(jal, AlignFrame.DEFAULT_WIDTH,
-                      AlignFrame.DEFAULT_HEIGHT, alignment.getVorbaId()
-                              .toString());
+                      AlignFrame.DEFAULT_HEIGHT,
+                      alignment.getVorbaId().toString());
               av = alignFrame.getViewport();
               newAlignmentViews.addElement(av);
-              String title = alignment
-                      .getProvenance()
+              String title = alignment.getProvenance()
                       .getEntry(
                               alignment.getProvenance().getEntryCount() - 1)
                       .getAction();
               if (alignment.getPropertyCount() > 0)
               {
-                for (int p = 0, pe = alignment.getPropertyCount(); p < pe; p++)
+                for (int p = 0, pe = alignment
+                        .getPropertyCount(); p < pe; p++)
                 {
                   if (alignment.getProperty(p).getName().equals("title"))
                   {
@@ -1977,7 +1993,8 @@ public class VamsasAppDatastore
         DataSet dataset = root.getDataSet(_ds);
         if (dataset.getSequenceMappingCount() > 0)
         {
-          for (int sm = 0, smCount = dataset.getSequenceMappingCount(); sm < smCount; sm++)
+          for (int sm = 0, smCount = dataset
+                  .getSequenceMappingCount(); sm < smCount; sm++)
           {
             Rangetype seqmap = new jalview.io.vamsas.Sequencemapping(this,
                     dataset.getSequenceMapping(sm));
@@ -2034,10 +2051,11 @@ public class VamsasAppDatastore
     // may not quite cope with this (without binding an array of annotations to
     // a vamsas alignment annotation)
     // summary flags saying what we found over the set of annotation rows.
-    boolean[] AeContent = new boolean[] { false, false, false, false, false };
+    boolean[] AeContent = new boolean[] { false, false, false, false,
+        false };
     int[] rangeMap = getMapping(annotation);
-    jalview.datamodel.Annotation[][] anot = new jalview.datamodel.Annotation[][]
-    { new jalview.datamodel.Annotation[rangeMap.length],
+    jalview.datamodel.Annotation[][] anot = new jalview.datamodel.Annotation[][] {
+        new jalview.datamodel.Annotation[rangeMap.length],
         new jalview.datamodel.Annotation[rangeMap.length] };
     boolean mergeable = true; // false if 'after positions cant be placed on
     // same annotation row as positions.
@@ -2082,16 +2100,14 @@ public class VamsasAppDatastore
             Glyph[] glyphs = ae[aa].getGlyph();
             for (int g = 0; g < glyphs.length; g++)
             {
-              if (glyphs[g]
-                      .getDict()
-                      .equals(uk.ac.vamsas.objects.utils.GlyphDictionary.PROTEIN_SS_3STATE))
+              if (glyphs[g].getDict().equals(
+                      uk.ac.vamsas.objects.utils.GlyphDictionary.PROTEIN_SS_3STATE))
               {
                 ss = glyphs[g].getContent();
                 AeContent[HASSECSTR] = true;
               }
-              else if (glyphs[g]
-                      .getDict()
-                      .equals(uk.ac.vamsas.objects.utils.GlyphDictionary.PROTEIN_HD_HYDRO))
+              else if (glyphs[g].getDict().equals(
+                      uk.ac.vamsas.objects.utils.GlyphDictionary.PROTEIN_HD_HYDRO))
               {
                 Cache.log.debug("ignoring hydrophobicity glyph marker.");
                 AeContent[HASHPHOB] = true;
@@ -2109,8 +2125,8 @@ public class VamsasAppDatastore
               }
               else
               {
-                Cache.log
-                        .debug("IMPLEMENTATION TODO: Ignoring unknown glyph type "
+                Cache.log.debug(
+                        "IMPLEMENTATION TODO: Ignoring unknown glyph type "
                                 + glyphs[g].getDict());
               }
             }
@@ -2121,9 +2137,9 @@ public class VamsasAppDatastore
             AeContent[HASVALS] = true;
             if (ae[aa].getValueCount() > 1)
             {
-              Cache.log.warn("ignoring additional "
-                      + (ae[aa].getValueCount() - 1)
-                      + " values in annotation element.");
+              Cache.log.warn(
+                      "ignoring additional " + (ae[aa].getValueCount() - 1)
+                              + " values in annotation element.");
             }
             val = ae[aa].getValue(0);
           }
@@ -2239,7 +2255,8 @@ public class VamsasAppDatastore
           {
             if (gl == null)
             {
-              gl = new GraphLine(val.floatValue(), "", java.awt.Color.black);
+              gl = new GraphLine(val.floatValue(), "",
+                      java.awt.Color.black);
             }
             else
             {
@@ -2272,8 +2289,8 @@ public class VamsasAppDatastore
     }
     if (parsedRangeAnnotation == null)
     {
-      Cache.log
-              .debug("Inserting empty annotation row elements for a whole-alignment annotation.");
+      Cache.log.debug(
+              "Inserting empty annotation row elements for a whole-alignment annotation.");
     }
     else
     {
@@ -2367,7 +2384,8 @@ public class VamsasAppDatastore
                         && arow[i].description.length() < 3)
                 {
                   // copy over the description as the display char.
-                  arow[i].displayCharacter = new String(arow[i].description);
+                  arow[i].displayCharacter = new String(
+                          arow[i].description);
                 }
               }
               else
@@ -2423,8 +2441,8 @@ public class VamsasAppDatastore
         }
       } catch (Exception e)
       {
-        Cache.log
-                .info("UNIMPLEMENTED : Couldn't parse non-integer group value for setting graphGroup correctly.");
+        Cache.log.info(
+                "UNIMPLEMENTED : Couldn't parse non-integer group value for setting graphGroup correctly.");
       }
       return jan;
 
@@ -2448,9 +2466,8 @@ public class VamsasAppDatastore
       int[] se = null;
       if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0)
       {
-        throw new Error(
-                MessageManager
-                        .getString("error.invalid_vamsas_rangetype_cannot_resolve_lists"));
+        throw new Error(MessageManager.getString(
+                "error.invalid_vamsas_rangetype_cannot_resolve_lists"));
       }
       if (dseta.getSegCount() > 0)
       {
@@ -2507,9 +2524,8 @@ public class VamsasAppDatastore
       int[] se = null;
       if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0)
       {
-        throw new Error(
-                MessageManager
-                        .getString("error.invalid_vamsas_rangetype_cannot_resolve_lists"));
+        throw new Error(MessageManager.getString(
+                "error.invalid_vamsas_rangetype_cannot_resolve_lists"));
       }
       if (dseta.getSegCount() > 0)
       {
@@ -2552,8 +2568,10 @@ public class VamsasAppDatastore
    * @param maprange
    *          where the from range is the local mapped range, and the to range
    *          is the 'mapped' range in the MapRangeType
-   * @param default unit for local
-   * @param default unit for mapped
+   * @param default
+   *          unit for local
+   * @param default
+   *          unit for mapped
    * @return MapList
    */
   private jalview.util.MapList parsemapType(MapType maprange, int localu,
@@ -2564,8 +2582,9 @@ public class VamsasAppDatastore
     int[] mappedRange = getMapping(maprange.getMapped());
     long lu = maprange.getLocal().hasUnit() ? maprange.getLocal().getUnit()
             : localu;
-    long mu = maprange.getMapped().hasUnit() ? maprange.getMapped()
-            .getUnit() : mappedu;
+    long mu = maprange.getMapped().hasUnit()
+            ? maprange.getMapped().getUnit()
+            : mappedu;
     ml = new jalview.util.MapList(localRange, mappedRange, (int) lu,
             (int) mu);
     return ml;
@@ -2637,9 +2656,9 @@ public class VamsasAppDatastore
     jalview.datamodel.Provenance jprov = new jalview.datamodel.Provenance();
     for (int i = 0; i < prov.getEntryCount(); i++)
     {
-      jprov.addEntry(prov.getEntry(i).getUser(), prov.getEntry(i)
-              .getAction(), prov.getEntry(i).getDate(), prov.getEntry(i)
-              .getId());
+      jprov.addEntry(prov.getEntry(i).getUser(),
+              prov.getEntry(i).getAction(), prov.getEntry(i).getDate(),
+              prov.getEntry(i).getId());
     }
 
     return jprov;
@@ -2706,8 +2725,8 @@ public class VamsasAppDatastore
     return vobj2jv;
   }
 
-  public void storeSequenceMappings(AlignmentViewport viewport, String title)
-          throws Exception
+  public void storeSequenceMappings(AlignmentViewport viewport,
+          String title) throws Exception
   {
     AlignmentViewport av = viewport;
     try
@@ -2721,13 +2740,13 @@ public class VamsasAppDatastore
         Cache.log.warn("Creating new dataset for an alignment.");
         jal.setDataset(null);
       }
-      dataset = (DataSet) ((Alignment) getjv2vObj(viewport
-              .getSequenceSetId())).getV_parent(); // jal.getDataset());
+      dataset = (DataSet) ((Alignment) getjv2vObj(
+              viewport.getSequenceSetId())).getV_parent(); // jal.getDataset());
       if (dataset == null)
       {
         dataset = (DataSet) getjv2vObj(jal.getDataset());
-        Cache.log
-                .error("Can't find the correct dataset for the alignment in this view. Creating new one.");
+        Cache.log.error(
+                "Can't find the correct dataset for the alignment in this view. Creating new one.");
 
       }
       // Store any sequence mappings.
@@ -2742,18 +2761,18 @@ public class VamsasAppDatastore
             jalview.datamodel.Mapping[] mps = acf.getProtMappings();
             for (int smp = 0; smp < mps.length; smp++)
             {
-              uk.ac.vamsas.objects.core.SequenceType mfrom = (SequenceType) getjv2vObj(dmps[smp]);
+              uk.ac.vamsas.objects.core.SequenceType mfrom = (SequenceType) getjv2vObj(
+                      dmps[smp]);
               if (mfrom != null)
               {
-                new jalview.io.vamsas.Sequencemapping(this, mps[smp],
-                        mfrom, dataset);
+                new jalview.io.vamsas.Sequencemapping(this, mps[smp], mfrom,
+                        dataset);
               }
               else
               {
-                Cache.log
-                        .warn("NO Vamsas Binding for local sequence! NOT CREATING MAPPING FOR "
-                                + dmps[smp].getDisplayId(true)
-                                + " to "
+                Cache.log.warn(
+                        "NO Vamsas Binding for local sequence! NOT CREATING MAPPING FOR "
+                                + dmps[smp].getDisplayId(true) + " to "
                                 + mps[smp].getTo().getName());
               }
             }
@@ -2763,8 +2782,8 @@ public class VamsasAppDatastore
     } catch (Exception e)
     {
       throw new Exception(MessageManager.formatMessage(
-              "exception.couldnt_store_sequence_mappings",
-              new String[] { title }), e);
+              "exception.couldnt_store_sequence_mappings", new String[]
+              { title }), e);
     }
   }
 
index 55e72eb..d526a31 100755 (executable)
@@ -74,12 +74,11 @@ public class WSWUBlastClient
   {
     this.ap = ap;
     this.al = al;
-    output.setText(MessageManager
-            .getString("label.wswublast_client_credits"));
+    output.setText(
+            MessageManager.getString("label.wswublast_client_credits"));
 
-    Desktop.addInternalFrame(output, MessageManager
-            .getString("label.blasting_for_unidentified_sequence"), 800,
-            300);
+    Desktop.addInternalFrame(output, MessageManager.getString(
+            "label.blasting_for_unidentified_sequence"), 800, 300);
 
     for (int i = 0; i < ids.size(); i++)
     {
@@ -129,8 +128,8 @@ public class WSWUBlastClient
           {
             identitiesFound = true;
 
-            int value = Integer.parseInt(data.substring(
-                    data.indexOf("(") + 1, data.indexOf("%")));
+            int value = Integer.parseInt(data
+                    .substring(data.indexOf("(") + 1, data.indexOf("%")));
 
             if (value >= maxFound)
             {
@@ -180,12 +179,12 @@ public class WSWUBlastClient
         if (entries != null)
         {
           oldseq.addDBRef(new jalview.datamodel.DBRefEntry(
-                  jalview.datamodel.DBRefSource.UNIPROT, "0", entries[0]
-                          .getAccessionId()));
+                  jalview.datamodel.DBRefSource.UNIPROT, "0",
+                  entries[0].getAccessionId()));
         }
       }
     }
-    ap.paintAlignment(true);
+    ap.paintAlignment(true, false);
 
   }
 
@@ -201,8 +200,8 @@ public class WSWUBlastClient
 
       for (int i = 0; i < 9; i++)
       {
-        java.net.URL url = getClass().getResource(
-                "/images/dna" + (i + 1) + ".gif");
+        java.net.URL url = getClass()
+                .getResource("/images/dna" + (i + 1) + ".gif");
 
         if (url != null)
         {
@@ -224,7 +223,8 @@ public class WSWUBlastClient
           output.setFrameIcon(imageIcon[imageIndex]);
           output.setTitle(MessageManager.formatMessage(
                   "label.blasting_for_unidentified_sequence_jobs_running",
-                  new String[] { Integer.valueOf(jobsRunning).toString() }));
+                  new String[]
+                  { Integer.valueOf(jobsRunning).toString() }));
         } catch (Exception ex)
         {
         }
index 091d30e..eaf6ecd 100644 (file)
@@ -1,6 +1,25 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.io.cache;
 
-
 import jalview.bin.Cache;
 
 import java.util.Hashtable;
@@ -22,8 +41,6 @@ public class AppCache
 
   private static final String DEFAULT_LIMIT_KEY = ".DEFAULT_LIMIT";
 
-
-
   private Hashtable<String, LinkedHashSet<String>> cacheItems;
 
   private AppCache()
@@ -48,7 +65,6 @@ public class AppCache
     return foundCache;
   }
 
-
   /**
    * Returns a singleton instance of AppCache
    * 
@@ -63,8 +79,6 @@ public class AppCache
     return instance;
   }
 
-
-
   /**
    * Method for persisting cache items for a given cache key
    * 
index 444670b..a837512 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.io.cache;
 
 import jalview.bin.Cache;
@@ -8,6 +28,7 @@ import java.awt.Dimension;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -50,12 +71,51 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
 
   private JMenuItem menuItemClearCache = new JMenuItem();
 
+  volatile boolean enterWasPressed = false;
+
+  /**
+   * @return flag indicating if the most recent keypress was enter
+   */
+  public boolean wasEnterPressed()
+  {
+    return enterWasPressed;
+  }
+
   public JvCacheableInputBox(String newCacheKey)
   {
     super();
     this.cacheKey = newCacheKey;
     setEditable(true);
-    setPrototypeDisplayValue("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
+    addKeyListener(new KeyListener()
+    {
+
+      @Override
+      public void keyTyped(KeyEvent e)
+      {
+        enterWasPressed = false;
+        if (e.getKeyCode() == KeyEvent.VK_ENTER)
+        {
+          enterWasPressed = true;
+        }
+        // let event bubble up
+      }
+
+      @Override
+      public void keyReleased(KeyEvent e)
+      {
+        // TODO Auto-generated method stub
+
+      }
+
+      @Override
+      public void keyPressed(KeyEvent e)
+      {
+        // TODO Auto-generated method stub
+
+      }
+    });
+    setPrototypeDisplayValue(
+            "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
     appCache = AppCache.getInstance();
     initCachePopupMenu();
     initCache(newCacheKey);
@@ -77,8 +137,8 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
       return;
     }
     // convert delimited cache items to a list of strings
-    List<String> persistedCacheItems = Arrays.asList(delimitedCacheStr
-            .split(AppCache.CACHE_DELIMITER));
+    List<String> persistedCacheItems = Arrays
+            .asList(delimitedCacheStr.split(AppCache.CACHE_DELIMITER));
 
     LinkedHashSet<String> foundCacheItems = appCache
             .getAllCachedItemsFor(cacheKey);
@@ -101,12 +161,12 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
   {
     pnlDefaultCache.setBackground(Color.WHITE);
     // pad panel so as to align with other menu items
-    pnlDefaultCache.setBorder(BorderFactory.createEmptyBorder(0,
-            LEFT_BOARDER_WIDTH, 0, 0));
+    pnlDefaultCache.setBorder(
+            BorderFactory.createEmptyBorder(0, LEFT_BOARDER_WIDTH, 0, 0));
     txtDefaultCacheSize.setPreferredSize(new Dimension(45, 20));
     txtDefaultCacheSize.setFont(new java.awt.Font("Verdana", 0, 12));
-    lblDefaultCacheSize.setText(MessageManager
-            .getString("label.default_cache_size"));
+    lblDefaultCacheSize
+            .setText(MessageManager.getString("label.default_cache_size"));
     lblDefaultCacheSize.setFont(new java.awt.Font("Verdana", 0, 12));
     // Force input to accept only Integer entries up to length - INPUT_LIMIT
     txtDefaultCacheSize.setDocument(new PlainDocument()
@@ -141,8 +201,8 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
     pnlDefaultCache.add(lblDefaultCacheSize);
     menuItemClearCache.setFont(new java.awt.Font("Verdana", 0, 12));
     pnlDefaultCache.add(txtDefaultCacheSize);
-    menuItemClearCache.setText(MessageManager
-            .getString("action.clear_cached_items"));
+    menuItemClearCache
+            .setText(MessageManager.getString("action.clear_cached_items"));
     menuItemClearCache.addActionListener(new ActionListener()
     {
       @Override
@@ -195,9 +255,9 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
       @Override
       public void run()
       {
-        int userLimit = txtDefaultCacheSize.getText().trim().isEmpty() ? Integer
-                .valueOf(AppCache.DEFAULT_LIMIT) : Integer
-                .valueOf(txtDefaultCacheSize.getText());
+        int userLimit = txtDefaultCacheSize.getText().trim().isEmpty()
+                ? Integer.valueOf(AppCache.DEFAULT_LIMIT)
+                : Integer.valueOf(txtDefaultCacheSize.getText());
         int cacheLimit = appCache.updateCacheLimit(cacheKey, userLimit);
         String userInput = getUserInput();
         if (userInput != null && !userInput.isEmpty())
@@ -259,7 +319,6 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
     });
   }
 
-
   /**
    * This method should be called to persist the in-memory cache when this
    * components parent frame is closed / exited
@@ -267,9 +326,9 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
   public void persistCache()
   {
     appCache.persistCache(cacheKey);
-    int userLimit = txtDefaultCacheSize.getText().trim().isEmpty() ? Integer
-            .valueOf(AppCache.DEFAULT_LIMIT) : Integer
-            .valueOf(txtDefaultCacheSize.getText());
+    int userLimit = txtDefaultCacheSize.getText().trim().isEmpty()
+            ? Integer.valueOf(AppCache.DEFAULT_LIMIT)
+            : Integer.valueOf(txtDefaultCacheSize.getText());
     appCache.updateCacheLimit(cacheKey, userLimit);
   }
 
@@ -280,8 +339,8 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
    */
   public String getUserInput()
   {
-    return getEditor().getItem() == null ? "" : getEditor().getItem()
-            .toString().trim();
+    return getEditor().getItem() == null ? ""
+            : getEditor().getItem().toString().trim();
   }
 
 }
index eb74eea..da0c245 100644 (file)
@@ -165,7 +165,8 @@ public class ExonerateHelper extends Gff2Helper
     SequenceI mapFromSequence = seq;
     SequenceI mapToSequence = mappedSequence;
     if ((type == MappingType.NucleotideToPeptide && featureIsOnTarget)
-            || (type == MappingType.PeptideToNucleotide && !featureIsOnTarget))
+            || (type == MappingType.PeptideToNucleotide
+                    && !featureIsOnTarget))
     {
       mapFromSequence = mappedSequence;
       mapToSequence = seq;
@@ -267,8 +268,8 @@ public class ExonerateHelper extends Gff2Helper
     {
       fromStart = alignToStart;
       toStart = alignFromStart;
-      toEnd = forwardStrand ? toStart + alignCount - 1 : toStart
-              - (alignCount - 1);
+      toEnd = forwardStrand ? toStart + alignCount - 1
+              : toStart - (alignCount - 1);
       int toLength = Math.abs(toEnd - toStart) + 1;
       int fromLength = toLength * type.getFromRatio() / type.getToRatio();
       fromEnd = fromStart + fromLength - 1;
@@ -352,12 +353,16 @@ public class ExonerateHelper extends Gff2Helper
     return false;
   }
 
+  /**
+   * An override to set feature group to "exonerate" instead of the default GFF
+   * source value (column 2)
+   */
   @Override
   protected SequenceFeature buildSequenceFeature(String[] gff,
           Map<String, List<String>> set)
   {
-    SequenceFeature sf = super.buildSequenceFeature(gff, set);
-    sf.setFeatureGroup("exonerate");
+    SequenceFeature sf = super.buildSequenceFeature(gff, TYPE_COL,
+            "exonerate", set);
 
     return sf;
   }
index 82e5313..c7e1d7a 100644 (file)
@@ -152,8 +152,8 @@ public class Gff3Helper extends GffHelperBase
      */
     if ("-".equals(strand))
     {
-      System.err
-              .println("Skipping mapping from reverse complement as not yet supported");
+      System.err.println(
+              "Skipping mapping from reverse complement as not yet supported");
       return null;
     }
 
@@ -244,7 +244,8 @@ public class Gff3Helper extends GffHelperBase
    * @return
    */
   @SuppressWarnings("unused")
-  protected String findTargetId(String target, Map<String, List<String>> set)
+  protected String findTargetId(String target,
+          Map<String, List<String>> set)
   {
     return target;
   }
@@ -275,8 +276,8 @@ public class Gff3Helper extends GffHelperBase
    * @throws IOException
    */
   protected SequenceFeature processProteinMatch(
-          Map<String, List<String>> set, SequenceI seq,
-          String[] gffColumns, AlignmentI align, List<SequenceI> newseqs,
+          Map<String, List<String>> set, SequenceI seq, String[] gffColumns,
+          AlignmentI align, List<SequenceI> newseqs,
           boolean relaxedIdMatching)
   {
     // This is currently tailored to InterProScan GFF output:
@@ -310,10 +311,9 @@ public class Gff3Helper extends GffHelperBase
          * give the mapped sequence a copy of the sequence feature, with 
          * start/end range adjusted 
          */
-        SequenceFeature sf2 = new SequenceFeature(sf);
-        sf2.setBegin(1);
         int sequenceFeatureLength = 1 + sf.getEnd() - sf.getBegin();
-        sf2.setEnd(sequenceFeatureLength);
+        SequenceFeature sf2 = new SequenceFeature(sf, 1,
+                sequenceFeatureLength, sf.getFeatureGroup(), sf.getScore());
         mappedSequence.addSequenceFeature(sf2);
 
         /*
@@ -321,8 +321,8 @@ public class Gff3Helper extends GffHelperBase
          * renamed with its qualified accession id; renaming has to wait until
          * all sequence reference resolution is complete
          */
-        String accessionId = StringUtils.listToDelimitedString(
-                set.get(NAME), ",");
+        String accessionId = StringUtils
+                .listToDelimitedString(set.get(NAME), ",");
         if (accessionId.length() > 0)
         {
           String database = sf.getType(); // TODO InterProScan only??
@@ -362,9 +362,11 @@ public class Gff3Helper extends GffHelperBase
    */
   @Override
   protected SequenceFeature buildSequenceFeature(String[] gff,
+          int typeColumn, String group,
           Map<String, List<String>> attributes)
   {
-    SequenceFeature sf = super.buildSequenceFeature(gff, attributes);
+    SequenceFeature sf = super.buildSequenceFeature(gff, typeColumn, group,
+            attributes);
     String desc = getDescription(sf, attributes);
     if (desc != null)
     {
index 48c33e5..1d4d3ac 100644 (file)
@@ -150,8 +150,8 @@ public abstract class GffHelperBase implements GffHelperI
        * restrict from range to make them match up
        * it's kind of arbitrary which end we truncate - here it is the end
        */
-      System.err.print("Truncating mapping from " + Arrays.toString(from)
-              + " to ");
+      System.err.print(
+              "Truncating mapping from " + Arrays.toString(from) + " to ");
       if (from[1] > from[0])
       {
         from[1] -= fromOverlap / toRatio;
@@ -169,8 +169,8 @@ public abstract class GffHelperBase implements GffHelperI
       /*
        * restrict to range to make them match up
        */
-      System.err.print("Truncating mapping to " + Arrays.toString(to)
-              + " to ");
+      System.err.print(
+              "Truncating mapping to " + Arrays.toString(to) + " to ");
       if (to[1] > to[0])
       {
         to[1] -= fromOverlap / fromRatio;
@@ -261,7 +261,8 @@ public abstract class GffHelperBase implements GffHelperI
   /**
    * Parses the input line to a map of name / value(s) pairs. For example the
    * line <br>
-   * Notes=Fe-S;Method=manual curation, prediction; source = Pfam; Notes = Metal <br>
+   * Notes=Fe-S;Method=manual curation, prediction; source = Pfam; Notes = Metal
+   * <br>
    * if parsed with delimiter=";" and separators {' ', '='} <br>
    * would return a map with { Notes={Fe=S, Metal}, Method={manual curation,
    * prediction}, source={Pfam}} <br>
@@ -337,6 +338,19 @@ public abstract class GffHelperBase implements GffHelperI
   protected SequenceFeature buildSequenceFeature(String[] gff,
           Map<String, List<String>> attributes)
   {
+    return buildSequenceFeature(gff, TYPE_COL, gff[SOURCE_COL], attributes);
+  }
+
+  /**
+   * @param gff
+   * @param typeColumn
+   * @param group
+   * @param attributes
+   * @return
+   */
+  protected SequenceFeature buildSequenceFeature(String[] gff,
+          int typeColumn, String group, Map<String, List<String>> attributes)
+  {
     try
     {
       int start = Integer.parseInt(gff[START_COL]);
@@ -355,8 +369,8 @@ public abstract class GffHelperBase implements GffHelperI
         // e.g. '.' - leave as zero
       }
 
-      SequenceFeature sf = new SequenceFeature(gff[TYPE_COL],
-              gff[SOURCE_COL], start, end, score, gff[SOURCE_COL]);
+      SequenceFeature sf = new SequenceFeature(gff[typeColumn],
+              gff[SOURCE_COL], start, end, score, group);
 
       sf.setStrand(gff[STRAND_COL]);
 
@@ -375,8 +389,8 @@ public abstract class GffHelperBase implements GffHelperI
          */
         for (Entry<String, List<String>> attr : attributes.entrySet())
         {
-          String values = StringUtils.listToDelimitedString(
-                  attr.getValue(), ",");
+          String values = StringUtils.listToDelimitedString(attr.getValue(),
+                  ",");
           sf.setValue(attr.getKey(), values);
           if (NOTE.equals(attr.getKey()))
           {
index e1334e1..948cdd2 100644 (file)
@@ -73,13 +73,19 @@ public class InterProScanHelper extends Gff3Helper
   }
 
   /**
- * 
- */
+   * An override that
+   * <ul>
+   * <li>uses Source (column 2) as feature type instead of the default column 3</li>
+   * <li>sets "InterProScan" as the feature group</li>
+   * <li>extracts "signature_desc" attribute as the feature description</li>
+   * </ul>
+   */
   @Override
   protected SequenceFeature buildSequenceFeature(String[] gff,
           Map<String, List<String>> attributes)
   {
-    SequenceFeature sf = super.buildSequenceFeature(gff, attributes);
+    SequenceFeature sf = super.buildSequenceFeature(gff, SOURCE_COL,
+            INTER_PRO_SCAN, attributes);
 
     /*
      * signature_desc is a more informative source of description
@@ -91,13 +97,6 @@ public class InterProScanHelper extends Gff3Helper
       sf.setDescription(description);
     }
 
-    /*
-     * Set sequence feature group as 'InterProScan', and type as the source
-     * database for this match (e.g. 'Pfam')
-     */
-    sf.setType(gff[SOURCE_COL]);
-    sf.setFeatureGroup(INTER_PRO_SCAN);
-
     return sf;
   }
 
@@ -112,8 +111,8 @@ public class InterProScanHelper extends Gff3Helper
     SequenceOntologyI so = SequenceOntologyFactory.getInstance();
     String type = columns[TYPE_COL];
     if (so.isA(type, SequenceOntologyI.PROTEIN_MATCH)
-            || (".".equals(columns[SOURCE_COL]) && so.isA(type,
-                    SequenceOntologyI.POLYPEPTIDE)))
+            || (".".equals(columns[SOURCE_COL])
+                    && so.isA(type, SequenceOntologyI.POLYPEPTIDE)))
     {
       return true;
     }
@@ -125,7 +124,8 @@ public class InterProScanHelper extends Gff3Helper
    * GFF field 'ID' rather than the usual 'Target' :-O
    */
   @Override
-  protected String findTargetId(String target, Map<String, List<String>> set)
+  protected String findTargetId(String target,
+          Map<String, List<String>> set)
   {
     List<String> ids = set.get(ID);
     if (ids == null || ids.size() != 1)
index 138fef7..1635682 100644 (file)
@@ -157,7 +157,8 @@ public class ParsePackedSet
         {
           jalview.io.FeaturesFile ff = new jalview.io.FeaturesFile(src);
           context.updateSetModified(ff.parse(context.getLastAlignment(),
-                  context.featureColours, false, context.relaxedIdMatching));
+                  context.featureColours, false,
+                  context.relaxedIdMatching));
         } catch (Exception e)
         {
           errmsg = ("Failed to parse the Features file associated with the alignment.");
@@ -232,8 +233,8 @@ public class ParsePackedSet
     {
       String type = args[i++];
       final String file = args[i++];
-      final JvDataType jtype = DataProvider.JvDataType.valueOf(type
-              .toUpperCase());
+      final JvDataType jtype = DataProvider.JvDataType
+              .valueOf(type.toUpperCase());
       if (jtype != null)
       {
         final FileParse fp;
@@ -271,8 +272,8 @@ public class ParsePackedSet
     ParsePackedSet pps;
     try
     {
-      newdm = (pps = new ParsePackedSet()).getAlignment(
-              context = new JalviewDataset(), dp);
+      newdm = (pps = new ParsePackedSet())
+              .getAlignment(context = new JalviewDataset(), dp);
     } catch (Exception e)
     {
       System.out.println("Test failed for these arguments.\n");
@@ -296,8 +297,8 @@ public class ParsePackedSet
     {
       if (context.getLastAlignmentSet().isModified())
       {
-        System.err
-                .println("Initial alignment set was modified and any associated views should be updated.");
+        System.err.println(
+                "Initial alignment set was modified and any associated views should be updated.");
       }
     }
   }
index 9db7a8e..a399c04 100644 (file)
 package jalview.io.vamsas;
 
 import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.io.VamsasAppDatastore;
 
+import java.util.List;
+
 import uk.ac.vamsas.objects.core.DataSet;
 import uk.ac.vamsas.objects.core.DbRef;
 import uk.ac.vamsas.objects.core.Sequence;
@@ -45,12 +48,12 @@ public class Datasetsequence extends DatastoreItem
   // private AlignmentI jvdset;
 
   public Datasetsequence(VamsasAppDatastore vamsasAppDatastore,
-          SequenceI sq, String dict, DataSet dataset)
+          SequenceI sq, String theDict, DataSet theDataset)
   {
     super(vamsasAppDatastore, sq, uk.ac.vamsas.objects.core.Sequence.class);
-    this.dataset = dataset;
+    this.dataset = theDataset;
     // this.jvdset = jvdset;
-    this.dict = dict;
+    this.dict = theDict;
     doSync();
   }
 
@@ -61,6 +64,7 @@ public class Datasetsequence extends DatastoreItem
     doJvUpdate();
   }
 
+  @Override
   public void addFromDocument()
   {
     Sequence vseq = (Sequence) vobj;
@@ -73,13 +77,15 @@ public class Datasetsequence extends DatastoreItem
     modified = true;
   }
 
+  @Override
   public void updateFromDoc()
   {
     Sequence sq = (Sequence) vobj;
     SequenceI sequence = (SequenceI) jvobj;
     if (!sequence.getSequenceAsString().equals(sq.getSequence()))
     {
-      log.warn("Potential Client Error ! - mismatch of dataset sequence: and jalview internal dataset sequence.");
+      log.warn(
+              "Potential Client Error ! - mismatch of dataset sequence: and jalview internal dataset sequence.");
     }
     else
     {
@@ -128,25 +134,21 @@ public class Datasetsequence extends DatastoreItem
    */
   private boolean updateSqFeatures()
   {
-    boolean modified = false;
+    boolean changed = false;
     SequenceI sq = (SequenceI) jvobj;
 
     // add or update any new features/references on dataset sequence
-    if (sq.getSequenceFeatures() != null)
+    List<SequenceFeature> sfs = sq.getSequenceFeatures();
+    for (SequenceFeature sf : sfs)
     {
-      int sfSize = sq.getSequenceFeatures().length;
-
-      for (int sf = 0; sf < sfSize; sf++)
-      {
-        modified |= new jalview.io.vamsas.Sequencefeature(datastore,
-                (jalview.datamodel.SequenceFeature) sq
-                        .getSequenceFeatures()[sf], dataset,
-                (Sequence) vobj).docWasUpdated();
-      }
+      changed |= new jalview.io.vamsas.Sequencefeature(datastore, sf,
+              dataset, (Sequence) vobj).docWasUpdated();
     }
-    return modified;
+
+    return changed;
   }
 
+  @Override
   public void addToDocument()
   {
     SequenceI sq = (SequenceI) jvobj;
@@ -183,7 +185,7 @@ public class Datasetsequence extends DatastoreItem
       for (int db = 0; db < entries.length; db++)
       {
         modifiedthedoc |= new jalview.io.vamsas.Dbref(datastore,
-        // dbentry =
+                // dbentry =
                 entries[db], sq, (Sequence) vobj, dataset).docWasUpdated();
 
       }
@@ -210,22 +212,25 @@ public class Datasetsequence extends DatastoreItem
       for (int db = 0; db < entries.length; db++)
       {
         modifiedtheseq |= new jalview.io.vamsas.Dbref(datastore,
-        // dbentry =
+                // dbentry =
                 entries[db], vsq, sq).jvWasUpdated();
       }
     }
     return modifiedtheseq;
   }
 
+  @Override
   public void conflict()
   {
-    log.warn("Conflict in dataset sequence update to document. Overwriting document");
+    log.warn(
+            "Conflict in dataset sequence update to document. Overwriting document");
     // TODO: could try to import from document data to jalview first. and then
     updateToDoc();
   }
 
   boolean modified = false;
 
+  @Override
   public void updateToDoc()
   {
     SequenceI sq = (SequenceI) jvobj;
index 1560ad0..56d9fa4 100644 (file)
@@ -76,8 +76,8 @@ public abstract class DatastoreItem
     }
     if (Cache.log.isDebugEnabled())
     {
-      Cache.log.debug("Returning null VorbaID binding for jalview object "
-              + jvobj);
+      Cache.log.debug(
+              "Returning null VorbaID binding for jalview object " + jvobj);
     }
     return null;
   }
@@ -95,8 +95,8 @@ public abstract class DatastoreItem
     if (id == null)
     {
       id = cdoc.registerObject(vobj);
-      Cache.log
-              .debug("Registering new object and returning null for getvObj2jv");
+      Cache.log.debug(
+              "Registering new object and returning null for getvObj2jv");
       return null;
     }
     if (vobj2jv.containsKey(vobj.getVorbaId()))
@@ -124,28 +124,27 @@ public abstract class DatastoreItem
       {
         Cache.log.error("Failed to get id for "
                 + (vobj.isRegisterable() ? "registerable"
-                        : "unregisterable") + " object " + vobj);
+                        : "unregisterable")
+                + " object " + vobj);
       }
     }
     if (vobj2jv.containsKey(vobj.getVorbaId())
             && !(vobj2jv.get(vobj.getVorbaId())).equals(jvobj))
     {
-      Cache.log
-              .debug("Warning? Overwriting existing vamsas id binding for "
+      Cache.log.debug(
+              "Warning? Overwriting existing vamsas id binding for "
                       + vobj.getVorbaId(),
-                      new Exception(
-                              MessageManager
-                                      .getString("exception.overwriting_vamsas_id_binding")));
+              new Exception(MessageManager.getString(
+                      "exception.overwriting_vamsas_id_binding")));
     }
     else if (jv2vobj.containsKey(jvobj)
             && !((VorbaId) jv2vobj.get(jvobj)).equals(vobj.getVorbaId()))
     {
-      Cache.log
-              .debug("Warning? Overwriting existing jalview object binding for "
+      Cache.log.debug(
+              "Warning? Overwriting existing jalview object binding for "
                       + jvobj,
-                      new Exception(
-                              MessageManager
-                                      .getString("exception.overwriting_jalview_id_binding")));
+              new Exception(MessageManager.getString(
+                      "exception.overwriting_jalview_id_binding")));
     }
     /*
      * Cache.log.error("Attempt to make conflicting object binding! "+vobj+" id "
@@ -197,7 +196,8 @@ public abstract class DatastoreItem
     {
       throw new Error(MessageManager.formatMessage(
               "error.implementation_error_old_jalview_object_not_bound",
-              new String[] { oldjvobject.toString() }));
+              new String[]
+              { oldjvobject.toString() }));
     }
     if (newjvobject != null)
     {
@@ -236,13 +236,11 @@ public abstract class DatastoreItem
     tojalview = true;
     if (jvobj != null && !(boundType.isAssignableFrom(jvobj.getClass())))
     {
-      throw new Error(
-              MessageManager
-                      .formatMessage(
-                              "error.implementation_error_vamsas_doc_class_should_bind_to_type",
-                              new String[] { vobj.getClass().toString(),
-                                  boundType.toString(),
-                                  jvobj.getClass().toString() }));
+      throw new Error(MessageManager.formatMessage(
+              "error.implementation_error_vamsas_doc_class_should_bind_to_type",
+              new String[]
+              { vobj.getClass().toString(), boundType.toString(),
+                  jvobj.getClass().toString() }));
     }
     dsReg.registerDsObj(this);
   }
@@ -268,13 +266,11 @@ public abstract class DatastoreItem
     vobj = getjv2vObj(jvobj);
     if (vobj != null && !(boundToType.isAssignableFrom(vobj.getClass())))
     {
-      throw new Error(
-              MessageManager
-                      .formatMessage(
-                              "error.implementation_error_vamsas_doc_class_should_bind_to_type",
-                              new String[] { jvobj2.getClass().toString(),
-                                  boundToType.toString(),
-                                  vobj.getClass().toString() }));
+      throw new Error(MessageManager.formatMessage(
+              "error.implementation_error_vamsas_doc_class_should_bind_to_type",
+              new String[]
+              { jvobj2.getClass().toString(), boundToType.toString(),
+                  vobj.getClass().toString() }));
     }
     dsReg.registerDsObj(this);
   }
@@ -460,9 +456,9 @@ public abstract class DatastoreItem
     jalview.datamodel.Provenance jprov = new jalview.datamodel.Provenance();
     for (int i = 0; i < prov.getEntryCount(); i++)
     {
-      jprov.addEntry(prov.getEntry(i).getUser(), prov.getEntry(i)
-              .getAction(), prov.getEntry(i).getDate(), prov.getEntry(i)
-              .getId());
+      jprov.addEntry(prov.getEntry(i).getUser(),
+              prov.getEntry(i).getAction(), prov.getEntry(i).getDate(),
+              prov.getEntry(i).getId());
     }
 
     return jprov;
index 3e2f4e5..bdef00f 100644 (file)
@@ -92,8 +92,8 @@ public class Dbref extends Rangetype
     }
     else
     {
-      jalview.bin.Cache.log.debug("Ignoring mapless DbRef.Map "
-              + jvobj.getSrcAccString());
+      jalview.bin.Cache.log.debug(
+              "Ignoring mapless DbRef.Map " + jvobj.getSrcAccString());
     }
 
   }
@@ -106,7 +106,8 @@ public class Dbref extends Rangetype
    */
   private void updateMapTo(jalview.datamodel.Mapping mp)
   {
-    log.info("Performing updateMapTo remove this message when we know what we're doing.");
+    log.info(
+            "Performing updateMapTo remove this message when we know what we're doing.");
     // TODO determine how sequences associated with database mappings are stored
     // in the document
     if (mp != null && mp.getTo() != null)
@@ -120,12 +121,11 @@ public class Dbref extends Rangetype
           // sync the dataset sequence, if it hasn't been done already.
           // TODO: ensure real dataset sequence corresponding to getTo is
           // recovered
-          dssync = new Datasetsequence(
-                  datastore,
-                  mp.getTo(),
-                  (mp.getMappedWidth() == mp.getWidth()) ? sequence
-                          .getDictionary()
-                          : ((mp.getMappedWidth() == 3) ? uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA
+          dssync = new Datasetsequence(datastore, mp.getTo(),
+                  (mp.getMappedWidth() == mp.getWidth())
+                          ? sequence.getDictionary()
+                          : ((mp.getMappedWidth() == 3)
+                                  ? uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA
                                   : uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_AA),
                   ds);
         }
@@ -175,9 +175,9 @@ public class Dbref extends Rangetype
   {
     DbRef vobj = (DbRef) this.vobj;
     DBRefEntry jvobj = (DBRefEntry) this.jvobj;
-    jalview.bin.Cache.log.debug("Conflict in dbentry update for "
-            + vobj.getAccessionId() + vobj.getSource() + " "
-            + vobj.getVorbaId());
+    jalview.bin.Cache.log
+            .debug("Conflict in dbentry update for " + vobj.getAccessionId()
+                    + vobj.getSource() + " " + vobj.getVorbaId());
     // TODO Auto-generated method stub
 
   }
@@ -187,9 +187,9 @@ public class Dbref extends Rangetype
     DbRef vobj = (DbRef) this.vobj;
     DBRefEntry jvobj = (DBRefEntry) this.jvobj;
     // add new dbref
-    sq.addDBRef(jvobj = new jalview.datamodel.DBRefEntry(vobj.getSource()
-            .toString(), vobj.getVersion().toString(), vobj
-            .getAccessionId().toString()));
+    sq.addDBRef(jvobj = new jalview.datamodel.DBRefEntry(
+            vobj.getSource().toString(), vobj.getVersion().toString(),
+            vobj.getAccessionId().toString()));
     if (vobj.getMapCount() > 0)
     {
       // TODO: Jalview ignores all the other maps
@@ -230,8 +230,8 @@ public class Dbref extends Rangetype
       }
       else
       {
-        jalview.bin.Cache.log.debug("Ignoring mapless DbRef.Map "
-                + jvobj.getSrcAccString());
+        jalview.bin.Cache.log.debug(
+                "Ignoring mapless DbRef.Map " + jvobj.getSrcAccString());
       }
     }
   }
index 96820d3..ee4fa83 100644 (file)
@@ -53,7 +53,8 @@ public abstract class Rangetype extends DatastoreItem
     super(datastore);
   }
 
-  public Rangetype(VamsasAppDatastore datastore, Vobject vobj, Class jvClass)
+  public Rangetype(VamsasAppDatastore datastore, Vobject vobj,
+          Class jvClass)
   {
     super(datastore, vobj, jvClass);
   }
@@ -78,9 +79,8 @@ public abstract class Rangetype extends DatastoreItem
       int[] se = null;
       if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0)
       {
-        throw new Error(
-                MessageManager
-                        .getString("error.invalid_vamsas_rangetype_cannot_resolve_lists"));
+        throw new Error(MessageManager.getString(
+                "error.invalid_vamsas_rangetype_cannot_resolve_lists"));
       }
       if (dseta.getSegCount() > 0)
       {
@@ -137,9 +137,8 @@ public abstract class Rangetype extends DatastoreItem
       int[] se = null;
       if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0)
       {
-        throw new Error(
-                MessageManager
-                        .getString("error.invalid_vamsas_rangetype_cannot_resolve_lists"));
+        throw new Error(MessageManager.getString(
+                "error.invalid_vamsas_rangetype_cannot_resolve_lists"));
       }
       if (dseta.getSegCount() > 0)
       {
@@ -186,9 +185,8 @@ public abstract class Rangetype extends DatastoreItem
       int[] se = null;
       if (range.getSegCount() > 0 && range.getPosCount() > 0)
       {
-        throw new Error(
-                MessageManager
-                        .getString("error.invalid_vamsas_rangetype_cannot_resolve_lists"));
+        throw new Error(MessageManager.getString(
+                "error.invalid_vamsas_rangetype_cannot_resolve_lists"));
       }
       if (range.getSegCount() > 0)
       {
@@ -247,8 +245,10 @@ public abstract class Rangetype extends DatastoreItem
    * @param maprange
    *          where the from range is the local mapped range, and the to range
    *          is the 'mapped' range in the MapRangeType
-   * @param default unit for local
-   * @param default unit for mapped
+   * @param default
+   *          unit for local
+   * @param default
+   *          unit for mapped
    * @return MapList
    */
   protected jalview.util.MapList parsemapType(MapType maprange, int localu,
@@ -259,8 +259,9 @@ public abstract class Rangetype extends DatastoreItem
     int[] mappedRange = getIntervals(maprange.getMapped());
     long lu = maprange.getLocal().hasUnit() ? maprange.getLocal().getUnit()
             : localu;
-    long mu = maprange.getMapped().hasUnit() ? maprange.getMapped()
-            .getUnit() : mappedu;
+    long mu = maprange.getMapped().hasUnit()
+            ? maprange.getMapped().getUnit()
+            : mappedu;
     ml = new jalview.util.MapList(localRange, mappedRange, (int) lu,
             (int) mu);
     return ml;
@@ -304,9 +305,8 @@ public abstract class Rangetype extends DatastoreItem
   {
     if (ml == null)
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_error_maplist_is_null"));
+      throw new Error(MessageManager
+              .getString("error.implementation_error_maplist_is_null"));
     }
     maprange.setLocal(new Local());
     maprange.setMapped(new Mapped());
index 61491b2..74f73d4 100644 (file)
@@ -97,10 +97,8 @@ public class Sequencefeature extends Rangetype
     DataSetAnnotations dsa = (DataSetAnnotations) vobj;
     if (dsa.getSeqRefCount() != 1)
     {
-      Cache.log
-              .warn("Not binding "
-                      + dsa.getVorbaId()
-                      + " to Sequence Feature - has multiple dataset sequence references.");
+      Cache.log.warn("Not binding " + dsa.getVorbaId()
+              + " to Sequence Feature - has multiple dataset sequence references.");
       return;
     }
     jalview.datamodel.SequenceFeature sf = (jalview.datamodel.SequenceFeature) jvobj;
@@ -130,8 +128,8 @@ public class Sequencefeature extends Rangetype
     if (dsa.getSeqRefCount() != 1)
     {
       replaceJvObjMapping(feature, null);
-      Cache.log
-              .warn("Binding of annotation to jalview feature has changed. Removing binding and recreating.");
+      Cache.log.warn(
+              "Binding of annotation to jalview feature has changed. Removing binding and recreating.");
       doSync(); // re-verify bindings.
     }
     else
@@ -158,10 +156,8 @@ public class Sequencefeature extends Rangetype
     {
       // conflicting update from document - we cannot map this feature anymore.
       replaceJvObjMapping(feature, null);
-      Cache.log
-              .warn("annotation ("
-                      + dsa.getVorbaId()
-                      + " bound to jalview feature cannot be mapped. Removing binding, deleting feature, and deleting feature.");
+      Cache.log.warn("annotation (" + dsa.getVorbaId()
+              + " bound to jalview feature cannot be mapped. Removing binding, deleting feature, and deleting feature.");
       // - consider deleting the feature ?
       dsSeq.deleteFeature(feature);
       // doSync();
@@ -202,8 +198,8 @@ public class Sequencefeature extends Rangetype
     vSeg.setInclusive(true);
     if (dsa.getSegCount() > 1)
     {
-      Cache.log
-              .debug("About to destroy complex annotation in vamsas document mapped to sequence feature ("
+      Cache.log.debug(
+              "About to destroy complex annotation in vamsas document mapped to sequence feature ("
                       + dsa.getVorbaId() + ")");
     }
     dsa.setSeg(new Seg[] { vSeg });
@@ -256,7 +252,8 @@ public class Sequencefeature extends Rangetype
           else if (vlu instanceof Integer)
           {
             valid = true;
-            nprop.setType(uk.ac.vamsas.objects.utils.Properties.INTEGERTYPE);
+            nprop.setType(
+                    uk.ac.vamsas.objects.utils.Properties.INTEGERTYPE);
           }
           else if (vlu instanceof Float)
           {
@@ -284,9 +281,39 @@ public class Sequencefeature extends Rangetype
   private SequenceFeature getJalviewSeqFeature(RangeAnnotation dseta)
   {
     int[] se = getBounds(dseta);
-    SequenceFeature sf = new jalview.datamodel.SequenceFeature(
-            dseta.getType(), dseta.getDescription(), dseta.getStatus(),
-            se[0], se[1], dseta.getGroup());
+
+    /*
+     * try to identify feature score
+     */
+    boolean scoreFound = false;
+    float theScore = 0f;
+    String featureType = dseta.getType();
+    if (dseta.getScoreCount() > 0)
+    {
+      Enumeration scr = dseta.enumerateScore();
+      while (scr.hasMoreElements())
+      {
+        Score score = (Score) scr.nextElement();
+        if (score.getName().equals(featureType))
+        {
+          theScore = score.getContent();
+          scoreFound = true;
+        }
+      }
+    }
+
+    SequenceFeature sf = null;
+    if (scoreFound)
+    {
+      sf = new SequenceFeature(featureType, dseta.getDescription(), se[0],
+              se[1], theScore, dseta.getGroup());
+    }
+    else
+    {
+      sf = new SequenceFeature(featureType, dseta.getDescription(), se[0],
+              se[1], dseta.getGroup());
+    }
+    sf.setStatus(dseta.getStatus());
     if (dseta.getLinkCount() > 0)
     {
       Link[] links = dseta.getLink();
@@ -302,11 +329,7 @@ public class Sequencefeature extends Rangetype
       while (scr.hasMoreElements())
       {
         Score score = (Score) scr.nextElement();
-        if (score.getName().equals(sf.getType()))
-        {
-          sf.setScore(score.getContent());
-        }
-        else
+        if (!score.getName().equals(sf.getType()))
         {
           sf.setValue(score.getName(), "" + score.getContent());
         }
index 160f5e2..2bcef3a 100644 (file)
@@ -102,10 +102,8 @@ public class Sequencemapping extends Rangetype
     if (ds != null && sequenceMapping.is__stored_in_document()
             && sequenceMapping.getV_parent() != ds)
     {
-      jalview.bin.Cache.log
-              .warn("Probable IMPLEMENTATION ERROR: "
-                      + ds
-                      + " doesn't match the parent of the bound sequence mapping object.");
+      jalview.bin.Cache.log.warn("Probable IMPLEMENTATION ERROR: " + ds
+              + " doesn't match the parent of the bound sequence mapping object.");
     }
   }
 
@@ -152,8 +150,8 @@ public class Sequencemapping extends Rangetype
     SequenceType to = (SequenceType) getjv2vObj(jvto);
     if (to == null)
     {
-      jalview.bin.Cache.log
-              .warn("FIXME NONFATAL - do a second update: Ignoring Forward Reference to seuqence not yet bound to vamsas seuqence object");
+      jalview.bin.Cache.log.warn(
+              "FIXME NONFATAL - do a second update: Ignoring Forward Reference to seuqence not yet bound to vamsas seuqence object");
       return;
     }
     SequenceMapping sequenceMapping = new SequenceMapping();
@@ -183,8 +181,8 @@ public class Sequencemapping extends Rangetype
 
     if (!dnaToProt)
     {
-      jalview.bin.Cache.log
-              .warn("Ignoring Mapping - don't support protein to protein mapping in vamsas document yet.");
+      jalview.bin.Cache.log.warn(
+              "Ignoring Mapping - don't support protein to protein mapping in vamsas document yet.");
       return;
     }
     if (ds == null)
@@ -211,8 +209,8 @@ public class Sequencemapping extends Rangetype
               true);
     }
     ds.addSequenceMapping(sequenceMapping);
-    sequenceMapping.setProvenance(this
-            .dummyProvenance("user defined coding region translation")); // TODO:
+    sequenceMapping.setProvenance(
+            this.dummyProvenance("user defined coding region translation")); // TODO:
     // correctly
     // construct
     // provenance
@@ -223,8 +221,8 @@ public class Sequencemapping extends Rangetype
     // mapping
     bindjvvobj(mjvmapping.getMap(), sequenceMapping);
 
-    jalview.bin.Cache.log.debug("Successfully created mapping "
-            + sequenceMapping.getVorbaId());
+    jalview.bin.Cache.log.debug(
+            "Successfully created mapping " + sequenceMapping.getVorbaId());
   }
 
   // private void update(jalview.util.MapList mjvmapping,
@@ -244,8 +242,8 @@ public class Sequencemapping extends Rangetype
   private void update(jalview.datamodel.Mapping mjvmapping,
           SequenceMapping sequenceMapping)
   {
-    jalview.bin.Cache.log
-            .error("Not implemented: Jalview Update Sequence DBRef Mapping");
+    jalview.bin.Cache.log.error(
+            "Not implemented: Jalview Update Sequence DBRef Mapping");
   }
 
   /**
@@ -297,8 +295,8 @@ public class Sequencemapping extends Rangetype
     if (from == null || to == null)
     {
 
-      jalview.bin.Cache.log
-              .error("Probable Vamsas implementation error : unbound dataset sequences involved in a mapping are being parsed!");
+      jalview.bin.Cache.log.error(
+              "Probable Vamsas implementation error : unbound dataset sequences involved in a mapping are being parsed!");
       return;
     }
 
@@ -442,8 +440,9 @@ public class Sequencemapping extends Rangetype
             boolean smaptolocal2tm = (tmpnnl) ? smap.equals(tmp.getMap())
                     : false;
             // smap to maps from te.map to te.local
-            boolean smaptotemap2local = (tmpnnl) ? smapI.equals(fmp
-                    .getMap()) : false;
+            boolean smaptotemap2local = (tmpnnl)
+                    ? smapI.equals(fmp.getMap())
+                    : false;
             if (smapfromlocal2fe && smaptotemap2local)
             {
               // smap implies mapping from to to from
index d800d20..aa130cc 100644 (file)
@@ -141,8 +141,8 @@ public class Tree extends DatastoreItem
   @Override
   public void conflict()
   {
-    Cache.log
-            .info("Update (with conflict) from vamsas document to alignment associated tree not implemented yet.");
+    Cache.log.info(
+            "Update (with conflict) from vamsas document to alignment associated tree not implemented yet.");
   }
 
   /*
@@ -162,7 +162,8 @@ public class Tree extends DatastoreItem
     else
     {
       // handle conflict
-      log.info("TODO: Add the locally modified tree in Jalview as a new tree in document, leaving locked tree unchanged.");
+      log.info(
+              "TODO: Add the locally modified tree in Jalview as a new tree in document, leaving locked tree unchanged.");
     }
   }
 
@@ -229,8 +230,8 @@ public class Tree extends DatastoreItem
       // or just correctly resolve the tree's seqData to the correct alignment
       // in
       // the document.
-      Vector alsqrefs = getjv2vObjs(findAlignmentSequences(jal, tp
-              .getTree().getOriginalData().getSequences()));
+      Vector alsqrefs = getjv2vObjs(findAlignmentSequences(jal,
+              tp.getTree().getOriginalData().getSequences()));
       Object[] alsqs = new Object[alsqrefs.size()];
       alsqrefs.copyInto(alsqs);
       vInput.setObjRef(alsqs);
@@ -270,7 +271,8 @@ public class Tree extends DatastoreItem
    * @return vector of alignment sequences in order of SeqCigar array (but
    *         missing unfound seqcigars)
    */
-  private Vector findAlignmentSequences(AlignmentI jal, SeqCigar[] sequences)
+  private Vector findAlignmentSequences(AlignmentI jal,
+          SeqCigar[] sequences)
   {
     SeqCigar[] tseqs = new SeqCigar[sequences.length];
     System.arraycopy(sequences, 0, tseqs, 0, sequences.length);
@@ -282,9 +284,8 @@ public class Tree extends DatastoreItem
       {
         for (int t = 0; t < sequences.length; t++)
         {
-          if (tseqs[t] != null
-                  && (tseqs[t].getRefSeq() == asq || tseqs[t].getRefSeq() == asq
-                          .getDatasetSequence()))
+          if (tseqs[t] != null && (tseqs[t].getRefSeq() == asq
+                  || tseqs[t].getRefSeq() == asq.getDatasetSequence()))
           // && tseqs[t].getStart()>=asq.getStart() &&
           // tseqs[t].getEnd()<=asq.getEnd())
           {
@@ -296,8 +297,8 @@ public class Tree extends DatastoreItem
     }
     if (alsq.size() < sequences.length)
     {
-      Cache.log
-              .warn("Not recovered all alignment sequences for given set of input sequence CIGARS");
+      Cache.log.warn(
+              "Not recovered all alignment sequences for given set of input sequence CIGARS");
     }
     return alsq;
   }
@@ -318,12 +319,12 @@ public class Tree extends DatastoreItem
 
     if (tp.getTree() == null)
     {
-      Cache.log.warn("Not updating SequenceTreeMap for "
-              + tree.getVorbaId());
+      Cache.log.warn(
+              "Not updating SequenceTreeMap for " + tree.getVorbaId());
       return;
     }
-    Vector<SequenceNode> leaves = tp.getTree().findLeaves(
-            tp.getTree().getTopNode());
+    Vector<SequenceNode> leaves = tp.getTree()
+            .findLeaves(tp.getTree().getTopNode());
     Treenode[] tn = tree.getTreenode(); // todo: select nodes for this
     // particular tree
     int sz = tn.length;
@@ -364,7 +365,8 @@ public class Tree extends DatastoreItem
         else
         {
           leaf.setPlaceholder(true);
-          leaf.setElement(new Sequence(leaf.getName(), "THISISAPLACEHLDER"));
+          leaf.setElement(
+                  new Sequence(leaf.getName(), "THISISAPLACEHLDER"));
         }
       }
     }
@@ -380,8 +382,8 @@ public class Tree extends DatastoreItem
    */
   public Treenode[] makeTreeNodes(TreeModel treeModel, Newick newick)
   {
-    Vector<SequenceNode> leaves = treeModel.findLeaves(treeModel
-            .getTopNode());
+    Vector<SequenceNode> leaves = treeModel
+            .findLeaves(treeModel.getTopNode());
     Vector tnv = new Vector();
     Enumeration l = leaves.elements();
     Hashtable nodespecs = new Hashtable();
@@ -416,10 +418,10 @@ public class Tree extends DatastoreItem
             else
             {
               System.err.println("WARNING: Unassociated treeNode "
-                      + tnode.element().toString()
-                      + " "
-                      + ((tnode.getName() != null) ? " label "
-                              + tnode.getName() : ""));
+                      + tnode.element().toString() + " "
+                      + ((tnode.getName() != null)
+                              ? " label " + tnode.getName()
+                              : ""));
             }
           }
         }
@@ -530,8 +532,8 @@ public class Tree extends DatastoreItem
       {
         if (tp.getEntry(pe).getInputCount() > 1)
         {
-          Cache.log
-                  .warn("Ignoring additional input spec in provenance entry "
+          Cache.log.warn(
+                  "Ignoring additional input spec in provenance entry "
                           + tp.getEntry(pe).toString());
         }
         // LATER: deal sensibly with multiple inputs
@@ -539,8 +541,8 @@ public class Tree extends DatastoreItem
         // is this the whole alignment or a specific set of sequences ?
         if (vInput.getObjRefCount() == 0)
         {
-          if (tree.getV_parent() != null
-                  && tree.getV_parent() instanceof uk.ac.vamsas.objects.core.Alignment)
+          if (tree.getV_parent() != null && tree
+                  .getV_parent() instanceof uk.ac.vamsas.objects.core.Alignment)
           {
             javport = getViewport(tree.getV_parent());
             jal = javport.getAlignment();
@@ -550,26 +552,27 @@ public class Tree extends DatastoreItem
         else
         {
           // Explicit reference - to alignment, sequences or what.
-          if (vInput.getObjRefCount() == 1
-                  && vInput.getObjRef(0) instanceof uk.ac.vamsas.objects.core.Alignment)
+          if (vInput.getObjRefCount() == 1 && vInput.getObjRef(
+                  0) instanceof uk.ac.vamsas.objects.core.Alignment)
           {
             // recover an AlignmentView for the input data
             javport = getViewport((Vobject) vInput.getObjRef(0));
             jal = javport.getAlignment();
             view = javport.getAlignment().getCompactAlignment();
           }
-          else if (vInput.getObjRef(0) instanceof uk.ac.vamsas.objects.core.AlignmentSequence)
+          else if (vInput.getObjRef(
+                  0) instanceof uk.ac.vamsas.objects.core.AlignmentSequence)
           {
             // recover an AlignmentView for the input data
-            javport = getViewport(((Vobject) vInput.getObjRef(0))
-                    .getV_parent());
+            javport = getViewport(
+                    ((Vobject) vInput.getObjRef(0)).getV_parent());
             jal = javport.getAlignment();
             jalview.datamodel.SequenceI[] seqs = new jalview.datamodel.SequenceI[vInput
                     .getObjRefCount()];
             for (int i = 0, iSize = vInput.getObjRefCount(); i < iSize; i++)
             {
-              SequenceI seq = (SequenceI) getvObj2jv((Vobject) vInput
-                      .getObjRef(i));
+              SequenceI seq = (SequenceI) getvObj2jv(
+                      (Vobject) vInput.getObjRef(i));
               seqs[i] = seq;
             }
             view = new jalview.datamodel.Alignment(seqs)
@@ -609,8 +612,8 @@ public class Tree extends DatastoreItem
         return new Object[] { new AlignmentView(view), jal };
       }
     }
-    Cache.log
-            .debug("Returning null for input data recovery from provenance.");
+    Cache.log.debug(
+            "Returning null for input data recovery from provenance.");
     return null;
   }
 
index 6daf275..29f3fa9 100644 (file)
@@ -39,19 +39,6 @@ public class JSFunctionExec implements Runnable
     jvlite.setExecutor(this);
   }
 
-  @Override
-  protected void finalize() throws Throwable
-  {
-    jvlite = null;
-    executor = null;
-    if (jsExecQueue != null)
-    {
-      jsExecQueue.clear();
-    }
-    jsExecQueue = null;
-    super.finalize();
-  }
-
   private Vector jsExecQueue;
 
   private Thread executor = null;
@@ -205,8 +192,8 @@ public class JSFunctionExec implements Runnable
               {
                 System.err.println("Falling back to javascript: url call");
               }
-              StringBuffer sb = new StringBuffer("javascript:" + _listener
-                      + "(");
+              StringBuffer sb = new StringBuffer(
+                      "javascript:" + _listener + "(");
               for (int i = 0; objects != null && i < objects.length; i++)
               {
                 if (i > 0)
@@ -216,9 +203,8 @@ public class JSFunctionExec implements Runnable
                 sb.append("\"");
                 // strip out nulls and complex objects that we can't pass this
                 // way.
-                if (objects[i] != null
-                        && !(objects[i].getClass().getName()
-                                .indexOf("jalview") == 0))
+                if (objects[i] != null && !(objects[i].getClass().getName()
+                        .indexOf("jalview") == 0))
                 {
                   sb.append(objects[i].toString());
                 }
index 51f6741..b5811aa 100644 (file)
@@ -73,7 +73,8 @@ public interface JalviewLiteJsApi
    * @return String list of selected sequence IDs, each terminated by the given
    *         separator
    */
-  public abstract String getSelectedSequencesFrom(AlignFrame alf, String sep);
+  public abstract String getSelectedSequencesFrom(AlignFrame alf,
+          String sep);
 
   /**
    * 
@@ -120,7 +121,8 @@ public interface JalviewLiteJsApi
    * @param sep
    *          separator between toselect fields
    */
-  public abstract void select(String sequenceIds, String columns, String sep);
+  public abstract void select(String sequenceIds, String columns,
+          String sep);
 
   /**
    * select regions of the given alignment frame
@@ -175,8 +177,8 @@ public interface JalviewLiteJsApi
    * @return selected sequences as flat file or empty string if there was no
    *         current selection
    */
-  public abstract String getSelectedSequencesAsAlignmentFrom(
-          AlignFrame alf, String format, String suffix);
+  public abstract String getSelectedSequencesAsAlignmentFrom(AlignFrame alf,
+          String format, String suffix);
 
   /**
    * get a separator separated list of sequence IDs reflecting the order of the
@@ -300,7 +302,8 @@ public interface JalviewLiteJsApi
    * @param alf
    * @param annotation
    */
-  public abstract void loadAnnotationFrom(AlignFrame alf, String annotation);
+  public abstract void loadAnnotationFrom(AlignFrame alf,
+          String annotation);
 
   /**
    * parse the given string as a jalview feature or GFF annotation file and
@@ -454,7 +457,8 @@ public interface JalviewLiteJsApi
    *          Jmol (e.g. first one is frame 1, second is frame 2, etc).
    * @see jalview.javascript.MouseOverStructureListener
    */
-  public abstract void setStructureListener(String listener, String modelSet);
+  public abstract void setStructureListener(String listener,
+          String modelSet);
 
   /**
    * remove any callback using the given listener function and associated with
@@ -567,8 +571,8 @@ public interface JalviewLiteJsApi
    * @see jalview.appletgui.AlignFrame#setFeatureGroupState(java.lang.String[],
    *      boolean)
    */
-  public abstract void setFeatureGroupStateOn(AlignFrame alf,
-          String groups, boolean state);
+  public abstract void setFeatureGroupStateOn(AlignFrame alf, String groups,
+          boolean state);
 
   public abstract void setFeatureGroupState(String groups, boolean state);
 
index fdf8b58..c2a963e 100644 (file)
@@ -27,8 +27,8 @@ import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.SequenceGroup;
 import jalview.structure.SelectionSource;
 
-public class JsSelectionSender extends JSFunctionExec implements
-        jalview.structure.SelectionListener, JsCallBack
+public class JsSelectionSender extends JSFunctionExec
+        implements jalview.structure.SelectionListener, JsCallBack
 {
 
   AlignFrame _af;
@@ -47,7 +47,8 @@ public class JsSelectionSender extends JSFunctionExec implements
   public void selection(SequenceGroup seqsel, ColumnSelection colsel,
           HiddenColumns hidden, SelectionSource source)
   {
-    // System.err.println("Testing selection event relay to jsfunction:"+_listener);
+    // System.err.println("Testing selection event relay to
+    // jsfunction:"+_listener);
     try
     {
       String setid = "";
@@ -64,8 +65,8 @@ public class JsSelectionSender extends JSFunctionExec implements
       }
       String[] seqs = new String[] {};
       String[] cols = new String[] {};
-      int strt = 0, end = (src == null) ? -1 : src.alignPanel.av
-              .getAlignment().getWidth();
+      int strt = 0, end = (src == null) ? -1
+              : src.alignPanel.av.getAlignment().getWidth();
       if (seqsel != null && seqsel.getSize() > 0)
       {
         seqs = new String[seqsel.getSize()];
@@ -107,12 +108,13 @@ public class JsSelectionSender extends JSFunctionExec implements
       }
       System.err.println("Relaying selection to jsfunction:" + _listener);
       executeJavascriptFunction(_listener,
-              new Object[] { src, setid, jvlite.arrayToSeparatorList(seqs),
+              new Object[]
+              { src, setid, jvlite.arrayToSeparatorList(seqs),
                   jvlite.arrayToSeparatorList(cols) });
     } catch (Exception ex)
     {
-      System.err
-              .println("Jalview Javascript exec error: Couldn't send selection message using function '"
+      System.err.println(
+              "Jalview Javascript exec error: Couldn't send selection message using function '"
                       + _listener + "'");
       ex.printStackTrace();
       if (ex instanceof netscape.javascript.JSException)
index 7b751f8..6a4d0f8 100644 (file)
@@ -26,8 +26,8 @@ import jalview.datamodel.SequenceI;
 import jalview.structure.VamsasListener;
 import jalview.structure.VamsasSource;
 
-public class MouseOverListener extends JSFunctionExec implements
-        VamsasListener, JsCallBack
+public class MouseOverListener extends JSFunctionExec
+        implements VamsasListener, JsCallBack
 {
   AlignFrame _af;
 
@@ -65,13 +65,14 @@ public class MouseOverListener extends JSFunctionExec implements
           // function
         }
         executeJavascriptFunction(_listener,
-                new Object[] { src, seq.getDisplayId(false), "" + (1 + i),
+                new Object[]
+                { src, seq.getDisplayId(false), "" + (1 + i),
                     "" + seq.findPosition(i) });
       } catch (Exception ex)
       {
 
-        System.err
-                .println("JalviewLite javascript error: Couldn't send mouseOver with handler '"
+        System.err.println(
+                "JalviewLite javascript error: Couldn't send mouseOver with handler '"
                         + _listener + "'");
         if (ex instanceof netscape.javascript.JSException)
         {
index c390b17..6071933 100644 (file)
@@ -70,8 +70,8 @@ import java.util.List;
  * @author Jim Procter (jprocter)
  * 
  */
-public class MouseOverStructureListener extends JSFunctionExec implements
-        JsCallBack, StructureListener
+public class MouseOverStructureListener extends JSFunctionExec
+        implements JsCallBack, StructureListener
 {
 
   String _listenerfn;
@@ -152,9 +152,9 @@ public class MouseOverStructureListener extends JSFunctionExec implements
         // JBPComment: yep - this is right! the Javascript harness uses the
         // absolute pdbFile URI to locate the PDB file in the external viewer
         executeJavascriptFunction(_listenerfn,
-                new String[] { "mouseover", "" + atom.getPdbFile(),
-                    "" + atom.getChain(), "" + (atom.getPdbResNum()),
-                    "" + atom.getAtomIndex() });
+                new String[]
+                { "mouseover", "" + atom.getPdbFile(), "" + atom.getChain(),
+                    "" + (atom.getPdbResNum()), "" + atom.getAtomIndex() });
       } catch (Exception ex)
       {
         System.err.println("Couldn't execute callback with " + _listenerfn
@@ -173,8 +173,8 @@ public class MouseOverStructureListener extends JSFunctionExec implements
 
     if (JalviewLite.debug)
     {
-      System.err.println(this.getClass().getName() + " modelSet[0]: "
-              + modelSet[0]);
+      System.err.println(
+              this.getClass().getName() + " modelSet[0]: " + modelSet[0]);
       ssm.reportMapping();
     }
 
@@ -206,12 +206,14 @@ public class MouseOverStructureListener extends JSFunctionExec implements
       SequenceRenderer sr = ((jalview.appletgui.AlignmentPanel) source)
               .getSequenceRenderer();
       FeatureRenderer fr = ((jalview.appletgui.AlignmentPanel) source).av
-              .isShowSequenceFeatures() ? new jalview.appletgui.FeatureRenderer(
-              ((jalview.appletgui.AlignmentPanel) source).av) : null;
+              .isShowSequenceFeatures()
+                      ? new jalview.appletgui.FeatureRenderer(
+                              ((jalview.appletgui.AlignmentPanel) source).av)
+                      : null;
       if (fr != null)
       {
-        ((jalview.appletgui.FeatureRenderer) fr)
-                .transferSettings(((jalview.appletgui.AlignmentPanel) source)
+        ((jalview.appletgui.FeatureRenderer) fr).transferSettings(
+                ((jalview.appletgui.AlignmentPanel) source)
                         .getFeatureRenderer());
       }
       ;
@@ -243,27 +245,25 @@ public class MouseOverStructureListener extends JSFunctionExec implements
         System.arraycopy(ccset, 0, ccomandset, sz, ccset.length);
         sz += ccset.length;
       }
-      if (jvlite.isJsMessageSetChanged(
-              mclass = "colourstruct",
+      if (jvlite.isJsMessageSetChanged(mclass = "colourstruct",
               mhandle = ((jalview.appletgui.AlignmentPanel) source).av
-                      .getViewId(), ccomandset))
+                      .getViewId(),
+              ccomandset))
       {
         jvlite.setJsMessageSet(mclass, mhandle, ccomandset);
         // and notify javascript handler
-        String st[] = new String[] {
-            "colourstruct",
+        String st[] = new String[] { "colourstruct",
             "" + ((jalview.appletgui.AlignmentPanel) source).av.getViewId(),
-            "" + ccomandset.length,
-            jvlite.arrayToSeparatorList(pdbfn.toArray(new String[pdbfn
-                    .size()])) };
+            "" + ccomandset.length, jvlite.arrayToSeparatorList(
+                    pdbfn.toArray(new String[pdbfn.size()])) };
         try
         {
           executeJavascriptFunction(true, _listenerfn, st);
         } catch (Exception ex)
         {
-          System.err.println("Couldn't execute callback with "
-                  + _listenerfn + " using args { " + st[0] + ", " + st[1]
-                  + ", " + st[2] + "," + st[3] + "}"); // + ","+st[4]+"\n");
+          System.err.println("Couldn't execute callback with " + _listenerfn
+                  + " using args { " + st[0] + ", " + st[1] + ", " + st[2]
+                  + "," + st[3] + "}"); // + ","+st[4]+"\n");
           ex.printStackTrace();
 
         }
@@ -299,13 +299,6 @@ public class MouseOverStructureListener extends JSFunctionExec implements
   }
 
   @Override
-  public void finalize() throws Throwable
-  {
-    jvlite = null;
-    super.finalize();
-  }
-
-  @Override
   public void releaseReferences(Object svl)
   {
 
index 072754e..fe5a520 100644 (file)
@@ -84,14 +84,14 @@ public abstract class GAlignExportSettings extends JPanel
 
   public void init()
   {
-    chkHiddenSeqs.setText(MessageManager
-            .getString("action.export_hidden_sequences"));
-    chkHiddenCols.setText(MessageManager
-            .getString("action.export_hidden_columns"));
-    chkExportAnnots.setText(MessageManager
-            .getString("action.export_annotations"));
-    chkExportFeats.setText(MessageManager
-            .getString("action.export_features"));
+    chkHiddenSeqs.setText(
+            MessageManager.getString("action.export_hidden_sequences"));
+    chkHiddenCols.setText(
+            MessageManager.getString("action.export_hidden_columns"));
+    chkExportAnnots
+            .setText(MessageManager.getString("action.export_annotations"));
+    chkExportFeats
+            .setText(MessageManager.getString("action.export_features"));
     chkExportGrps.setText(MessageManager.getString("action.export_groups"));
     btnOk.setText(MessageManager.getString("action.ok"));
     btnCancel.setText(MessageManager.getString("action.cancel"));
@@ -165,10 +165,10 @@ public abstract class GAlignExportSettings extends JPanel
     chkHiddenCols.setSelected(chkHiddenCols.isEnabled() && isSelected);
     chkExportAnnots.setSelected(isComplexAlignFile
             && chkExportAnnots.isEnabled() && isSelected);
-    chkExportFeats.setSelected(isComplexAlignFile
-            && chkExportFeats.isEnabled() && isSelected);
-    chkExportGrps.setSelected(isComplexAlignFile
-            && chkExportGrps.isEnabled() && isSelected);
+    chkExportFeats.setSelected(
+            isComplexAlignFile && chkExportFeats.isEnabled() && isSelected);
+    chkExportGrps.setSelected(
+            isComplexAlignFile && chkExportGrps.isEnabled() && isSelected);
   }
 
   public boolean isShowDialog()
index 88cc0a8..86d0c85 100755 (executable)
@@ -260,14 +260,15 @@ public class GAlignFrame extends JInternalFrame
     };
 
     // FIXME getDefaultToolkit throws an exception in Headless mode
-    KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_S, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask()
-            | KeyEvent.SHIFT_MASK, false);
+    KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_S,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()
+                    | KeyEvent.SHIFT_MASK,
+            false);
     addMenuActionAndAccelerator(keyStroke, saveAs, al);
 
     closeMenuItem.setText(MessageManager.getString("action.close"));
-    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_W, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_W,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
     al = new ActionListener()
     {
       @Override
@@ -289,8 +290,8 @@ public class GAlignFrame extends JInternalFrame
     webService.setText(MessageManager.getString("action.web_service"));
     JMenuItem selectAllSequenceMenuItem = new JMenuItem(
             MessageManager.getString("action.select_all"));
-    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_A, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_A,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
     al = new ActionListener()
     {
       @Override
@@ -316,8 +317,8 @@ public class GAlignFrame extends JInternalFrame
 
     JMenuItem invertSequenceMenuItem = new JMenuItem(
             MessageManager.getString("action.invert_sequence_selection"));
-    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_I, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_I,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
     al = new ActionListener()
     {
       @Override
@@ -340,8 +341,8 @@ public class GAlignFrame extends JInternalFrame
     });
     JMenuItem expandAlignment = new JMenuItem(
             MessageManager.getString("action.view_flanking_regions"));
-    expandAlignment.setToolTipText(MessageManager
-            .getString("label.view_flanking_regions"));
+    expandAlignment.setToolTipText(
+            MessageManager.getString("label.view_flanking_regions"));
     expandAlignment.addActionListener(new ActionListener()
     {
       @Override
@@ -352,8 +353,8 @@ public class GAlignFrame extends JInternalFrame
     });
     JMenuItem remove2LeftMenuItem = new JMenuItem(
             MessageManager.getString("action.remove_left"));
-    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_L, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_L,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
     al = new ActionListener()
     {
       @Override
@@ -366,8 +367,8 @@ public class GAlignFrame extends JInternalFrame
 
     JMenuItem remove2RightMenuItem = new JMenuItem(
             MessageManager.getString("action.remove_right"));
-    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_R, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_R,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
     al = new ActionListener()
     {
       @Override
@@ -380,8 +381,8 @@ public class GAlignFrame extends JInternalFrame
 
     JMenuItem removeGappedColumnMenuItem = new JMenuItem(
             MessageManager.getString("action.remove_empty_columns"));
-    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_E, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_E,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
     al = new ActionListener()
     {
       @Override
@@ -394,9 +395,10 @@ public class GAlignFrame extends JInternalFrame
 
     JMenuItem removeAllGapsMenuItem = new JMenuItem(
             MessageManager.getString("action.remove_all_gaps"));
-    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_E, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask()
-            | KeyEvent.SHIFT_MASK, false);
+    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_E,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()
+                    | KeyEvent.SHIFT_MASK,
+            false);
     al = new ActionListener()
     {
       @Override
@@ -447,8 +449,8 @@ public class GAlignFrame extends JInternalFrame
         viewTextMenuItem_actionPerformed(e);
       }
     });
-    showNonconservedMenuItem.setText(MessageManager
-            .getString("label.show_non_conserved"));
+    showNonconservedMenuItem
+            .setText(MessageManager.getString("label.show_non_conserved"));
     showNonconservedMenuItem.setState(false);
     showNonconservedMenuItem.addActionListener(new ActionListener()
     {
@@ -501,8 +503,8 @@ public class GAlignFrame extends JInternalFrame
 
     JMenuItem removeRedundancyMenuItem = new JMenuItem(
             MessageManager.getString("action.remove_redundancy"));
-    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_D, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_D,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
     al = new ActionListener()
     {
       @Override
@@ -530,14 +532,14 @@ public class GAlignFrame extends JInternalFrame
     statusBar.setFont(new java.awt.Font("Verdana", 0, 11));
     statusBar.setBorder(BorderFactory.createLineBorder(Color.black));
     statusBar.setText(MessageManager.getString("label.status_bar"));
-    outputTextboxMenu.setText(MessageManager
-            .getString("label.out_to_textbox"));
+    outputTextboxMenu
+            .setText(MessageManager.getString("label.out_to_textbox"));
 
     annotationPanelMenuItem.setActionCommand("");
-    annotationPanelMenuItem.setText(MessageManager
-            .getString("label.show_annotations"));
-    annotationPanelMenuItem.setState(Cache.getDefault("SHOW_ANNOTATIONS",
-            true));
+    annotationPanelMenuItem
+            .setText(MessageManager.getString("label.show_annotations"));
+    annotationPanelMenuItem
+            .setState(Cache.getDefault("SHOW_ANNOTATIONS", true));
     annotationPanelMenuItem.addActionListener(new ActionListener()
     {
       @Override
@@ -546,8 +548,8 @@ public class GAlignFrame extends JInternalFrame
         annotationPanelMenuItem_actionPerformed(e);
       }
     });
-    showAllAlAnnotations.setText(MessageManager
-            .getString("label.show_all_al_annotations"));
+    showAllAlAnnotations.setText(
+            MessageManager.getString("label.show_all_al_annotations"));
     final boolean isAnnotationPanelShown = annotationPanelMenuItem
             .getState();
     showAllAlAnnotations.setEnabled(isAnnotationPanelShown);
@@ -559,8 +561,8 @@ public class GAlignFrame extends JInternalFrame
         showAllAnnotations_actionPerformed(false, true);
       }
     });
-    hideAllAlAnnotations.setText(MessageManager
-            .getString("label.hide_all_al_annotations"));
+    hideAllAlAnnotations.setText(
+            MessageManager.getString("label.hide_all_al_annotations"));
     hideAllAlAnnotations.setEnabled(isAnnotationPanelShown);
     hideAllAlAnnotations.addActionListener(new ActionListener()
     {
@@ -570,8 +572,8 @@ public class GAlignFrame extends JInternalFrame
         hideAllAnnotations_actionPerformed(false, true);
       }
     });
-    showAllSeqAnnotations.setText(MessageManager
-            .getString("label.show_all_seq_annotations"));
+    showAllSeqAnnotations.setText(
+            MessageManager.getString("label.show_all_seq_annotations"));
     showAllSeqAnnotations.setEnabled(isAnnotationPanelShown);
     showAllSeqAnnotations.addActionListener(new ActionListener()
     {
@@ -581,8 +583,8 @@ public class GAlignFrame extends JInternalFrame
         showAllAnnotations_actionPerformed(true, false);
       }
     });
-    hideAllSeqAnnotations.setText(MessageManager
-            .getString("label.hide_all_seq_annotations"));
+    hideAllSeqAnnotations.setText(
+            MessageManager.getString("label.hide_all_seq_annotations"));
     hideAllSeqAnnotations.setEnabled(isAnnotationPanelShown);
     hideAllSeqAnnotations.addActionListener(new ActionListener()
     {
@@ -600,8 +602,8 @@ public class GAlignFrame extends JInternalFrame
     final JCheckBoxMenuItem sortAnnByLabel = new JCheckBoxMenuItem(
             MessageManager.getString("label.sort_annotations_by_label"));
 
-    sortAnnBySequence
-            .setSelected(sortAnnotationsBy == SequenceAnnotationOrder.SEQUENCE_AND_LABEL);
+    sortAnnBySequence.setSelected(
+            sortAnnotationsBy == SequenceAnnotationOrder.SEQUENCE_AND_LABEL);
     sortAnnBySequence.addActionListener(new ActionListener()
     {
       @Override
@@ -609,13 +611,14 @@ public class GAlignFrame extends JInternalFrame
       {
         boolean newState = sortAnnBySequence.getState();
         sortAnnByLabel.setSelected(false);
-        setAnnotationSortOrder(newState ? SequenceAnnotationOrder.SEQUENCE_AND_LABEL
-                : SequenceAnnotationOrder.NONE);
+        setAnnotationSortOrder(
+                newState ? SequenceAnnotationOrder.SEQUENCE_AND_LABEL
+                        : SequenceAnnotationOrder.NONE);
         sortAnnotations_actionPerformed();
       }
     });
-    sortAnnByLabel
-            .setSelected(sortAnnotationsBy == SequenceAnnotationOrder.LABEL_AND_SEQUENCE);
+    sortAnnByLabel.setSelected(
+            sortAnnotationsBy == SequenceAnnotationOrder.LABEL_AND_SEQUENCE);
     sortAnnByLabel.addActionListener(new ActionListener()
     {
       @Override
@@ -623,14 +626,14 @@ public class GAlignFrame extends JInternalFrame
       {
         boolean newState = sortAnnByLabel.getState();
         sortAnnBySequence.setSelected(false);
-        setAnnotationSortOrder(newState ? SequenceAnnotationOrder.LABEL_AND_SEQUENCE
-                : SequenceAnnotationOrder.NONE);
+        setAnnotationSortOrder(
+                newState ? SequenceAnnotationOrder.LABEL_AND_SEQUENCE
+                        : SequenceAnnotationOrder.NONE);
         sortAnnotations_actionPerformed();
       }
     });
     colourTextMenuItem = new JCheckBoxMenuItem(
-            MessageManager
-            .getString("label.colour_text"));
+            MessageManager.getString("label.colour_text"));
     colourTextMenuItem.addActionListener(new ActionListener()
     {
       @Override
@@ -675,8 +678,8 @@ public class GAlignFrame extends JInternalFrame
 
     undoMenuItem.setEnabled(false);
     undoMenuItem.setText(MessageManager.getString("action.undo"));
-    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_Z, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_Z,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
     al = new ActionListener()
     {
       @Override
@@ -689,8 +692,8 @@ public class GAlignFrame extends JInternalFrame
 
     redoMenuItem.setEnabled(false);
     redoMenuItem.setText(MessageManager.getString("action.redo"));
-    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_Y, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_Y,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
     al = new ActionListener()
     {
       @Override
@@ -713,8 +716,8 @@ public class GAlignFrame extends JInternalFrame
 
     JMenuItem printMenuItem = new JMenuItem(
             MessageManager.getString("action.print"));
-    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_P, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_P,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
     al = new ActionListener()
     {
       @Override
@@ -739,8 +742,8 @@ public class GAlignFrame extends JInternalFrame
 
     JMenuItem findMenuItem = new JMenuItem(
             MessageManager.getString("action.find"));
-    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_F, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_F,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
     findMenuItem.setToolTipText(JvSwingUtils.wrapTooltip(true,
             MessageManager.getString("label.find_tip")));
     al = new ActionListener()
@@ -753,8 +756,8 @@ public class GAlignFrame extends JInternalFrame
     };
     addMenuActionAndAccelerator(keyStroke, findMenuItem, al);
 
-    showSeqFeatures.setText(MessageManager
-            .getString("label.show_sequence_features"));
+    showSeqFeatures.setText(
+            MessageManager.getString("label.show_sequence_features"));
     showSeqFeatures.addActionListener(new ActionListener()
     {
       @Override
@@ -769,8 +772,8 @@ public class GAlignFrame extends JInternalFrame
      * void actionPerformed(ActionEvent actionEvent) {
      * showSeqFeaturesHeight_actionPerformed(actionEvent); } });
      */
-    showDbRefsMenuitem.setText(MessageManager
-            .getString("label.show_database_refs"));
+    showDbRefsMenuitem
+            .setText(MessageManager.getString("label.show_database_refs"));
     showDbRefsMenuitem.addActionListener(new ActionListener()
     {
 
@@ -781,8 +784,8 @@ public class GAlignFrame extends JInternalFrame
       }
 
     });
-    showNpFeatsMenuitem.setText(MessageManager
-            .getString("label.show_non_positional_features"));
+    showNpFeatsMenuitem.setText(
+            MessageManager.getString("label.show_non_positional_features"));
     showNpFeatsMenuitem.addActionListener(new ActionListener()
     {
 
@@ -793,8 +796,8 @@ public class GAlignFrame extends JInternalFrame
       }
 
     });
-    showGroupConservation.setText(MessageManager
-            .getString("label.group_conservation"));
+    showGroupConservation
+            .setText(MessageManager.getString("label.group_conservation"));
     showGroupConservation.addActionListener(new ActionListener()
     {
 
@@ -806,8 +809,8 @@ public class GAlignFrame extends JInternalFrame
 
     });
 
-    showGroupConsensus.setText(MessageManager
-            .getString("label.group_consensus"));
+    showGroupConsensus
+            .setText(MessageManager.getString("label.group_consensus"));
     showGroupConsensus.addActionListener(new ActionListener()
     {
 
@@ -818,8 +821,8 @@ public class GAlignFrame extends JInternalFrame
       }
 
     });
-    showConsensusHistogram.setText(MessageManager
-            .getString("label.show_consensus_histogram"));
+    showConsensusHistogram.setText(
+            MessageManager.getString("label.show_consensus_histogram"));
     showConsensusHistogram.addActionListener(new ActionListener()
     {
 
@@ -830,8 +833,8 @@ public class GAlignFrame extends JInternalFrame
       }
 
     });
-    showSequenceLogo.setText(MessageManager
-            .getString("label.show_consensus_logo"));
+    showSequenceLogo
+            .setText(MessageManager.getString("label.show_consensus_logo"));
     showSequenceLogo.addActionListener(new ActionListener()
     {
 
@@ -842,8 +845,8 @@ public class GAlignFrame extends JInternalFrame
       }
 
     });
-    normaliseSequenceLogo.setText(MessageManager
-            .getString("label.norm_consensus_logo"));
+    normaliseSequenceLogo
+            .setText(MessageManager.getString("label.norm_consensus_logo"));
     normaliseSequenceLogo.addActionListener(new ActionListener()
     {
 
@@ -854,8 +857,8 @@ public class GAlignFrame extends JInternalFrame
       }
 
     });
-    applyAutoAnnotationSettings.setText(MessageManager
-            .getString("label.apply_all_groups"));
+    applyAutoAnnotationSettings
+            .setText(MessageManager.getString("label.apply_all_groups"));
     applyAutoAnnotationSettings.setState(false);
     applyAutoAnnotationSettings.setVisible(true);
     applyAutoAnnotationSettings.addActionListener(new ActionListener()
@@ -874,8 +877,8 @@ public class GAlignFrame extends JInternalFrame
             MessageManager.getString("label.show_last"));
     buttonGroup.add(showAutoFirst);
     buttonGroup.add(showAutoLast);
-    final boolean autoFirst = Cache.getDefault(
-            Preferences.SHOW_AUTOCALC_ABOVE, false);
+    final boolean autoFirst = Cache
+            .getDefault(Preferences.SHOW_AUTOCALC_ABOVE, false);
     showAutoFirst.setSelected(autoFirst);
     setShowAutoCalculatedAbove(autoFirst);
     showAutoFirst.addActionListener(new ActionListener()
@@ -900,8 +903,8 @@ public class GAlignFrame extends JInternalFrame
 
     JMenuItem deleteGroups = new JMenuItem(
             MessageManager.getString("action.undefine_groups"));
-    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_U, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_U,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
     al = new ActionListener()
     {
       @Override
@@ -925,8 +928,8 @@ public class GAlignFrame extends JInternalFrame
 
     JMenuItem createGroup = new JMenuItem(
             MessageManager.getString("action.create_group"));
-    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_G, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_G,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
     al = new ActionListener()
     {
       @Override
@@ -939,9 +942,10 @@ public class GAlignFrame extends JInternalFrame
 
     JMenuItem unGroup = new JMenuItem(
             MessageManager.getString("action.remove_group"));
-    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_G, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask()
-            | KeyEvent.SHIFT_MASK, false);
+    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_G,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()
+                    | KeyEvent.SHIFT_MASK,
+            false);
     al = new ActionListener()
     {
       @Override
@@ -953,8 +957,8 @@ public class GAlignFrame extends JInternalFrame
     addMenuActionAndAccelerator(keyStroke, unGroup, al);
 
     copy.setText(MessageManager.getString("action.copy"));
-    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_C, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_C,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
 
     al = new ActionListener()
     {
@@ -967,8 +971,8 @@ public class GAlignFrame extends JInternalFrame
     addMenuActionAndAccelerator(keyStroke, copy, al);
 
     cut.setText(MessageManager.getString("action.cut"));
-    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_X, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_X,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
     al = new ActionListener()
     {
       @Override
@@ -993,9 +997,10 @@ public class GAlignFrame extends JInternalFrame
     pasteMenu.setText(MessageManager.getString("action.paste"));
     JMenuItem pasteNew = new JMenuItem(
             MessageManager.getString("label.to_new_alignment"));
-    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_V, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask()
-            | KeyEvent.SHIFT_MASK, false);
+    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_V,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()
+                    | KeyEvent.SHIFT_MASK,
+            false);
     al = new ActionListener()
     {
       @Override
@@ -1008,8 +1013,8 @@ public class GAlignFrame extends JInternalFrame
 
     JMenuItem pasteThis = new JMenuItem(
             MessageManager.getString("label.to_this_alignment"));
-    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_V, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_V,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
     al = new ActionListener()
     {
       @Override
@@ -1029,8 +1034,8 @@ public class GAlignFrame extends JInternalFrame
         createPNG(null);
       }
     });
-    createPNG.setActionCommand(MessageManager
-            .getString("label.save_png_image"));
+    createPNG.setActionCommand(
+            MessageManager.getString("label.save_png_image"));
 
     JMenuItem font = new JMenuItem(MessageManager.getString("action.font"));
     font.addActionListener(new ActionListener()
@@ -1041,8 +1046,8 @@ public class GAlignFrame extends JInternalFrame
         font_actionPerformed(e);
       }
     });
-    seqLimits.setText(MessageManager
-            .getString("label.show_sequence_limits"));
+    seqLimits.setText(
+            MessageManager.getString("label.show_sequence_limits"));
     seqLimits.setState(jalview.bin.Cache.getDefault("SHOW_JVSUFFIX", true));
     seqLimits.addActionListener(new ActionListener()
     {
@@ -1074,8 +1079,8 @@ public class GAlignFrame extends JInternalFrame
 
     JMenuItem loadTreeMenuItem = new JMenuItem(
             MessageManager.getString("label.load_associated_tree"));
-    loadTreeMenuItem.setActionCommand(MessageManager
-            .getString("label.load_tree_for_sequence_set"));
+    loadTreeMenuItem.setActionCommand(
+            MessageManager.getString("label.load_tree_for_sequence_set"));
     loadTreeMenuItem.addActionListener(new ActionListener()
     {
       @Override
@@ -1119,8 +1124,8 @@ public class GAlignFrame extends JInternalFrame
     });
     centreColumnLabelsMenuItem.setVisible(true);
     centreColumnLabelsMenuItem.setState(false);
-    centreColumnLabelsMenuItem.setText(MessageManager
-            .getString("label.centre_column_labels"));
+    centreColumnLabelsMenuItem.setText(
+            MessageManager.getString("label.centre_column_labels"));
     centreColumnLabelsMenuItem.addActionListener(new ActionListener()
     {
       @Override
@@ -1131,8 +1136,8 @@ public class GAlignFrame extends JInternalFrame
     });
     followHighlightMenuItem.setVisible(true);
     followHighlightMenuItem.setState(true);
-    followHighlightMenuItem.setText(MessageManager
-            .getString("label.automatic_scrolling"));
+    followHighlightMenuItem
+            .setText(MessageManager.getString("label.automatic_scrolling"));
     followHighlightMenuItem.addActionListener(new ActionListener()
     {
 
@@ -1165,8 +1170,8 @@ public class GAlignFrame extends JInternalFrame
       {
       }
     });
-    sortByAnnotScore.setText(MessageManager
-            .getString("label.sort_by_score"));
+    sortByAnnotScore
+            .setText(MessageManager.getString("label.sort_by_score"));
     sort.add(sortByAnnotScore);
     sort.addMenuListener(new javax.swing.event.MenuListener()
     {
@@ -1189,12 +1194,12 @@ public class GAlignFrame extends JInternalFrame
     });
     sortByAnnotScore.setVisible(false);
 
-    calculateTree.setText(MessageManager
-            .getString("action.calculate_tree_pca"));
+    calculateTree
+            .setText(MessageManager.getString("action.calculate_tree_pca"));
 
     padGapsMenuitem.setText(MessageManager.getString("label.pad_gaps"));
-    padGapsMenuitem.setState(jalview.bin.Cache
-            .getDefault("PAD_GAPS", false));
+    padGapsMenuitem
+            .setState(jalview.bin.Cache.getDefault("PAD_GAPS", false));
     padGapsMenuitem.addActionListener(new ActionListener()
     {
       @Override
@@ -1214,8 +1219,8 @@ public class GAlignFrame extends JInternalFrame
         vamsasStore_actionPerformed(e);
       }
     });
-    showTranslation.setText(MessageManager
-            .getString("label.translate_cDNA"));
+    showTranslation
+            .setText(MessageManager.getString("label.translate_cDNA"));
     showTranslation.addActionListener(new ActionListener()
     {
       @Override
@@ -1233,8 +1238,8 @@ public class GAlignFrame extends JInternalFrame
         showReverse_actionPerformed(false);
       }
     });
-    showReverseComplement.setText(MessageManager
-            .getString("label.reverse_complement"));
+    showReverseComplement
+            .setText(MessageManager.getString("label.reverse_complement"));
     showReverseComplement.addActionListener(new ActionListener()
     {
       @Override
@@ -1261,8 +1266,8 @@ public class GAlignFrame extends JInternalFrame
     showProducts.setText(MessageManager.getString("label.get_cross_refs"));
 
     runGroovy.setText(MessageManager.getString("label.run_groovy"));
-    runGroovy.setToolTipText(MessageManager
-            .getString("label.run_groovy_tip"));
+    runGroovy.setToolTipText(
+            MessageManager.getString("label.run_groovy_tip"));
     runGroovy.addActionListener(new ActionListener()
     {
       @Override
@@ -1303,10 +1308,10 @@ public class GAlignFrame extends JInternalFrame
         associatedData_actionPerformed(e);
       }
     });
-    autoCalculate.setText(MessageManager
-            .getString("label.autocalculate_consensus"));
-    autoCalculate.setState(jalview.bin.Cache.getDefault(
-            "AUTO_CALC_CONSENSUS", true));
+    autoCalculate.setText(
+            MessageManager.getString("label.autocalculate_consensus"));
+    autoCalculate.setState(
+            jalview.bin.Cache.getDefault("AUTO_CALC_CONSENSUS", true));
     autoCalculate.addActionListener(new ActionListener()
     {
       @Override
@@ -1315,12 +1320,10 @@ public class GAlignFrame extends JInternalFrame
         autoCalculate_actionPerformed(e);
       }
     });
-    sortByTree.setText(MessageManager
-            .getString("label.sort_alignment_new_tree"));
-    sortByTree
-            .setToolTipText("<html>"
-                    + MessageManager
-                            .getString("label.enable_automatically_sort_alignment_when_open_new_tree"));
+    sortByTree.setText(
+            MessageManager.getString("label.sort_alignment_new_tree"));
+    sortByTree.setToolTipText("<html>" + MessageManager.getString(
+            "label.enable_automatically_sort_alignment_when_open_new_tree"));
     sortByTree
             .setState(jalview.bin.Cache.getDefault("SORT_BY_TREE", false));
     sortByTree.addActionListener(new ActionListener()
@@ -1332,12 +1335,11 @@ public class GAlignFrame extends JInternalFrame
       }
     });
 
-    listenToViewSelections.setText(MessageManager
-            .getString("label.listen_for_selections"));
+    listenToViewSelections.setText(
+            MessageManager.getString("label.listen_for_selections"));
     listenToViewSelections
-            .setToolTipText("<html>"
-                    + MessageManager
-                            .getString("label.selections_mirror_selections_made_same_sequences_other_views"));
+            .setToolTipText("<html>" + MessageManager.getString(
+                    "label.selections_mirror_selections_made_same_sequences_other_views"));
     listenToViewSelections.setState(false);
     listenToViewSelections.addActionListener(new ActionListener()
     {
@@ -1403,8 +1405,8 @@ public class GAlignFrame extends JInternalFrame
     statusPanel.setLayout(new GridLayout());
     JMenuItem showAllSeqs = new JMenuItem(
             MessageManager.getString("label.all_sequences"));
-    showAllSeqs.setToolTipText(MessageManager
-            .getString("label.toggle_sequence_visibility"));
+    showAllSeqs.setToolTipText(
+            MessageManager.getString("label.toggle_sequence_visibility"));
     showAllSeqs.addActionListener(new ActionListener()
     {
       @Override
@@ -1415,8 +1417,8 @@ public class GAlignFrame extends JInternalFrame
     });
     JMenuItem showAllColumns = new JMenuItem(
             MessageManager.getString("label.all_columns"));
-    showAllColumns.setToolTipText(MessageManager
-            .getString("label.toggle_columns_visibility"));
+    showAllColumns.setToolTipText(
+            MessageManager.getString("label.toggle_columns_visibility"));
     showAllColumns.addActionListener(new ActionListener()
     {
       @Override
@@ -1428,8 +1430,8 @@ public class GAlignFrame extends JInternalFrame
     JMenu hideMenu = new JMenu(MessageManager.getString("action.hide"));
     JMenuItem hideSelSequences = new JMenuItem(
             MessageManager.getString("label.selected_sequences"));
-    hideSelSequences.setToolTipText(MessageManager
-            .getString("label.toggle_sequence_visibility"));
+    hideSelSequences.setToolTipText(
+            MessageManager.getString("label.toggle_sequence_visibility"));
     hideSelSequences.addActionListener(new ActionListener()
     {
       @Override
@@ -1440,8 +1442,8 @@ public class GAlignFrame extends JInternalFrame
     });
     JMenuItem hideSelColumns = new JMenuItem(
             MessageManager.getString("label.selected_columns"));
-    hideSelColumns.setToolTipText(MessageManager
-            .getString("label.toggle_columns_visibility"));
+    hideSelColumns.setToolTipText(
+            MessageManager.getString("label.toggle_columns_visibility"));
     hideSelColumns.addActionListener(new ActionListener()
     {
       @Override
@@ -1483,8 +1485,8 @@ public class GAlignFrame extends JInternalFrame
         showAllhidden_actionPerformed(e);
       }
     });
-    hiddenMarkers.setText(MessageManager
-            .getString("action.show_hidden_markers"));
+    hiddenMarkers.setText(
+            MessageManager.getString("action.show_hidden_markers"));
     hiddenMarkers.addActionListener(new ActionListener()
     {
       @Override
@@ -1496,9 +1498,10 @@ public class GAlignFrame extends JInternalFrame
 
     JMenuItem invertColSel = new JMenuItem(
             MessageManager.getString("action.invert_column_selection"));
-    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_I, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask()
-            | KeyEvent.ALT_MASK, false);
+    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_I,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()
+                    | KeyEvent.ALT_MASK,
+            false);
     al = new ActionListener()
     {
       @Override
@@ -1559,8 +1562,8 @@ public class GAlignFrame extends JInternalFrame
     });
 
     JMenuItem save = new JMenuItem(MessageManager.getString("action.save"));
-    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_S, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_S,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
     al = new ActionListener()
     {
       @Override
@@ -1584,8 +1587,8 @@ public class GAlignFrame extends JInternalFrame
 
     JMenuItem newView = new JMenuItem(
             MessageManager.getString("action.new_view"));
-    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_T, Toolkit
-            .getDefaultToolkit().getMenuShortcutKeyMask(), false);
+    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_T,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
     al = new ActionListener()
     {
       @Override
@@ -1603,8 +1606,8 @@ public class GAlignFrame extends JInternalFrame
     formatMenu.setText(MessageManager.getString("action.format"));
     JMenu selectMenu = new JMenu(MessageManager.getString("action.select"));
 
-    idRightAlign.setText(MessageManager
-            .getString("label.right_align_sequence_id"));
+    idRightAlign.setText(
+            MessageManager.getString("label.right_align_sequence_id"));
     idRightAlign.addActionListener(new ActionListener()
     {
       @Override
@@ -1662,8 +1665,8 @@ public class GAlignFrame extends JInternalFrame
     });
     JMenuItem selectHighlighted = new JMenuItem(
             MessageManager.getString("action.select_highlighted_columns"));
-    selectHighlighted.setToolTipText(MessageManager
-            .getString("tooltip.select_highlighted_columns"));
+    selectHighlighted.setToolTipText(
+            MessageManager.getString("tooltip.select_highlighted_columns"));
     al = new ActionListener()
     {
       @Override
@@ -1782,7 +1785,6 @@ public class GAlignFrame extends JInternalFrame
     autoAnnMenu.add(showGroupConsensus);
     annotationsMenu.add(autoAnnMenu);
 
-
     sort.add(sortIDMenuItem);
     sort.add(sortLengthMenuItem);
     sort.add(sortGroupMenuItem);
@@ -1888,8 +1890,8 @@ public class GAlignFrame extends JInternalFrame
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        conservationMenuItem_actionPerformed(conservationMenuItem
-                .isSelected());
+        conservationMenuItem_actionPerformed(
+                conservationMenuItem.isSelected());
       }
     });
 
@@ -1913,8 +1915,7 @@ public class GAlignFrame extends JInternalFrame
         modifyPID_actionPerformed();
       }
     });
-    modifyConservation = new JMenuItem(
-            MessageManager
+    modifyConservation = new JMenuItem(MessageManager
             .getString("label.modify_conservation_threshold"));
     modifyConservation.addActionListener(new ActionListener()
     {
index 157dddd..abc0b3d 100644 (file)
@@ -132,12 +132,12 @@ public class GCutAndPasteHtmlTransfer extends JInternalFrame
       }
     });
     close.setAccelerator(javax.swing.KeyStroke.getKeyStroke(
-            java.awt.event.KeyEvent.VK_W, Toolkit.getDefaultToolkit()
-                    .getMenuShortcutKeyMask(), false));
+            java.awt.event.KeyEvent.VK_W,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false));
     selectAll.setText(MessageManager.getString("action.select_all"));
     selectAll.setAccelerator(javax.swing.KeyStroke.getKeyStroke(
-            java.awt.event.KeyEvent.VK_A, Toolkit.getDefaultToolkit()
-                    .getMenuShortcutKeyMask(), false));
+            java.awt.event.KeyEvent.VK_A,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false));
     selectAll.addActionListener(new ActionListener()
     {
       @Override
@@ -149,8 +149,8 @@ public class GCutAndPasteHtmlTransfer extends JInternalFrame
     jMenu1.setText(MessageManager.getString("action.file"));
     save.setText(MessageManager.getString("action.save"));
     save.setAccelerator(javax.swing.KeyStroke.getKeyStroke(
-            java.awt.event.KeyEvent.VK_S, Toolkit.getDefaultToolkit()
-                    .getMenuShortcutKeyMask(), false));
+            java.awt.event.KeyEvent.VK_S,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false));
     save.addActionListener(new ActionListener()
     {
       @Override
@@ -160,8 +160,8 @@ public class GCutAndPasteHtmlTransfer extends JInternalFrame
       }
     });
     copyItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(
-            java.awt.event.KeyEvent.VK_C, Toolkit.getDefaultToolkit()
-                    .getMenuShortcutKeyMask(), false));
+            java.awt.event.KeyEvent.VK_C,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false));
 
     editMenubar.add(jMenu1);
     editMenubar.add(editMenu);
@@ -190,10 +190,10 @@ public class GCutAndPasteHtmlTransfer extends JInternalFrame
         copyItem_actionPerformed(e);
       }
     });
-    displaySource.setText(MessageManager
-            .getString("action.show_html_source"));
-    displaySource.setToolTipText(MessageManager
-            .getString("label.select_copy_raw_html"));
+    displaySource
+            .setText(MessageManager.getString("action.show_html_source"));
+    displaySource.setToolTipText(
+            MessageManager.getString("label.select_copy_raw_html"));
     displaySource.addActionListener(new ActionListener()
     {
 
index 21705f0..97ac840 100755 (executable)
@@ -122,8 +122,8 @@ public class GCutAndPasteTransfer extends JInternalFrame
 
     selectAll.setText(MessageManager.getString("action.select_all"));
     selectAll.setAccelerator(javax.swing.KeyStroke.getKeyStroke(
-            java.awt.event.KeyEvent.VK_A, Toolkit.getDefaultToolkit()
-                    .getMenuShortcutKeyMask(), false));
+            java.awt.event.KeyEvent.VK_A,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false));
     selectAll.addActionListener(new ActionListener()
     {
       @Override
@@ -135,8 +135,8 @@ public class GCutAndPasteTransfer extends JInternalFrame
     jMenu1.setText(MessageManager.getString("action.file"));
     save.setText(MessageManager.getString("action.save"));
     save.setAccelerator(javax.swing.KeyStroke.getKeyStroke(
-            java.awt.event.KeyEvent.VK_S, Toolkit.getDefaultToolkit()
-                    .getMenuShortcutKeyMask(), false));
+            java.awt.event.KeyEvent.VK_S,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false));
     save.addActionListener(new ActionListener()
     {
       @Override
@@ -146,11 +146,11 @@ public class GCutAndPasteTransfer extends JInternalFrame
       }
     });
     copyItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(
-            java.awt.event.KeyEvent.VK_C, Toolkit.getDefaultToolkit()
-                    .getMenuShortcutKeyMask(), false));
+            java.awt.event.KeyEvent.VK_C,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false));
     pasteMenu.setAccelerator(javax.swing.KeyStroke.getKeyStroke(
-            java.awt.event.KeyEvent.VK_V, Toolkit.getDefaultToolkit()
-                    .getMenuShortcutKeyMask(), false));
+            java.awt.event.KeyEvent.VK_V,
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false));
     editMenubar.add(jMenu1);
     editMenubar.add(editMenu);
     textarea.setFont(new java.awt.Font("Monospaced", Font.PLAIN, 12));
index a2612e8..a91769a 100755 (executable)
@@ -63,8 +63,8 @@ public class GDasSourceBrowser extends JPanel
   private void jbInit() throws Exception
   {
     this.setLayout(gridBagLayout1);
-    refresh.setText(MessageManager
-            .getString("label.refresh_available_sources"));
+    refresh.setText(
+            MessageManager.getString("label.refresh_available_sources"));
     refresh.addActionListener(new ActionListener()
     {
       public void actionPerformed(ActionEvent e)
@@ -137,27 +137,32 @@ public class GDasSourceBrowser extends JPanel
     this.add(jPanel1, new GridBagConstraints(0, 3, 3, 1, 1.0, 1.0,
             GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
             new Insets(0, 0, 0, 0), 0, 0));
-    this.add(fullDetailsScrollpane, new GridBagConstraints(1, 0, 2, 1, 1.0,
-            1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
-            new Insets(3, 0, 0, 3), 240, 130));
-    this.add(scrollPane, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0,
-            GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(
-                    3, 2, 0, 0), 150, 130));
+    this.add(fullDetailsScrollpane,
+            new GridBagConstraints(1, 0, 2, 1, 1.0, 1.0,
+                    GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+                    new Insets(3, 0, 0, 3), 240, 130));
+    this.add(scrollPane,
+            new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0,
+                    GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+                    new Insets(3, 2, 0, 0), 150, 130));
     jPanel2.add(registryLabel, java.awt.BorderLayout.WEST);
     jPanel2.add(registryURL, java.awt.BorderLayout.CENTER);
     jPanel2.add(reset, java.awt.BorderLayout.EAST);
     this.add(jPanel2, new GridBagConstraints(0, 2, 3, 1, 0.0, 0.0,
             GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
             new Insets(5, 10, 0, 10), 339, 0));
-    this.add(jScrollPane2, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0,
-            GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(
-                    0, 0, 0, 60), 80, 60));
-    this.add(jScrollPane4, new GridBagConstraints(2, 1, 1, 1, 1.0, 1.0,
-            GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(
-                    0, -80, 0, 0), 80, 60));
-    this.add(jScrollPane3, new GridBagConstraints(1, 1, 1, 1, 1.0, 1.0,
-            GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(
-                    0, -60, 0, 80), 80, 60));
+    this.add(jScrollPane2,
+            new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0,
+                    GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+                    new Insets(0, 0, 0, 60), 80, 60));
+    this.add(jScrollPane4,
+            new GridBagConstraints(2, 1, 1, 1, 1.0, 1.0,
+                    GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+                    new Insets(0, -80, 0, 0), 80, 60));
+    this.add(jScrollPane3,
+            new GridBagConstraints(1, 1, 1, 1, 1.0, 1.0,
+                    GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+                    new Insets(0, -60, 0, 80), 80, 60));
   }
 
   protected JTable table = new JTable();
index 3e3691c..a4afb74 100755 (executable)
@@ -153,13 +153,14 @@ public class GDesktop extends JFrame
     VamsasMenu.setToolTipText(MessageManager
             .getString("label.share_data_vamsas_applications"));
     VamsasStMenu.setText(MessageManager.getString("label.connect_to"));
-    VamsasStMenu.setToolTipText(MessageManager
-            .getString("label.join_existing_vamsas_session"));
-    inputLocalFileMenuItem.setText(MessageManager
-            .getString("label.load_tree_from_file"));
-    inputLocalFileMenuItem.setAccelerator(javax.swing.KeyStroke
-            .getKeyStroke(java.awt.event.KeyEvent.VK_O, Toolkit
-                    .getDefaultToolkit().getMenuShortcutKeyMask(), false));
+    VamsasStMenu.setToolTipText(
+            MessageManager.getString("label.join_existing_vamsas_session"));
+    inputLocalFileMenuItem
+            .setText(MessageManager.getString("label.load_tree_from_file"));
+    inputLocalFileMenuItem.setAccelerator(
+            javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O,
+                    Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(),
+                    false));
     inputLocalFileMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
@@ -184,8 +185,8 @@ public class GDesktop extends JFrame
         }
       }
     });
-    inputTextboxMenuItem.setText(MessageManager
-            .getString("label.from_textbox"));
+    inputTextboxMenuItem
+            .setText(MessageManager.getString("label.from_textbox"));
     inputTextboxMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
@@ -213,8 +214,8 @@ public class GDesktop extends JFrame
         aboutMenuItem_actionPerformed(e);
       }
     });
-    documentationMenuItem.setText(MessageManager
-            .getString("label.documentation"));
+    documentationMenuItem
+            .setText(MessageManager.getString("label.documentation"));
     documentationMenuItem.setAccelerator(javax.swing.KeyStroke
             .getKeyStroke(java.awt.event.KeyEvent.VK_F1, 0, false));
     documentationMenuItem
@@ -257,8 +258,8 @@ public class GDesktop extends JFrame
       }
     });
     inputMenu.setText(MessageManager.getString("label.input_alignment"));
-    vamsasStart.setText(MessageManager
-            .getString("label.new_vamsas_session"));
+    vamsasStart
+            .setText(MessageManager.getString("label.new_vamsas_session"));
     vamsasStart.setVisible(false);
     vamsasStart.addActionListener(new ActionListener()
     {
@@ -268,8 +269,8 @@ public class GDesktop extends JFrame
         vamsasStart_actionPerformed(e);
       }
     });
-    vamsasImport.setText(MessageManager
-            .getString("action.load_vamsas_session"));
+    vamsasImport.setText(
+            MessageManager.getString("action.load_vamsas_session"));
     vamsasImport.setVisible(false);
     vamsasImport.addActionListener(new ActionListener()
     {
@@ -279,8 +280,8 @@ public class GDesktop extends JFrame
         vamsasImport_actionPerformed(e);
       }
     });
-    vamsasSave.setText(MessageManager
-            .getString("action.save_vamsas_session"));
+    vamsasSave.setText(
+            MessageManager.getString("action.save_vamsas_session"));
     vamsasSave.setVisible(false);
     vamsasSave.addActionListener(new ActionListener()
     {
@@ -290,8 +291,8 @@ public class GDesktop extends JFrame
         vamsasSave_actionPerformed(e);
       }
     });
-    inputSequence.setText(MessageManager
-            .getString("action.fetch_sequences"));
+    inputSequence
+            .setText(MessageManager.getString("action.fetch_sequences"));
     inputSequence.addActionListener(new ActionListener()
     {
       @Override
@@ -300,8 +301,8 @@ public class GDesktop extends JFrame
         inputSequence_actionPerformed(e);
       }
     });
-    vamsasStop.setText(MessageManager
-            .getString("label.stop_vamsas_session"));
+    vamsasStop
+            .setText(MessageManager.getString("label.stop_vamsas_session"));
     vamsasStop.setVisible(false);
     vamsasStop.addActionListener(new ActionListener()
     {
@@ -320,8 +321,8 @@ public class GDesktop extends JFrame
         closeAll_actionPerformed(e);
       }
     });
-    raiseRelated.setText(MessageManager
-            .getString("action.raise_associated_windows"));
+    raiseRelated.setText(
+            MessageManager.getString("action.raise_associated_windows"));
     raiseRelated.addActionListener(new ActionListener()
     {
       @Override
@@ -330,8 +331,8 @@ public class GDesktop extends JFrame
         raiseRelated_actionPerformed(e);
       }
     });
-    minimizeAssociated.setText(MessageManager
-            .getString("action.minimize_associated_windows"));
+    minimizeAssociated.setText(
+            MessageManager.getString("action.minimize_associated_windows"));
     minimizeAssociated.addActionListener(new ActionListener()
     {
       @Override
@@ -340,8 +341,8 @@ public class GDesktop extends JFrame
         minimizeAssociated_actionPerformed(e);
       }
     });
-    garbageCollect.setText(MessageManager
-            .getString("label.collect_garbage"));
+    garbageCollect
+            .setText(MessageManager.getString("label.collect_garbage"));
     garbageCollect.addActionListener(new ActionListener()
     {
       @Override
@@ -350,8 +351,8 @@ public class GDesktop extends JFrame
         garbageCollect_actionPerformed(e);
       }
     });
-    showMemusage.setText(MessageManager
-            .getString("label.show_memory_usage"));
+    showMemusage
+            .setText(MessageManager.getString("label.show_memory_usage"));
     showMemusage.addActionListener(new ActionListener()
     {
       @Override
@@ -390,10 +391,10 @@ public class GDesktop extends JFrame
       }
     });
     experimentalFeatures = new JCheckBoxMenuItem();
-    experimentalFeatures.setText(MessageManager
-            .getString("label.show_experimental"));
-    experimentalFeatures.setToolTipText(MessageManager
-            .getString("label.show_experimental_tip"));
+    experimentalFeatures
+            .setText(MessageManager.getString("label.show_experimental"));
+    experimentalFeatures.setToolTipText(
+            MessageManager.getString("label.show_experimental_tip"));
     experimentalFeatures.addActionListener(new ActionListener()
     {
       @Override
@@ -527,7 +528,8 @@ public class GDesktop extends JFrame
    * @param e
    *          DOCUMENT ME!
    */
-  protected void inputTextboxMenuItem_actionPerformed(AlignmentViewPanel avp)
+  protected void inputTextboxMenuItem_actionPerformed(
+          AlignmentViewPanel avp)
   {
   }
 
index c335b33..1ea4ab5 100755 (executable)
@@ -59,7 +59,8 @@ public class GFinder extends JPanel
 
   protected JButton createFeatures = new JButton();
 
-  protected JvCacheableInputBox<String> searchBox = new JvCacheableInputBox<String>(getCacheKey());
+  protected JvCacheableInputBox<String> searchBox = new JvCacheableInputBox<String>(
+          getCacheKey());
 
   BorderLayout mainBorderLayout = new BorderLayout();
 
@@ -136,13 +137,13 @@ public class GFinder extends JPanel
     searchBox.setFont(new java.awt.Font("Verdana", Font.PLAIN, 12));
     ((JTextComponent) searchBox.getEditor().getEditorComponent())
             .addCaretListener(new CaretListener()
-    {
-      @Override
-      public void caretUpdate(CaretEvent e)
-      {
-        textfield_caretUpdate(e);
-      }
-    });
+            {
+              @Override
+              public void caretUpdate(CaretEvent e)
+              {
+                textfield_caretUpdate(e);
+              }
+            });
     searchBox.getEditor().getEditorComponent()
             .addKeyListener(new java.awt.event.KeyAdapter()
             {
@@ -160,8 +161,8 @@ public class GFinder extends JPanel
     caseSensitive.setHorizontalAlignment(SwingConstants.LEFT);
     caseSensitive.setText(MessageManager.getString("label.match_case"));
 
-    searchDescription.setText(MessageManager
-            .getString("label.include_description"));
+    searchDescription
+            .setText(MessageManager.getString("label.include_description"));
 
     actionsPanel.add(findNext, null);
     actionsPanel.add(findAll, null);
@@ -205,7 +206,6 @@ public class GFinder extends JPanel
   {
   }
 
-
   public void createFeatures_actionPerformed()
   {
   }
@@ -231,8 +231,8 @@ public class GFinder extends JPanel
           if (al != null && al.getHeight() > 0)
           {
             str = jalview.analysis.AlignSeq.extractGaps(
-                    jalview.util.Comparison.GapChars, al.getSequenceAt(0)
-                            .getSequenceAsString());
+                    jalview.util.Comparison.GapChars,
+                    al.getSequenceAt(0).getSequenceAsString());
 
           }
         }
@@ -240,10 +240,6 @@ public class GFinder extends JPanel
     }
   }
 
-
-
-
-
   /**
    * Returns unique key used for storing Finder cache items in the cache data
    * structure
@@ -255,6 +251,4 @@ public class GFinder extends JPanel
     return FINDER_CACHE_KEY;
   }
 
-
-
 }
index 3715acc..a183794 100755 (executable)
@@ -185,8 +185,8 @@ public class GPCAPanel extends JInternalFrame
       }
     });
     JMenuItem outputProjPoints = new JMenuItem();
-    outputProjPoints.setText(MessageManager
-            .getString("label.output_transformed_points"));
+    outputProjPoints.setText(
+            MessageManager.getString("label.output_transformed_points"));
     outputProjPoints.addActionListener(new ActionListener()
     {
       @Override
@@ -224,8 +224,8 @@ public class GPCAPanel extends JInternalFrame
       {
       }
     });
-    scoreModelMenu.setText(MessageManager
-            .getString("label.select_score_model"));
+    scoreModelMenu
+            .setText(MessageManager.getString("label.select_score_model"));
     scoreModelMenu.addMenuListener(new MenuListener()
     {
       @Override
@@ -273,8 +273,8 @@ public class GPCAPanel extends JInternalFrame
         originalSeqData_actionPerformed(e);
       }
     });
-    associateViewsMenu.setText(MessageManager
-            .getString("label.associate_nodes_with"));
+    associateViewsMenu.setText(
+            MessageManager.getString("label.associate_nodes_with"));
     calcSettings.setText(MessageManager.getString("action.change_params"));
     nuclSetting
             .setText(MessageManager.getString("label.nucleotide_matrix"));
index b064551..7649cf4 100755 (executable)
@@ -75,16 +75,15 @@ public class GPairwiseAlignPanel extends JPanel
     textarea.setText("");
     textarea.setWrapStyleWord(false);
     viewInEditorButton.setFont(new java.awt.Font("Verdana", 0, 12));
-    viewInEditorButton.setText(MessageManager
-            .getString("label.view_alignment_editor"));
-    viewInEditorButton
-            .addActionListener(new java.awt.event.ActionListener()
-            {
-              public void actionPerformed(ActionEvent e)
-              {
-                viewInEditorButton_actionPerformed(e);
-              }
-            });
+    viewInEditorButton.setText(
+            MessageManager.getString("label.view_alignment_editor"));
+    viewInEditorButton.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        viewInEditorButton_actionPerformed(e);
+      }
+    });
     this.add(scrollPane, BorderLayout.CENTER);
     scrollPane.getViewport().add(textarea, null);
     this.add(jPanel1, BorderLayout.SOUTH);
index 1ad95dd..1ca0802 100755 (executable)
@@ -81,8 +81,8 @@ public class GPreferences extends JPanel
 {
   private static final Font LABEL_FONT = JvSwingUtils.getLabelFont();
 
-  private static final Font LABEL_FONT_ITALIC = JvSwingUtils.getLabelFont(
-          false, true);
+  private static final Font LABEL_FONT_ITALIC = JvSwingUtils
+          .getLabelFont(false, true);
 
   /*
    * Visual tab components
@@ -95,11 +95,11 @@ public class GPreferences extends JPanel
 
   protected JCheckBox rightAlign = new JCheckBox();
 
-  protected JComboBox<String> fontSizeCB = new JComboBox<String>();
+  protected JComboBox<String> fontSizeCB = new JComboBox<>();
 
-  protected JComboBox<String> fontStyleCB = new JComboBox<String>();
+  protected JComboBox<String> fontStyleCB = new JComboBox<>();
 
-  protected JComboBox<String> fontNameCB = new JComboBox<String>();
+  protected JComboBox<String> fontNameCB = new JComboBox<>();
 
   protected JCheckBox showOccupancy = new JCheckBox();
 
@@ -111,15 +111,15 @@ public class GPreferences extends JPanel
 
   protected JCheckBox scaleProteinToCdna = new JCheckBox();
 
-  protected JComboBox<String> gapSymbolCB = new JComboBox<String>();
+  protected JComboBox<String> gapSymbolCB = new JComboBox<>();
 
   protected JCheckBox wrap = new JCheckBox();
 
-  protected JComboBox<String> sortby = new JComboBox<String>();
+  protected JComboBox<String> sortby = new JComboBox<>();
 
-  protected JComboBox<String> sortAnnBy = new JComboBox<String>();
+  protected JComboBox<String> sortAnnBy = new JComboBox<>();
 
-  protected JComboBox<String> sortAutocalc = new JComboBox<String>();
+  protected JComboBox<String> sortAutocalc = new JComboBox<>();
 
   protected JCheckBox startupCheckbox = new JCheckBox();
 
@@ -159,7 +159,7 @@ public class GPreferences extends JPanel
 
   protected JCheckBox addTempFactor = new JCheckBox();
 
-  protected JComboBox<String> structViewer = new JComboBox<String>();
+  protected JComboBox<String> structViewer = new JComboBox<>();
 
   protected JTextField chimeraPath = new JTextField();
 
@@ -176,9 +176,22 @@ public class GPreferences extends JPanel
 
   protected JPanel maxColour = new JPanel();
 
-  protected JComboBox<String> protColour = new JComboBox<String>();
+  protected JComboBox<String> protColour = new JComboBox<>();
 
-  protected JComboBox<String> nucColour = new JComboBox<String>();
+  protected JComboBox<String> nucColour = new JComboBox<>();
+
+  /*
+   * Overview tab components
+   */
+  protected JPanel gapColour = new JPanel();
+
+  protected JPanel hiddenColour = new JPanel();
+
+  protected JCheckBox useLegacyGap;
+
+  protected JCheckBox showHiddenAtStart;
+
+  protected JLabel gapLabel;
 
   /*
    * Connections tab components
@@ -216,7 +229,7 @@ public class GPreferences extends JPanel
   /*
    * Output tab components
    */
-  protected JComboBox<Object> epsRendering = new JComboBox<Object>();
+  protected JComboBox<Object> epsRendering = new JComboBox<>();
 
   protected JLabel userIdWidthlabel = new JLabel();
 
@@ -294,6 +307,9 @@ public class GPreferences extends JPanel
     tabbedPane.add(initColoursTab(),
             MessageManager.getString("label.colours"));
 
+    tabbedPane.add(initOverviewTab(),
+            MessageManager.getString("label.overview"));
+
     tabbedPane.add(initStructureTab(),
             MessageManager.getString("label.structure"));
 
@@ -357,18 +373,18 @@ public class GPreferences extends JPanel
     JPanel editingTab = new JPanel();
     editingTab.setLayout(null);
     autoCalculateConsCheck.setFont(LABEL_FONT);
-    autoCalculateConsCheck.setText(MessageManager
-            .getString("label.autocalculate_consensus"));
+    autoCalculateConsCheck.setText(
+            MessageManager.getString("label.autocalculate_consensus"));
     autoCalculateConsCheck.setBounds(new Rectangle(21, 52, 209, 23));
     padGaps.setFont(LABEL_FONT);
-    padGaps.setText(MessageManager.getString("label.pad_gaps_when_editing"));
+    padGaps.setText(
+            MessageManager.getString("label.pad_gaps_when_editing"));
     padGaps.setBounds(new Rectangle(22, 94, 168, 23));
     sortByTree.setFont(LABEL_FONT);
     sortByTree
             .setText(MessageManager.getString("label.sort_with_new_tree"));
-    sortByTree
-            .setToolTipText(MessageManager
-                    .getString("label.any_trees_calculated_or_loaded_alignment_automatically_sort"));
+    sortByTree.setToolTipText(MessageManager.getString(
+            "label.any_trees_calculated_or_loaded_alignment_automatically_sort"));
     sortByTree.setBounds(new Rectangle(22, 136, 168, 23));
     editingTab.add(autoCalculateConsCheck);
     editingTab.add(padGaps);
@@ -428,11 +444,10 @@ public class GPreferences extends JPanel
     pirjv.setFont(LABEL_FONT);
     pirjv.setHorizontalAlignment(SwingConstants.LEFT);
     autoIdWidth.setFont(LABEL_FONT);
-    autoIdWidth.setText(MessageManager
-            .getString("label.automatically_set_id_width"));
-    autoIdWidth.setToolTipText(JvSwingUtils.wrapTooltip(true,
-            MessageManager
-                    .getString("label.adjusts_width_generated_eps_png")));
+    autoIdWidth.setText(
+            MessageManager.getString("label.automatically_set_id_width"));
+    autoIdWidth.setToolTipText(JvSwingUtils.wrapTooltip(true, MessageManager
+            .getString("label.adjusts_width_generated_eps_png")));
     autoIdWidth.setBounds(new Rectangle(228, 96, 188, 23));
     autoIdWidth.addActionListener(new ActionListener()
     {
@@ -444,14 +459,13 @@ public class GPreferences extends JPanel
       }
     });
     userIdWidthlabel.setFont(LABEL_FONT);
-    userIdWidthlabel.setText(MessageManager
-            .getString("label.figure_id_column_width"));
-    userIdWidth
-            .setToolTipText(JvSwingUtils.wrapTooltip(true, MessageManager
-                    .getString("label.manually_specify_width_left_column")));
-    userIdWidthlabel
-            .setToolTipText(JvSwingUtils.wrapTooltip(true, MessageManager
-                    .getString("label.manually_specify_width_left_column")));
+    userIdWidthlabel.setText(
+            MessageManager.getString("label.figure_id_column_width"));
+    userIdWidth.setToolTipText(JvSwingUtils.wrapTooltip(true, MessageManager
+            .getString("label.manually_specify_width_left_column")));
+    userIdWidthlabel.setToolTipText(
+            JvSwingUtils.wrapTooltip(true, MessageManager.getString(
+                    "label.manually_specify_width_left_column")));
     userIdWidthlabel.setBounds(new Rectangle(236, 120, 168, 23));
     userIdWidth.setFont(JvSwingUtils.getTextAreaFont());
     userIdWidth.setText("");
@@ -466,8 +480,8 @@ public class GPreferences extends JPanel
       }
     });
     modellerOutput.setFont(LABEL_FONT);
-    modellerOutput.setText(MessageManager
-            .getString("label.use_modeller_output"));
+    modellerOutput
+            .setText(MessageManager.getString("label.use_modeller_output"));
     modellerOutput.setBounds(new Rectangle(228, 226, 168, 23));
     embbedBioJSON.setFont(LABEL_FONT);
     embbedBioJSON.setText(MessageManager.getString("label.embbed_biojson"));
@@ -506,8 +520,8 @@ public class GPreferences extends JPanel
     JLabel browserLabel = new JLabel();
     browserLabel.setFont(LABEL_FONT);
     browserLabel.setHorizontalAlignment(SwingConstants.TRAILING);
-    browserLabel.setText(MessageManager
-            .getString("label.default_browser_unix"));
+    browserLabel.setText(
+            MessageManager.getString("label.default_browser_unix"));
     defaultBrowser.setFont(LABEL_FONT);
     defaultBrowser.setText("");
 
@@ -527,9 +541,10 @@ public class GPreferences extends JPanel
     initConnTabCheckboxes();
 
     // Add default Browser text box
-    connectTab.add(browserLabel, new GridBagConstraints(0, 0, 1, 1, 0.0,
-            0.0, GridBagConstraints.WEST, GridBagConstraints.NONE,
-            new Insets(10, 0, 5, 5), 5, 1));
+    connectTab.add(browserLabel,
+            new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
+                    GridBagConstraints.WEST, GridBagConstraints.NONE,
+                    new Insets(10, 0, 5, 5), 5, 1));
     defaultBrowser.setFont(LABEL_FONT);
     defaultBrowser.setText("");
 
@@ -543,21 +558,25 @@ public class GPreferences extends JPanel
             new Insets(10, 0, 5, 12), 4, 10));
 
     // Add usage stats, version check and questionnaire checkboxes
-    connectTab.add(usagestats, new GridBagConstraints(0, 2, 1, 1, 1.0, 0.0,
-            GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
-            new Insets(0, 2, 5, 5), 70, 1));
-    connectTab.add(questionnaire, new GridBagConstraints(1, 2, 1, 1, 1.0,
-            0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
-            new Insets(0, 2, 5, 10), 70, 1));
-    connectTab.add(versioncheck, new GridBagConstraints(0, 3, 1, 1, 1.0,
-            0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
-            new Insets(0, 2, 5, 5), 70, 1));
+    connectTab.add(usagestats,
+            new GridBagConstraints(0, 2, 1, 1, 1.0, 0.0,
+                    GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
+                    new Insets(0, 2, 5, 5), 70, 1));
+    connectTab.add(questionnaire,
+            new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0,
+                    GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
+                    new Insets(0, 2, 5, 10), 70, 1));
+    connectTab.add(versioncheck,
+            new GridBagConstraints(0, 3, 1, 1, 1.0, 0.0,
+                    GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
+                    new Insets(0, 2, 5, 5), 70, 1));
 
     // Add padding so the panel doesn't look ridiculous
     JPanel spacePanel = new JPanel();
-    connectTab.add(spacePanel, new GridBagConstraints(0, 4, 1, 1, 1.0, 1.0,
-            GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0,
-                    0, 0, 5), 70, 1));
+    connectTab.add(spacePanel,
+            new GridBagConstraints(0, 4, 1, 1, 1.0, 1.0,
+                    GridBagConstraints.WEST, GridBagConstraints.BOTH,
+                    new Insets(0, 0, 0, 5), 70, 1));
 
     return connectTab;
   }
@@ -590,8 +609,8 @@ public class GPreferences extends JPanel
 
     // Panel for links functionality
     JPanel linkPanel = new JPanel(new GridBagLayout());
-    linkPanel.setBorder(new TitledBorder(MessageManager
-            .getString("label.url_linkfrom_sequence_id")));
+    linkPanel.setBorder(new TitledBorder(
+            MessageManager.getString("label.url_linkfrom_sequence_id")));
 
     // Put the Url links panel together
 
@@ -690,7 +709,7 @@ public class GPreferences extends JPanel
     // no current selection, so initially disable delete/edit buttons
     editLink.setEnabled(false);
     deleteLink.setEnabled(false);
-    
+
     newLink.addActionListener(new java.awt.event.ActionListener()
     {
       @Override
@@ -793,21 +812,26 @@ public class GPreferences extends JPanel
             MessageManager.getString("label.proxy_server"));
     proxyPanel.setBorder(titledBorder1);
     proxyPanel.setLayout(new GridBagLayout());
-    proxyPanel.add(serverLabel, new GridBagConstraints(0, 1, 1, 1, 0.0,
-            0.0, GridBagConstraints.WEST, GridBagConstraints.NONE,
-            new Insets(0, 2, 2, 0), 5, 0));
-    proxyPanel.add(portLabel, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0,
-            GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,
-                    0, 2, 0), 11, 0));
-    proxyPanel.add(useProxy, new GridBagConstraints(0, 0, 2, 1, 0.0, 0.0,
-            GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,
-                    2, 5, 185), 2, -4));
-    proxyPanel.add(proxyPortTB, new GridBagConstraints(3, 1, 1, 1, 1.0,
-            0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
-            new Insets(0, 2, 2, 2), 54, 1));
-    proxyPanel.add(proxyServerTB, new GridBagConstraints(1, 1, 1, 1, 1.0,
-            0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
-            new Insets(0, 2, 2, 0), 263, 1));
+    proxyPanel.add(serverLabel,
+            new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0,
+                    GridBagConstraints.WEST, GridBagConstraints.NONE,
+                    new Insets(0, 2, 2, 0), 5, 0));
+    proxyPanel.add(portLabel,
+            new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0,
+                    GridBagConstraints.WEST, GridBagConstraints.NONE,
+                    new Insets(0, 0, 2, 0), 11, 0));
+    proxyPanel.add(useProxy,
+            new GridBagConstraints(0, 0, 2, 1, 0.0, 0.0,
+                    GridBagConstraints.WEST, GridBagConstraints.NONE,
+                    new Insets(0, 2, 5, 185), 2, -4));
+    proxyPanel.add(proxyPortTB,
+            new GridBagConstraints(3, 1, 1, 1, 1.0, 0.0,
+                    GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
+                    new Insets(0, 2, 2, 2), 54, 1));
+    proxyPanel.add(proxyServerTB,
+            new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0,
+                    GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
+                    new Insets(0, 2, 2, 0), 263, 1));
 
     return proxyPanel;
   }
@@ -818,22 +842,22 @@ public class GPreferences extends JPanel
   private void initConnTabCheckboxes()
   {
     // Usage stats checkbox label
-    usagestats.setText(MessageManager
-            .getString("label.send_usage_statistics"));
+    usagestats.setText(
+            MessageManager.getString("label.send_usage_statistics"));
     usagestats.setFont(LABEL_FONT);
     usagestats.setHorizontalAlignment(SwingConstants.RIGHT);
     usagestats.setHorizontalTextPosition(SwingConstants.LEADING);
 
     // Questionnaire checkbox label
-    questionnaire.setText(MessageManager
-            .getString("label.check_for_questionnaires"));
+    questionnaire.setText(
+            MessageManager.getString("label.check_for_questionnaires"));
     questionnaire.setFont(LABEL_FONT);
     questionnaire.setHorizontalAlignment(SwingConstants.RIGHT);
     questionnaire.setHorizontalTextPosition(SwingConstants.LEADING);
 
     // Check for latest version checkbox label
-    versioncheck.setText(MessageManager
-            .getString("label.check_for_latest_version"));
+    versioncheck.setText(
+            MessageManager.getString("label.check_for_latest_version"));
     versioncheck.setFont(LABEL_FONT);
     versioncheck.setHorizontalAlignment(SwingConstants.RIGHT);
     versioncheck.setHorizontalTextPosition(SwingConstants.LEADING);
@@ -880,8 +904,8 @@ public class GPreferences extends JPanel
   private JPanel initColoursTab()
   {
     JPanel coloursTab = new JPanel();
-    coloursTab.setBorder(new TitledBorder(MessageManager
-            .getString("action.open_new_alignment")));
+    coloursTab.setBorder(new TitledBorder(
+            MessageManager.getString("action.open_new_alignment")));
     coloursTab.setLayout(new FlowLayout());
     JLabel mincolourLabel = new JLabel();
     mincolourLabel.setFont(LABEL_FONT);
@@ -919,10 +943,11 @@ public class GPreferences extends JPanel
     JLabel protColourLabel = new JLabel();
     protColourLabel.setFont(LABEL_FONT);
     protColourLabel.setHorizontalAlignment(SwingConstants.LEFT);
-    protColourLabel.setText(MessageManager
-            .getString("label.prot_alignment_colour") + " ");
-    JvSwingUtils.addtoLayout(coloursTab, MessageManager
-            .getString("label.default_colour_scheme_for_alignment"),
+    protColourLabel.setText(
+            MessageManager.getString("label.prot_alignment_colour") + " ");
+    JvSwingUtils.addtoLayout(coloursTab,
+            MessageManager
+                    .getString("label.default_colour_scheme_for_alignment"),
             protColourLabel, protColour);
 
     nucColour.setFont(LABEL_FONT);
@@ -930,27 +955,175 @@ public class GPreferences extends JPanel
     JLabel nucColourLabel = new JLabel();
     nucColourLabel.setFont(LABEL_FONT);
     nucColourLabel.setHorizontalAlignment(SwingConstants.LEFT);
-    nucColourLabel.setText(MessageManager
-            .getString("label.nuc_alignment_colour") + " ");
-    JvSwingUtils.addtoLayout(coloursTab, MessageManager
-            .getString("label.default_colour_scheme_for_alignment"),
+    nucColourLabel.setText(
+            MessageManager.getString("label.nuc_alignment_colour") + " ");
+    JvSwingUtils.addtoLayout(coloursTab,
+            MessageManager
+                    .getString("label.default_colour_scheme_for_alignment"),
             nucColourLabel, nucColour);
 
     JPanel annotationShding = new JPanel();
-    annotationShding.setBorder(new TitledBorder(MessageManager
-            .getString("label.annotation_shading_default")));
+    annotationShding.setBorder(new TitledBorder(
+            MessageManager.getString("label.annotation_shading_default")));
     annotationShding.setLayout(new GridLayout(1, 2));
-    JvSwingUtils.addtoLayout(annotationShding, MessageManager
-            .getString("label.default_minimum_colour_annotation_shading"),
+    JvSwingUtils.addtoLayout(annotationShding,
+            MessageManager.getString(
+                    "label.default_minimum_colour_annotation_shading"),
             mincolourLabel, minColour);
-    JvSwingUtils.addtoLayout(annotationShding, MessageManager
-            .getString("label.default_maximum_colour_annotation_shading"),
+    JvSwingUtils.addtoLayout(annotationShding,
+            MessageManager.getString(
+                    "label.default_maximum_colour_annotation_shading"),
             maxcolourLabel, maxColour);
     coloursTab.add(annotationShding); // , FlowLayout.LEFT);
     return coloursTab;
   }
 
   /**
+   * Initialises the Overview tabbed panel.
+   * 
+   * @return
+   */
+  private JPanel initOverviewTab()
+  {
+    JPanel overviewPanel = new JPanel();
+    overviewPanel.setBorder(new TitledBorder(
+            MessageManager.getString("label.overview_settings")));
+
+    gapColour.setFont(LABEL_FONT);
+    // fixing the border colours stops apparent colour bleed from the panel
+    gapColour.setBorder(
+            BorderFactory.createEtchedBorder(Color.white, Color.lightGray));
+    gapColour.setPreferredSize(new Dimension(40, 20));
+    gapColour.addMouseListener(new MouseAdapter()
+    {
+      @Override
+      public void mousePressed(MouseEvent e)
+      {
+        gapColour_actionPerformed(gapColour);
+      }
+    });
+
+    hiddenColour.setFont(LABEL_FONT);
+    // fixing the border colours stops apparent colour bleed from the panel
+    hiddenColour.setBorder(
+            BorderFactory.createEtchedBorder(Color.white, Color.lightGray));
+    hiddenColour.setPreferredSize(new Dimension(40, 20));
+    hiddenColour.addMouseListener(new MouseAdapter()
+    {
+      @Override
+      public void mousePressed(MouseEvent e)
+      {
+        hiddenColour_actionPerformed(hiddenColour);
+      }
+    });
+    
+    useLegacyGap = new JCheckBox(
+            MessageManager.getString("label.ov_legacy_gap"));
+    useLegacyGap.setFont(LABEL_FONT);
+    useLegacyGap.setHorizontalAlignment(SwingConstants.LEFT);
+    useLegacyGap.setVerticalTextPosition(SwingConstants.TOP);
+    gapLabel = new JLabel(
+            MessageManager.getString("label.gap_colour"));
+    gapLabel.setFont(LABEL_FONT);
+    gapLabel.setHorizontalAlignment(SwingConstants.LEFT);
+    gapLabel.setVerticalTextPosition(SwingConstants.TOP);
+    showHiddenAtStart = new JCheckBox(
+            MessageManager.getString("label.ov_show_hide_default"));
+    showHiddenAtStart.setFont(LABEL_FONT);
+    showHiddenAtStart.setHorizontalAlignment(SwingConstants.LEFT);
+    showHiddenAtStart.setVerticalTextPosition(SwingConstants.TOP);
+    JLabel hiddenLabel = new JLabel(
+            MessageManager.getString("label.hidden_colour"));
+    hiddenLabel.setFont(LABEL_FONT);
+    hiddenLabel.setHorizontalAlignment(SwingConstants.LEFT);
+    hiddenLabel.setVerticalTextPosition(SwingConstants.TOP);
+
+    useLegacyGap.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        useLegacyGaps_actionPerformed(e);
+      }
+    });
+
+    overviewPanel.setLayout(new GridBagLayout());
+    GridBagConstraints c1 = new GridBagConstraints();
+
+    c1.fill = GridBagConstraints.HORIZONTAL;
+    c1.gridx = 0;
+    c1.gridy = 0;
+    c1.weightx = 1;
+    c1.ipady = 20;
+    c1.anchor = GridBagConstraints.FIRST_LINE_START;
+    overviewPanel.add(useLegacyGap, c1);
+
+    GridBagConstraints c2 = new GridBagConstraints();
+    c2.fill = GridBagConstraints.HORIZONTAL;
+    c2.gridx = 1;
+    c2.gridy = 0;
+    c2.insets = new Insets(0, 15, 0, 10);
+    overviewPanel.add(gapLabel, c2);
+
+    GridBagConstraints c3 = new GridBagConstraints();
+    c3.fill = GridBagConstraints.HORIZONTAL;
+    c3.gridx = 2;
+    c3.gridy = 0;
+    c3.insets = new Insets(0, 0, 0, 15);
+    overviewPanel.add(gapColour, c3);
+
+    GridBagConstraints c4 = new GridBagConstraints();
+    c4.fill = GridBagConstraints.HORIZONTAL;
+    c4.gridx = 0;
+    c4.gridy = 1;
+    c4.weightx = 1;
+    overviewPanel.add(showHiddenAtStart, c4);
+
+    GridBagConstraints c5 = new GridBagConstraints();
+    c5.fill = GridBagConstraints.HORIZONTAL;
+    c5.gridx = 1;
+    c5.gridy = 1;
+    c5.insets = new Insets(0, 15, 0, 10);
+    overviewPanel.add(hiddenLabel, c5);
+
+    GridBagConstraints c6 = new GridBagConstraints();
+    c6.fill = GridBagConstraints.HORIZONTAL;
+    c6.gridx = 2;
+    c6.gridy = 1;
+    c6.insets = new Insets(0, 0, 0, 15);
+    overviewPanel.add(hiddenColour, c6);
+
+    JButton resetButton = new JButton(
+            MessageManager.getString("label.reset_to_defaults"));
+
+    resetButton.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        resetOvDefaults_actionPerformed(e);
+      }
+    });
+
+    GridBagConstraints c7 = new GridBagConstraints();
+    c7.fill = GridBagConstraints.NONE;
+    c7.gridx = 0;
+    c7.gridy = 2;
+    c7.insets = new Insets(10, 0, 0, 0);
+    c7.anchor = GridBagConstraints.WEST;
+    overviewPanel.add(resetButton, c7);
+
+    // Add padding so the panel doesn't look ridiculous
+    JPanel spacePanel = new JPanel();
+    overviewPanel.add(spacePanel,
+            new GridBagConstraints(0, 3, 1, 1, 1.0, 1.0,
+                    GridBagConstraints.WEST, GridBagConstraints.BOTH,
+                    new Insets(0, 0, 0, 5), 0, 0));
+
+    return overviewPanel;
+  }
+
+  /**
    * Initialises the Structure tabbed panel.
    * 
    * @return
@@ -959,8 +1132,8 @@ public class GPreferences extends JPanel
   {
     structureTab = new JPanel();
 
-    structureTab.setBorder(new TitledBorder(MessageManager
-            .getString("label.structure_options")));
+    structureTab.setBorder(new TitledBorder(
+            MessageManager.getString("label.structure_options")));
     structureTab.setLayout(null);
     final int width = 400;
     final int height = 22;
@@ -994,8 +1167,8 @@ public class GPreferences extends JPanel
 
     ypos += lineSpacing;
     addSecondaryStructure.setFont(LABEL_FONT);
-    addSecondaryStructure.setText(MessageManager
-            .getString("label.autoadd_secstr"));
+    addSecondaryStructure
+            .setText(MessageManager.getString("label.autoadd_secstr"));
     addSecondaryStructure.setBounds(new Rectangle(25, ypos, width, height));
     structureTab.add(addSecondaryStructure);
 
@@ -1022,8 +1195,8 @@ public class GPreferences extends JPanel
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        structureViewer_actionPerformed((String) structViewer
-                .getSelectedItem());
+        structureViewer_actionPerformed(
+                (String) structViewer.getSelectedItem());
       }
     });
     structureTab.add(structViewer);
@@ -1110,8 +1283,8 @@ public class GPreferences extends JPanel
     JFileChooser chooser = new JFileChooser();
 
     // chooser.setFileView(new JalviewFileView());
-    chooser.setDialogTitle(MessageManager
-            .getString("label.open_local_file"));
+    chooser.setDialogTitle(
+            MessageManager.getString("label.open_local_file"));
     chooser.setToolTipText(MessageManager.getString("action.open"));
 
     int value = chooser.showOpenDialog(this);
@@ -1151,8 +1324,8 @@ public class GPreferences extends JPanel
   private JPanel initVisualTab()
   {
     JPanel visualTab = new JPanel();
-    visualTab.setBorder(new TitledBorder(MessageManager
-            .getString("action.open_new_alignment")));
+    visualTab.setBorder(new TitledBorder(
+            MessageManager.getString("action.open_new_alignment")));
     visualTab.setLayout(null);
     fullScreen.setFont(LABEL_FONT);
     fullScreen.setHorizontalAlignment(SwingConstants.RIGHT);
@@ -1187,21 +1360,21 @@ public class GPreferences extends JPanel
     showGroupbits.setFont(LABEL_FONT);
     showGroupbits.setHorizontalAlignment(SwingConstants.RIGHT);
     showGroupbits.setHorizontalTextPosition(SwingConstants.LEFT);
-    showGroupbits.setText(MessageManager.getString("action.show_group")
-            + ":");
+    showGroupbits
+            .setText(MessageManager.getString("action.show_group") + ":");
     JLabel showConsensbits = new JLabel();
     showConsensbits.setFont(LABEL_FONT);
     showConsensbits.setHorizontalAlignment(SwingConstants.RIGHT);
     showConsensbits.setHorizontalTextPosition(SwingConstants.LEFT);
-    showConsensbits.setText(MessageManager.getString("label.consensus")
-            + ":");
+    showConsensbits
+            .setText(MessageManager.getString("label.consensus") + ":");
     showConsensHistogram.setEnabled(false);
     showConsensHistogram.setFont(LABEL_FONT);
     showConsensHistogram.setHorizontalAlignment(SwingConstants.RIGHT);
     showConsensHistogram.setHorizontalTextPosition(SwingConstants.LEFT);
     showConsensHistogram.setSelected(true);
-    showConsensHistogram.setText(MessageManager
-            .getString("label.histogram"));
+    showConsensHistogram
+            .setText(MessageManager.getString("label.histogram"));
     showConsensLogo.setEnabled(false);
     showConsensLogo.setFont(LABEL_FONT);
     showConsensLogo.setHorizontalAlignment(SwingConstants.RIGHT);
@@ -1219,22 +1392,22 @@ public class GPreferences extends JPanel
     showGroupConservation.setHorizontalAlignment(SwingConstants.RIGHT);
     showGroupConservation.setHorizontalTextPosition(SwingConstants.LEFT);
     showGroupConservation.setSelected(true);
-    showGroupConservation.setText(MessageManager
-            .getString("label.conservation"));
+    showGroupConservation
+            .setText(MessageManager.getString("label.conservation"));
     showNpTooltip.setEnabled(true);
     showNpTooltip.setFont(LABEL_FONT);
     showNpTooltip.setHorizontalAlignment(SwingConstants.RIGHT);
     showNpTooltip.setHorizontalTextPosition(SwingConstants.LEFT);
     showNpTooltip.setSelected(true);
-    showNpTooltip.setText(MessageManager
-            .getString("label.non_positional_features"));
+    showNpTooltip.setText(
+            MessageManager.getString("label.non_positional_features"));
     showDbRefTooltip.setEnabled(true);
     showDbRefTooltip.setFont(LABEL_FONT);
     showDbRefTooltip.setHorizontalAlignment(SwingConstants.RIGHT);
     showDbRefTooltip.setHorizontalTextPosition(SwingConstants.LEFT);
     showDbRefTooltip.setSelected(true);
-    showDbRefTooltip.setText(MessageManager
-            .getString("label.database_references"));
+    showDbRefTooltip
+            .setText(MessageManager.getString("label.database_references"));
     annotations.setFont(LABEL_FONT);
     annotations.setHorizontalAlignment(SwingConstants.RIGHT);
     annotations.setHorizontalTextPosition(SwingConstants.LEFT);
@@ -1269,8 +1442,8 @@ public class GPreferences extends JPanel
     showUnconserved.setHorizontalAlignment(SwingConstants.RIGHT);
     showUnconserved.setHorizontalTextPosition(SwingConstants.LEFT);
     showUnconserved.setSelected(true);
-    showUnconserved.setText(MessageManager
-            .getString("action.show_unconserved"));
+    showUnconserved
+            .setText(MessageManager.getString("action.show_unconserved"));
     showUnconserved.addActionListener(new ActionListener()
     {
       @Override
@@ -1308,10 +1481,10 @@ public class GPreferences extends JPanel
     scaleProteinToCdna.setFont(LABEL_FONT);
     scaleProteinToCdna.setHorizontalAlignment(SwingConstants.RIGHT);
     scaleProteinToCdna.setHorizontalTextPosition(SwingConstants.LEADING);
-    scaleProteinToCdna.setText(MessageManager
-            .getString("label.scale_protein_to_cdna"));
-    scaleProteinToCdna.setToolTipText(MessageManager
-            .getString("label.scale_protein_to_cdna_tip"));
+    scaleProteinToCdna.setText(
+            MessageManager.getString("label.scale_protein_to_cdna"));
+    scaleProteinToCdna.setToolTipText(
+            MessageManager.getString("label.scale_protein_to_cdna_tip"));
     JLabel gapLabel = new JLabel();
     gapLabel.setFont(LABEL_FONT);
     gapLabel.setHorizontalAlignment(SwingConstants.RIGHT);
@@ -1403,12 +1576,10 @@ public class GPreferences extends JPanel
     autoAnnotSettings.add(showConsensbits);
     autoAnnotSettings.add(showConsensHistogram);
     autoAnnotSettings.add(showConsensLogo);
-    
-    
 
     JPanel tooltipSettings = new JPanel();
-    tooltipSettings.setBorder(new TitledBorder(MessageManager
-            .getString("label.sequence_id_tooltip")));
+    tooltipSettings.setBorder(new TitledBorder(
+            MessageManager.getString("label.sequence_id_tooltip")));
     tooltipSettings.setBounds(173, 140, 220, 62);
     tooltipSettings.setLayout(new GridLayout(2, 1));
     tooltipSettings.add(showDbRefTooltip);
@@ -1427,11 +1598,11 @@ public class GPreferences extends JPanel
     idItalics.setFont(LABEL_FONT_ITALIC);
     idItalics.setHorizontalAlignment(SwingConstants.RIGHT);
     idItalics.setHorizontalTextPosition(SwingConstants.LEADING);
-    idItalics.setText(MessageManager
-            .getString("label.sequence_name_italics"));
+    idItalics.setText(
+            MessageManager.getString("label.sequence_name_italics"));
     openoverv.setFont(LABEL_FONT);
-    openoverv.setActionCommand(MessageManager
-            .getString("label.open_overview"));
+    openoverv.setActionCommand(
+            MessageManager.getString("label.open_overview"));
     openoverv.setHorizontalAlignment(SwingConstants.RIGHT);
     openoverv.setHorizontalTextPosition(SwingConstants.LEFT);
     openoverv.setText(MessageManager.getString("label.open_overview"));
@@ -1484,12 +1655,28 @@ public class GPreferences extends JPanel
   {
   }
 
+  protected void gapColour_actionPerformed(JPanel panel)
+  {
+  }
+
+  protected void hiddenColour_actionPerformed(JPanel panel)
+  {
+  }
+
   protected void showunconserved_actionPerformed(ActionEvent e)
   {
     // TODO Auto-generated method stub
 
   }
 
+  protected void useLegacyGaps_actionPerformed(ActionEvent e)
+  {
+  }
+
+  protected void resetOvDefaults_actionPerformed(ActionEvent e)
+  {
+  }
+
   /**
    * DOCUMENT ME!
    * 
@@ -1564,8 +1751,8 @@ public class GPreferences extends JPanel
   /**
    * Customer renderer for JTable: supports column of radio buttons
    */
-  public class RadioButtonRenderer extends JRadioButton implements
-          TableCellRenderer
+  public class RadioButtonRenderer extends JRadioButton
+          implements TableCellRenderer
   {
     public RadioButtonRenderer()
     {
@@ -1582,14 +1769,14 @@ public class GPreferences extends JPanel
 
       // set colours to match rest of table
       if (isSelected)
-       {
-         setBackground(table.getSelectionBackground());
-         setForeground(table.getSelectionForeground());
-       }
-       else
-       {
-         setBackground(table.getBackground());
-         setForeground(table.getForeground());
+      {
+        setBackground(table.getSelectionBackground());
+        setForeground(table.getSelectionForeground());
+      }
+      else
+      {
+        setBackground(table.getBackground());
+        setForeground(table.getForeground());
       }
       return this;
     }
@@ -1599,37 +1786,37 @@ public class GPreferences extends JPanel
    * Customer cell editor for JTable: supports column of radio buttons in
    * conjunction with renderer
    */
-  public class RadioButtonEditor extends AbstractCellEditor implements
-            TableCellEditor
-    {
-      private JRadioButton button = new JRadioButton();
+  public class RadioButtonEditor extends AbstractCellEditor
+          implements TableCellEditor
+  {
+    private JRadioButton button = new JRadioButton();
 
-      public RadioButtonEditor()
-      {
+    public RadioButtonEditor()
+    {
       button.setHorizontalAlignment(SwingConstants.CENTER);
       this.button.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
         {
-          @Override
-          public void actionPerformed(ActionEvent e)
-          {
-            fireEditingStopped();
-          }
-        });
-      }
+          fireEditingStopped();
+        }
+      });
+    }
 
-      @Override
-      public Component getTableCellEditorComponent(JTable table,
-              Object value, boolean isSelected, int row, int column)
-      {
+    @Override
+    public Component getTableCellEditorComponent(JTable table, Object value,
+            boolean isSelected, int row, int column)
+    {
       button.setSelected((boolean) value);
-        return button;
-      }
+      return button;
+    }
 
-      @Override
-      public Object getCellEditorValue()
-      {
+    @Override
+    public Object getCellEditorValue()
+    {
       return button.isSelected();
-      }
+    }
 
   }
 }
index eb1a348..5170a6c 100644 (file)
@@ -63,12 +63,12 @@ public class GRestInputParamEditDialog
   protected void jbInit()
   {
     dpane = new JPanel(new MigLayout("", "[][][fill]", "[][fill][]"));
-    dpane.setPreferredSize(new Dimension(
-            110 + 100 + OptsAndParamsPage.PARAM_WIDTH, 400));
+    dpane.setPreferredSize(
+            new Dimension(110 + 100 + OptsAndParamsPage.PARAM_WIDTH, 400));
     typeList = new JList();
     typeList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-    typeList.getSelectionModel().addListSelectionListener(
-            new ListSelectionListener()
+    typeList.getSelectionModel()
+            .addListSelectionListener(new ListSelectionListener()
             {
 
               @Override
@@ -107,16 +107,16 @@ public class GRestInputParamEditDialog
             MessageManager.getString("label.input_parameter_name"),
             new JLabel(MessageManager.getString("label.name")), tok,
             "grow,spanx 3,wrap");
-    JPanel paramsType = new JPanel(new MigLayout("", "[grow 100,fill]",
-            "[grow 100,fill]"));
-    paramsType.setBorder(new TitledBorder(MessageManager
-            .getString("label.select_input_type")));
+    JPanel paramsType = new JPanel(
+            new MigLayout("", "[grow 100,fill]", "[grow 100,fill]"));
+    paramsType.setBorder(new TitledBorder(
+            MessageManager.getString("label.select_input_type")));
     JScrollPane jlistScroller = new JScrollPane();
     jlistScroller.setViewportView(typeList);
     paramsType.add(jlistScroller, "spanx 2,spany 2");
     dpane.add(paramsType);
-    optionsPanel.setBorder(new TitledBorder(MessageManager
-            .getString("label.set_options_for_type")));
+    optionsPanel.setBorder(new TitledBorder(
+            MessageManager.getString("label.set_options_for_type")));
     optionsPanel.add(optionView);
     dpane.add(optionsPanel, "wrap");
     okcancel = new JPanel(new MigLayout("", "[center][center]", "[]"));
index 3329780..a4dca4b 100644 (file)
@@ -95,8 +95,8 @@ public class GRestServiceEditorPane extends JPanel
     inputs.setLayout(new MigLayout("", "[grow 85,fill][]", ""));
     paste = new JPanel();
     paste.setName(MessageManager.getString("label.cut_paste"));
-    paste.setLayout(new MigLayout("", "[grow 100, fill]",
-            "[][grow 100,fill]"));
+    paste.setLayout(
+            new MigLayout("", "[grow 100, fill]", "[][grow 100,fill]"));
 
     panels = new JTabbedPane();
     panels.addTab(details.getName(), details);
@@ -109,8 +109,9 @@ public class GRestServiceEditorPane extends JPanel
     cpanel = details;
     name = new JTextArea(1, 12);
 
-    JvSwingUtils.mgAddtoLayout(cpanel, MessageManager
-            .getString("label.short_descriptive_name_for_service"),
+    JvSwingUtils.mgAddtoLayout(cpanel,
+            MessageManager
+                    .getString("label.short_descriptive_name_for_service"),
             new JLabel(MessageManager.getString("label.name")), name,
             "wrap");
     action = new JComboBox();
@@ -137,8 +138,8 @@ public class GRestServiceEditorPane extends JPanel
     urlsuff = new JTextArea();
     urlsuff.setColumns(60);
 
-    JvSwingUtils.mgAddtoLayout(cpanel, MessageManager
-            .getString("label.optional_suffix"),
+    JvSwingUtils.mgAddtoLayout(cpanel,
+            MessageManager.getString("label.optional_suffix"),
             new JLabel(MessageManager.getString("label.url_suffix")),
             urlsuff, "wrap");
 
@@ -160,11 +161,9 @@ public class GRestServiceEditorPane extends JPanel
     });
     vSeparable = new JCheckBox(
             MessageManager.getString("label.result_vertically_separable"));
-    vSeparable
-            .setToolTipText(JvSwingUtils.wrapTooltip(
-                    true,
-                    MessageManager
-                            .getString("label.when_checked_job_visible_region_and_results")));
+    vSeparable.setToolTipText(
+            JvSwingUtils.wrapTooltip(true, MessageManager.getString(
+                    "label.when_checked_job_visible_region_and_results")));
     vSeparable.addActionListener(new ActionListener()
     {
 
@@ -178,8 +177,9 @@ public class GRestServiceEditorPane extends JPanel
     gapChar = new JComboBox();
     JvSwingUtils.mgAddtoLayout(cpanel,
             MessageManager.getString("label.preferred_gap_character"),
-            new JLabel(MessageManager.getString("label.gap_character")
-                    + ":"), gapChar, "wrap");
+            new JLabel(
+                    MessageManager.getString("label.gap_character") + ":"),
+            gapChar, "wrap");
 
     cpanel.add(hSeparable);
     cpanel.add(vSeparable);
@@ -187,8 +187,8 @@ public class GRestServiceEditorPane extends JPanel
     // Input and Output lists
     // Inputparams
     JPanel iprmsList = new JPanel();
-    iprmsList.setBorder(new TitledBorder(MessageManager
-            .getString("label.data_input_parameters")));
+    iprmsList.setBorder(new TitledBorder(
+            MessageManager.getString("label.data_input_parameters")));
     iprmsList.setLayout(new MigLayout("", "[grow 90, fill][]"));
     iprmVp = new JScrollPane();
     iprmVp.getViewport().setView(iprms = new JList());
@@ -322,12 +322,12 @@ public class GRestServiceEditorPane extends JPanel
             });
 
     JPanel rparamList = new JPanel();
-    rparamList.setBorder(new TitledBorder(MessageManager
-            .getString("label.data_returned_by_service")));
+    rparamList.setBorder(new TitledBorder(
+            MessageManager.getString("label.data_returned_by_service")));
     rparamList.setLayout(new MigLayout("", "[grow 90, fill][]"));
     rdata = new JList();
-    rdata.setToolTipText(MessageManager
-            .getString("label.right_click_to_edit_currently_selected_parameter"));
+    rdata.setToolTipText(MessageManager.getString(
+            "label.right_click_to_edit_currently_selected_parameter"));
     rdata.addMouseListener(new MouseListener()
     {
 
@@ -388,10 +388,10 @@ public class GRestServiceEditorPane extends JPanel
     urldescVp = new JScrollPane();
     urldescVp.setViewportView(urldesc);
     JPanel urldescPane = new JPanel();
-    urldescPane.setLayout(new MigLayout("", "[grow 100, fill]",
-            "[grow 100, fill]"));
-    urldescPane.setBorder(new TitledBorder(MessageManager
-            .getString("label.rsbs_encoded_service")));
+    urldescPane.setLayout(
+            new MigLayout("", "[grow 100, fill]", "[grow 100, fill]"));
+    urldescPane.setBorder(new TitledBorder(
+            MessageManager.getString("label.rsbs_encoded_service")));
     urldescPane.add(urldescVp, "span");
     paste.add(urldescPane, "span");
     urldescPane.setToolTipText(JvSwingUtils.wrapTooltip(true,
@@ -402,10 +402,10 @@ public class GRestServiceEditorPane extends JPanel
     parseResVp.setViewportView(parseRes);
     parseRes.setWrapStyleWord(true);
     parseRes.setColumns(60);
-    parseWarnings = new JPanel(new MigLayout("", "[grow 100, fill]",
-            "[grow 100, fill]"));
-    parseWarnings.setBorder(new TitledBorder(MessageManager
-            .getString("label.parsing_errors")));
+    parseWarnings = new JPanel(
+            new MigLayout("", "[grow 100, fill]", "[grow 100, fill]"));
+    parseWarnings.setBorder(new TitledBorder(
+            MessageManager.getString("label.parsing_errors")));
     parseWarnings.setToolTipText(JvSwingUtils.wrapTooltip(true,
             MessageManager.getString("label.result_of_parsing_rsbs")));
     parseWarnings.add(parseResVp, "center");
index ab3ea2c..a43e504 100755 (executable)
@@ -183,9 +183,10 @@ public class GSequenceLink extends JPanel
       height = 176;
     }
 
-    this.add(jPanel1, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0,
-            GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(
-                    5, 4, 6, 5), 390, height));
+    this.add(jPanel1,
+            new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0,
+                    GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+                    new Insets(5, 4, 6, 5), 390, height));
   }
 
   @Override
index 0c79c6c..356c294 100755 (executable)
@@ -168,8 +168,8 @@ public class GSliderPanel extends JPanel
     allGroupsCheck.setEnabled(false);
     allGroupsCheck.setFont(new java.awt.Font("Verdana", 0, 11));
     allGroupsCheck.setOpaque(false);
-    allGroupsCheck.setText(MessageManager
-            .getString("action.apply_all_groups"));
+    allGroupsCheck
+            .setText(MessageManager.getString("action.apply_all_groups"));
     allGroupsCheck.addActionListener(new java.awt.event.ActionListener()
     {
       @Override
index 7c4dcf3..2c618ba 100644 (file)
@@ -153,7 +153,8 @@ public class GSplitFrame extends JInternalFrame
       return false;
     }
     Point p = comp.getLocationOnScreen();
-    Rectangle r = new Rectangle(p.x, p.y, comp.getWidth(), comp.getHeight());
+    Rectangle r = new Rectangle(p.x, p.y, comp.getWidth(),
+            comp.getHeight());
     return r.contains(loc);
   }
 
@@ -173,8 +174,8 @@ public class GSplitFrame extends JInternalFrame
     else
     {
       this.dividerRatio = splitPane.getDividerLocation()
-              / (double) (splitPane.getHeight() - splitPane
-                      .getDividerSize());
+              / (double) (splitPane.getHeight()
+                      - splitPane.getDividerSize());
     }
 
     if (alignFrame == this.topFrame)
index 041fefd..7c4672a 100644 (file)
@@ -72,12 +72,13 @@ import javax.swing.table.TableColumn;
 
 @SuppressWarnings("serial")
 /**
- * GUI layout for structure chooser 
+ * GUI layout for structure chooser
+ * 
  * @author tcnofoegbu
  *
  */
-public abstract class GStructureChooser extends JPanel implements
-        ItemListener
+public abstract class GStructureChooser extends JPanel
+        implements ItemListener
 {
   protected JPanel statusPanel = new JPanel();
 
@@ -134,17 +135,17 @@ public abstract class GStructureChooser extends JPanel implements
   protected JCheckBox chk_invertFilter = new JCheckBox(
           MessageManager.getString("label.invert"));
 
-  protected ImageIcon loadingImage = new ImageIcon(getClass().getResource(
-          "/images/loading.gif"));
+  protected ImageIcon loadingImage = new ImageIcon(
+          getClass().getResource("/images/loading.gif"));
 
-  protected ImageIcon goodImage = new ImageIcon(getClass().getResource(
-          "/images/good.png"));
+  protected ImageIcon goodImage = new ImageIcon(
+          getClass().getResource("/images/good.png"));
 
-  protected ImageIcon errorImage = new ImageIcon(getClass().getResource(
-          "/images/error.png"));
+  protected ImageIcon errorImage = new ImageIcon(
+          getClass().getResource("/images/error.png"));
 
-  protected ImageIcon warningImage = new ImageIcon(getClass().getResource(
-          "/images/warning.gif"));
+  protected ImageIcon warningImage = new ImageIcon(
+          getClass().getResource("/images/warning.gif"));
 
   protected JLabel lbl_warning = new JLabel(warningImage);
 
@@ -164,6 +165,9 @@ public abstract class GStructureChooser extends JPanel implements
 
   protected static final String VIEWS_ENTER_ID = "VIEWS_ENTER_ID";
 
+  /**
+   * 'cached' structure view
+   */
   protected static final String VIEWS_LOCAL_PDB = "VIEWS_LOCAL_PDB";
 
   protected JTable tbl_local_pdb = new JTable();
@@ -249,10 +253,11 @@ public abstract class GStructureChooser extends JPanel implements
         // e.printStackTrace();
       }
       toolTipText = (toolTipText == null ? null
-              : (toolTipText.length() > 500 ? JvSwingUtils.wrapTooltip(
-                      true, "\"" + toolTipText.subSequence(0, 500)
-                              + "...\"") : JvSwingUtils.wrapTooltip(true,
-                      toolTipText)));
+              : (toolTipText.length() > 500
+                      ? JvSwingUtils.wrapTooltip(true,
+                              "\"" + toolTipText.subSequence(0, 500)
+                                      + "...\"")
+                      : JvSwingUtils.wrapTooltip(true, toolTipText)));
       return toolTipText;
     }
   };
@@ -280,9 +285,11 @@ public abstract class GStructureChooser extends JPanel implements
    */
   private void jbInit() throws Exception
   {
-    Integer width = tempUserPrefs.get("structureChooser.width") == null ? 800
+    Integer width = tempUserPrefs.get("structureChooser.width") == null
+            ? 800
             : tempUserPrefs.get("structureChooser.width");
-    Integer height = tempUserPrefs.get("structureChooser.height") == null ? 400
+    Integer height = tempUserPrefs.get("structureChooser.height") == null
+            ? 400
             : tempUserPrefs.get("structureChooser.height");
     tbl_summary.setAutoCreateRowSorter(true);
     tbl_summary.getTableHeader().setReorderingAllowed(false);
@@ -459,8 +466,8 @@ public abstract class GStructureChooser extends JPanel implements
     scrl_foundStructures.setPreferredSize(new Dimension(width, height));
 
     scrl_localPDB.setPreferredSize(new Dimension(width, height));
-    scrl_localPDB
-            .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+    scrl_localPDB.setHorizontalScrollBarPolicy(
+            JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
 
     cmb_filterOption.setFont(new java.awt.Font("Verdana", 0, 12));
     chk_invertFilter.setFont(new java.awt.Font("Verdana", 0, 12));
@@ -468,8 +475,8 @@ public abstract class GStructureChooser extends JPanel implements
     chk_rememberSettings.setVisible(false);
     txt_search.setToolTipText(JvSwingUtils.wrapTooltip(true,
             MessageManager.getString("label.enter_pdb_id")));
-    cmb_filterOption.setToolTipText(MessageManager
-            .getString("info.select_filter_option"));
+    cmb_filterOption.setToolTipText(
+            MessageManager.getString("info.select_filter_option"));
     txt_search.getDocument().addDocumentListener(new DocumentListener()
     {
       @Override
@@ -548,8 +555,8 @@ public abstract class GStructureChooser extends JPanel implements
           btn_view.setVisible(false);
           btn_cancel.setVisible(false);
           previousWantedFields = pdbDocFieldPrefs
-                  .getStructureSummaryFields().toArray(
-                          new FTSDataColumnI[0]);
+                  .getStructureSummaryFields()
+                  .toArray(new FTSDataColumnI[0]);
         }
         if (sourceTabbedPane.getTitleAt(index)
                 .equals(foundStructureSummary))
@@ -588,8 +595,8 @@ public abstract class GStructureChooser extends JPanel implements
     statusPanel.add(statusBar, null);
     this.add(pnl_actionsAndStatus, java.awt.BorderLayout.SOUTH);
 
-    mainFrame
-            .addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
+    mainFrame.addInternalFrameListener(
+            new javax.swing.event.InternalFrameAdapter()
             {
               @Override
               public void internalFrameClosing(InternalFrameEvent e)
@@ -747,8 +754,9 @@ public abstract class GStructureChooser extends JPanel implements
     public AssociateSeqOptions(SequenceI seq)
     {
       this.sequence = seq;
-      this.name = (seq.getName().length() >= 23) ? seq.getName().substring(
-              0, 23) : seq.getName();
+      this.name = (seq.getName().length() >= 23)
+              ? seq.getName().substring(0, 23)
+              : seq.getName();
     }
 
     public AssociateSeqOptions(String name, SequenceI seq)
@@ -804,8 +812,8 @@ public abstract class GStructureChooser extends JPanel implements
       this.setLayout(new FlowLayout());
       this.add(cmb_assSeq);
       this.add(lbl_associateSeq);
-      cmb_assSeq.setToolTipText(MessageManager
-              .getString("info.associate_wit_sequence"));
+      cmb_assSeq.setToolTipText(
+              MessageManager.getString("info.associate_wit_sequence"));
       cmb_assSeq.addItemListener(this);
     }
 
@@ -851,8 +859,8 @@ public abstract class GStructureChooser extends JPanel implements
    * @author tcnofoegbu
    *
    */
-  public abstract class CustomComboSeparatorsRenderer implements
-          ListCellRenderer<Object>
+  public abstract class CustomComboSeparatorsRenderer
+          implements ListCellRenderer<Object>
   {
     private ListCellRenderer<Object> regent;
 
@@ -860,14 +868,14 @@ public abstract class GStructureChooser extends JPanel implements
 
     private JSeparator jSeparator = new JSeparator();
 
-    public CustomComboSeparatorsRenderer(ListCellRenderer<Object> listCellRenderer)
+    public CustomComboSeparatorsRenderer(
+            ListCellRenderer<Object> listCellRenderer)
     {
       this.regent = listCellRenderer;
     }
 
     @Override
-    public Component getListCellRendererComponent(JList list,
-            Object value,
+    public Component getListCellRendererComponent(JList list, Object value,
             int index, boolean isSelected, boolean cellHasFocus)
     {
 
@@ -875,7 +883,7 @@ public abstract class GStructureChooser extends JPanel implements
               index, isSelected, cellHasFocus);
       if (index != -1
               && addSeparatorAfter(list, (FilterOption) value, index))
-      { 
+      {
         separatorPanel.removeAll();
         separatorPanel.add(comp, BorderLayout.CENTER);
         separatorPanel.add(jSeparator, BorderLayout.SOUTH);
@@ -888,8 +896,7 @@ public abstract class GStructureChooser extends JPanel implements
     }
 
     protected abstract boolean addSeparatorAfter(JList list,
-            FilterOption value,
-            int index);
+            FilterOption value, int index);
   }
 
   protected abstract void stateChanged(ItemEvent e);
@@ -901,7 +908,8 @@ public abstract class GStructureChooser extends JPanel implements
   protected abstract void txt_search_ActionPerformed();
 
   public abstract void populateCmbAssociateSeqOptions(
-          JComboBox<AssociateSeqOptions> cmb_assSeq, JLabel lbl_associateSeq);
+          JComboBox<AssociateSeqOptions> cmb_assSeq,
+          JLabel lbl_associateSeq);
 
   public abstract void cmbAssSeqStateChanged();
 
index d8f3f61..83d8590 100644 (file)
@@ -37,8 +37,8 @@ import javax.swing.JMenuItem;
 import javax.swing.JPanel;
 import javax.swing.JRadioButtonMenuItem;
 
-public abstract class GStructureViewer extends JInternalFrame implements
-        JalviewStructureDisplayI, ColourChangeListener
+public abstract class GStructureViewer extends JInternalFrame
+        implements JalviewStructureDisplayI, ColourChangeListener
 {
   // private AAStructureBindingModel bindingModel;
 
@@ -93,7 +93,8 @@ public abstract class GStructureViewer extends JInternalFrame implements
     fileMenu.setText(MessageManager.getString("action.file"));
 
     savemenu = new JMenu();
-    savemenu.setActionCommand(MessageManager.getString("action.save_image"));
+    savemenu.setActionCommand(
+            MessageManager.getString("action.save_image"));
     savemenu.setText(MessageManager.getString("action.save_as"));
 
     JMenuItem pdbFile = new JMenuItem();
@@ -170,8 +171,8 @@ public abstract class GStructureViewer extends JInternalFrame implements
       }
     });
     alignStructs = new JMenuItem();
-    alignStructs.setText(MessageManager
-            .getString("label.superpose_structures"));
+    alignStructs.setText(
+            MessageManager.getString("label.superpose_structures"));
     alignStructs.addActionListener(new ActionListener()
     {
       @Override
index fa5e905..c506fc6 100755 (executable)
@@ -127,8 +127,8 @@ public class GTreePanel extends JInternalFrame
       {
       }
     });
-    sortAssocViews.setText(MessageManager
-            .getString("label.sort_alignment_by_tree"));
+    sortAssocViews.setText(
+            MessageManager.getString("label.sort_alignment_by_tree"));
     sortAssocViews.addActionListener(new java.awt.event.ActionListener()
     {
       public void actionPerformed(ActionEvent e)
@@ -144,8 +144,8 @@ public class GTreePanel extends JInternalFrame
         font_actionPerformed(e);
       }
     });
-    bootstrapMenu.setText(MessageManager
-            .getString("label.show_bootstrap_values"));
+    bootstrapMenu.setText(
+            MessageManager.getString("label.show_bootstrap_values"));
     bootstrapMenu.addActionListener(new java.awt.event.ActionListener()
     {
       public void actionPerformed(ActionEvent e)
@@ -187,11 +187,10 @@ public class GTreePanel extends JInternalFrame
       }
     });
     saveAsMenu.setText(MessageManager.getString("action.save_as"));
-    placeholdersMenu
-            .setToolTipText(MessageManager
-                    .getString("label.marks_leaves_tree_not_associated_with_sequence"));
-    placeholdersMenu.setText(MessageManager
-            .getString("label.mark_unlinked_leaves"));
+    placeholdersMenu.setToolTipText(MessageManager.getString(
+            "label.marks_leaves_tree_not_associated_with_sequence"));
+    placeholdersMenu.setText(
+            MessageManager.getString("label.mark_unlinked_leaves"));
     placeholdersMenu.addActionListener(new ActionListener()
     {
       public void actionPerformed(ActionEvent e)
@@ -215,8 +214,8 @@ public class GTreePanel extends JInternalFrame
         originalSeqData_actionPerformed(e);
       }
     });
-    associateLeavesMenu.setText(MessageManager
-            .getString("label.associate_leaves_with"));
+    associateLeavesMenu.setText(
+            MessageManager.getString("label.associate_leaves_with"));
     this.getContentPane().add(scrollPane, BorderLayout.CENTER);
     jMenuBar1.add(fileMenu);
     jMenuBar1.add(viewMenu);
index 5384cc0..3d7d779 100755 (executable)
@@ -207,11 +207,10 @@ public class GUserDefinedColours extends JPanel
     label.setFont(new java.awt.Font("Verdana", Font.ITALIC, 10));
     label.setOpaque(false);
     label.setPreferredSize(new Dimension(260, 34));
-    label.setText(MessageManager
-            .formatMessage(
-                    "label.html_content",
-                    new String[] { MessageManager
-                            .getString("label.save_colour_scheme_with_unique_name_added_to_colour_menu") }));
+    label.setText(
+            MessageManager.formatMessage("label.html_content", new String[]
+            { MessageManager.getString(
+                    "label.save_colour_scheme_with_unique_name_added_to_colour_menu") }));
     caseSensitive.setText(MessageManager.getString("label.case_sensitive"));
     caseSensitive.addActionListener(new ActionListener()
     {
@@ -223,8 +222,8 @@ public class GUserDefinedColours extends JPanel
     });
     lcaseColour
             .setText(MessageManager.getString("label.lower_case_colour"));
-    lcaseColour.setToolTipText(MessageManager
-            .getString("label.lower_case_tip"));
+    lcaseColour.setToolTipText(
+            MessageManager.getString("label.lower_case_tip"));
 
     saveLoadPanel.add(savebutton);
     saveLoadPanel.add(loadbutton);
@@ -256,7 +255,8 @@ public class GUserDefinedColours extends JPanel
       // Java 7 default has 5 options rather than 3 for choosing colours; keep
       // the first only
       colorChooser
-              .setChooserPanels(new AbstractColorChooserPanel[] { choosers[0] });
+              .setChooserPanels(new AbstractColorChooserPanel[]
+              { choosers[0] });
     }
 
     selectedButtons = new ArrayList<JButton>();
index 9169e63..ba84411 100755 (executable)
@@ -119,8 +119,8 @@ public class GWebserviceInfo extends JPanel
     });
     buttonPanel.setLayout(gridBagLayout1);
     buttonPanel.setOpaque(false);
-    showResultsNewFrame.setText(MessageManager
-            .getString("label.new_window"));
+    showResultsNewFrame
+            .setText(MessageManager.getString("label.new_window"));
     mergeResults.setText(MessageManager.getString("action.merge_results"));
     this.setBackground(Color.white);
     this.add(jPanel1, BorderLayout.NORTH);
@@ -128,9 +128,10 @@ public class GWebserviceInfo extends JPanel
     jScrollPane1.getViewport().add(infoText, null);
     jPanel1.add(titlePanel, BorderLayout.NORTH);
     titlePanel.add(buttonPanel, BorderLayout.EAST);
-    buttonPanel.add(cancel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
-            GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(
-                    19, 6, 16, 4), 0, 0));
+    buttonPanel.add(cancel,
+            new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
+                    GridBagConstraints.CENTER, GridBagConstraints.NONE,
+                    new Insets(19, 6, 16, 4), 0, 0));
     this.add(statusPanel, java.awt.BorderLayout.SOUTH);
     statusPanel.add(statusBar, null);
   }
index 1eae7fc..c3fd4fa 100644 (file)
@@ -183,8 +183,8 @@ public class GWsPreferences extends JPanel
     });
     enableJws2Services
             .setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
-    enableJws2Services.setText(MessageManager
-            .getString("label.enable_jabaws_services"));
+    enableJws2Services.setText(
+            MessageManager.getString("label.enable_jabaws_services"));
     enableJws2Services.addActionListener(new ActionListener()
     {
       public void actionPerformed(ActionEvent e)
@@ -193,12 +193,10 @@ public class GWsPreferences extends JPanel
       }
     });
     displayWsWarning.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
-    displayWsWarning.setText(MessageManager
-            .getString("label.display_warnings"));
     displayWsWarning
-            .setToolTipText("<html>"
-                    + MessageManager
-                            .getString("label.option_want_informed_web_service_URL_cannot_be_accessed_jalview_when_starts_up"));
+            .setText(MessageManager.getString("label.display_warnings"));
+    displayWsWarning.setToolTipText("<html>" + MessageManager.getString(
+            "label.option_want_informed_web_service_URL_cannot_be_accessed_jalview_when_starts_up"));
     displayWsWarning.addActionListener(new ActionListener()
     {
       public void actionPerformed(ActionEvent e)
@@ -226,8 +224,8 @@ public class GWsPreferences extends JPanel
     });
 
     deleteWsUrl.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
-    deleteWsUrl.setText(MessageManager
-            .getString("label.delete_service_url"));
+    deleteWsUrl
+            .setText(MessageManager.getString("label.delete_service_url"));
     deleteWsUrl.addActionListener(new ActionListener()
     {
       public void actionPerformed(ActionEvent e)
@@ -237,8 +235,8 @@ public class GWsPreferences extends JPanel
     });
     moveWsUrlUp.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
     moveWsUrlUp.setText(MessageManager.getString("action.move_up"));
-    moveWsUrlUp.setToolTipText(MessageManager
-            .getString("label.move_url_up"));
+    moveWsUrlUp
+            .setToolTipText(MessageManager.getString("label.move_url_up"));
     moveWsUrlUp.addActionListener(new ActionListener()
     {
       public void actionPerformed(ActionEvent e)
@@ -248,8 +246,8 @@ public class GWsPreferences extends JPanel
     });
     moveWsUrlDown.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
     moveWsUrlDown.setText(MessageManager.getString("action.move_down"));
-    moveWsUrlDown.setToolTipText(MessageManager
-            .getString("label.move_url_down"));
+    moveWsUrlDown.setToolTipText(
+            MessageManager.getString("label.move_url_down"));
     moveWsUrlDown.addActionListener(new ActionListener()
     {
       public void actionPerformed(ActionEvent e)
@@ -258,8 +256,8 @@ public class GWsPreferences extends JPanel
       }
     });
     newSbrsUrl.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
-    newSbrsUrl.setText(MessageManager
-            .getString("label.add_sbrs_definition"));
+    newSbrsUrl
+            .setText(MessageManager.getString("label.add_sbrs_definition"));
     newSbrsUrl.addActionListener(new ActionListener()
     {
       public void actionPerformed(ActionEvent e)
@@ -268,8 +266,8 @@ public class GWsPreferences extends JPanel
       }
     });
     editSbrsUrl.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
-    editSbrsUrl.setText(MessageManager
-            .getString("label.edit_sbrs_definition"));
+    editSbrsUrl.setText(
+            MessageManager.getString("label.edit_sbrs_definition"));
     editSbrsUrl.addActionListener(new ActionListener()
     {
       public void actionPerformed(ActionEvent e)
@@ -279,8 +277,8 @@ public class GWsPreferences extends JPanel
     });
 
     deleteSbrsUrl.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
-    deleteSbrsUrl.setText(MessageManager
-            .getString("label.delete_sbrs_definition"));
+    deleteSbrsUrl.setText(
+            MessageManager.getString("label.delete_sbrs_definition"));
     deleteSbrsUrl.addActionListener(new ActionListener()
     {
       public void actionPerformed(ActionEvent e)
index c526302..62fb20a 100644 (file)
@@ -66,8 +66,8 @@ public class BioJSRepositoryPojo
             .get("latestReleaseVersion");
 
     JSONArray repositoriesJsonArray = (JSONArray) JsonObj.get("releases");
-    for (Iterator<JSONObject> repoIter = repositoriesJsonArray.iterator(); repoIter
-            .hasNext();)
+    for (Iterator<JSONObject> repoIter = repositoriesJsonArray
+            .iterator(); repoIter.hasNext();)
     {
       JSONObject repoObj = repoIter.next();
       BioJSReleasePojo repo = new BioJSReleasePojo();
index a9e57a9..673b09d 100644 (file)
@@ -43,7 +43,8 @@ public class AlignmentAnnotationPojo
 
   @Attributes(
     required = false,
-    enums = { "0", "1", "2" },
+    enums =
+    { "0", "1", "2" },
     description = "Determines the rendering for the annotation<br><ul><li>0 - No graph</li><li>1 - Bar Graph</li><li>2 - Line graph</li></ul>")
   private int graphType;
 
index 575b697..94d1bde 100644 (file)
@@ -65,10 +65,11 @@ public class AlignmentPojo
 
   @Attributes(
     required = false,
-    enums = { "None", "User Defined", "Clustal", "Zappo", "Taylor",
-        "Nucleotide", "Pyrimidine", "Purine", "Turn", "Helix", "Strand",
-        "Buried", "Hydro", "T-Coffee Scores", "RNA Interaction type",
-        "Blosum62", "RNA Helices", "% Identity" },
+    enums =
+    { "None", "User Defined", "Clustal", "Zappo", "Taylor", "Nucleotide",
+        "Pyrimidine", "Purine", "Turn", "Helix", "Strand", "Buried",
+        "Hydro", "T-Coffee Scores", "RNA Interaction type", "Blosum62",
+        "RNA Helices", "% Identity" },
     description = "The <a href=\"#colourScheme\">Colour Scheme</a> applied to the alignment")
   private String colourScheme;
 
index d49c1d5..f01dd52 100644 (file)
@@ -36,7 +36,8 @@ public class AnnotationPojo
 
   @Attributes(
     required = true,
-    enums = { "E", "H", "\u0000", ")", "(" },
+    enums =
+    { "E", "H", "\u0000", ")", "(" },
     description = "Determines what is rendered for the secondary </br>structure <ul><li>’E’ - indicates Beta Sheet/Strand <li>’H’ - indicates alpha helix </li><li> â€˜\\u0000’ - indicates blank</li></ul></br>For RNA Helix (only shown when working with</br> nucleotide sequences): <ul><li> â€˜(’ - indicates bases pair with columns upstream</br> (to right) </li><li> â€™(’ - indicate region pairs with bases to the left</li></ul>")
   private char secondaryStructure;
 
index 98fed15..56e9bcb 100644 (file)
@@ -34,8 +34,11 @@ public class SequencePojo
   @Attributes(required = true, description = "Sequence name")
   private String name;
 
-  @Attributes(required = false, description = "Sequence type", enums = {
-      "DNA", "RNA", "Protein" })
+  @Attributes(
+    required = false,
+    description = "Sequence type",
+    enums =
+    { "DNA", "RNA", "Protein" })
   private String type;
 
   @Attributes(
@@ -62,7 +65,8 @@ public class SequencePojo
   {
   }
 
-  public SequencePojo(int start, int end, String id, String name, String seq)
+  public SequencePojo(int start, int end, String id, String name,
+          String seq)
   {
     this.id = id;
     this.name = name;
index b39d3c9..8910c67 100755 (executable)
@@ -63,7 +63,7 @@ public class Matrix implements MatrixI
   {
 
   }
-  
+
   /**
    * Creates a new Matrix object containing a copy of the supplied array values.
    * For example
@@ -482,8 +482,8 @@ public class Matrix implements MatrixI
           if (iter == maxIter)
           {
             throw new Exception(MessageManager.formatMessage(
-                    "exception.matrix_too_many_iteration", new String[] {
-                        "tqli", Integer.valueOf(maxIter).toString() }));
+                    "exception.matrix_too_many_iteration", new String[]
+                    { "tqli", Integer.valueOf(maxIter).toString() }));
           }
           else
           {
@@ -529,7 +529,8 @@ public class Matrix implements MatrixI
             {
               f = getValue(k - 1, i);
               setValue(k - 1, i, (s * getValue(k - 1, i - 1)) + (c * f));
-              setValue(k - 1, i - 1, (c * getValue(k - 1, i - 1)) - (s * f));
+              setValue(k - 1, i - 1,
+                      (c * getValue(k - 1, i - 1)) - (s * f));
             }
           }
 
@@ -745,8 +746,8 @@ public class Matrix implements MatrixI
           if (iter == maxIter)
           {
             throw new Exception(MessageManager.formatMessage(
-                    "exception.matrix_too_many_iteration", new String[] {
-                        "tqli2", Integer.valueOf(maxIter).toString() }));
+                    "exception.matrix_too_many_iteration", new String[]
+                    { "tqli2", Integer.valueOf(maxIter).toString() }));
           }
           else
           {
@@ -864,7 +865,8 @@ public class Matrix implements MatrixI
    * 
    * @param ps
    *          DOCUMENT ME!
-   * @param format TODO
+   * @param format
+   *          TODO
    */
   @Override
   public void printE(PrintStream ps, String format)
@@ -886,9 +888,10 @@ public class Matrix implements MatrixI
   {
     return e;
   }
-  
+
   @Override
-  public int height() {
+  public int height()
+  {
     return rows;
   }
 
index 94b9333..5b93c76 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.math;
 
 import java.io.PrintStream;
@@ -42,7 +62,7 @@ public interface MatrixI
    * @return
    */
   double[] getRow(int i);
-  
+
   MatrixI copy();
 
   MatrixI transpose();
index 9d92645..5971227 100755 (executable)
@@ -71,14 +71,14 @@ public class RotatableMatrix
    */
   public void print()
   {
-    System.out.println(matrix[0][0] + " " + matrix[0][1] + " "
-            + matrix[0][2]);
+    System.out.println(
+            matrix[0][0] + " " + matrix[0][1] + " " + matrix[0][2]);
 
-    System.out.println(matrix[1][0] + " " + matrix[1][1] + " "
-            + matrix[1][2]);
+    System.out.println(
+            matrix[1][0] + " " + matrix[1][1] + " " + matrix[1][2]);
 
-    System.out.println(matrix[2][0] + " " + matrix[2][1] + " "
-            + matrix[2][2]);
+    System.out.println(
+            matrix[2][0] + " " + matrix[2][1] + " " + matrix[2][2]);
   }
 
   /**
index 72f0963..86592a0 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.math;
 
 import jalview.ext.android.SparseDoubleArray;
@@ -26,7 +46,8 @@ public class SparseMatrix extends Matrix
   public SparseMatrix(double[][] v)
   {
     rows = v.length;
-    if (rows > 0) {
+    if (rows > 0)
+    {
       cols = v[0].length;
     }
     sparseColumns = new SparseDoubleArray[cols];
index 518c179..8a80d41 100644 (file)
@@ -76,7 +76,7 @@ public class AnnotationRenderer
   ResidueShaderI profcolour = null;
 
   private ColumnSelection columnSelection;
-  
+
   private HiddenColumns hiddenColumns;
 
   private ProfilesI hconsensus;
@@ -162,7 +162,8 @@ public class AnnotationRenderer
           boolean validRes, boolean validEnd)
   {
     g.setColor(STEM_COLOUR);
-    int sCol = (lastSSX / charWidth) + startRes;
+    int sCol = (lastSSX / charWidth)
+            + hiddenColumns.adjustForHiddenColumns(startRes);
     int x1 = lastSSX;
     int x2 = (x * charWidth);
 
@@ -186,8 +187,9 @@ public class AnnotationRenderer
          * display a backward arrow
          */
         g.fillPolygon(new int[] { lastSSX + 5, lastSSX + 5, lastSSX },
-                new int[] { y + iconOffset, y + 14 + iconOffset,
-                    y + 8 + iconOffset }, 3);
+                new int[]
+                { y + iconOffset, y + 14 + iconOffset, y + 8 + iconOffset },
+                3);
         x1 += 5;
       }
       if (diffdownstream)
@@ -204,8 +206,10 @@ public class AnnotationRenderer
          * if annotation ending with an opeing base pair half of the stem, 
          * display a forward arrow
          */
-        g.fillPolygon(new int[] { x2 - 5, x2 - 5, x2 }, new int[] {
-            y + iconOffset, y + 14 + iconOffset, y + 8 + iconOffset }, 3);
+        g.fillPolygon(new int[] { x2 - 5, x2 - 5, x2 },
+                new int[]
+                { y + iconOffset, y + 14 + iconOffset, y + 8 + iconOffset },
+                3);
         x2 -= 5;
       }
       if (diffupstream)
@@ -225,7 +229,8 @@ public class AnnotationRenderer
     // System.out.println(nonCanColor);
 
     g.setColor(nonCanColor);
-    int sCol = (lastSSX / charWidth) + startRes;
+    int sCol = (lastSSX / charWidth)
+            + hiddenColumns.adjustForHiddenColumns(startRes);
     int x1 = lastSSX;
     int x2 = (x * charWidth);
 
@@ -237,7 +242,8 @@ public class AnnotationRenderer
     boolean diffdownstream = !validRes || !validEnd
             || row_annotations[column] == null
             || !dc.equals(row_annotations[column].displayCharacter);
-    // System.out.println("Column "+column+" diff up: "+diffupstream+" down:"+diffdownstream);
+    // System.out.println("Column "+column+" diff up: "+diffupstream+"
+    // down:"+diffdownstream);
     // If a closing base pair half of the stem, display a backward arrow
     if (column > 0 && Rna.isClosingParenthesis(dc))
     {
@@ -247,8 +253,9 @@ public class AnnotationRenderer
       // dc.equals(row_annotations[column-2].displayCharacter))
       {
         g.fillPolygon(new int[] { lastSSX + 5, lastSSX + 5, lastSSX },
-                new int[] { y + iconOffset, y + 14 + iconOffset,
-                    y + 8 + iconOffset }, 3);
+                new int[]
+                { y + iconOffset, y + 14 + iconOffset, y + 8 + iconOffset },
+                3);
         x1 += 5;
       }
       if (diffdownstream)
@@ -262,8 +269,10 @@ public class AnnotationRenderer
       // display a forward arrow
       if (diffdownstream)
       {
-        g.fillPolygon(new int[] { x2 - 5, x2 - 5, x2 }, new int[] {
-            y + iconOffset, y + 14 + iconOffset, y + 8 + iconOffset }, 3);
+        g.fillPolygon(new int[] { x2 - 5, x2 - 5, x2 },
+                new int[]
+                { y + iconOffset, y + 14 + iconOffset, y + 8 + iconOffset },
+                3);
         x2 -= 5;
       }
       if (diffupstream)
@@ -325,7 +334,8 @@ public class AnnotationRenderer
        * the alignment has no colourscheme set
        * (would like to use user preference but n/a for applet)
        */
-      ColourSchemeI col = av.getAlignment().isNucleotide() ? new NucleotideColourScheme()
+      ColourSchemeI col = av.getAlignment().isNucleotide()
+              ? new NucleotideColourScheme()
               : new ZappoColourScheme();
       profcolour = new ResidueShader(col);
     }
@@ -352,9 +362,8 @@ public class AnnotationRenderer
     // properties/rendering attributes as a global 'alignment group' which holds
     // all vis settings for the alignment as a whole rather than a subset
     //
-    if (aa.autoCalculated
-            && (aa.label.startsWith("Consensus") || aa.label
-                    .startsWith("cDNA Consensus")))
+    if (aa.autoCalculated && (aa.label.startsWith("Consensus")
+            || aa.label.startsWith("cDNA Consensus")))
     {
       boolean forComplement = aa.label.startsWith("cDNA Consensus");
       if (aa.groupRef != null && aa.groupRef.consensusData != null
@@ -371,13 +380,12 @@ public class AnnotationRenderer
       {
         if (forComplement)
         {
-          return AAFrequency.extractCdnaProfile(
-                  complementConsensus[column], av_ignoreGapsConsensus);
+          return AAFrequency.extractCdnaProfile(complementConsensus[column],
+                  av_ignoreGapsConsensus);
         }
         else
         {
-          return AAFrequency.extractProfile(
-hconsensus.get(column),
+          return AAFrequency.extractProfile(hconsensus.get(column),
                   av_ignoreGapsConsensus);
         }
       }
@@ -463,7 +471,8 @@ hconsensus.get(column),
             .getAlignmentStrucConsensusAnnotation();
     final AlignmentAnnotation complementConsensusAnnot = av
             .getComplementConsensusAnnotation();
-    boolean renderHistogram = true, renderProfile = true, normaliseProfile = false, isRNA = rna;
+    boolean renderHistogram = true, renderProfile = true,
+            normaliseProfile = false, isRNA = rna;
 
     BitSet graphGroupDrawn = new BitSet();
     int charOffset = 0; // offset for a label
@@ -514,8 +523,8 @@ hconsensus.get(column),
       lastSS = ' ';
       lastSSX = 0;
 
-      if (!useClip
-              || ((y - charHeight) < visHeight && (y + row.height + charHeight * 2) >= sOffset))
+      if (!useClip || ((y - charHeight) < visHeight
+              && (y + row.height + charHeight * 2) >= sOffset))
       {// if_in_visible_region
         if (!clipst)
         {
@@ -555,8 +564,8 @@ hconsensus.get(column),
         {
           y += charHeight;
           usedFaded = true;
-          g.drawImage(fadedImage, 0, y - row.height, imgWidth, y, 0, y
-                  - row.height, imgWidth, y, annotationPanel);
+          g.drawImage(fadedImage, 0, y - row.height, imgWidth, y, 0,
+                  y - row.height, imgWidth, y, annotationPanel);
           g.setColor(Color.black);
           // g.drawString("Calculating "+aa[i].label+"....",20, y-row.height/2);
 
@@ -614,7 +623,8 @@ hconsensus.get(column),
           {
             validRes = true;
           }
-          final String displayChar = validRes ? row_annotations[column].displayCharacter
+          final String displayChar = validRes
+                  ? row_annotations[column].displayCharacter
                   : null;
           if (x > -1)
           {
@@ -684,17 +694,17 @@ hconsensus.get(column),
 
               if (column == 0 || row.graph > 0)
               {
-                g.drawString(displayChar, (x * charWidth) + charOffset, y
-                        + iconOffset);
+                g.drawString(displayChar, (x * charWidth) + charOffset,
+                        y + iconOffset);
               }
-              else if (row_annotations[column - 1] == null
-                      || (labelAllCols
-                              || !displayChar
-                                      .equals(row_annotations[column - 1].displayCharacter) || (displayChar
-                              .length() < 2 && row_annotations[column].secondaryStructure == ' ')))
+              else if (row_annotations[column - 1] == null || (labelAllCols
+                      || !displayChar.equals(
+                              row_annotations[column - 1].displayCharacter)
+                      || (displayChar.length() < 2
+                              && row_annotations[column].secondaryStructure == ' ')))
               {
-                g.drawString(displayChar, x * charWidth + charOffset, y
-                        + iconOffset);
+                g.drawString(displayChar, x * charWidth + charOffset,
+                        y + iconOffset);
               }
               g.setFont(ofont);
             }
@@ -758,7 +768,8 @@ hconsensus.get(column),
               {
 
                 int nb_annot = x - temp;
-                // System.out.println("\t type :"+lastSS+"\t x :"+x+"\t nbre annot :"+nb_annot);
+                // System.out.println("\t type :"+lastSS+"\t x :"+x+"\t nbre
+                // annot :"+nb_annot);
                 switch (lastSS)
                 {
                 case '(': // Stem case for RNA secondary structure
@@ -852,8 +863,8 @@ hconsensus.get(column),
                   break;
                 default:
                   g.setColor(Color.gray);
-                  g.fillRect(lastSSX, y + 6 + iconOffset, (x * charWidth)
-                          - lastSSX, 2);
+                  g.fillRect(lastSSX, y + 6 + iconOffset,
+                          (x * charWidth) - lastSSX, 2);
                   temp = x;
                   break;
                 }
@@ -1052,7 +1063,7 @@ hconsensus.get(column),
         {
           clipend = true;
         }
-      }// end if_in_visible_region
+      } // end if_in_visible_region
       if (row.graph > 0 && row.hasText)
       {
         y += charHeight;
@@ -1069,13 +1080,13 @@ hconsensus.get(column),
       {
         if (clipst)
         {
-          System.err.println("Start clip at : " + yfrom + " (index " + f_i
-                  + ")");
+          System.err.println(
+                  "Start clip at : " + yfrom + " (index " + f_i + ")");
         }
         if (clipend)
         {
-          System.err.println("End clip at : " + yto + " (index " + f_to
-                  + ")");
+          System.err.println(
+                  "End clip at : " + yto + " (index " + f_to + ")");
         }
       }
       ;
@@ -1098,8 +1109,8 @@ hconsensus.get(column),
   private Color sdNOTCANONICAL_COLOUR;
 
   void drawGlyphLine(Graphics g, Annotation[] row, int lastSSX, int x,
-          int y, int iconOffset, int startRes, int column,
-          boolean validRes, boolean validEnd)
+          int y, int iconOffset, int startRes, int column, boolean validRes,
+          boolean validEnd)
   {
     g.setColor(GLYPHLINE_COLOR);
     g.fillRect(lastSSX, y + 6 + iconOffset, (x * charWidth) - lastSSX, 2);
@@ -1107,35 +1118,39 @@ hconsensus.get(column),
 
   void drawSheetAnnot(Graphics g, Annotation[] row,
 
-  int lastSSX, int x, int y, int iconOffset, int startRes, int column,
-          boolean validRes, boolean validEnd)
+          int lastSSX, int x, int y, int iconOffset, int startRes,
+          int column, boolean validRes, boolean validEnd)
   {
     g.setColor(SHEET_COLOUR);
 
     if (!validEnd || !validRes || row == null || row[column] == null
             || row[column].secondaryStructure != 'E')
     {
-      g.fillRect(lastSSX, y + 4 + iconOffset,
-              (x * charWidth) - lastSSX - 4, 7);
-      g.fillPolygon(new int[] { (x * charWidth) - 4, (x * charWidth) - 4,
-          (x * charWidth) }, new int[] { y + iconOffset,
-          y + 14 + iconOffset, y + 7 + iconOffset }, 3);
+      g.fillRect(lastSSX, y + 4 + iconOffset, (x * charWidth) - lastSSX - 4,
+              7);
+      g.fillPolygon(
+              new int[]
+              { (x * charWidth) - 4, (x * charWidth) - 4, (x * charWidth) },
+              new int[]
+              { y + iconOffset, y + 14 + iconOffset, y + 7 + iconOffset },
+              3);
     }
     else
     {
-      g.fillRect(lastSSX, y + 4 + iconOffset,
-              (x + 1) * charWidth - lastSSX, 7);
+      g.fillRect(lastSSX, y + 4 + iconOffset, (x + 1) * charWidth - lastSSX,
+              7);
     }
 
   }
 
   void drawHelixAnnot(Graphics g, Annotation[] row, int lastSSX, int x,
-          int y, int iconOffset, int startRes, int column,
-          boolean validRes, boolean validEnd)
+          int y, int iconOffset, int startRes, int column, boolean validRes,
+          boolean validEnd)
   {
     g.setColor(HELIX_COLOUR);
 
-    int sCol = (lastSSX / charWidth) + startRes;
+    int sCol = (lastSSX / charWidth)
+            + hiddenColumns.adjustForHiddenColumns(startRes);
     int x1 = lastSSX;
     int x2 = (x * charWidth);
 
@@ -1163,8 +1178,8 @@ hconsensus.get(column),
       else
       {
         // g.setColor(Color.magenta);
-        g.fillRoundRect(lastSSX + ofs, y + 4 + iconOffset, x2 - x1 - ofs
-                + 1, 8, 0, 0);
+        g.fillRoundRect(lastSSX + ofs, y + 4 + iconOffset,
+                x2 - x1 - ofs + 1, 8, 0, 0);
 
       }
 
@@ -1190,8 +1205,8 @@ hconsensus.get(column),
   }
 
   void drawLineGraph(Graphics g, AlignmentAnnotation _aa,
-          Annotation[] aa_annotations, int sRes, int eRes, int y,
-          float min, float max, int graphHeight)
+          Annotation[] aa_annotations, int sRes, int eRes, int y, float min,
+          float max, int graphHeight)
   {
     if (sRes > aa_annotations.length)
     {
@@ -1259,13 +1274,13 @@ hconsensus.get(column),
         g.setColor(aa_annotations[column].colour);
       }
 
-      y1 = y
-              - (int) (((aa_annotations[column - 1].value - min) / range) * graphHeight);
-      y2 = y
-              - (int) (((aa_annotations[column].value - min) / range) * graphHeight);
+      y1 = y - (int) (((aa_annotations[column - 1].value - min) / range)
+              * graphHeight);
+      y2 = y - (int) (((aa_annotations[column].value - min) / range)
+              * graphHeight);
 
-      g.drawLine(x * charWidth - charWidth / 2, y1, x * charWidth
-              + charWidth / 2, y2);
+      g.drawLine(x * charWidth - charWidth / 2, y1,
+              x * charWidth + charWidth / 2, y2);
       x++;
     }
 
@@ -1274,7 +1289,8 @@ hconsensus.get(column),
       g.setColor(_aa.threshold.colour);
       Graphics2D g2 = (Graphics2D) g;
       g2.setStroke(new BasicStroke(1, BasicStroke.CAP_SQUARE,
-              BasicStroke.JOIN_ROUND, 3f, new float[] { 5f, 3f }, 0f));
+              BasicStroke.JOIN_ROUND, 3f, new float[]
+              { 5f, 3f }, 0f));
 
       y2 = (int) (y - ((_aa.threshold.value - min) / range) * graphHeight);
       g.drawLine(0, y2, (eRes - sRes) * charWidth, y2);
@@ -1336,8 +1352,8 @@ hconsensus.get(column),
         g.setColor(aa_annotations[column].colour);
       }
 
-      y1 = y
-              - (int) (((aa_annotations[column].value - min) / (range)) * _aa.graphHeight);
+      y1 = y - (int) (((aa_annotations[column].value - min) / (range))
+              * _aa.graphHeight);
 
       if (renderHistogram)
       {
@@ -1411,10 +1427,10 @@ hconsensus.get(column),
             ht += scl;
             // next profl[] position is profile % for the character(s)
             scl = htn * scale * profl[c++];
-            lm = ofont.getLineMetrics(dc, 0, 1, g.getFontMetrics()
-                    .getFontRenderContext());
-            Font font = ofont.deriveFont(AffineTransform.getScaleInstance(
-                    wdth, scl / lm.getAscent()));
+            lm = ofont.getLineMetrics(dc, 0, 1,
+                    g.getFontMetrics().getFontRenderContext());
+            Font font = ofont.deriveFont(AffineTransform
+                    .getScaleInstance(wdth, scl / lm.getAscent()));
             g.setFont(font);
             lm = g.getFontMetrics().getLineMetrics(dc, 0, 1, g);
 
@@ -1442,8 +1458,8 @@ hconsensus.get(column),
             }
             g.setColor(colour == Color.white ? Color.lightGray : colour);
 
-            hght = (ht + (scl - lm.getDescent() - lm.getBaselineOffsets()[lm
-                    .getBaselineIndex()]));
+            hght = (ht + (scl - lm.getDescent()
+                    - lm.getBaselineOffsets()[lm.getBaselineIndex()]));
 
             g.drawChars(dc, 0, dc.length, x * charWidth, (int) hght);
             valuesProcessed++;
@@ -1458,10 +1474,11 @@ hconsensus.get(column),
       g.setColor(_aa.threshold.colour);
       Graphics2D g2 = (Graphics2D) g;
       g2.setStroke(new BasicStroke(1, BasicStroke.CAP_SQUARE,
-              BasicStroke.JOIN_ROUND, 3f, new float[] { 5f, 3f }, 0f));
+              BasicStroke.JOIN_ROUND, 3f, new float[]
+              { 5f, 3f }, 0f));
 
-      y2 = (int) (y - ((_aa.threshold.value - min) / range)
-              * _aa.graphHeight);
+      y2 = (int) (y
+              - ((_aa.threshold.value - min) / range) * _aa.graphHeight);
       g.drawLine(0, y2, (eRes - sRes) * charWidth, y2);
       g2.setStroke(new BasicStroke());
     }
index 46490cd..1c50aab 100644 (file)
@@ -22,22 +22,38 @@ package jalview.renderer;
 
 import jalview.api.AlignmentColsCollectionI;
 import jalview.api.AlignmentRowsCollectionI;
+import jalview.api.RendererListenerI;
 import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Annotation;
+import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.renderer.seqfeatures.FeatureColourFinder;
 import jalview.renderer.seqfeatures.FeatureRenderer;
 import jalview.viewmodel.OverviewDimensions;
 
+import java.awt.AlphaComposite;
 import java.awt.Color;
 import java.awt.Graphics;
+import java.awt.Graphics2D;
 import java.awt.image.BufferedImage;
+import java.beans.PropertyChangeSupport;
 
 public class OverviewRenderer
 {
-  private FeatureColourFinder finder;
+  // transparency of hidden cols/seqs overlay
+  private final float TRANSPARENCY = 0.5f;
+
+  private final Color HIDDEN_COLOUR = Color.DARK_GRAY.darker();
+
+  public static final String UPDATE = "OverviewUpdate";
+
+  private static final int MAX_PROGRESS = 100;
 
-  private jalview.api.SequenceRenderer sr;
+  private PropertyChangeSupport changeSupport = new PropertyChangeSupport(
+          this);
+
+  private FeatureColourFinder finder;
 
   // image to render on
   private BufferedImage miniMe;
@@ -48,17 +64,32 @@ public class OverviewRenderer
   // raw number of pixels to allocate to each row
   private float pixelsPerSeq;
 
+  // height in pixels of graph
+  private int graphHeight;
+
   // flag to indicate whether to halt drawing
   private volatile boolean redraw = false;
 
-  public OverviewRenderer(jalview.api.SequenceRenderer seqRenderer,
-          FeatureRenderer fr, OverviewDimensions od)
+  // reference to alignment, needed to get sequence groups
+  private AlignmentI al;
+
+  private ResidueShaderI shader;
+
+  private OverviewResColourFinder resColFinder;
+
+  public OverviewRenderer(FeatureRenderer fr, OverviewDimensions od,
+          AlignmentI alignment,
+          ResidueShaderI resshader, OverviewResColourFinder colFinder)
   {
-    sr = seqRenderer;
     finder = new FeatureColourFinder(fr);
+    resColFinder = colFinder;
+
+    al = alignment;
+    shader = resshader;
 
     pixelsPerCol = od.getPixelsPerCol();
     pixelsPerSeq = od.getPixelsPerSeq();
+    graphHeight = od.getGraphHeight();
     miniMe = new BufferedImage(od.getWidth(), od.getHeight(),
             BufferedImage.TYPE_INT_RGB);
   }
@@ -78,6 +109,12 @@ public class OverviewRenderer
     int rgbcolor = Color.white.getRGB();
     int seqIndex = 0;
     int pixelRow = 0;
+    int alignmentHeight = miniMe.getHeight() - graphHeight;
+    int totalPixels = miniMe.getWidth() * alignmentHeight;
+
+    int lastRowUpdate = 0;
+    int lastUpdate = 0;
+    changeSupport.firePropertyChange(UPDATE, -1, 0);
 
     for (int alignmentRow : rows)
     {
@@ -85,15 +122,17 @@ public class OverviewRenderer
       {
         break;
       }
-
+    
       // get details of this alignment row
-      boolean hidden = rows.isHidden(alignmentRow);
       SequenceI seq = rows.getSequence(alignmentRow);
 
+      // rate limiting step when rendering overview for lots of groups
+      SequenceGroup[] allGroups = al.findAllGroups(seq);
+
       // calculate where this row extends to in pixels
       int endRow = Math.min(Math.round((seqIndex + 1) * pixelsPerSeq) - 1,
               miniMe.getHeight() - 1);
-
+    
       int colIndex = 0;
       int pixelCol = 0;
       for (int alignmentCol : cols)
@@ -102,22 +141,19 @@ public class OverviewRenderer
         {
           break;
         }
-
+    
         // calculate where this column extends to in pixels
-        int endCol = Math.min(
-                Math.round((colIndex + 1) * pixelsPerCol) - 1,
+        int endCol = Math.min(Math.round((colIndex + 1) * pixelsPerCol) - 1,
                 miniMe.getWidth() - 1);
-
+    
         // don't do expensive colour determination if we're not going to use it
         // NB this is important to avoid performance issues in the overview
         // panel
         if (pixelCol <= endCol)
         {
-          // determine the colour based on the sequence and column position
-          rgbcolor = getColumnColourFromSequence(seq,
-                  hidden || cols.isHidden(alignmentCol), alignmentCol,
-                  finder);
-
+          rgbcolor = getColumnColourFromSequence(allGroups, seq,
+                  alignmentCol, finder);
+    
           // fill in the appropriate number of pixels
           for (int row = pixelRow; row <= endRow; ++row)
           {
@@ -127,35 +163,193 @@ public class OverviewRenderer
             }
           }
 
+          // store last update value
+          lastUpdate = sendProgressUpdate(
+                  (pixelCol + 1) * (endRow - pixelRow), totalPixels,
+                  lastRowUpdate, lastUpdate);
+
           pixelCol = endCol + 1;
         }
         colIndex++;
       }
-      pixelRow = endRow + 1;
+
+      if (pixelRow != endRow + 1)
+      {
+        // store row offset and last update value
+        lastRowUpdate = sendProgressUpdate(endRow + 1, alignmentHeight, 0,
+                lastUpdate);
+        lastUpdate = lastRowUpdate;
+        pixelRow = endRow + 1;
+      }
       seqIndex++;
     }
+
+    overlayHiddenRegions(rows, cols);
+    // final update to progress bar if present
+    if (redraw)
+    {
+      sendProgressUpdate(pixelRow - 1, alignmentHeight, 0, 0);
+    }
+    else
+    {
+      sendProgressUpdate(alignmentHeight, miniMe.getHeight(), 0, 0);
+    }
     return miniMe;
   }
 
   /*
+   * Calculate progress update value and fire event
+   * @param rowOffset number of rows to offset calculation by
+   * @return new rowOffset - return value only to be used when at end of a row
+   */
+  private int sendProgressUpdate(int position, int maximum, int rowOffset,
+          int lastUpdate)
+  {
+    int newUpdate = rowOffset
+            + Math.round(MAX_PROGRESS * ((float) position / maximum));
+    if (newUpdate > lastUpdate)
+    {
+      changeSupport.firePropertyChange(UPDATE, rowOffset, newUpdate);
+      return newUpdate;
+    }
+    return newUpdate;
+  }
+
+  /*
    * Find the colour of a sequence at a specified column position
+   * 
+   * @param seq
+   *          sequence to get colour for
+   * @param lastcol
+   *          column position to get colour for
+   * @param fcfinder
+   *          FeatureColourFinder to use
+   * @return colour of sequence at this position, as RGB
    */
-  private int getColumnColourFromSequence(jalview.datamodel.SequenceI seq,
-          boolean isHidden, int lastcol, FeatureColourFinder fcfinder)
+  private int getColumnColourFromSequence(SequenceGroup[] allGroups,
+          jalview.datamodel.SequenceI seq,
+          int lastcol, FeatureColourFinder fcfinder)
   {
     Color color = Color.white;
 
     if ((seq != null) && (seq.getLength() > lastcol))
     {
-      color = sr.getResidueColour(seq, lastcol, fcfinder);
+      color = resColFinder.getResidueColour(true, shader, allGroups, seq,
+              lastcol,
+              fcfinder);
     }
 
-    if (isHidden)
+    return color.getRGB();
+  }
+
+  /**
+   * Overlay the hidden regions on the overview image
+   * 
+   * @param rows
+   *          collection of rows the overview is built over
+   * @param cols
+   *          collection of columns the overview is built over
+   */
+  private void overlayHiddenRegions(AlignmentRowsCollectionI rows,
+          AlignmentColsCollectionI cols)
+  {
+    if (cols.hasHidden() || rows.hasHidden())
     {
-      color = color.darker().darker();
+      BufferedImage mask = buildHiddenImage(rows, cols, miniMe.getWidth(),
+              miniMe.getHeight());
+
+      Graphics2D g = (Graphics2D) miniMe.getGraphics();
+      g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
+              TRANSPARENCY));
+      g.drawImage(mask, 0, 0, miniMe.getWidth(), miniMe.getHeight(), null);
     }
+  }
 
-    return color.getRGB();
+  /**
+   * Build a masking image of hidden columns and rows to be applied on top of
+   * the main overview image.
+   * 
+   * @param rows
+   *          collection of rows the overview is built over
+   * @param cols
+   *          collection of columns the overview is built over
+   * @param width
+   *          width of overview in pixels
+   * @param height
+   *          height of overview in pixels
+   * @return BufferedImage containing mask of hidden regions
+   */
+  private BufferedImage buildHiddenImage(AlignmentRowsCollectionI rows,
+          AlignmentColsCollectionI cols, int width, int height)
+  {
+    // new masking image
+    BufferedImage hiddenImage = new BufferedImage(width, height,
+            BufferedImage.TYPE_INT_ARGB);
+
+    int colIndex = 0;
+    int pixelCol = 0;
+
+    Color hidden = resColFinder.getHiddenColour();
+
+    Graphics2D g2d = (Graphics2D) hiddenImage.getGraphics();
+
+    // set background to transparent
+    g2d.setComposite(AlphaComposite.Clear);
+    g2d.fillRect(0, 0, width, height);
+
+    // set next colour to opaque
+    g2d.setComposite(AlphaComposite.Src);
+
+    for (int alignmentCol : cols)
+    {
+      if (redraw)
+      {
+        break;
+      }
+
+      // calculate where this column extends to in pixels
+      int endCol = Math.min(Math.round((colIndex + 1) * pixelsPerCol) - 1,
+              hiddenImage.getWidth() - 1);
+
+      if (pixelCol <= endCol)
+      {
+        // determine the colour based on the sequence and column position
+        if (cols.isHidden(alignmentCol))
+        {
+          g2d.setColor(hidden);
+          g2d.fillRect(pixelCol, 0, endCol - pixelCol + 1, height);
+        }
+
+        pixelCol = endCol + 1;
+      }
+      colIndex++;
+
+    }
+
+    int seqIndex = 0;
+    int pixelRow = 0;
+    for (int alignmentRow : rows)
+    {
+      if (redraw)
+      {
+        break;
+      }
+
+      // calculate where this row extends to in pixels
+      int endRow = Math.min(Math.round((seqIndex + 1) * pixelsPerSeq) - 1,
+              miniMe.getHeight() - 1);
+
+      // get details of this alignment row
+      if (rows.isHidden(alignmentRow))
+      {
+        g2d.setColor(hidden);
+        g2d.fillRect(0, pixelRow, width, endRow - pixelRow + 1);
+      }
+      pixelRow = endRow + 1;
+      seqIndex++;
+    }
+
+    return hiddenImage;
   }
 
   /**
@@ -186,16 +380,17 @@ public class OverviewRenderer
     {
       if (redraw)
       {
+        changeSupport.firePropertyChange(UPDATE, MAX_PROGRESS - 1, 0);
         break;
       }
+
       if (alignmentCol >= annotations.length)
       {
         break; // no more annotations to draw here
       }
       else
       {
-        int endCol = Math.min(
-                Math.round((colIndex + 1) * pixelsPerCol) - 1,
+        int endCol = Math.min(Math.round((colIndex + 1) * pixelsPerCol) - 1,
                 miniMe.getWidth() - 1);
 
         if (annotations[alignmentCol] != null)
@@ -209,7 +404,8 @@ public class OverviewRenderer
             g.setColor(annotations[alignmentCol].colour);
           }
 
-          height = (int) ((annotations[alignmentCol].value / anno.graphMax) * y);
+          height = (int) ((annotations[alignmentCol].value / anno.graphMax)
+                  * y);
           if (height > y)
           {
             height = y;
@@ -217,12 +413,22 @@ public class OverviewRenderer
 
           g.fillRect(pixelCol, y - height, endCol - pixelCol + 1, height);
         }
+
         pixelCol = endCol + 1;
         colIndex++;
       }
     }
+    changeSupport.firePropertyChange(UPDATE, MAX_PROGRESS - 1,
+            MAX_PROGRESS);
   }
 
+  /**
+   * Allows redraw flag to be set
+   * 
+   * @param b
+   *          value to set redraw to: true = redraw is occurring, false = no
+   *          redraw
+   */
   public void setRedraw(boolean b)
   {
     synchronized (this)
@@ -230,4 +436,14 @@ public class OverviewRenderer
       redraw = b;
     }
   }
+
+  public void addPropertyChangeListener(RendererListenerI listener)
+  {
+    changeSupport.addPropertyChangeListener(listener);
+  }
+
+  public void removePropertyChangeListener(RendererListenerI listener)
+  {
+    changeSupport.removePropertyChangeListener(listener);
+  }
 }
diff --git a/src/jalview/renderer/OverviewResColourFinder.java b/src/jalview/renderer/OverviewResColourFinder.java
new file mode 100644 (file)
index 0000000..a497d92
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.renderer;
+
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.util.Comparison;
+
+import java.awt.Color;
+
+public class OverviewResColourFinder extends ResidueColourFinder
+{
+  final Color GAP_COLOUR; // default colour to use at gaps
+
+  final Color RESIDUE_COLOUR; // default colour to use at residues
+
+  final Color HIDDEN_COLOUR; // colour for hidden regions
+
+  boolean useLegacy = false;
+
+  public static final Color OVERVIEW_DEFAULT_GAP = Color.lightGray;
+
+  public static final Color OVERVIEW_DEFAULT_LEGACY_GAP = Color.white;
+
+  public static final Color OVERVIEW_DEFAULT_HIDDEN = Color.darkGray
+          .darker();
+
+  /**
+   * Constructor without colour settings (used by applet)
+   */
+  public OverviewResColourFinder()
+  {
+    this(false, OVERVIEW_DEFAULT_GAP, OVERVIEW_DEFAULT_HIDDEN);
+  }
+
+  /**
+   * Constructor with colour settings
+   * 
+   * @param useLegacyColouring
+   *          whether to use legacy gap colouring (white gaps, grey residues)
+   * @param gapCol
+   *          gap colour if not legacy
+   * @param hiddenCol
+   *          hidden region colour (transparency applied by rendering code)
+   */
+  public OverviewResColourFinder(boolean useLegacyColouring, Color gapCol,
+          Color hiddenCol)
+  {
+    if (useLegacyColouring)
+    {
+      GAP_COLOUR = Color.white;
+      RESIDUE_COLOUR = Color.lightGray;
+      HIDDEN_COLOUR = hiddenCol;
+    }
+    else
+    {
+      GAP_COLOUR = gapCol;
+      RESIDUE_COLOUR = Color.white;
+      HIDDEN_COLOUR = hiddenCol;
+    }
+  }
+
+  @Override
+  public Color getBoxColour(ResidueShaderI shader, SequenceI seq, int i)
+  {
+    Color resBoxColour = RESIDUE_COLOUR;
+    char currentChar = seq.getCharAt(i);
+
+    // In the overview window, gaps are coloured grey, unless the colour scheme
+    // specifies a gap colour, in which case gaps honour the colour scheme
+    // settings
+    if (shader.getColourScheme() != null)
+    {
+      if (Comparison.isGap(currentChar)
+              && (!shader.getColourScheme().hasGapColour()))
+      {
+        resBoxColour = GAP_COLOUR;
+      }
+      else
+      {
+        resBoxColour = shader.findColour(currentChar, i, seq);
+      }
+    }
+    else if (Comparison.isGap(currentChar))
+    {
+      resBoxColour = GAP_COLOUR;
+    }
+
+    return resBoxColour;
+  }
+
+  /**
+   * {@inheritDoc} In the overview, the showBoxes setting is ignored, as the
+   * overview displays the colours regardless.
+   */
+  @Override
+  protected Color getResidueBoxColour(boolean showBoxes,
+          ResidueShaderI shader,
+          SequenceGroup[] allGroups, SequenceI seq, int i)
+  {
+    ResidueShaderI currentShader;
+    SequenceGroup currentSequenceGroup = getCurrentSequenceGroup(allGroups,
+            i);
+    if (currentSequenceGroup != null)
+    {
+      currentShader = currentSequenceGroup.getGroupColourScheme();
+    }
+    else
+    {
+      currentShader = shader;
+    }
+
+    return getBoxColour(currentShader, seq, i);
+  }
+
+  /**
+   * Supply hidden colour
+   * 
+   * @return colour of hidden regions
+   */
+  protected Color getHiddenColour()
+  {
+    return HIDDEN_COLOUR;
+  }
+}
diff --git a/src/jalview/renderer/ResidueColourFinder.java b/src/jalview/renderer/ResidueColourFinder.java
new file mode 100644 (file)
index 0000000..2da7233
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.renderer;
+
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
+
+import java.awt.Color;
+
+public class ResidueColourFinder
+{
+  public ResidueColourFinder()
+  {
+  }
+
+  /**
+   * Get the colour of a residue in a sequence
+   * 
+   * @param showBoxes
+   *          true if the viewport's Show Boxes setting is true
+   * @param shader
+   *          the viewport's colour scheme
+   * @param allGroups
+   *          all the groups which seq participates in
+   * @param seq
+   *          the sequence containing the residue
+   * @param position
+   *          the position of the residue in the sequence
+   * @param finder
+   *          FeatureColourFinder for the viewport
+   * @return colour of the residue
+   */
+  public Color getResidueColour(boolean showBoxes, ResidueShaderI shader,
+          SequenceGroup[] allGroups,
+          final SequenceI seq, int position, FeatureColourFinder finder)
+  {
+    Color col = getResidueBoxColour(showBoxes, shader, allGroups, seq,
+            position);
+
+    // if there's a FeatureColourFinder we might override the residue colour
+    // here with feature colouring
+    if (finder != null)
+    {
+      col = finder.findFeatureColour(col, seq, position);
+    }
+    return col;
+  }
+
+  /**
+   * Get the residue colour without accounting for any features
+   * 
+   * @param showBoxes
+   *          true if the viewport's Show Boxes setting is true
+   * @param shader
+   *          the viewport's colour scheme
+   * @param allGroups
+   *          all the groups which seq participates in
+   * @param seq
+   *          the sequence containing the residue
+   * @param i
+   *          the position of the residue in the sequence
+   * @return
+   */
+  protected Color getResidueBoxColour(boolean showBoxes,
+          ResidueShaderI shader,
+          SequenceGroup[] allGroups,
+          SequenceI seq, int i)
+  {
+    SequenceGroup currentSequenceGroup = getCurrentSequenceGroup(allGroups,
+            i);
+    if (currentSequenceGroup != null)
+    {
+      if (currentSequenceGroup.getDisplayBoxes())
+      {
+        return getBoxColour(currentSequenceGroup.getGroupColourScheme(),
+                seq, i);
+      }
+    }
+    else if (showBoxes)
+    {
+      return getBoxColour(shader, seq, i);
+    }
+  
+    return Color.white;
+  }
+
+  /**
+   * Search all the groups for a sequence to find the one which a given res
+   * falls into
+   * 
+   * @param allGroups
+   *          all the groups a sequence participates in
+   * @param res
+   *          the residue to search for
+   * @return a sequence group for res, or null if no sequence group applies
+   */
+  public SequenceGroup getCurrentSequenceGroup(SequenceGroup[] allGroups,
+          int res)
+  {
+    if (allGroups == null)
+    {
+      return null;
+    }
+
+    for (int i = 0; i < allGroups.length; i++)
+    {
+      if ((allGroups[i].getStartRes() <= res)
+              && (allGroups[i].getEndRes() >= res))
+      {
+        return (allGroups[i]);
+      }
+    }
+
+    return null;
+  }
+
+  /**
+   * DOCUMENT ME!
+   * 
+   * @param shader
+   *          the viewport's colour scheme
+   * @param seq
+   *          the sequence containing the residue
+   * @param i
+   *          the position of the residue in the sequence
+   */
+  public Color getBoxColour(ResidueShaderI shader, SequenceI seq, int i)
+  {
+    Color resBoxColour = Color.white;
+    if (shader.getColourScheme() != null)
+    {
+      resBoxColour = shader.findColour(seq.getCharAt(i), i, seq);
+    }
+    return resBoxColour;
+  }
+
+}
index 8ecb2ad..c031170 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.renderer;
 
 import jalview.analysis.Conservation;
@@ -19,7 +39,8 @@ import java.util.Map;
  * the factors that may influence residue colouring are
  * <ul>
  * <li>the colour scheme that provides a colour for each aligned residue</li>
- * <li>any threshold for colour, based on percentage identity with consensus</li>
+ * <li>any threshold for colour, based on percentage identity with
+ * consensus</li>
  * <li>any graduation based on conservation of physico-chemical properties</li>
  * </ul>
  * 
@@ -153,7 +174,7 @@ public class ResidueShader implements ResidueShaderI
       conservation = cons.getConsSequence().getSequenceAsString()
               .toCharArray();
     }
-  
+
   }
 
   /**
@@ -214,21 +235,29 @@ public class ResidueShader implements ResidueShaderI
   @Override
   public Color findColour(char symbol, int position, SequenceI seq)
   {
+    if (colourScheme == null)
+    {
+      return Color.white; // Colour is 'None'
+    }
+
     /*
      * get 'base' colour
      */
     ProfileI profile = consensus == null ? null : consensus.get(position);
-    String modalResidue = profile == null ? null : profile
-            .getModalResidue();
-    float pid = profile == null ? 0f : profile
-            .getPercentageIdentity(ignoreGaps);
-    Color colour = colourScheme == null ? Color.white : colourScheme
-            .findColour(symbol, position, seq, modalResidue, pid);
+    String modalResidue = profile == null ? null
+            : profile.getModalResidue();
+    float pid = profile == null ? 0f
+            : profile.getPercentageIdentity(ignoreGaps);
+    Color colour = colourScheme.findColour(symbol, position, seq,
+            modalResidue, pid);
 
     /*
      * apply PID threshold and consensus fading if in force
      */
-    colour = adjustColour(symbol, position, colour);
+    if (!Comparison.isGap(symbol))
+    {
+      colour = adjustColour(symbol, position, colour);
+    }
 
     return colour;
   }
@@ -256,7 +285,7 @@ public class ResidueShader implements ResidueShaderI
     {
       colour = Color.white;
     }
-  
+
     if (conservationColouring)
     {
       colour = applyConservation(colour, column);
@@ -290,14 +319,14 @@ public class ResidueShader implements ResidueShaderI
       // Faster than toUpperCase
       residue -= ('a' - 'A');
     }
-  
+
     if (consensus == null)
     {
       return false;
     }
-  
+
     ProfileI profile = consensus.get(column);
-  
+
     /*
      * test whether this is the consensus (or joint consensus) residue
      */
@@ -309,7 +338,7 @@ public class ResidueShader implements ResidueShaderI
         return true;
       }
     }
-  
+
     return false;
   }
 
@@ -337,7 +366,7 @@ public class ResidueShader implements ResidueShaderI
       return currentColour;
     }
     char conservationScore = conservation[column];
-  
+
     /*
      * if residues are fully conserved (* or 11), or all properties
      * are conserved (+ or 10), leave colour unchanged
@@ -348,24 +377,24 @@ public class ResidueShader implements ResidueShaderI
     {
       return currentColour;
     }
-  
+
     if (Comparison.isGap(conservationScore))
     {
       return Color.white;
     }
-  
+
     /*
      * convert score 0-9 to a bleaching factor 1.1 - 0.2
      */
     float bleachFactor = (11 - (conservationScore - '0')) / 10f;
-  
+
     /*
      * scale this up by 0-5 (percentage slider / 20)
      * as a result, scores of:         0  1  2  3  4  5  6  7  8  9
      * fade to white at slider value: 18 20 22 25 29 33 40 50 67 100%
      */
     bleachFactor *= (conservationIncrement / 20f);
-  
+
     return ColorUtils.bleachColour(currentColour, bleachFactor);
   }
 
index a914a1a..4d97171 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.renderer;
 
 import jalview.analysis.Conservation;
@@ -55,7 +75,8 @@ public interface ResidueShaderI
    * @param seq
    * @return
    */
-  public abstract Color findColour(char symbol, int position, SequenceI seq);
+  public abstract Color findColour(char symbol, int position,
+          SequenceI seq);
 
   public abstract ColourSchemeI getColourScheme();
 
index 9fec256..d92608c 100644 (file)
@@ -34,12 +34,24 @@ import java.util.List;
  */
 public class ScaleRenderer
 {
+  /**
+   * Represents one major or minor scale mark
+   */
   public final class ScaleMark
   {
+    /**
+     * true for a major scale mark, false for minor
+     */
     public final boolean major;
 
+    /**
+     * visible column position (0..) e.g. 19
+     */
     public final int column;
 
+    /**
+     * text (if any) to show e.g. "20"
+     */
     public final String text;
 
     ScaleMark(boolean isMajor, int col, String txt)
@@ -48,19 +60,27 @@ public class ScaleRenderer
       column = col;
       text = txt;
     }
+
+    /**
+     * String representation for inspection when debugging only
+     */
+    @Override
+    public String toString()
+    {
+      return String.format("%s:%d:%s", major ? "major" : "minor", column,
+              text);
+    }
   }
 
   /**
-   * calculate positions markers on the alignment ruler
+   * Calculates position markers on the alignment ruler
    * 
    * @param av
    * @param startx
-   *          left-most column in visible view
+   *          left-most column in visible view (0..)
    * @param endx
-   *          - right-most column in visible view
-   * @return List of ScaleMark holding boolean: true/false for major/minor mark,
-   *         marker position in alignment column coords, a String to be rendered
-   *         at the position (or null)
+   *          - right-most column in visible view (0..)
+   * @return
    */
   public List<ScaleMark> calculateMarks(AlignViewportI av, int startx,
           int endx)
@@ -87,41 +107,40 @@ public class ScaleRenderer
       scalestartx += 5;
     }
     List<ScaleMark> marks = new ArrayList<ScaleMark>();
-    String string;
-    int refN, iadj;
     // todo: add a 'reference origin column' to set column number relative to
-    for (int i = scalestartx; i < endx; i += 5)
+    for (int i = scalestartx; i <= endx; i += 5)
     {
       if (((i - refSp) % 10) == 0)
       {
+        String text;
         if (refSeq == null)
         {
-          iadj = av.getAlignment().getHiddenColumns()
+          int iadj = av.getAlignment().getHiddenColumns()
                   .adjustForHiddenColumns(i - 1) + 1;
-          string = String.valueOf(iadj);
+          text = String.valueOf(iadj);
         }
         else
         {
-          iadj = av.getAlignment().getHiddenColumns()
+          int iadj = av.getAlignment().getHiddenColumns()
                   .adjustForHiddenColumns(i - 1);
-          refN = refSeq.findPosition(iadj);
+          int refN = refSeq.findPosition(iadj);
           // TODO show bounds if position is a gap
           // - ie L--R -> "1L|2R" for
           // marker
           if (iadj < refStartI)
           {
-            string = String.valueOf(iadj - refStartI);
+            text = String.valueOf(iadj - refStartI);
           }
           else if (iadj > refEndI)
           {
-            string = "+" + String.valueOf(iadj - refEndI);
+            text = "+" + String.valueOf(iadj - refEndI);
           }
           else
           {
-            string = String.valueOf(refN) + refSeq.getCharAt(iadj);
+            text = String.valueOf(refN) + refSeq.getCharAt(iadj);
           }
         }
-        marks.add(new ScaleMark(true, i - startx - 1, string));
+        marks.add(new ScaleMark(true, i - startx - 1, text));
       }
       else
       {
index 1db2004..cfe2735 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.renderer.seqfeatures;
 
 import jalview.api.FeatureRenderer;
@@ -55,7 +75,7 @@ public class FeatureColourFinder
    * @param defaultColour
    * @param seq
    * @param column
-   *          alignment column position (base zero)
+   *          alignment column position (0..)
    * @return
    */
   public Color findFeatureColour(Color defaultColour, SequenceI seq,
@@ -81,7 +101,7 @@ public class FeatureColourFinder
       }
     }
 
-    Color c = featureRenderer.findFeatureColour(seq, column, g);
+    Color c = featureRenderer.findFeatureColour(seq, column + 1, g);
     if (c == null)
     {
       return defaultColour;
index 759101d..1f47da3 100644 (file)
@@ -21,6 +21,8 @@
 package jalview.renderer.seqfeatures;
 
 import jalview.api.AlignViewportI;
+import jalview.api.FeatureColourI;
+import jalview.datamodel.Range;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.util.Comparison;
@@ -31,6 +33,7 @@ import java.awt.Color;
 import java.awt.FontMetrics;
 import java.awt.Graphics;
 import java.awt.Graphics2D;
+import java.util.List;
 
 public class FeatureRenderer extends FeatureRendererModel
 {
@@ -98,8 +101,7 @@ public class FeatureRenderer extends FeatureRendererModel
 
       g.setColor(featureColour);
 
-      g.fillRect((i - start) * charWidth, y1, charWidth,
-              charHeight);
+      g.fillRect((i - start) * charWidth, y1, charWidth, charHeight);
 
       if (colourOnly || !validCharWidth)
       {
@@ -108,8 +110,8 @@ public class FeatureRenderer extends FeatureRendererModel
 
       g.setColor(Color.white);
       int charOffset = (charWidth - fm.charWidth(s)) / 2;
-      g.drawString(String.valueOf(s), charOffset
-              + (charWidth * (i - start)), pady);
+      g.drawString(String.valueOf(s),
+              charOffset + (charWidth * (i - start)), pady);
     }
     return true;
   }
@@ -197,8 +199,8 @@ public class FeatureRenderer extends FeatureRendererModel
 
       g.setColor(Color.black);
       int charOffset = (charWidth - fm.charWidth(s)) / 2;
-      g.drawString(String.valueOf(s), charOffset
-              + (charWidth * (i - start)), pady);
+      g.drawString(String.valueOf(s),
+              charOffset + (charWidth * (i - start)), pady);
     }
     return true;
   }
@@ -214,18 +216,12 @@ public class FeatureRenderer extends FeatureRendererModel
       return null;
     }
 
-    SequenceFeature[] sequenceFeatures = seq.getSequenceFeatures();
-
-    if (sequenceFeatures == null || sequenceFeatures.length == 0)
-    {
-      return null;
-    }
-
-    if (Comparison.isGap(seq.getCharAt(column)))
+    // column is 'base 1' but getCharAt is an array index (ie from 0)
+    if (Comparison.isGap(seq.getCharAt(column - 1)))
     {
       /*
        * returning null allows the colour scheme to provide gap colour
-       * - normally white, but can be customised otherwise
+       * - normally white, but can be customised
        */
       return null;
     }
@@ -236,7 +232,7 @@ public class FeatureRenderer extends FeatureRendererModel
       /*
        * simple case - just find the topmost rendered visible feature colour
        */
-      renderedColour = findFeatureColour(seq, seq.findPosition(column));
+      renderedColour = findFeatureColour(seq, column);
     }
     else
     {
@@ -273,8 +269,11 @@ public class FeatureRenderer extends FeatureRendererModel
           final SequenceI seq, int start, int end, int y1,
           boolean colourOnly)
   {
-    SequenceFeature[] sequenceFeatures = seq.getSequenceFeatures();
-    if (sequenceFeatures == null || sequenceFeatures.length == 0)
+    /*
+     * if columns are all gapped, or sequence has no features, nothing to do
+     */
+    Range visiblePositions = seq.findPositions(start+1, end+1);
+    if (visiblePositions == null || !seq.getFeatures().hasFeatures())
     {
       return null;
     }
@@ -288,10 +287,6 @@ public class FeatureRenderer extends FeatureRendererModel
               transparency));
     }
 
-    int startPos = seq.findPosition(start);
-    int endPos = seq.findPosition(end);
-
-    int sfSize = sequenceFeatures.length;
     Color drawnColour = null;
 
     /*
@@ -305,54 +300,55 @@ public class FeatureRenderer extends FeatureRendererModel
         continue;
       }
 
-      // loop through all features in sequence to find
-      // current feature to render
-      for (int sfindex = 0; sfindex < sfSize; sfindex++)
+      FeatureColourI fc = getFeatureStyle(type);
+      List<SequenceFeature> overlaps = seq.getFeatures().findFeatures(
+              visiblePositions.getBegin(), visiblePositions.getEnd(), type);
+
+      filterFeaturesForDisplay(overlaps, fc);
+
+      for (SequenceFeature sf : overlaps)
       {
-        final SequenceFeature sequenceFeature = sequenceFeatures[sfindex];
-        if (!sequenceFeature.type.equals(type))
+        Color featureColour = fc.getColor(sf);
+        if (featureColour == null)
         {
+          // score feature outwith threshold for colouring
           continue;
         }
 
         /*
-         * a feature type may be flagged as shown but the group 
-         * an instance of it belongs to may be hidden
+         * if feature starts/ends outside the visible range,
+         * restrict to visible positions (or if a contact feature,
+         * to a single position)
          */
-        if (featureGroupNotShown(sequenceFeature))
+        int visibleStart = sf.getBegin();
+        if (visibleStart < visiblePositions.getBegin())
         {
-          continue;
+          visibleStart = sf.isContactFeature() ? sf.getEnd()
+                  : visiblePositions.getBegin();
         }
-
-        /*
-         * check feature overlaps the target range
-         * TODO: efficient retrieval of features overlapping a range
-         */
-        if (sequenceFeature.getBegin() > endPos
-                || sequenceFeature.getEnd() < startPos)
+        int visibleEnd = sf.getEnd();
+        if (visibleEnd > visiblePositions.getEnd())
         {
-          continue;
+          visibleEnd = sf.isContactFeature() ? sf.getBegin()
+                  : visiblePositions.getEnd();
         }
 
-        Color featureColour = getColour(sequenceFeature);
-        if (featureColour == null)
-        {
-          // score feature outwith threshold for colouring
-          continue;
-        }
+        int featureStartCol = seq.findIndex(visibleStart);
+        int featureEndCol = sf.begin == sf.end ? featureStartCol : seq
+                .findIndex(visibleEnd);
+
+        // Color featureColour = getColour(sequenceFeature);
 
-        boolean isContactFeature = sequenceFeature.isContactFeature();
+        boolean isContactFeature = sf.isContactFeature();
 
         if (isContactFeature)
         {
-          boolean drawn = renderFeature(g, seq,
-                  seq.findIndex(sequenceFeature.begin) - 1,
-                  seq.findIndex(sequenceFeature.begin) - 1, featureColour,
-                  start, end, y1, colourOnly);
-          drawn |= renderFeature(g, seq,
-                  seq.findIndex(sequenceFeature.end) - 1,
-                  seq.findIndex(sequenceFeature.end) - 1, featureColour,
-                  start, end, y1, colourOnly);
+          boolean drawn = renderFeature(g, seq, featureStartCol - 1,
+                  featureStartCol - 1, featureColour, start, end, y1,
+                  colourOnly);
+          drawn |= renderFeature(g, seq, featureEndCol - 1,
+                  featureEndCol - 1, featureColour, start, end, y1,
+                  colourOnly);
           if (drawn)
           {
             drawnColour = featureColour;
@@ -360,6 +356,10 @@ public class FeatureRenderer extends FeatureRendererModel
         }
         else
         {
+          /*
+           * showing feature score by height of colour
+           * is not implemented as a selectable option 
+           *
           if (av.isShowSequenceFeaturesHeight()
                   && !Float.isNaN(sequenceFeature.score))
           {
@@ -375,15 +375,16 @@ public class FeatureRenderer extends FeatureRendererModel
           }
           else
           {
+          */
             boolean drawn = renderFeature(g, seq,
-                    seq.findIndex(sequenceFeature.begin) - 1,
-                    seq.findIndex(sequenceFeature.end) - 1, featureColour,
+                    featureStartCol - 1,
+                    featureEndCol - 1, featureColour,
                     start, end, y1, colourOnly);
             if (drawn)
             {
               drawnColour = featureColour;
             }
-          }
+          /*}*/
         }
       }
     }
@@ -401,24 +402,6 @@ public class FeatureRenderer extends FeatureRendererModel
   }
 
   /**
-   * Answers true if the feature belongs to a feature group which is not
-   * currently displayed, else false
-   * 
-   * @param sequenceFeature
-   * @return
-   */
-  protected boolean featureGroupNotShown(
-          final SequenceFeature sequenceFeature)
-  {
-    return featureGroups != null
-            && sequenceFeature.featureGroup != null
-            && sequenceFeature.featureGroup.length() != 0
-            && featureGroups.containsKey(sequenceFeature.featureGroup)
-            && !featureGroups.get(sequenceFeature.featureGroup)
-                    .booleanValue();
-  }
-
-  /**
    * Called when alignment in associated view has new/modified features to
    * discover and display.
    * 
@@ -430,23 +413,23 @@ public class FeatureRenderer extends FeatureRendererModel
   }
 
   /**
-   * Returns the sequence feature colour rendered at the given sequence
-   * position, or null if none found. The feature of highest render order (i.e.
-   * on top) is found, subject to both feature type and feature group being
-   * visible, and its colour returned.
+   * Returns the sequence feature colour rendered at the given column position,
+   * or null if none found. The feature of highest render order (i.e. on top) is
+   * found, subject to both feature type and feature group being visible, and
+   * its colour returned. This method is suitable when no feature transparency
+   * applied (only the topmost visible feature colour is rendered).
+   * <p>
+   * Note this method does not check for a gap in the column so would return the
+   * colour for features enclosing a gapped column. Check for gap before calling
+   * if different behaviour is wanted.
    * 
    * @param seq
-   * @param pos
+   * @param column
+   *          (1..)
    * @return
    */
-  Color findFeatureColour(SequenceI seq, int pos)
+  Color findFeatureColour(SequenceI seq, int column)
   {
-    SequenceFeature[] sequenceFeatures = seq.getSequenceFeatures();
-    if (sequenceFeatures == null || sequenceFeatures.length == 0)
-    {
-      return null;
-    }
-  
     /*
      * check for new feature added while processing
      */
@@ -456,7 +439,8 @@ public class FeatureRenderer extends FeatureRendererModel
      * inspect features in reverse renderOrder (the last in the array is 
      * displayed on top) until we find one that is rendered at the position
      */
-    for (int renderIndex = renderOrder.length - 1; renderIndex >= 0; renderIndex--)
+    for (int renderIndex = renderOrder.length
+            - 1; renderIndex >= 0; renderIndex--)
     {
       String type = renderOrder[renderIndex];
       if (!showFeatureOfType(type))
@@ -464,37 +448,21 @@ public class FeatureRenderer extends FeatureRendererModel
         continue;
       }
 
-      for (int sfindex = 0; sfindex < sequenceFeatures.length; sfindex++)
+      List<SequenceFeature> overlaps = seq.findFeatures(column, column,
+              type);
+      for (SequenceFeature sequenceFeature : overlaps)
       {
-        SequenceFeature sequenceFeature = sequenceFeatures[sfindex];
-        if (!sequenceFeature.type.equals(type))
+        if (!featureGroupNotShown(sequenceFeature))
         {
-          continue;
-        }
-
-        if (featureGroupNotShown(sequenceFeature))
-        {
-          continue;
-        }
-
-        /*
-         * check the column position is within the feature range
-         * (or is one of the two contact positions for a contact feature)
-         */
-        boolean featureIsAtPosition = sequenceFeature.begin <= pos
-                && sequenceFeature.end >= pos;
-        if (sequenceFeature.isContactFeature())
-        {
-          featureIsAtPosition = sequenceFeature.begin == pos
-                  || sequenceFeature.end == pos;
-        }
-        if (featureIsAtPosition)
-        {
-          return getColour(sequenceFeature);
+          Color col = getColour(sequenceFeature);
+          if (col != null)
+          {
+            return col;
+          }
         }
       }
     }
-  
+
     /*
      * no displayed feature found at position
      */
index 220d3ab..c28ea5f 100755 (executable)
@@ -188,15 +188,16 @@ public class AnnotationColourGradient extends FollowerColourScheme
         seqannot = new IdentityHashMap<SequenceI, AlignmentAnnotation>();
       }
       // resolve the context containing all the annotation for the sequence
-      AnnotatedCollectionI alcontext = alignment instanceof AlignmentI ? alignment
+      AnnotatedCollectionI alcontext = alignment instanceof AlignmentI
+              ? alignment
               : alignment.getContext();
       boolean f = true, rna = false;
-      for (AlignmentAnnotation alan : alcontext.findAnnotation(annotation
-              .getCalcId()))
+      for (AlignmentAnnotation alan : alcontext
+              .findAnnotation(annotation.getCalcId()))
       {
         if (alan.sequenceRef != null
-                && (alan.label != null && annotation != null && alan.label
-                        .equals(annotation.label)))
+                && (alan.label != null && annotation != null
+                        && alan.label.equals(annotation.label)))
         {
           if (!rna && alan.isRNA())
           {
@@ -252,8 +253,8 @@ public class AnnotationColourGradient extends FollowerColourScheme
 
   public Color getMaxColour()
   {
-    return new Color(redMin + redRange, greenMin + greenRange, blueMin
-            + blueRange);
+    return new Color(redMin + redRange, greenMin + greenRange,
+            blueMin + blueRange);
   }
 
   /**
@@ -287,8 +288,9 @@ public class AnnotationColourGradient extends FollowerColourScheme
     /*
      * locate the annotation we are configured to colour by
      */
-    AlignmentAnnotation ann = (seqAssociated && seqannot != null ? seqannot
-            .get(seq) : this.annotation);
+    AlignmentAnnotation ann = (seqAssociated && seqannot != null
+            ? seqannot.get(seq)
+            : this.annotation);
 
     /*
      * if gap or no annotation at position, no colour (White)
@@ -316,8 +318,10 @@ public class AnnotationColourGradient extends FollowerColourScheme
      */
     if (annotationThreshold != null)
     {
-      if ((aboveAnnotationThreshold == ABOVE_THRESHOLD && aj.value < annotationThreshold.value)
-              || (aboveAnnotationThreshold == BELOW_THRESHOLD && aj.value > annotationThreshold.value))
+      if ((aboveAnnotationThreshold == ABOVE_THRESHOLD
+              && aj.value < annotationThreshold.value)
+              || (aboveAnnotationThreshold == BELOW_THRESHOLD
+                      && aj.value > annotationThreshold.value))
       {
         return Color.white;
       }
@@ -354,8 +358,10 @@ public class AnnotationColourGradient extends FollowerColourScheme
           }
           else
           {
-            result = ann.annotations[j].secondaryStructure == 'H' ? AnnotationRenderer.HELIX_COLOUR
-                    : ann.annotations[j].secondaryStructure == 'E' ? AnnotationRenderer.SHEET_COLOUR
+            result = ann.annotations[j].secondaryStructure == 'H'
+                    ? AnnotationRenderer.HELIX_COLOUR
+                    : ann.annotations[j].secondaryStructure == 'E'
+                            ? AnnotationRenderer.SHEET_COLOUR
                             : AnnotationRenderer.STEM_COLOUR;
           }
         }
index 70f4910..02f9b3e 100755 (executable)
@@ -33,6 +33,7 @@ import java.util.Map;
 public class Blosum62ColourScheme extends ResidueColourScheme
 {
   private static final Color LIGHT_BLUE = new Color(204, 204, 255);
+
   private static final Color DARK_BLUE = new Color(154, 154, 255);
 
   public Blosum62ColourScheme()
index f13a90c..ec13343 100755 (executable)
@@ -43,8 +43,8 @@ public class ClustalxColourScheme extends ResidueColourScheme
   {
     RED(0.9f, 0.2f, 0.1f), BLUE(0.5f, 0.7f, 0.9f), GREEN(0.1f, 0.8f, 0.1f),
     ORANGE(0.9f, 0.6f, 0.3f), CYAN(0.1f, 0.7f, 0.7f),
-    PINK(0.9f, 0.5f, 0.5f), MAGENTA(0.8f, 0.3f, 0.8f), YELLOW(0.8f, 0.8f,
-            0.0f);
+    PINK(0.9f, 0.5f, 0.5f), MAGENTA(0.8f, 0.3f, 0.8f),
+    YELLOW(0.8f, 0.8f, 0.0f);
 
     final Color colour;
 
@@ -53,6 +53,7 @@ public class ClustalxColourScheme extends ResidueColourScheme
       colour = new Color(r, g, b);
     }
   }
+
   private class ConsensusColour
   {
     Consensus[] cons;
@@ -106,19 +107,18 @@ public class ClustalxColourScheme extends ResidueColourScheme
 
     for (SequenceI sq : seqs)
     {
-      char[] seq = sq.getSequence();
-
-      int end_j = seq.length - 1;
+      int end_j = sq.getLength() - 1;
+      int length = sq.getLength();
 
       for (int i = 0; i <= end_j; i++)
       {
-        if ((seq.length - 1) < i)
+        if (length - 1 < i)
         {
           res = 23;
         }
         else
         {
-          res = ResidueProperties.aaIndex[seq[i]];
+          res = ResidueProperties.aaIndex[sq.getCharAt(i)];
         }
         cons2[i][res]++;
       }
@@ -297,8 +297,7 @@ public class ClustalxColourScheme extends ResidueColourScheme
 
     for (int k = 0; k < residueColour[i].cons.length; k++)
     {
-      if (residueColour[i].cons[k].isConserved(cons2, j, size,
-              includeGaps))
+      if (residueColour[i].cons[k].isConserved(cons2, j, size, includeGaps))
       {
         colour = residueColour[i].c;
       }
index f16ca21..d70b4e2 100755 (executable)
@@ -98,4 +98,11 @@ public interface ColourSchemeI
    * @return
    */
   boolean isSimple();
+
+  /**
+   * Answers true if the colour scheme has a colour specified for gaps.
+   * 
+   * @return
+   */
+  boolean hasGapColour();
 }
index 8660f3e..9f08688 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.schemes;
 
 import jalview.binding.JalviewUserColours;
@@ -30,14 +50,14 @@ public class ColourSchemeLoader
     {
       InputStreamReader in = new InputStreamReader(
               new FileInputStream(file), "UTF-8");
-  
+
       jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours();
-  
+
       org.exolab.castor.xml.Unmarshaller unmar = new org.exolab.castor.xml.Unmarshaller(
               jucs);
       jucs = (jalview.schemabinding.version2.JalviewUserColours) unmar
               .unmarshal(in);
-  
+
       /*
        * non-case-sensitive colours are for 20 amino acid codes,
        * B, Z, X and Gap
@@ -46,7 +66,7 @@ public class ColourSchemeLoader
       newColours = new Color[24];
       Color[] lowerCase = new Color[23];
       boolean caseSensitive = false;
-  
+
       String name;
       int index;
       for (int i = 0; i < jucs.getColourCount(); i++)
@@ -64,9 +84,9 @@ public class ColourSchemeLoader
         {
           continue;
         }
-  
-        Color color = new Color(Integer.parseInt(jucs.getColour(i)
-                .getRGB(), 16));
+
+        Color color = new Color(
+                Integer.parseInt(jucs.getColour(i).getRGB(), 16));
         if (name.toLowerCase().equals(name))
         {
           caseSensitive = true;
@@ -77,7 +97,7 @@ public class ColourSchemeLoader
           newColours[index] = color;
         }
       }
-  
+
       /*
        * instantiate the colour scheme
        */
@@ -92,19 +112,19 @@ public class ColourSchemeLoader
       // Could be old Jalview Archive format
       try
       {
-        InputStreamReader in = new InputStreamReader(new FileInputStream(
-                file), "UTF-8");
-  
+        InputStreamReader in = new InputStreamReader(
+                new FileInputStream(file), "UTF-8");
+
         jalview.binding.JalviewUserColours jucs = new jalview.binding.JalviewUserColours();
-  
+
         jucs = JalviewUserColours.unmarshal(in);
-  
+
         newColours = new Color[jucs.getColourCount()];
-  
+
         for (int i = 0; i < 24; i++)
         {
-          newColours[i] = new Color(Integer.parseInt(jucs.getColour(i)
-                  .getRGB(), 16));
+          newColours[i] = new Color(
+                  Integer.parseInt(jucs.getColour(i).getRGB(), 16));
         }
         ucs = new UserColourScheme(newColours);
         ucs.setName(jucs.getSchemeName());
@@ -112,13 +132,13 @@ public class ColourSchemeLoader
       {
         ex2.printStackTrace();
       }
-  
+
       if (newColours == null)
       {
         System.out.println("Error loading User ColourFile\n" + ex);
       }
     }
-  
+
     return ucs;
   }
 
index 3e8e87a..fc92cd9 100755 (executable)
@@ -44,7 +44,8 @@ public class ColourSchemeProperty
    * Returns a colour scheme for the given name, with which the given data may
    * be coloured. The name is not case-sensitive, and may be one of
    * <ul>
-   * <li>any currently registered colour scheme; Jalview by default provides</li>
+   * <li>any currently registered colour scheme; Jalview by default
+   * provides</li>
    * <ul>
    * <li>Clustal</li>
    * <li>Blosum62</li>
@@ -61,9 +62,11 @@ public class ColourSchemeProperty
    * <li>T-Coffee Scores</li>
    * <li>RNA Helices</li>
    * </ul>
-   * <li>the name of a programmatically added colour scheme</li> <li>an AWT
-   * colour name e.g. red</li> <li>an AWT hex rgb colour e.g. ff2288</li> <li>
-   * residue colours list e.g. D,E=red;K,R,H=0022FF;c=yellow</li> </ul>
+   * <li>the name of a programmatically added colour scheme</li>
+   * <li>an AWT colour name e.g. red</li>
+   * <li>an AWT hex rgb colour e.g. ff2288</li>
+   * <li>residue colours list e.g. D,E=red;K,R,H=0022FF;c=yellow</li>
+   * </ul>
    * 
    * If none of these formats is matched, the string is converted to a colour
    * using a hashing algorithm. For name "None", returns null.
@@ -85,8 +88,8 @@ public class ColourSchemeProperty
      * if this is the name of a registered colour scheme, just
      * create a new instance of it
      */
-    ColourSchemeI scheme = ColourSchemes.getInstance().getColourScheme(
-            name, forData, null);
+    ColourSchemeI scheme = ColourSchemes.getInstance().getColourScheme(name,
+            forData, null);
     if (scheme != null)
     {
       return scheme;
@@ -146,8 +149,7 @@ public class ColourSchemeProperty
    */
   public static String getColourName(ColourSchemeI cs)
   {
-    return cs == null ? ResidueColourScheme.NONE : cs
-            .getSchemeName();
+    return cs == null ? ResidueColourScheme.NONE : cs.getSchemeName();
   }
 
 }
index 269811b..99e9759 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.schemes;
 
 import jalview.datamodel.AnnotatedCollectionI;
@@ -99,7 +119,7 @@ public class ColourSchemes
       schemes.remove(name.toLowerCase());
     }
   }
-  
+
   /**
    * Returns an instance of the colour scheme with which the given view may be
    * coloured
index 6cb095b..923bd85 100644 (file)
@@ -77,10 +77,11 @@ public class CovariationColourScheme extends ResidueColourScheme
       positionsToHelix.put(this.annotation._rnasecstr[x].getEnd(),
               this.annotation._rnasecstr[x].getFeatureGroup());
 
-      if (Integer.parseInt(this.annotation._rnasecstr[x].getFeatureGroup()) > numHelix)
+      if (Integer.parseInt(
+              this.annotation._rnasecstr[x].getFeatureGroup()) > numHelix)
       {
-        numHelix = Integer.parseInt(this.annotation._rnasecstr[x]
-                .getFeatureGroup());
+        numHelix = Integer
+                .parseInt(this.annotation._rnasecstr[x].getFeatureGroup());
       }
 
     }
index dbe4901..54d1c6c 100644 (file)
@@ -125,8 +125,8 @@ public class FeatureColour implements FeatureColourI
       Color colour = ColorUtils.parseColourString(descriptor);
       if (colour == null)
       {
-        throw new IllegalArgumentException("Invalid colour descriptor: "
-                + descriptor);
+        throw new IllegalArgumentException(
+                "Invalid colour descriptor: " + descriptor);
       }
       return new FeatureColour(colour);
     }
@@ -236,8 +236,8 @@ public class FeatureColour implements FeatureColourI
         {
           if (!ttype.toLowerCase().startsWith("no"))
           {
-            System.err.println("Ignoring unrecognised threshold type : "
-                    + ttype);
+            System.err.println(
+                    "Ignoring unrecognised threshold type : " + ttype);
           }
         }
       }
@@ -256,8 +256,8 @@ public class FeatureColour implements FeatureColourI
       }
       if (gcol.hasMoreTokens())
       {
-        System.err
-                .println("Ignoring additional tokens in parameters in graduated colour specification\n");
+        System.err.println(
+                "Ignoring additional tokens in parameters in graduated colour specification\n");
         while (gcol.hasMoreTokens())
         {
           System.err.println("|" + gcol.nextToken());
@@ -542,8 +542,7 @@ public class FeatureColour implements FeatureColourI
   {
     if (isColourByLabel())
     {
-      return ColorUtils
-              .createColourFromName(feature.getDescription());
+      return ColorUtils.createColourFromName(feature.getDescription());
     }
 
     if (!isGraduatedColour())
@@ -551,16 +550,27 @@ public class FeatureColour implements FeatureColourI
       return getColour();
     }
 
-    // todo should we check for above/below threshold here?
-    if (range == 0.0)
-    {
-      return getMaxColour();
-    }
+    /*
+     * graduated colour case, optionally with threshold
+     * Float.NaN is assigned minimum visible score colour
+     */
     float scr = feature.getScore();
     if (Float.isNaN(scr))
     {
       return getMinColour();
     }
+    if (isAboveThreshold() && scr <= threshold)
+    {
+      return null;
+    }
+    if (isBelowThreshold() && scr >= threshold)
+    {
+      return null;
+    }
+    if (range == 0.0)
+    {
+      return getMaxColour();
+    }
     float scl = (scr - base) / range;
     if (isHighToLow)
     {
@@ -602,44 +612,6 @@ public class FeatureColour implements FeatureColourI
     return (isHighToLow) ? (base + range) : base;
   }
 
-  /**
-   * Answers true if the feature has a simple colour, or is coloured by label,
-   * or has a graduated colour and the score of this feature instance is within
-   * the range to render (if any), i.e. does not lie below or above any
-   * threshold set.
-   * 
-   * @param feature
-   * @return
-   */
-  @Override
-  public boolean isColored(SequenceFeature feature)
-  {
-    if (isColourByLabel() || !isGraduatedColour())
-    {
-      return true;
-    }
-
-    float val = feature.getScore();
-    if (Float.isNaN(val))
-    {
-      return true;
-    }
-    if (Float.isNaN(this.threshold))
-    {
-      return true;
-    }
-
-    if (isAboveThreshold() && val <= threshold)
-    {
-      return false;
-    }
-    if (isBelowThreshold() && val >= threshold)
-    {
-      return false;
-    }
-    return true;
-  }
-
   @Override
   public boolean isSimpleColour()
   {
index 185d2b4..e1fc02d 100644 (file)
@@ -1,6 +1,25 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.schemes;
 
-
 /**
  * An enum with the colour schemes supported by Jalview.
  */
@@ -10,19 +29,20 @@ public enum JalviewColourScheme
    * the order of declaration is the default order in which 
    * items are added to Colour menus
    */
-  Clustal("Clustal", ClustalxColourScheme.class), Blosum62("Blosum62",
-          Blosum62ColourScheme.class), PID("% Identity",
-          PIDColourScheme.class), Zappo("Zappo", ZappoColourScheme.class),
-  Taylor("Taylor", TaylorColourScheme.class), Hydrophobic("Hydrophobic",
-          HydrophobicColourScheme.class), Helix("Helix Propensity",
-          HelixColourScheme.class), Strand("Strand Propensity",
-          StrandColourScheme.class), Turn("Turn Propensity",
-          TurnColourScheme.class), Buried("Buried Index",
-          BuriedColourScheme.class), Nucleotide("Nucleotide",
-          NucleotideColourScheme.class), PurinePyrimidine(
-          "Purine/Pyrimidine", PurinePyrimidineColourScheme.class),
-  RNAHelices("RNA Helices", RNAHelicesColour.class), TCoffee(
-          "T-Coffee Scores", TCoffeeColourScheme.class);
+  Clustal("Clustal", ClustalxColourScheme.class),
+  Blosum62("Blosum62", Blosum62ColourScheme.class),
+  PID("% Identity", PIDColourScheme.class),
+  Zappo("Zappo", ZappoColourScheme.class),
+  Taylor("Taylor", TaylorColourScheme.class),
+  Hydrophobic("Hydrophobic", HydrophobicColourScheme.class),
+  Helix("Helix Propensity", HelixColourScheme.class),
+  Strand("Strand Propensity", StrandColourScheme.class),
+  Turn("Turn Propensity", TurnColourScheme.class),
+  Buried("Buried Index", BuriedColourScheme.class),
+  Nucleotide("Nucleotide", NucleotideColourScheme.class),
+  PurinePyrimidine("Purine/Pyrimidine", PurinePyrimidineColourScheme.class),
+  RNAHelices("RNA Helices", RNAHelicesColour.class),
+  TCoffee("T-Coffee Scores", TCoffeeColourScheme.class);
   // RNAInteraction("RNA Interaction type", RNAInteractionColourScheme.class)
 
   private String name;
index 657d6b0..fc922b9 100755 (executable)
@@ -65,8 +65,7 @@ public class PIDColourScheme extends ResidueColourScheme
     /*
      * test whether this is the consensus (or joint consensus) residue
      */
-    boolean matchesConsensus = consensusResidue.contains(
-            String.valueOf(c));
+    boolean matchesConsensus = consensusResidue.contains(String.valueOf(c));
     if (matchesConsensus)
     {
       for (int i = 0; i < thresholds.length; i++)
index 056a167..dbc9c03 100644 (file)
@@ -125,9 +125,9 @@ public class RNAHelicesColour extends ResidueColourScheme
   public void refresh()
   {
 
-    if (annotation != null
-            && ((annotation._rnasecstr == null || lastrefresh != annotation._rnasecstr
-                    .hashCode()) && annotation.isValidStruc()))
+    if (annotation != null && ((annotation._rnasecstr == null
+            || lastrefresh != annotation._rnasecstr.hashCode())
+            && annotation.isValidStruc()))
     {
       annotation.getRNAStruc();
       lastrefresh = annotation._rnasecstr.hashCode();
@@ -151,11 +151,11 @@ public class RNAHelicesColour extends ResidueColourScheme
         positionsToHelix.put(this.annotation._rnasecstr[x].getEnd(),
                 this.annotation._rnasecstr[x].getFeatureGroup());
 
-        if (Integer.parseInt(this.annotation._rnasecstr[x]
-                .getFeatureGroup()) > numHelix)
+        if (Integer.parseInt(
+                this.annotation._rnasecstr[x].getFeatureGroup()) > numHelix)
         {
-          numHelix = Integer.parseInt(this.annotation._rnasecstr[x]
-                  .getFeatureGroup());
+          numHelix = Integer.parseInt(
+                  this.annotation._rnasecstr[x].getFeatureGroup());
         }
 
       }
index 15cb157..9809fa9 100644 (file)
@@ -58,7 +58,7 @@ public class RNAHelicesColourChooser
     oldcs = av.getGlobalColourScheme();
     if (av.getAlignment().getGroups() != null)
     {
-      oldgroupColours = new Hashtable<SequenceGroup, ColourSchemeI>();
+      oldgroupColours = new Hashtable<>();
       for (SequenceGroup sg : ap.getAlignment().getGroups())
       {
         if (sg.getColourScheme() != null)
@@ -71,7 +71,7 @@ public class RNAHelicesColourChooser
     this.ap = ap;
 
     adjusting = true;
-    Vector<String> list = new Vector<String>();
+    Vector<String> list = new Vector<>();
     int index = 1;
     AlignmentAnnotation[] anns = av.getAlignment().getAlignmentAnnotation();
     if (anns != null)
@@ -105,6 +105,6 @@ public class RNAHelicesColourChooser
 
     av.setGlobalColourScheme(rhc);
 
-    ap.paintAlignment(true);
+    ap.paintAlignment(true, true);
   }
 }
index 6aa798e..2f7a5e0 100755 (executable)
@@ -62,8 +62,9 @@ public abstract class ResidueColourScheme implements ColourSchemeI
   /**
    * Creates a new ResidueColourScheme object.
    * 
-   * @param final int[] index table into colors (ResidueProperties.naIndex or
-   *        ResidueProperties.aaIndex)
+   * @param final
+   *          int[] index table into colors (ResidueProperties.naIndex or
+   *          ResidueProperties.aaIndex)
    * @param colors
    *          colours for symbols in sequences
    */
@@ -98,8 +99,7 @@ public abstract class ResidueColourScheme implements ColourSchemeI
   {
     Color colour = Color.white;
 
-    if (colors != null && symbolIndex != null
-            && c < symbolIndex.length
+    if (colors != null && symbolIndex != null && c < symbolIndex.length
             && symbolIndex[c] < colors.length)
     {
       colour = colors[symbolIndex[c]];
@@ -208,4 +208,14 @@ public abstract class ResidueColourScheme implements ColourSchemeI
   {
     return true;
   }
+
+  /**
+   * Default method returns false. Override this to return true in colour
+   * schemes that have a colour associated with gap residues.
+   */
+  @Override
+  public boolean hasGapColour()
+  {
+    return false;
+  }
 }
index 751175d..55df1d1 100755 (executable)
@@ -363,8 +363,11 @@ public class ResidueProperties
   };
 
   // Added for PurinePyrimidineColourScheme
-  public static final Color[] purinepyrimidine = {
-      new Color(255, 131, 250), // A, G, R purines purplish/orchid
+  public static final Color[] purinepyrimidine = { new Color(255, 131, 250), // A,
+                                                                             // G,
+                                                                             // R
+                                                                             // purines
+                                                                             // purplish/orchid
       new Color(64, 224, 208), // C,U, T, Y pyrimidines turquoise
       Color.white, // all other nucleotides
       Color.white // Gap
@@ -379,7 +382,7 @@ public class ResidueProperties
       Color.green, // Q
       Color.red, // E
       Color.magenta, // G
-      midBlue,// Color.red, // H
+      midBlue, // Color.red, // H
       Color.pink, // I
       Color.pink, // L
       midBlue, // K
@@ -426,9 +429,9 @@ public class ResidueProperties
       0.0 // X
   };
 
-  public static final double[] helix = { 1.42, 0.98, 0.67, 1.01, 0.70,
-      1.11, 1.51, 0.57, 1.00, 1.08, 1.21, 1.16, 1.45, 1.13, 0.57, 0.77,
-      0.83, 1.08, 0.69, 1.06, 0.84, 1.31, 1.00, 0.0 };
+  public static final double[] helix = { 1.42, 0.98, 0.67, 1.01, 0.70, 1.11,
+      1.51, 0.57, 1.00, 1.08, 1.21, 1.16, 1.45, 1.13, 0.57, 0.77, 0.83,
+      1.08, 0.69, 1.06, 0.84, 1.31, 1.00, 0.0 };
 
   public static final double helixmin = 0.57;
 
@@ -450,9 +453,9 @@ public class ResidueProperties
 
   public static final double turnmax = 1.56;
 
-  public static final double[] buried = { 1.7, 0.1, 0.4, 0.4, 4.6, 0.3,
-      0.3, 1.8, 0.8, 3.1, 2.4, 0.05, 1.9, 2.2, 0.6, 0.8, 0.7, 1.6, 0.5,
-      2.9, 0.4, 0.3, 1.358, 0.00 };
+  public static final double[] buried = { 1.7, 0.1, 0.4, 0.4, 4.6, 0.3, 0.3,
+      1.8, 0.8, 3.1, 2.4, 0.05, 1.9, 2.2, 0.6, 0.8, 0.7, 1.6, 0.5, 2.9, 0.4,
+      0.3, 1.358, 0.00 };
 
   public static final double buriedmin = 0.05;
 
@@ -643,16 +646,16 @@ public class ResidueProperties
         }
         else
         {
-          System.err
-                  .println("Inconsistency in the IUBMB ambiguity code nomenclature table: collision for "
+          System.err.println(
+                  "Inconsistency in the IUBMB ambiguity code nomenclature table: collision for "
                           + acode.getKey() + " in residue " + r);
         }
       }
     }
     // and programmatically add in the ambiguity codes that yield the same amino
     // acid
-    String[] unambcodons = codonHash2.keySet().toArray(
-            new String[codonHash2.size()]);
+    String[] unambcodons = codonHash2.keySet()
+            .toArray(new String[codonHash2.size()]);
     for (String codon : unambcodons)
     {
       String residue = codonHash2.get(codon);
@@ -671,7 +674,8 @@ public class ResidueProperties
         }
       }
       // enumerate all combinations and test for veracity of translation
-      int tpos[] = new int[codon.length()], cpos[] = new int[codon.length()];
+      int tpos[] = new int[codon.length()],
+              cpos[] = new int[codon.length()];
       for (int i = 0; i < tpos.length; i++)
       {
         tpos[i] = -1;
@@ -924,7 +928,7 @@ public class ResidueProperties
     charged.put("Q", ZERO);
     charged.put("D", ONE);
     charged.put("N", ZERO); // Asparagine is polar but not
-                                          // charged.
+                            // charged.
     // Alternative would be charged and
     // negative (in basic form)?
     charged.put("S", ZERO);
@@ -1053,7 +1057,9 @@ public class ResidueProperties
   }
   static
   {
-    int[][] propMatrixF = new int[maxProteinIndex][maxProteinIndex], propMatrixPos = new int[maxProteinIndex][maxProteinIndex], propMatrixEpos = new int[maxProteinIndex][maxProteinIndex];
+    int[][] propMatrixF = new int[maxProteinIndex][maxProteinIndex],
+            propMatrixPos = new int[maxProteinIndex][maxProteinIndex],
+            propMatrixEpos = new int[maxProteinIndex][maxProteinIndex];
     for (int i = 0; i < maxProteinIndex; i++)
     {
       int maxF = 0, maxP = 0, maxEP = 0;
@@ -2625,8 +2631,8 @@ public class ResidueProperties
     {
       return '0';
     }
-    Integer index = ResidueProperties.aa3Hash.get(threeLetterCode
-            .toUpperCase());
+    Integer index = ResidueProperties.aa3Hash
+            .get(threeLetterCode.toUpperCase());
     return index == null ? '0' : aa[index].charAt(0);
   }
 }
index 13d1d55..812dca7 100644 (file)
@@ -87,7 +87,8 @@ public class TCoffeeColourScheme extends ResidueColourScheme
     // Search alignment to get all tcoffee annotation and pick one set of
     // annotation to use to colour seqs.
     seqMap = new IdentityHashMap<SequenceI, Color[]>();
-    AnnotatedCollectionI alcontext = alignment instanceof AlignmentI ? alignment
+    AnnotatedCollectionI alcontext = alignment instanceof AlignmentI
+            ? alignment
             : alignment.getContext();
     if (alcontext == null)
     {
@@ -154,8 +155,8 @@ public class TCoffeeColourScheme extends ResidueColourScheme
   @Override
   public boolean isApplicableTo(AnnotatedCollectionI ac)
   {
-    AnnotatedCollectionI alcontext = ac instanceof AlignmentI ? ac : ac
-            .getContext();
+    AnnotatedCollectionI alcontext = ac instanceof AlignmentI ? ac
+            : ac.getContext();
     if (alcontext == null)
     {
       return false;
index 256862d..bf62e45 100755 (executable)
@@ -222,7 +222,8 @@ public class UserColourScheme extends ResidueColourScheme
             {
               lowerCaseColours = new Color[colors.length];
             }
-            lowerCaseColours[colIndex] = ColorUtils.parseColourString(colour);
+            lowerCaseColours[colIndex] = ColorUtils
+                    .parseColourString(colour);
           }
           else
           {
@@ -232,8 +233,8 @@ public class UserColourScheme extends ResidueColourScheme
       }
     } catch (Exception ex)
     {
-      System.out.println("Error parsing userDefinedColours:\n" + token
-              + "\n" + ex);
+      System.out.println(
+              "Error parsing userDefinedColours:\n" + token + "\n" + ex);
     }
 
   }
@@ -263,8 +264,8 @@ public class UserColourScheme extends ResidueColourScheme
   }
 
   /**
-   * Answers the customised name of the colour scheme, if it has one, else
-   * "User Defined"
+   * Answers the customised name of the colour scheme, if it has one, else "User
+   * Defined"
    */
   @Override
   public String getSchemeName()
@@ -286,7 +287,7 @@ public class UserColourScheme extends ResidueColourScheme
     /*
      * step 1: build a map from colours to the symbol(s) that have the colour
      */
-    Map<Color, List<String>> colours = new HashMap<Color, List<String>>();
+    Map<Color, List<String>> colours = new HashMap<>();
 
     for (char symbol = 'A'; symbol <= 'Z'; symbol++)
     {
@@ -319,7 +320,7 @@ public class UserColourScheme extends ResidueColourScheme
     /*
      * step 2: make a list of { A,G,R=12f9d6 } residues/colour specs
      */
-    List<String> residueColours = new ArrayList<String>();
+    List<String> residueColours = new ArrayList<>();
     for (Entry<Color, List<String>> cols : colours.entrySet())
     {
       boolean first = true;
@@ -349,4 +350,10 @@ public class UserColourScheme extends ResidueColourScheme
     Collections.sort(residueColours);
     return StringUtils.listToDelimitedString(residueColours, ";");
   }
+
+  @Override
+  public boolean hasGapColour()
+  {
+    return (findColour(' ') != null);
+  }
 }
index a7384f8..00012ab 100644 (file)
@@ -35,5 +35,6 @@ public interface SecondaryStructureListener
    * @param position
    *          the dataset sequence position (base 1)
    */
-  public void mouseOverSequence(SequenceI sequence, int index, int position);
+  public void mouseOverSequence(SequenceI sequence, int index,
+          int position);
 }
index fe878ce..bdac2be 100644 (file)
@@ -39,6 +39,5 @@ public interface SelectionListener
    */
   public void selection(jalview.datamodel.SequenceGroup seqsel,
           jalview.datamodel.ColumnSelection colsel,
-          jalview.datamodel.HiddenColumns hidden,
-          SelectionSource source);
+          jalview.datamodel.HiddenColumns hidden, SelectionSource source);
 }
index db0b47e..35e2536 100644 (file)
@@ -66,7 +66,7 @@ public class StructureSelectionManager
 
   static IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager> instances;
 
-  private List<StructureMapping> mappings = new ArrayList<StructureMapping>();
+  private List<StructureMapping> mappings = new ArrayList<>();
 
   private boolean processSecondaryStructure = false;
 
@@ -74,20 +74,16 @@ public class StructureSelectionManager
 
   private boolean addTempFacAnnot = false;
 
-  private IProgressIndicator progressIndicator;
-
   private SiftsClient siftsClient = null;
 
-  private long progressSessionId;
-
   /*
    * Set of any registered mappings between (dataset) sequences.
    */
-  private List<AlignedCodonFrame> seqmappings = new ArrayList<AlignedCodonFrame>();
+  private List<AlignedCodonFrame> seqmappings = new ArrayList<>();
 
-  private List<CommandListener> commandListeners = new ArrayList<CommandListener>();
+  private List<CommandListener> commandListeners = new ArrayList<>();
 
-  private List<SelectionListener> sel_listeners = new ArrayList<SelectionListener>();
+  private List<SelectionListener> sel_listeners = new ArrayList<>();
 
   /**
    * @return true if will try to use external services for processing secondary
@@ -161,8 +157,8 @@ public class StructureSelectionManager
     }
     else
     {
-      System.err.println("reportMapping: There are " + mappings.size()
-              + " mappings.");
+      System.err.println(
+              "reportMapping: There are " + mappings.size() + " mappings.");
       int i = 0;
       for (StructureMapping sm : mappings)
       {
@@ -175,9 +171,9 @@ public class StructureSelectionManager
    * map between the PDB IDs (or structure identifiers) used by Jalview and the
    * absolute filenames for PDB data that corresponds to it
    */
-  Map<String, String> pdbIdFileName = new HashMap<String, String>();
+  Map<String, String> pdbIdFileName = new HashMap<>();
 
-  Map<String, String> pdbFileNameId = new HashMap<String, String>();
+  Map<String, String> pdbFileNameId = new HashMap<>();
 
   public void registerPDBFile(String idForFile, String absoluteFile)
   {
@@ -214,9 +210,8 @@ public class StructureSelectionManager
       {
         if (instances != null)
         {
-          throw new Error(
-                  MessageManager
-                          .getString("error.implementation_error_structure_selection_manager_null"),
+          throw new Error(MessageManager.getString(
+                  "error.implementation_error_structure_selection_manager_null"),
                   new NullPointerException(MessageManager
                           .getString("exception.ssm_context_is_null")));
         }
@@ -229,7 +224,7 @@ public class StructureSelectionManager
     }
     if (instances == null)
     {
-      instances = new java.util.IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager>();
+      instances = new java.util.IdentityHashMap<>();
     }
     StructureSelectionManager instance = instances.get(context);
     if (instance == null)
@@ -325,9 +320,11 @@ public class StructureSelectionManager
    * @return null or the structure data parsed as a pdb file
    */
   synchronized public StructureFile setMapping(SequenceI[] sequence,
-          String[] targetChains, String pdbFile, DataSourceType protocol)
+          String[] targetChains, String pdbFile, DataSourceType protocol, 
+          IProgressIndicator progress)
   {
-    return setMapping(true, sequence, targetChains, pdbFile, protocol);
+    return computeMapping(true, sequence, targetChains, pdbFile, protocol,
+            progress);
   }
 
   /**
@@ -341,7 +338,9 @@ public class StructureSelectionManager
    *          - one or more sequences to be mapped to pdbFile
    * @param targetChainIds
    *          - optional chain specification for mapping each sequence to pdb
-   *          (may be nill, individual elements may be nill)
+   *          (may be nill, individual elements may be nill) - JBPNote: JAL-2693
+   *          - this should be List<List<String>>, empty lists indicate no
+   *          predefined mappings
    * @param pdbFile
    *          - structure data resource
    * @param sourceType
@@ -352,6 +351,16 @@ public class StructureSelectionManager
           SequenceI[] sequenceArray, String[] targetChainIds,
           String pdbFile, DataSourceType sourceType)
   {
+    return computeMapping(forStructureView, sequenceArray, targetChainIds,
+            pdbFile, sourceType, null);
+  }
+
+  synchronized public StructureFile computeMapping(
+          boolean forStructureView, SequenceI[] sequenceArray,
+          String[] targetChainIds, String pdbFile, DataSourceType sourceType,
+          IProgressIndicator progress)
+  {
+    long progressSessionId = System.currentTimeMillis() * 3;
     /*
      * There will be better ways of doing this in the future, for now we'll use
      * the tried and tested MCview pdb mapping
@@ -433,8 +442,8 @@ public class StructureSelectionManager
       }
       else if (seq.getName().indexOf("|") > -1)
       {
-        targetChainId = seq.getName().substring(
-                seq.getName().lastIndexOf("|") + 1);
+        targetChainId = seq.getName()
+                .substring(seq.getName().lastIndexOf("|") + 1);
         if (targetChainId.length() > 1)
         {
           if (targetChainId.trim().length() == 0)
@@ -499,12 +508,14 @@ public class StructureSelectionManager
         pdbFile = "INLINE" + pdb.getId();
       }
 
-      List<StructureMapping> seqToStrucMapping = new ArrayList<StructureMapping>();
+      List<StructureMapping> seqToStrucMapping = new ArrayList<>();
       if (isMapUsingSIFTs && seq.isProtein())
       {
-        setProgressBar(null);
-        setProgressBar(MessageManager
-                .getString("status.obtaining_mapping_with_sifts"));
+        if (progress!=null) {
+          progress.setProgressBar(MessageManager
+                .getString("status.obtaining_mapping_with_sifts"),
+                  progressSessionId);
+        }
         jalview.datamodel.Mapping sqmpping = maxAlignseq
                 .getMappingFromS1(false);
         if (targetChainId != null && !targetChainId.trim().isEmpty())
@@ -537,7 +548,7 @@ public class StructureSelectionManager
         }
         else
         {
-          List<StructureMapping> foundSiftsMappings = new ArrayList<StructureMapping>();
+          List<StructureMapping> foundSiftsMappings = new ArrayList<>();
           for (PDBChain chain : pdb.getChains())
           {
             try
@@ -574,20 +585,25 @@ public class StructureSelectionManager
       }
       else
       {
-        setProgressBar(null);
-        setProgressBar(MessageManager
-                .getString("status.obtaining_mapping_with_nw_alignment"));
-        StructureMapping nwMapping = getNWMappings(seq, pdbFile,
-                maxChainId, maxChain, pdb, maxAlignseq);
+        if (progress != null)
+        {
+          progress.setProgressBar(MessageManager
+                                 .getString("status.obtaining_mapping_with_nw_alignment"),
+                  progressSessionId);
+        }
+        StructureMapping nwMapping = getNWMappings(seq, pdbFile, maxChainId,
+                maxChain, pdb, maxAlignseq);
         seqToStrucMapping.add(nwMapping);
         ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
-
       }
-
       if (forStructureView)
       {
         mappings.addAll(seqToStrucMapping);
       }
+      if (progress != null)
+      {
+        progress.setProgressBar(null, progressSessionId);
+      }
     }
     return pdb;
   }
@@ -637,8 +653,8 @@ public class StructureSelectionManager
           AlignSeq maxAlignseq)
   {
     final StringBuilder mappingDetails = new StringBuilder(128);
-    mappingDetails.append(NEWLINE).append(
-            "Sequence \u27f7 Structure mapping details");
+    mappingDetails.append(NEWLINE)
+            .append("Sequence \u27f7 Structure mapping details");
     mappingDetails.append(NEWLINE);
     mappingDetails
             .append("Method: inferred with Needleman & Wunsch alignment");
@@ -670,18 +686,19 @@ public class StructureSelectionManager
             .append(" ");
     mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
     mappingDetails.append(NEWLINE).append("SEQ start/end ");
-    mappingDetails.append(
-            String.valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
+    mappingDetails
+            .append(String
+                    .valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
             .append(" ");
-    mappingDetails.append(String.valueOf(maxAlignseq.seq1end
-            + (seq.getStart() - 1)));
+    mappingDetails.append(
+            String.valueOf(maxAlignseq.seq1end + (seq.getStart() - 1)));
     mappingDetails.append(NEWLINE);
     maxChain.makeExactMapping(maxAlignseq, seq);
     jalview.datamodel.Mapping sqmpping = maxAlignseq
             .getMappingFromS1(false);
     maxChain.transferRESNUMFeatures(seq, null);
 
-    HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
+    HashMap<Integer, int[]> mapping = new HashMap<>();
     int resNum = -10000;
     int index = 0;
     char insCode = ' ';
@@ -696,8 +713,9 @@ public class StructureSelectionManager
         insCode = tmp.insCode;
         if (tmp.alignmentMapping >= -1)
         {
-          mapping.put(tmp.alignmentMapping + 1, new int[] { tmp.resNumber,
-              tmp.atomIndex });
+          mapping.put(tmp.alignmentMapping + 1,
+                  new int[]
+                  { tmp.resNumber, tmp.atomIndex });
         }
       }
 
@@ -734,7 +752,7 @@ public class StructureSelectionManager
      * Remove mappings to the closed listener's PDB files, but first check if
      * another listener is still interested
      */
-    List<String> pdbs = new ArrayList<String>(Arrays.asList(pdbfiles));
+    List<String> pdbs = new ArrayList<>(Arrays.asList(pdbfiles));
 
     StructureListener sl;
     for (int i = 0; i < listeners.size(); i++)
@@ -755,7 +773,7 @@ public class StructureSelectionManager
      */
     if (pdbs.size() > 0)
     {
-      List<StructureMapping> tmp = new ArrayList<StructureMapping>();
+      List<StructureMapping> tmp = new ArrayList<>();
       for (StructureMapping sm : mappings)
       {
         if (!pdbs.contains(sm.pdbfile))
@@ -775,7 +793,8 @@ public class StructureSelectionManager
    * @param chain
    * @param pdbfile
    */
-  public void mouseOverStructure(int pdbResNum, String chain, String pdbfile)
+  public void mouseOverStructure(int pdbResNum, String chain,
+          String pdbfile)
   {
     AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
     List<AtomSpec> atoms = Collections.singletonList(atomSpec);
@@ -807,7 +826,8 @@ public class StructureSelectionManager
       return;
     }
 
-    SearchResultsI results = findAlignmentPositionsForStructurePositions(atoms);
+    SearchResultsI results = findAlignmentPositionsForStructurePositions(
+            atoms);
     for (Object li : listeners)
     {
       if (li instanceof SequenceListener)
@@ -839,7 +859,7 @@ public class StructureSelectionManager
                 && sm.pdbchain.equals(atom.getChain()))
         {
           int indexpos = sm.getSeqPos(atom.getPdbResNum());
-          if (lastipos != indexpos && lastseq != sm.sequence)
+          if (lastipos != indexpos || lastseq != sm.sequence)
           {
             results.addResult(sm.sequence, indexpos, indexpos);
             lastipos = indexpos;
@@ -947,11 +967,10 @@ public class StructureSelectionManager
       return;
     }
     int atomNo;
-    List<AtomSpec> atoms = new ArrayList<AtomSpec>();
+    List<AtomSpec> atoms = new ArrayList<>();
     for (StructureMapping sm : mappings)
     {
-      if (sm.sequence == seq
-              || sm.sequence == seq.getDatasetSequence()
+      if (sm.sequence == seq || sm.sequence == seq.getDatasetSequence()
               || (sm.sequence.getDatasetSequence() != null && sm.sequence
                       .getDatasetSequence() == seq.getDatasetSequence()))
       {
@@ -961,8 +980,8 @@ public class StructureSelectionManager
 
           if (atomNo > 0)
           {
-            atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain, sm
-                    .getPDBResNum(index), atomNo));
+            atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain,
+                    sm.getPDBResNum(index), atomNo));
           }
         }
       }
@@ -1056,7 +1075,7 @@ public class StructureSelectionManager
 
   public StructureMapping[] getMapping(String pdbfile)
   {
-    List<StructureMapping> tmp = new ArrayList<StructureMapping>();
+    List<StructureMapping> tmp = new ArrayList<>();
     for (StructureMapping sm : mappings)
     {
       if (sm.pdbfile.equals(pdbfile))
@@ -1216,7 +1235,7 @@ public class StructureSelectionManager
     }
   }
 
-  Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
+  Vector<AlignmentViewPanelListener> view_listeners = new Vector<>();
 
   public synchronized void sendViewPosition(
           jalview.api.AlignmentViewPanel source, int startRes, int endRes,
@@ -1328,8 +1347,8 @@ public class StructureSelectionManager
   {
     if (command instanceof EditCommand)
     {
-      return MappingUtils.mapEditCommand((EditCommand) command, undo,
-              mapTo, gapChar, seqmappings);
+      return MappingUtils.mapEditCommand((EditCommand) command, undo, mapTo,
+              gapChar, seqmappings);
     }
     else if (command instanceof OrderCommand)
     {
@@ -1339,35 +1358,6 @@ public class StructureSelectionManager
     return null;
   }
 
-  public IProgressIndicator getProgressIndicator()
-  {
-    return progressIndicator;
-  }
-
-  public void setProgressIndicator(IProgressIndicator progressIndicator)
-  {
-    this.progressIndicator = progressIndicator;
-  }
-
-  public long getProgressSessionId()
-  {
-    return progressSessionId;
-  }
-
-  public void setProgressSessionId(long progressSessionId)
-  {
-    this.progressSessionId = progressSessionId;
-  }
-
-  public void setProgressBar(String message)
-  {
-    if (progressIndicator == null)
-    {
-      return;
-    }
-    progressIndicator.setProgressBar(message, progressSessionId);
-  }
-
   public List<AlignedCodonFrame> getSequenceMappings()
   {
     return seqmappings;
index 1637631..2528286 100644 (file)
@@ -53,9 +53,9 @@ import java.util.List;
  * @author gmcarstairs
  *
  */
-public abstract class AAStructureBindingModel extends
-        SequenceStructureBindingModel implements StructureListener,
-        StructureSelectionManagerProvider
+public abstract class AAStructureBindingModel
+        extends SequenceStructureBindingModel
+        implements StructureListener, StructureSelectionManagerProvider
 {
 
   private StructureSelectionManager ssm;
@@ -142,7 +142,6 @@ public abstract class AAStructureBindingModel extends
    * @param ssm
    * @param pdbentry
    * @param sequenceIs
-   * @param chains
    * @param protocol
    */
   public AAStructureBindingModel(StructureSelectionManager ssm,
@@ -154,8 +153,60 @@ public abstract class AAStructureBindingModel extends
     this.nucleotide = Comparison.isNucleotide(sequenceIs);
     this.pdbEntry = pdbentry;
     this.protocol = protocol;
+    resolveChains();
   }
 
+  private boolean resolveChains()
+  {
+    /**
+     * final count of chain mappings discovered
+     */
+    int chainmaps = 0;
+    // JBPNote: JAL-2693 - this should be a list of chain mappings per
+    // [pdbentry][sequence]
+    String[][] newchains = new String[pdbEntry.length][];
+    int pe = 0;
+    for (PDBEntry pdb : pdbEntry)
+    {
+      SequenceI[] seqsForPdb = sequence[pe];
+      if (seqsForPdb != null)
+      {
+        newchains[pe] = new String[seqsForPdb.length];
+        int se = 0;
+        for (SequenceI asq : seqsForPdb)
+        {
+          String chain = (chains != null && chains[pe] != null)
+                  ? chains[pe][se]
+                  : null;
+          SequenceI sq = (asq.getDatasetSequence() == null) ? asq
+                  : asq.getDatasetSequence();
+          if (sq.getAllPDBEntries() != null)
+          {
+            for (PDBEntry pdbentry : sq.getAllPDBEntries())
+            {
+              if (pdb.getFile() != null && pdbentry.getFile() != null
+                      && pdb.getFile().equals(pdbentry.getFile()))
+              {
+                String chaincode = pdbentry.getChainCode();
+                if (chaincode != null && chaincode.length() > 0)
+                {
+                  chain = chaincode;
+                  chainmaps++;
+                  break;
+                }
+              }
+            }
+          }
+          newchains[pe][se] = chain;
+          se++;
+        }
+        pe++;
+      }
+    }
+
+    chains = newchains;
+    return chainmaps > 0;
+  }
   public StructureSelectionManager getSsm()
   {
     return ssm;
@@ -300,7 +351,8 @@ public abstract class AAStructureBindingModel extends
     {
       throw new Error(MessageManager.formatMessage(
               "error.implementation_error_no_pdbentry_from_index",
-              new Object[] { Integer.valueOf(pe).toString() }));
+              new Object[]
+              { Integer.valueOf(pe).toString() }));
     }
     final String nullChain = "TheNullChain";
     List<SequenceI> s = new ArrayList<SequenceI>();
@@ -638,8 +690,8 @@ public abstract class AAStructureBindingModel extends
 
     if (waiting)
     {
-      System.err
-              .println("Timed out waiting for structure viewer to load file "
+      System.err.println(
+              "Timed out waiting for structure viewer to load file "
                       + notLoaded);
       return false;
     }
@@ -657,10 +709,8 @@ public abstract class AAStructureBindingModel extends
         {
           for (SequenceI s : seqs)
           {
-            if (s == seq
-                    || (s.getDatasetSequence() != null && s
-                            .getDatasetSequence() == seq
-                            .getDatasetSequence()))
+            if (s == seq || (s.getDatasetSequence() != null
+                    && s.getDatasetSequence() == seq.getDatasetSequence()))
             {
               return true;
             }
@@ -732,7 +782,8 @@ public abstract class AAStructureBindingModel extends
    * 
    * @return
    */
-  public abstract SequenceRenderer getSequenceRenderer(AlignmentViewPanel alignment);
+  public abstract SequenceRenderer getSequenceRenderer(
+          AlignmentViewPanel alignment);
 
   protected abstract void colourBySequence(
           StructureMappingcommandSet[] colourBySequenceCommands);
@@ -757,9 +808,9 @@ public abstract class AAStructureBindingModel extends
       return;
     }
     String[] files = getStructureFiles();
-  
+
     SequenceRenderer sr = getSequenceRenderer(alignmentv);
-  
+
     StructureMappingcommandSet[] colourBySequenceCommands = getColourBySequenceCommands(
             files, sr, alignmentv);
     colourBySequence(colourBySequenceCommands);
index afe4073..e656431 100644 (file)
@@ -22,8 +22,8 @@ package jalview.structures.models;
 
 import jalview.api.SequenceStructureBinding;
 
-public class SequenceStructureBindingModel implements
-        SequenceStructureBinding
+public class SequenceStructureBindingModel
+        implements SequenceStructureBinding
 {
 
   /**
index 07f4068..86d5660 100644 (file)
@@ -149,8 +149,7 @@ public class CustomUrlProvider extends UrlProviderImpl
     {
       Map.Entry<String, String> pair = it.next();
       urls.put(pair.getKey(),
- new UrlLink(pair.getKey(), pair.getValue(),
-              pair.getKey()));
+              new UrlLink(pair.getKey(), pair.getValue(), pair.getKey()));
     }
     upgradeOldLinks(urls);
     return urls;
@@ -161,10 +160,24 @@ public class CustomUrlProvider extends UrlProviderImpl
    */
   private void upgradeOldLinks(HashMap<String, UrlLink> urls)
   {
+    boolean upgrade = false;
     // upgrade old SRS link
     if (urls.containsKey(SRS_LABEL))
     {
       urls.remove(SRS_LABEL);
+      upgrade = true;
+    }
+    // upgrade old EBI link - easier just to remove and re-add than faffing
+    // around checking exact url
+    if (urls.containsKey(UrlConstants.DEFAULT_LABEL))
+    {
+      // note because this is called separately for selected and nonselected
+      // urls, the default url will not always be present
+      urls.remove(UrlConstants.DEFAULT_LABEL);
+      upgrade = true;
+    }
+    if (upgrade)
+    {
       UrlLink link = new UrlLink(UrlConstants.DEFAULT_STRING);
       link.setLabel(UrlConstants.DEFAULT_LABEL);
       urls.put(UrlConstants.DEFAULT_LABEL, link);
@@ -296,15 +309,13 @@ public class CustomUrlProvider extends UrlProviderImpl
         }
         if (link.getIsSelected())
         {
-          selurls.put(link.getId(),
-                  new UrlLink(link.getDescription(), link.getUrl(), link.getDescription()));
+          selurls.put(link.getId(), new UrlLink(link.getDescription(),
+                  link.getUrl(), link.getDescription()));
         }
         else
         {
-          unselurls
-                  .put(link.getId(),
-                          new UrlLink(link.getDescription(), link.getUrl(), link
-                                  .getDescription()));
+          unselurls.put(link.getId(), new UrlLink(link.getDescription(),
+                  link.getUrl(), link.getDescription()));
         }
         // sort out primary and selected ids
         if (link.getIsPrimary())
@@ -336,7 +347,8 @@ public class CustomUrlProvider extends UrlProviderImpl
   @Override
   public boolean contains(String id)
   {
-    return (selectedUrls.containsKey(id) || nonselectedUrls.containsKey(id));
+    return (selectedUrls.containsKey(id)
+            || nonselectedUrls.containsKey(id));
   }
 
 }
index c938666..0988e7d 100644 (file)
@@ -76,8 +76,7 @@ public class IdentifiersUrlProvider extends UrlProviderImpl
    *          name of identifiers.org download file
    * @return hashmap of identifiers.org data, keyed by MIRIAM id
    */
-  private HashMap<String, UrlLink> readIdentifiers(
-          String idFileName)
+  private HashMap<String, UrlLink> readIdentifiers(String idFileName)
   {
     JSONParser parser = new JSONParser();
 
@@ -99,8 +98,8 @@ public class IdentifiersUrlProvider extends UrlProviderImpl
       }
       else
       {
-        System.out
-                .println("Unexpected key returned from identifiers jalview service");
+        System.out.println(
+                "Unexpected key returned from identifiers jalview service");
         return idData;
       }
 
index 09566c3..39d6b35 100644 (file)
@@ -72,8 +72,8 @@ public class UrlLinkDisplay
 
   private UrlLink link;
 
-  public UrlLinkDisplay(String rowId, UrlLink rowLink,
-          boolean rowSelected, boolean rowDefault)
+  public UrlLinkDisplay(String rowId, UrlLink rowLink, boolean rowSelected,
+          boolean rowDefault)
   {
     id = rowId;
     isPrimary = rowDefault;
index d6d26b5..a0f42f0 100644 (file)
@@ -162,8 +162,8 @@ public class UrlLinkTableModel extends AbstractTableModel
   public boolean isRowDeletable(int rowIndex)
   {
     // to delete, row must be a user entered row, and not the default row
-    return (dataProvider.isUserEntry(data.get(rowIndex).getId()) && !data
-            .get(rowIndex).getIsPrimary());
+    return (dataProvider.isUserEntry(data.get(rowIndex).getId())
+            && !data.get(rowIndex).getIsPrimary());
   }
 
   @Override
index bd01e89..2cb0173 100644 (file)
@@ -84,11 +84,11 @@ public class UrlProvider implements UrlProviderI
       }
     }
 
-    System.out
-            .println("Error initialising UrlProvider - no custom url provider");
+    System.out.println(
+            "Error initialising UrlProvider - no custom url provider");
     return null;
   }
-  
+
   @Override
   public boolean setPrimaryUrl(String id)
   {
@@ -120,7 +120,7 @@ public class UrlProvider implements UrlProviderI
     }
     return outcome;
   }
-  
+
   @Override
   public String writeUrlsAsString(boolean selected)
   {
@@ -235,7 +235,7 @@ public class UrlProvider implements UrlProviderI
     }
     return target;
   }
-  
+
   @Override
   public String choosePrimaryUrl()
   {
index c1a57ca..d2fd359 100644 (file)
@@ -46,7 +46,8 @@ public abstract class UrlProviderImpl implements UrlProviderI
 
   protected String primaryUrl;
 
-  protected String getPrimaryUrl(String seqid, HashMap<String, UrlLink> urls)
+  protected String getPrimaryUrl(String seqid,
+          HashMap<String, UrlLink> urls)
   {
     if (seqid.length() < MIN_SUBST_LENGTH)
     {
@@ -103,8 +104,8 @@ public abstract class UrlProviderImpl implements UrlProviderI
       {
         isSelected = selected;
       }
-      displayLinks.add(new UrlLinkDisplay(key, entry.getValue(),
-              isSelected, isPrimary));
+      displayLinks.add(new UrlLinkDisplay(key, entry.getValue(), isSelected,
+              isPrimary));
     }
     return displayLinks;
   }
@@ -120,4 +121,3 @@ public abstract class UrlProviderImpl implements UrlProviderI
     return !isMiriamId(id);
   }
 }
-
index b96113e..6d756c4 100644 (file)
@@ -20,7 +20,6 @@
  */
 package jalview.urls.api;
 
-
 /**
  * Interface to UrlProvider factories
  * 
index 7a585be..6698414 100644 (file)
@@ -48,8 +48,8 @@ import java.io.PipedInputStream;
 import java.io.PipedOutputStream;
 import java.io.PrintStream;
 
-public class AWTConsole extends WindowAdapter implements WindowListener,
-        ActionListener, Runnable
+public class AWTConsole extends WindowAdapter
+        implements WindowListener, ActionListener, Runnable
 {
   private Frame frame;
 
index 4a0b80a..0bc09cc 100755 (executable)
@@ -69,14 +69,14 @@ import java.lang.reflect.Method;
  * functionality or any adverse or unexpected effects of using this software.
  * <p>
  * Credits: <br>
- * Steven Spencer, JavaWorld magazine (<a
- * href="http://www.javaworld.com/javaworld/javatips/jw-javatip66.html">Java Tip
- * 66</a>) <br>
+ * Steven Spencer, JavaWorld magazine
+ * (<a href="http://www.javaworld.com/javaworld/javatips/jw-javatip66.html">Java
+ * Tip 66</a>) <br>
  * Thanks also to Ron B. Yeh, Eric Shapiro, Ben Engber, Paul Teitlebaum, Andrea
  * Cantatore, Larry Barowski, Trevor Bedzek, Frank Miedrich, and Ron Rabakukk
  * 
- * @author Eric Albert (<a
- *         href="mailto:ejalbert@cs.stanford.edu">ejalbert@cs.stanford.edu</a>)
+ * @author Eric Albert (<a href=
+ *         "mailto:ejalbert@cs.stanford.edu">ejalbert@cs.stanford.edu</a>)
  * @version 1.4b1 (Released June 20, 2001)
  */
 public class BrowserLauncher
@@ -338,17 +338,22 @@ public class BrowserLauncher
         aeDescClass = Class.forName("com.apple.MacOS.AEDesc");
 
         aeTargetConstructor = aeTargetClass
-                .getDeclaredConstructor(new Class[] { int.class });
+                .getDeclaredConstructor(new Class[]
+                { int.class });
         appleEventConstructor = appleEventClass
-                .getDeclaredConstructor(new Class[] { int.class, int.class,
-                    aeTargetClass, int.class, int.class });
+                .getDeclaredConstructor(new Class[]
+                { int.class, int.class, aeTargetClass, int.class,
+                    int.class });
         aeDescConstructor = aeDescClass
-                .getDeclaredConstructor(new Class[] { String.class });
+                .getDeclaredConstructor(new Class[]
+                { String.class });
 
         makeOSType = osUtilsClass.getDeclaredMethod("makeOSType",
-                new Class[] { String.class });
+                new Class[]
+                { String.class });
         putParameter = appleEventClass.getDeclaredMethod("putParameter",
-                new Class[] { int.class, aeDescClass });
+                new Class[]
+                { int.class, aeDescClass });
         sendNoReply = appleEventClass.getDeclaredMethod("sendNoReply",
                 new Class[] {});
 
@@ -399,11 +404,14 @@ public class BrowserLauncher
                 .getDeclaredField("kSystemFolderType");
         kSystemFolderType = systemFolderField.get(null);
         findFolder = mrjFileUtilsClass.getDeclaredMethod("findFolder",
-                new Class[] { mrjOSTypeClass });
-        getFileCreator = mrjFileUtilsClass.getDeclaredMethod(
-                "getFileCreator", new Class[] { File.class });
+                new Class[]
+                { mrjOSTypeClass });
+        getFileCreator = mrjFileUtilsClass
+                .getDeclaredMethod("getFileCreator", new Class[]
+                { File.class });
         getFileType = mrjFileUtilsClass.getDeclaredMethod("getFileType",
-                new Class[] { File.class });
+                new Class[]
+                { File.class });
       } catch (ClassNotFoundException cnfe)
       {
         errorMessage = cnfe.getMessage();
@@ -439,9 +447,11 @@ public class BrowserLauncher
       {
         Class linker = Class.forName("com.apple.mrj.jdirect.Linker");
         Constructor constructor = linker
-                .getConstructor(new Class[] { Class.class });
+                .getConstructor(new Class[]
+                { Class.class });
         linkage = constructor
-                .newInstance(new Object[] { BrowserLauncher.class });
+                .newInstance(new Object[]
+                { BrowserLauncher.class });
       } catch (ClassNotFoundException cnfe)
       {
         errorMessage = cnfe.getMessage();
@@ -477,7 +487,8 @@ public class BrowserLauncher
       {
         mrjFileUtilsClass = Class.forName("com.apple.mrj.MRJFileUtils");
         openURL = mrjFileUtilsClass.getDeclaredMethod("openURL",
-                new Class[] { String.class });
+                new Class[]
+                { String.class });
       } catch (ClassNotFoundException cnfe)
       {
         errorMessage = cnfe.getMessage();
@@ -524,14 +535,18 @@ public class BrowserLauncher
       try
       {
         Integer finderCreatorCode = (Integer) makeOSType.invoke(null,
-                new Object[] { FINDER_CREATOR });
+                new Object[]
+                { FINDER_CREATOR });
         Object aeTarget = aeTargetConstructor
-                .newInstance(new Object[] { finderCreatorCode });
+                .newInstance(new Object[]
+                { finderCreatorCode });
         Integer gurlType = (Integer) makeOSType.invoke(null,
-                new Object[] { GURL_EVENT });
-        Object appleEvent = appleEventConstructor.newInstance(new Object[] {
-            gurlType, gurlType, aeTarget, kAutoGenerateReturnID,
-            kAnyTransactionID });
+                new Object[]
+                { GURL_EVENT });
+        Object appleEvent = appleEventConstructor
+                .newInstance(new Object[]
+                { gurlType, gurlType, aeTarget, kAutoGenerateReturnID,
+                    kAnyTransactionID });
 
         // Don't set browser = appleEvent because then the next time we call
         // locateBrowser(), we'll get the same AppleEvent, to which we'll
@@ -569,7 +584,8 @@ public class BrowserLauncher
       try
       {
         systemFolder = (File) findFolder.invoke(null,
-                new Object[] { kSystemFolderType });
+                new Object[]
+                { kSystemFolderType });
       } catch (IllegalArgumentException iare)
       {
         browser = null;
@@ -615,7 +631,8 @@ public class BrowserLauncher
           if (FINDER_TYPE.equals(fileType.toString()))
           {
             Object fileCreator = getFileCreator.invoke(null,
-                    new Object[] { file });
+                    new Object[]
+                    { file });
 
             if (FINDER_CREATOR.equals(fileCreator.toString()))
             {
@@ -696,8 +713,9 @@ public class BrowserLauncher
   {
     if (!loadedWithoutErrors)
     {
-      throw new IOException(MessageManager.formatMessage(
-              "exception.browser_not_found", new String[] { errorMessage }));
+      throw new IOException(MessageManager
+              .formatMessage("exception.browser_not_found", new String[]
+              { errorMessage }));
     }
 
     Object browser = locateBrowser();
@@ -705,8 +723,8 @@ public class BrowserLauncher
     if (browser == null)
     {
       throw new IOException(MessageManager.formatMessage(
-              "exception.browser_unable_to_locate",
-              new String[] { errorMessage }));
+              "exception.browser_unable_to_locate", new String[]
+              { errorMessage }));
     }
 
     switch (jvm)
@@ -719,13 +737,15 @@ public class BrowserLauncher
       {
         aeDesc = aeDescConstructor.newInstance(new Object[] { url });
         putParameter.invoke(browser,
-                new Object[] { keyDirectObject, aeDesc });
+                new Object[]
+                { keyDirectObject, aeDesc });
         sendNoReply.invoke(browser, new Object[] {});
       } catch (InvocationTargetException ite)
       {
         throw new IOException(MessageManager.formatMessage(
                 "exception.invocation_target_exception_creating_aedesc",
-                new String[] { ite.getMessage() }));
+                new String[]
+                { ite.getMessage() }));
       } catch (IllegalAccessException iae)
       {
         throw new IOException(MessageManager.formatMessage(
@@ -771,15 +791,15 @@ public class BrowserLauncher
         else
         {
           throw new IOException(MessageManager.formatMessage(
-                  "exception.unable_to_launch_url", new String[] { Integer
-                          .valueOf(result).toString() }));
+                  "exception.unable_to_launch_url", new String[]
+                  { Integer.valueOf(result).toString() }));
         }
       }
       else
       {
         throw new IOException(MessageManager.formatMessage(
-                "exception.unable_to_create_internet_config",
-                new String[] { Integer.valueOf(result).toString() }));
+                "exception.unable_to_create_internet_config", new String[]
+                { Integer.valueOf(result).toString() }));
       }
 
       break;
@@ -792,13 +812,13 @@ public class BrowserLauncher
       } catch (InvocationTargetException ite)
       {
         throw new IOException(MessageManager.formatMessage(
-                "exception.invocation_target_calling_url",
-                new String[] { ite.getMessage() }));
+                "exception.invocation_target_calling_url", new String[]
+                { ite.getMessage() }));
       } catch (IllegalAccessException iae)
       {
         throw new IOException(MessageManager.formatMessage(
-                "exception.illegal_access_calling_url",
-                new String[] { iae.getMessage() }));
+                "exception.illegal_access_calling_url", new String[]
+                { iae.getMessage() }));
       }
 
       break;
@@ -808,8 +828,9 @@ public class BrowserLauncher
 
       // Add quotes around the URL to allow ampersands and other special
       // characters to work.
-      Process process = Runtime.getRuntime().exec(
-              new String[] { (String) browser, FIRST_WINDOWS_PARAMETER,
+      Process process = Runtime.getRuntime()
+              .exec(new String[]
+              { (String) browser, FIRST_WINDOWS_PARAMETER,
                   SECOND_WINDOWS_PARAMETER, THIRD_WINDOWS_PARAMETER,
                   '"' + url + '"' });
 
@@ -823,8 +844,8 @@ public class BrowserLauncher
       } catch (InterruptedException ie)
       {
         throw new IOException(MessageManager.formatMessage(
-                "exception.interrupted_launching_browser",
-                new String[] { ie.getMessage() }));
+                "exception.interrupted_launching_browser", new String[]
+                { ie.getMessage() }));
       }
 
       break;
@@ -842,10 +863,9 @@ public class BrowserLauncher
        * NETSCAPE_REMOTE_PARAMETER+" "+ NETSCAPE_OPEN_PARAMETER_START + url +
        * NETSCAPE_OPEN_NEW_WINDOW + NETSCAPE_OPEN_PARAMETER_END);
        */
-      process = Runtime.getRuntime().exec(
-              new String[] {
-                  (String) browser,
-                  NETSCAPE_REMOTE_PARAMETER,
+      process = Runtime.getRuntime()
+              .exec(new String[]
+              { (String) browser, NETSCAPE_REMOTE_PARAMETER,
 
                   NETSCAPE_OPEN_PARAMETER_START + url
                           + NETSCAPE_OPEN_NEW_WINDOW
@@ -862,8 +882,8 @@ public class BrowserLauncher
       } catch (InterruptedException ie)
       {
         throw new IOException(MessageManager.formatMessage(
-                "exception.interrupted_launching_browser",
-                new String[] { ie.getMessage() }));
+                "exception.interrupted_launching_browser", new String[]
+                { ie.getMessage() }));
       }
 
       break;
index b66e80d..a01c035 100644 (file)
@@ -71,7 +71,7 @@ public final class CaseInsensitiveString
   @Override
   public int hashCode()
   {
-    return value == null ? super.hashCode() : value.toUpperCase()
-            .hashCode();
+    return value == null ? super.hashCode()
+            : value.toUpperCase().hashCode();
   }
 }
index d7829df..d4be322 100644 (file)
@@ -134,12 +134,12 @@ public class ColorUtils
      * prop = proportion of the way value is from minValue to maxValue
      */
     float prop = (value - minValue) / (maxValue - minValue);
-    float r = minColour.getRed() + prop
-            * (maxColour.getRed() - minColour.getRed());
-    float g = minColour.getGreen() + prop
-            * (maxColour.getGreen() - minColour.getGreen());
-    float b = minColour.getBlue() + prop
-            * (maxColour.getBlue() - minColour.getBlue());
+    float r = minColour.getRed()
+            + prop * (maxColour.getRed() - minColour.getRed());
+    float g = minColour.getGreen()
+            + prop * (maxColour.getGreen() - minColour.getGreen());
+    float b = minColour.getBlue()
+            + prop * (maxColour.getBlue() - minColour.getBlue());
     return new Color(r / 255, g / 255, b / 255);
   }
 
@@ -210,7 +210,7 @@ public class ColorUtils
       return null;
     }
     colour = colour.trim();
-  
+
     Color col = null;
     try
     {
@@ -219,12 +219,12 @@ public class ColorUtils
     } catch (NumberFormatException ex)
     {
     }
-  
+
     if (col == null)
     {
       col = ColorUtils.getAWTColorFromName(colour);
     }
-  
+
     if (col == null)
     {
       try
@@ -242,7 +242,7 @@ public class ColorUtils
         // non-numeric token or out of 0-255 range
       }
     }
-  
+
     return col;
   }
 
@@ -263,32 +263,34 @@ public class ColorUtils
     int lsize = name.length();
     int start = 0;
     int end = lsize / 3;
-  
+
     int rgbOffset = Math.abs(name.hashCode() % 10) * 15; // 0-135
-  
+
     /*
      * red: first third
      */
-    int r = Math.abs(name.substring(start, end).hashCode() + rgbOffset) % 210 + 20;
+    int r = Math.abs(name.substring(start, end).hashCode() + rgbOffset)
+            % 210 + 20;
     start = end;
     end += lsize / 3;
     if (end > lsize)
     {
       end = lsize;
     }
-  
+
     /*
      * green: second third
      */
-    int g = Math.abs(name.substring(start, end).hashCode() + rgbOffset) % 210 + 20;
-  
+    int g = Math.abs(name.substring(start, end).hashCode() + rgbOffset)
+            % 210 + 20;
+
     /*
      * blue: third third
      */
     int b = Math.abs(name.substring(end).hashCode() + rgbOffset) % 210 + 20;
-  
+
     Color color = new Color(r, g, b);
-  
+
     return color;
   }
 
@@ -307,7 +309,7 @@ public class ColorUtils
     }
     Color col = null;
     name = name.toLowerCase();
-  
+
     // or make a static map; or use reflection on the field name
     switch (name)
     {
@@ -351,7 +353,7 @@ public class ColorUtils
       col = Color.yellow;
       break;
     }
-  
+
     return col;
   }
 }
index 22e1ab7..d4fc233 100644 (file)
@@ -40,8 +40,9 @@ public class Comparison
 
   public static final char GAP_DASH = '-';
 
-  public static final String GapChars = new String(new char[] { GAP_SPACE,
-      GAP_DOT, GAP_DASH });
+  public static final String GapChars = new String(
+          new char[]
+          { GAP_SPACE, GAP_DOT, GAP_DASH });
 
   /**
    * DOCUMENT ME!
@@ -71,7 +72,8 @@ public class Comparison
    *          int
    * @return float
    */
-  public static float compare(SequenceI ii, SequenceI jj, int start, int end)
+  public static float compare(SequenceI ii, SequenceI jj, int start,
+          int end)
   {
     String si = ii.getSequenceAsString();
     String sj = jj.getSequenceAsString();
@@ -97,8 +99,8 @@ public class Comparison
     {
       for (int j = 0; j < jlen; j++)
       {
-        if (si.substring(start + j, start + j + 1).equals(
-                sj.substring(start + j, start + j + 1)))
+        if (si.substring(start + j, start + j + 1)
+                .equals(sj.substring(start + j, start + j + 1)))
         {
           match++;
         }
@@ -112,8 +114,8 @@ public class Comparison
     {
       for (int j = 0; j < jlen; j++)
       {
-        if (si.substring(start + j, start + j + 1).equals(
-                sj.substring(start + j, start + j + 1)))
+        if (si.substring(start + j, start + j + 1)
+                .equals(sj.substring(start + j, start + j + 1)))
         {
           match++;
         }
@@ -150,7 +152,8 @@ public class Comparison
    * @deprecated use PIDModel.computePID()
    */
   @Deprecated
-  public final static float PID(String seq1, String seq2, int start, int end)
+  public final static float PID(String seq1, String seq2, int start,
+          int end)
   {
     return PID(seq1, seq2, start, end, true, false);
   }
@@ -282,35 +285,10 @@ public class Comparison
     {
       return false;
     }
-    char[][] letters = new char[seqs.length][];
-    for (int i = 0; i < seqs.length; i++)
-    {
-      if (seqs[i] != null)
-      {
-        char[] sequence = seqs[i].getSequence();
-        if (sequence != null)
-        {
-          letters[i] = sequence;
-        }
-      }
-    }
-
-    return areNucleotide(letters);
-  }
 
-  /**
-   * Answers true if more than 85% of the sequence residues (ignoring gaps) are
-   * A, G, C, T or U, else false. This is just a heuristic guess and may give a
-   * wrong answer (as AGCT are also amino acid codes).
-   * 
-   * @param letters
-   * @return
-   */
-  static final boolean areNucleotide(char[][] letters)
-  {
     int ntCount = 0;
     int aaCount = 0;
-    for (char[] seq : letters)
+    for (SequenceI seq : seqs)
     {
       if (seq == null)
       {
@@ -318,8 +296,10 @@ public class Comparison
       }
       // TODO could possibly make an informed guess just from the first sequence
       // to save a lengthy calculation
-      for (char c : seq)
+      int len = seq.getLength();
+      for (int i = 0; i < len; i++)
       {
+        char c = seq.getCharAt(i);
         if (isNucleotide(c))
         {
           ntCount++;
@@ -419,8 +399,8 @@ public class Comparison
         flattened.add(s);
       }
     }
-    final SequenceI[] oneDArray = flattened.toArray(new SequenceI[flattened
-            .size()]);
+    final SequenceI[] oneDArray = flattened
+            .toArray(new SequenceI[flattened.size()]);
     return isNucleotide(oneDArray);
   }
 
index 04cb75e..50a34fc 100755 (executable)
@@ -140,8 +140,8 @@ public class DBRefUtils
       return false;
     }
     String coordsys = dasCoordinateSystemsLookup.get(string.toLowerCase());
-    return coordsys == null ? false : coordsys.equals(dBRefEntry
-            .getSource());
+    return coordsys == null ? false
+            : coordsys.equals(dBRefEntry.getSource());
   }
 
   /**
@@ -257,9 +257,8 @@ public class DBRefUtils
           if (refa.getAccessionId() == null
                   || refb.getAccessionId().equals(refa.getAccessionId()))
           {
-            if (refa.getMap() == null
-                    || (refb.getMap() != null && refb.getMap().equals(
-                            refa.getMap())))
+            if (refa.getMap() == null || (refb.getMap() != null
+                    && refb.getMap().equals(refa.getMap())))
             {
               return true;
             }
@@ -301,19 +300,18 @@ public class DBRefUtils
     @Override
     public boolean matches(DBRefEntry refa, DBRefEntry refb)
     {
-      if (refa.getSource() != null
-              && refb.getSource() != null
+      if (refa.getSource() != null && refb.getSource() != null
               && DBRefUtils.getCanonicalName(refb.getSource()).equals(
                       DBRefUtils.getCanonicalName(refa.getSource())))
       {
         // We dont care about version
         if (refa.getAccessionId() != null && refb.getAccessionId() != null
-        // FIXME should be && not || here?
+                // FIXME should be && not || here?
                 || refb.getAccessionId().equals(refa.getAccessionId()))
         {
           if ((refa.getMap() == null || refb.getMap() == null)
-                  || (refa.getMap() != null && refb.getMap() != null && refb
-                          .getMap().equals(refa.getMap())))
+                  || (refa.getMap() != null && refb.getMap() != null
+                          && refb.getMap().equals(refa.getMap())))
           {
             return true;
           }
@@ -334,8 +332,7 @@ public class DBRefUtils
     @Override
     public boolean matches(DBRefEntry refa, DBRefEntry refb)
     {
-      if (refa.getSource() != null
-              && refb.getSource() != null
+      if (refa.getSource() != null && refb.getSource() != null
               && DBRefUtils.getCanonicalName(refb.getSource()).equals(
                       DBRefUtils.getCanonicalName(refa.getSource())))
       {
@@ -346,11 +343,12 @@ public class DBRefUtils
           if ((refa.getMap() == null && refb.getMap() == null)
                   || (refa.getMap() != null && refb.getMap() != null))
           {
-            if ((refb.getMap().getMap() == null && refa.getMap().getMap() == null)
+            if ((refb.getMap().getMap() == null
+                    && refa.getMap().getMap() == null)
                     || (refb.getMap().getMap() != null
-                            && refa.getMap().getMap() != null && refb
-                            .getMap().getMap().getInverse()
-                            .equals(refa.getMap().getMap())))
+                            && refa.getMap().getMap() != null
+                            && refb.getMap().getMap().getInverse()
+                                    .equals(refa.getMap().getMap())))
             {
               return true;
             }
@@ -372,8 +370,7 @@ public class DBRefUtils
     @Override
     public boolean matches(DBRefEntry refa, DBRefEntry refb)
     {
-      if (refa.getSource() != null
-              && refb.getSource() != null
+      if (refa.getSource() != null && refb.getSource() != null
               && DBRefUtils.getCanonicalName(refb.getSource()).equals(
                       DBRefUtils.getCanonicalName(refa.getSource())))
       {
@@ -388,12 +385,13 @@ public class DBRefUtils
           {
             return true;
           }
-          if (refa.getMap() != null
-                  && refb.getMap() != null
-                  && ((refb.getMap().getMap() == null && refa.getMap()
-                          .getMap() == null) || (refb.getMap().getMap() != null
-                          && refa.getMap().getMap() != null && refb
-                          .getMap().getMap().equals(refa.getMap().getMap()))))
+          if (refa.getMap() != null && refb.getMap() != null
+                  && ((refb.getMap().getMap() == null
+                          && refa.getMap().getMap() == null)
+                          || (refb.getMap().getMap() != null
+                                  && refa.getMap().getMap() != null
+                                  && refb.getMap().getMap()
+                                          .equals(refa.getMap().getMap()))))
           {
             return true;
           }
@@ -413,8 +411,7 @@ public class DBRefUtils
     @Override
     public boolean matches(DBRefEntry refa, DBRefEntry refb)
     {
-      if (refa.getSource() != null
-              && refb.getSource() != null
+      if (refa.getSource() != null && refb.getSource() != null
               && DBRefUtils.getCanonicalName(refb.getSource()).equals(
                       DBRefUtils.getCanonicalName(refa.getSource())))
       {
@@ -428,11 +425,12 @@ public class DBRefUtils
             return true;
           }
           if ((refa.getMap() != null && refb.getMap() != null)
-                  && (refb.getMap().getMap() == null && refa.getMap()
-                          .getMap() == null)
+                  && (refb.getMap().getMap() == null
+                          && refa.getMap().getMap() == null)
                   || (refb.getMap().getMap() != null
-                          && refa.getMap().getMap() != null && (refb
-                          .getMap().getMap().equals(refa.getMap().getMap()))))
+                          && refa.getMap().getMap() != null
+                          && (refb.getMap().getMap()
+                                  .equals(refa.getMap().getMap()))))
           {
             return true;
           }
@@ -561,8 +559,8 @@ public class DBRefUtils
     {
       return true;
     }
-    return DBRefUtils.getCanonicalName(o1).equals(
-            DBRefUtils.getCanonicalName(o2));
+    return DBRefUtils.getCanonicalName(o1)
+            .equals(DBRefUtils.getCanonicalName(o2));
   }
 
   /**
@@ -578,8 +576,8 @@ public class DBRefUtils
   public static DBRefEntry[] selectDbRefs(boolean selectDna,
           DBRefEntry[] refs)
   {
-    return selectRefs(refs, selectDna ? DBRefSource.DNACODINGDBS
-            : DBRefSource.PROTEINDBS);
+    return selectRefs(refs,
+            selectDna ? DBRefSource.DNACODINGDBS : DBRefSource.PROTEINDBS);
     // could attempt to find other cross
     // refs here - ie PDB xrefs
     // (not dna, not protein seq)
@@ -693,8 +691,7 @@ public class DBRefUtils
       }
 
       // collate candidates and promote them
-      DBRefEntry[] candidates = selectRefs(
-              selfs.toArray(new DBRefEntry[0]),
+      DBRefEntry[] candidates = selectRefs(selfs.toArray(new DBRefEntry[0]),
               promType.toArray(new String[0]));
       if (candidates != null)
       {
@@ -724,9 +721,9 @@ public class DBRefUtils
           toPromote.add(cand);
           if (!cand.isPrimaryCandidate())
           {
-            System.out.println("Warning: Couldn't promote dbref "
-                    + cand.toString() + " for sequence "
-                    + sequence.toString());
+            System.out.println(
+                    "Warning: Couldn't promote dbref " + cand.toString()
+                            + " for sequence " + sequence.toString());
           }
         }
       }
index bf52027..ce7ab6d 100755 (executable)
@@ -790,8 +790,8 @@ public class Format
     {
       w = width;
     }
-    else if (((fmt == 'd') || (fmt == 'i') || (fmt == 'x') || (fmt == 'X') || (fmt == 'o'))
-            && (precision > 0))
+    else if (((fmt == 'd') || (fmt == 'i') || (fmt == 'x') || (fmt == 'X')
+            || (fmt == 'o')) && (precision > 0))
     {
       w = precision;
     }
@@ -833,7 +833,8 @@ public class Format
     double factor = 1;
     String leading_zeroes = "";
 
-    for (int i = 1; (i <= precision) && (factor <= 0x7FFFFFFFFFFFFFFFL); i++)
+    for (int i = 1; (i <= precision)
+            && (factor <= 0x7FFFFFFFFFFFFFFFL); i++)
     {
       factor *= 10;
       leading_zeroes = leading_zeroes + "0";
index e2e83a4..a26dfbb 100644 (file)
@@ -198,9 +198,8 @@ public class GroupUrlLink
     for (int pass = 0; pass < mtch.length; pass++)
     {
       int mlength = 3 + mtch[pass].length();
-      if (link.indexOf("$" + mtch[pass] + "=/") == ptok[pass]
-              && (p = link.indexOf("/=$", ptok[pass] + mlength)) > ptok[pass]
-                      + mlength)
+      if (link.indexOf("$" + mtch[pass] + "=/") == ptok[pass] && (p = link
+              .indexOf("/=$", ptok[pass] + mlength)) > ptok[pass] + mlength)
       {
         // Extract Regex and suffix
         if (ptok[pass + 1] < p + 3)
@@ -215,8 +214,8 @@ public class GroupUrlLink
         regexReplace[pass] = link.substring(ptok[pass] + mlength, p);
         try
         {
-          com.stevesoft.pat.Regex rg = com.stevesoft.pat.Regex.perlCode("/"
-                  + regexReplace[pass] + "/");
+          com.stevesoft.pat.Regex rg = com.stevesoft.pat.Regex
+                  .perlCode("/" + regexReplace[pass] + "/");
           if (rg == null)
           {
             invalidMessage = "Invalid Regular Expression : '"
@@ -384,8 +383,8 @@ public class GroupUrlLink
    * @param dsstring
    * @return
    */
-  private Hashtable replacementArgs(String[] idstrings,
-          String[] seqstrings, String dsstring)
+  private Hashtable replacementArgs(String[] idstrings, String[] seqstrings,
+          String dsstring)
   {
     Hashtable rstrings = new Hashtable();
     rstrings.put(tokens[0], idstrings);
@@ -393,9 +392,8 @@ public class GroupUrlLink
     rstrings.put(tokens[2], new String[] { dsstring });
     if (idstrings.length != seqstrings.length)
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.idstring_seqstrings_only_one_per_sequence"));
+      throw new Error(MessageManager.getString(
+              "error.idstring_seqstrings_only_one_per_sequence"));
     }
     return rstrings;
   }
@@ -415,15 +413,16 @@ public class GroupUrlLink
    * @return URL stub objects ready to pass to constructFrom
    * @throws UrlStringTooLongException
    */
-  public Object[] makeUrlStubs(String[] ids, String[] seqstr,
-          String string, boolean b) throws UrlStringTooLongException
+  public Object[] makeUrlStubs(String[] ids, String[] seqstr, String string,
+          boolean b) throws UrlStringTooLongException
   {
     Hashtable rstrings = replacementArgs(ids, seqstr, string);
     Object[] stubs = makeUrlsIf(false, rstrings, b);
     if (stubs != null)
     {
       return new Object[] { stubs[0], stubs[1], rstrings,
-          new boolean[] { b } };
+          new boolean[]
+          { b } };
     }
     // TODO Auto-generated method stub
     return null;
@@ -458,9 +457,8 @@ public class GroupUrlLink
    *         }, String[] { url })}
    * @throws UrlStringTooLongException
    */
-  protected Object[] makeUrlsIf(boolean createFullUrl,
-          Hashtable repstrings, boolean onlyIfMatches)
-          throws UrlStringTooLongException
+  protected Object[] makeUrlsIf(boolean createFullUrl, Hashtable repstrings,
+          boolean onlyIfMatches) throws UrlStringTooLongException
   {
     int pass = 0;
 
@@ -486,7 +484,8 @@ public class GroupUrlLink
           {
             throw new Error(MessageManager.formatMessage(
                     "error.cannot_have_mixed_length_replacement_vectors",
-                    new String[] { (mtch[i]),
+                    new String[]
+                    { (mtch[i]),
                         Integer.valueOf(idseq[i].length).toString(),
                         Integer.valueOf(maxs).toString() }));
           }
@@ -494,9 +493,8 @@ public class GroupUrlLink
       }
       else
       {
-        throw new Error(
-                MessageManager
-                        .getString("error.cannot_have_zero_length_vector_replacement_strings"));
+        throw new Error(MessageManager.getString(
+                "error.cannot_have_zero_length_vector_replacement_strings"));
       }
     }
     // iterate through input, collating segments to be inserted into url
@@ -508,8 +506,8 @@ public class GroupUrlLink
       matched[pass] = new StringBuffer();
       if (regexReplace[pass] != null)
       {
-        rgxs[pass] = com.stevesoft.pat.Regex.perlCode("/"
-                + regexReplace[pass] + "/");
+        rgxs[pass] = com.stevesoft.pat.Regex
+                .perlCode("/" + regexReplace[pass] + "/");
       }
       else
       {
@@ -708,7 +706,8 @@ public class GroupUrlLink
     }
 
     return new Object[] { new int[] { seqsmatched }, thismatched, matched,
-        new String[] { submiturl.toString() } };
+        new String[]
+        { submiturl.toString() } };
   }
 
   /**
@@ -825,16 +824,16 @@ public class GroupUrlLink
         "EnVision2|Seqs|http://www.ebi.ac.uk/enfin-srv/envision2/pages/linkin.jsf?workflow=$SEQUENCEIDS$&datasetName=$DATASETID$&input=$SEQUENCES$&inputType=1|,",
         "EnVision2 Seqs|http://www.ebi.ac.uk/enfin-srv/envision2/pages/linkin.jsf?workflow=Default&datasetName=JalviewSeqs$DATASETID$&input=$SEQUENCES=/([a-zA-Z]+)/=$&inputType=1|,",
         "EnVision2 Seqs|http://www.ebi.ac.uk/enfin-srv/envision2/pages/linkin.jsf?workflow=Default&datasetName=JalviewSeqs$DATASETID$&input=$SEQUENCES=/[A-Za-z]+/=$&inputType=1|,"
-    /*
-     * http://www.ebi.ac.uk/enfin-srv/envision2/pages/linkin.jsf?input=P38389,P38398
-     * &inputType=0&workflow=Enfin%20Default%20Workflow&datasetName=
-     * linkInDatasetFromPRIDE
-     */
+        /*
+         * http://www.ebi.ac.uk/enfin-srv/envision2/pages/linkin.jsf?input=P38389,P38398
+         * &inputType=0&workflow=Enfin%20Default%20Workflow&datasetName=
+         * linkInDatasetFromPRIDE
+         */
     };
 
-    SequenceI[] seqs = new SequenceI[] { new Sequence(
-            "StupidLabel:gi|9234|pdb|102L|A",
-            "asdiasdpasdpadpwpadasdpaspdw"), };
+    SequenceI[] seqs = new SequenceI[] {
+        new Sequence("StupidLabel:gi|9234|pdb|102L|A",
+                "asdiasdpasdpadpwpadasdpaspdw"), };
     String[][] seqsandids = formStrings(seqs);
     for (int i = 0; i < links.length; i++)
     {
@@ -842,15 +841,15 @@ public class GroupUrlLink
       if (ul.isValid())
       {
         System.out.println("\n\n\n");
-        System.out.println("Link " + i + " " + links[i] + " : "
-                + ul.toString());
+        System.out.println(
+                "Link " + i + " " + links[i] + " : " + ul.toString());
         System.out.println(" pref : " + ul.getUrl_prefix());
         System.out.println(" IdReplace : " + ul.getIDRegexReplace());
         System.out.println(" SeqReplace : " + ul.getSeqRegexReplace());
         System.out.println(" Suffixes : " + ul.getUrl_suffix());
 
-        System.out
-                .println("<insert input id and sequence strings here> Without onlyIfMatches:");
+        System.out.println(
+                "<insert input id and sequence strings here> Without onlyIfMatches:");
         Object[] urls;
         try
         {
@@ -861,8 +860,8 @@ public class GroupUrlLink
         {
           System.out.println("too long exception " + ex);
         }
-        System.out
-                .println("<insert input id and sequence strings here> With onlyIfMatches set:");
+        System.out.println(
+                "<insert input id and sequence strings here> With onlyIfMatches set:");
         try
         {
           urls = ul.makeUrls(seqsandids[0], seqsandids[1], "mydataset",
index fa2533f..7840261 100755 (executable)
@@ -79,7 +79,8 @@ public class ImageMaker
   public enum TYPE
   {
     EPS("EPS", MessageManager.getString("label.eps_file"), getEPSChooser()),
-    PNG("PNG", MessageManager.getString("label.png_image"), getPNGChooser()),
+    PNG("PNG", MessageManager.getString("label.png_image"),
+            getPNGChooser()),
     SVG("SVG", "SVG", getSVGChooser());
 
     private JalviewFileChooser chooser;
@@ -133,8 +134,8 @@ public class ImageMaker
 
       if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
       {
-        jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
-                .getSelectedFile().getParent());
+        jalview.bin.Cache.setProperty("LAST_DIRECTORY",
+                chooser.getSelectedFile().getParent());
         file = chooser.getSelectedFile();
       }
       else
@@ -169,8 +170,8 @@ public class ImageMaker
       {
         System.out.println("Error creating " + type.getName() + " file.");
 
-        setProgressMessage(MessageManager.formatMessage(
-                "info.error_creating_file", type.getName()));
+        setProgressMessage(MessageManager
+                .formatMessage("info.error_creating_file", type.getName()));
       }
     }
   }
@@ -247,8 +248,8 @@ public class ImageMaker
       pg.setAccurateTextMode(accurateText);
 
       graphics = pg;
-      setProgressMessage(MessageManager.formatMessage(
-              "status.export_complete", type.getName()));
+      setProgressMessage(MessageManager
+              .formatMessage("status.export_complete", type.getName()));
     } catch (Exception ex)
     {
     }
@@ -261,8 +262,8 @@ public class ImageMaker
     Graphics2D ig2 = (Graphics2D) graphics;
     ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
             RenderingHints.VALUE_ANTIALIAS_ON);
-    setProgressMessage(MessageManager.formatMessage(
-            "status.export_complete", type.getName()));
+    setProgressMessage(MessageManager
+            .formatMessage("status.export_complete", type.getName()));
 
   }
 
@@ -298,8 +299,8 @@ public class ImageMaker
               SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
     }
 
-    setProgressMessage(MessageManager.formatMessage(
-            "status.export_complete", type.getName()));
+    setProgressMessage(MessageManager
+            .formatMessage("status.export_complete", type.getName()));
     graphics = g2;
   }
 
diff --git a/src/jalview/util/IntRangeComparator.java b/src/jalview/util/IntRangeComparator.java
new file mode 100644 (file)
index 0000000..a0a29f2
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.util;
+
+import java.util.Comparator;
+
+/**
+ * A comparator to order [from, to] ranges into ascending or descending order of
+ * their start position
+ */
+public class IntRangeComparator implements Comparator<int[]>
+{
+  public static final Comparator<int[]> ASCENDING = new IntRangeComparator(
+          true);
+
+  public static final Comparator<int[]> DESCENDING = new IntRangeComparator(
+          false);
+
+  boolean forwards;
+
+  IntRangeComparator(boolean forward)
+  {
+    forwards = forward;
+  }
+
+  @Override
+  public int compare(int[] o1, int[] o2)
+  {
+    int compared = Integer.compare(o1[0], o2[0]);
+    return forwards ? compared : -compared;
+  }
+
+}
\ No newline at end of file
index 58abdc3..4658724 100644 (file)
@@ -103,10 +103,9 @@ public class MapList
     {
       return false;
     }
-    return Arrays
-            .deepEquals(fromShifts.toArray(), obj.fromShifts.toArray())
-            && Arrays
-                    .deepEquals(toShifts.toArray(), obj.toShifts.toArray());
+    return Arrays.deepEquals(fromShifts.toArray(), obj.fromShifts.toArray())
+            && Arrays.deepEquals(toShifts.toArray(),
+                    obj.toShifts.toArray());
   }
 
   /**
@@ -373,10 +372,12 @@ public class MapList
        * drop this range if it lies within the last range
        */
       if ((lastDirection == 1 && range[0] >= lastRange[0]
-              && range[0] <= lastRange[1] && range[1] >= lastRange[0] && range[1] <= lastRange[1])
+              && range[0] <= lastRange[1] && range[1] >= lastRange[0]
+              && range[1] <= lastRange[1])
               || (lastDirection == -1 && range[0] <= lastRange[0]
                       && range[0] >= lastRange[1]
-                      && range[1] <= lastRange[0] && range[1] >= lastRange[1]))
+                      && range[1] <= lastRange[0]
+                      && range[1] >= lastRange[1]))
       {
         changed = true;
         continue;
@@ -391,8 +392,10 @@ public class MapList
       boolean sameDirection = range[1] == range[0]
               || direction == lastDirection;
       boolean extending = range[0] == lastRange[1] + lastDirection;
-      boolean overlapping = (lastDirection == 1 && range[0] >= lastRange[0] && range[0] <= lastRange[1])
-              || (lastDirection == -1 && range[0] <= lastRange[0] && range[0] >= lastRange[1]);
+      boolean overlapping = (lastDirection == 1 && range[0] >= lastRange[0]
+              && range[0] <= lastRange[1])
+              || (lastDirection == -1 && range[0] <= lastRange[0]
+                      && range[0] >= lastRange[1]);
       if (sameDirection && (overlapping || extending))
       {
         lastRange[1] = range[1];
@@ -961,15 +964,17 @@ public class MapList
     // TODO not used - remove?
     if (local)
     {
-      return ((getFromLowest() >= map.getFromLowest() && getFromHighest() <= map
-              .getFromHighest()) || (getFromLowest() <= map.getFromLowest() && getFromHighest() >= map
-              .getFromHighest()));
+      return ((getFromLowest() >= map.getFromLowest()
+              && getFromHighest() <= map.getFromHighest())
+              || (getFromLowest() <= map.getFromLowest()
+                      && getFromHighest() >= map.getFromHighest()));
     }
     else
     {
-      return ((getToLowest() >= map.getToLowest() && getToHighest() <= map
-              .getToHighest()) || (getToLowest() <= map.getToLowest() && getToHighest() >= map
-              .getToHighest()));
+      return ((getToLowest() >= map.getToLowest()
+              && getToHighest() <= map.getToHighest())
+              || (getToLowest() <= map.getToLowest()
+                      && getToHighest() >= map.getToHighest()));
     }
   }
 
index b2ec120..9c5c109 100644 (file)
@@ -219,8 +219,9 @@ public final class MappingUtils
              * Shift Delete start position left, as it acts on positions to its
              * right.
              */
-            int mappedEditPos = action == Action.DELETE_GAP ? match[0]
-                    - mappedCount : match[0];
+            int mappedEditPos = action == Action.DELETE_GAP
+                    ? match[0] - mappedCount
+                    : match[0];
             Edit e = result.new Edit(action, new SequenceI[] { targetSeq },
                     mappedEditPos, mappedCount, gapChar);
             result.addEdit(e);
@@ -230,15 +231,15 @@ public final class MappingUtils
              */
             if (action == Action.INSERT_GAP)
             {
-              copyTarget.setSequence(new String(StringUtils.insertCharAt(
-                      copyTarget.getSequence(), mappedEditPos, mappedCount,
-                      gapChar)));
+              copyTarget.setSequence(new String(
+                      StringUtils.insertCharAt(copyTarget.getSequence(),
+                              mappedEditPos, mappedCount, gapChar)));
             }
             else if (action == Action.DELETE_GAP)
             {
-              copyTarget.setSequence(new String(StringUtils.deleteChars(
-                      copyTarget.getSequence(), mappedEditPos,
-                      mappedEditPos + mappedCount)));
+              copyTarget.setSequence(new String(
+                      StringUtils.deleteChars(copyTarget.getSequence(),
+                              mappedEditPos, mappedEditPos + mappedCount)));
             }
           }
         }
@@ -363,8 +364,9 @@ public final class MappingUtils
 
       for (AlignedCodonFrame acf : codonFrames)
       {
-        SequenceI mappedSequence = targetIsNucleotide ? acf
-                .getDnaForAaSeq(selected) : acf.getAaForDnaSeq(selected);
+        SequenceI mappedSequence = targetIsNucleotide
+                ? acf.getDnaForAaSeq(selected)
+                : acf.getAaForDnaSeq(selected);
         if (mappedSequence != null)
         {
           for (SequenceI seq : mapTo.getAlignment().getSequences())
@@ -377,7 +379,8 @@ public final class MappingUtils
                * Found a sequence mapping. Locate the start/end mapped residues.
                */
               List<AlignedCodonFrame> mapping = Arrays
-                      .asList(new AlignedCodonFrame[] { acf });
+                      .asList(new AlignedCodonFrame[]
+                      { acf });
               SearchResultsI sr = buildSearchResults(selected,
                       startResiduePos, mapping);
               for (SearchResultMatchI m : sr.getResults())
@@ -398,11 +401,11 @@ public final class MappingUtils
                * returns a base 1 position, SequenceGroup uses base 0
                */
               int mappedStartCol = seq.findIndex(mappedStartResidue) - 1;
-              minStartCol = minStartCol == -1 ? mappedStartCol : Math.min(
-                      minStartCol, mappedStartCol);
+              minStartCol = minStartCol == -1 ? mappedStartCol
+                      : Math.min(minStartCol, mappedStartCol);
               int mappedEndCol = seq.findIndex(mappedEndResidue) - 1;
-              maxEndCol = maxEndCol == -1 ? mappedEndCol : Math.max(
-                      maxEndCol, mappedEndCol);
+              maxEndCol = maxEndCol == -1 ? mappedEndCol
+                      : Math.max(maxEndCol, mappedEndCol);
               mappedGroup.addSequence(seq, false);
               break;
             }
@@ -429,8 +432,8 @@ public final class MappingUtils
    *          the mappings available
    * @return
    */
-  public static CommandI mapOrderCommand(OrderCommand command,
-          boolean undo, AlignmentI mapTo, List<AlignedCodonFrame> mappings)
+  public static CommandI mapOrderCommand(OrderCommand command, boolean undo,
+          AlignmentI mapTo, List<AlignedCodonFrame> mappings)
   {
     SequenceI[] sortOrder = command.getSequenceOrder(undo);
     List<SequenceI> mappedOrder = new ArrayList<>();
@@ -592,10 +595,9 @@ public final class MappingUtils
    * @param toSequences
    * @param fromGapChar
    */
-  protected static void mapColumn(int col,
-          List<AlignedCodonFrame> mappings, ColumnSelection mappedColumns,
-          List<SequenceI> fromSequences, List<SequenceI> toSequences,
-          char fromGapChar)
+  protected static void mapColumn(int col, List<AlignedCodonFrame> mappings,
+          ColumnSelection mappedColumns, List<SequenceI> fromSequences,
+          List<SequenceI> toSequences, char fromGapChar)
   {
     int[] mappedTo = findMappedColumns(col, mappings, fromSequences,
             toSequences, fromGapChar);
@@ -701,8 +703,8 @@ public final class MappingUtils
     {
       if (mapping.involvesSequence(seq))
       {
-        List<char[]> codons = mapping.getMappedCodons(
-                seq.getDatasetSequence(), dsPos);
+        List<char[]> codons = mapping
+                .getMappedCodons(seq.getDatasetSequence(), dsPos);
         if (codons != null)
         {
           result.addAll(codons);
@@ -790,8 +792,9 @@ public final class MappingUtils
             SequenceI otherDataset = otherseq.getDatasetSequence();
             if (otherseq == sequence
                     || otherseq == sequence.getDatasetSequence()
-                    || (otherDataset != null && (otherDataset == sequence || otherDataset == sequence
-                            .getDatasetSequence())))
+                    || (otherDataset != null && (otherDataset == sequence
+                            || otherDataset == sequence
+                                    .getDatasetSequence())))
             {
               // skip sequences in subset which directly relate to sequence
               continue;
@@ -831,8 +834,8 @@ public final class MappingUtils
     {
       if (range.length % 2 != 0)
       {
-        System.err.println("Error unbalance start/end ranges: "
-                + ranges.toString());
+        System.err.println(
+                "Error unbalance start/end ranges: " + ranges.toString());
         return 0;
       }
       for (int i = 0; i < range.length - 1; i += 2)
@@ -936,4 +939,55 @@ public final class MappingUtils
     }
     return copy;
   }
+
+  /**
+   * Removes the specified number of positions from the given ranges. Provided
+   * to allow a stop codon to be stripped from a CDS sequence so that it matches
+   * the peptide translation length.
+   * 
+   * @param positions
+   * @param ranges
+   *          a list of (single) [start, end] ranges
+   * @return
+   */
+  public static void removeEndPositions(int positions,
+          List<int[]> ranges)
+  {
+    int toRemove = positions;
+    Iterator<int[]> it = new ReverseListIterator<>(ranges);
+    while (toRemove > 0)
+    {
+      int[] endRange = it.next();
+      if (endRange.length != 2)
+      {
+        /*
+         * not coded for [start1, end1, start2, end2, ...]
+         */
+        System.err
+                .println("MappingUtils.removeEndPositions doesn't handle multiple  ranges");
+        return;
+      }
+
+      int length = endRange[1] - endRange[0] + 1;
+      if (length <= 0)
+      {
+        /*
+         * not coded for a reverse strand range (end < start)
+         */
+        System.err
+                .println("MappingUtils.removeEndPositions doesn't handle reverse strand");
+        return;
+      }
+      if (length > toRemove)
+      {
+        endRange[1] -= toRemove;
+        toRemove = 0;
+      }
+      else
+      {
+        toRemove -= length;
+        it.remove();
+      }
+    }
+  }
 }
index 4001cb2..3494181 100644 (file)
@@ -38,8 +38,8 @@ public class MessageManager
 
   private static ResourceBundle rb;
 
-  private static Logger log = Logger.getLogger(MessageManager.class
-          .getCanonicalName());
+  private static Logger log = Logger
+          .getLogger(MessageManager.class.getCanonicalName());
 
   private static Locale loc;
 
@@ -119,8 +119,8 @@ public class MessageManager
       name = rb.getString(smkey);
     } catch (Exception x)
     {
-      log.finest("I18N missing key with root " + keyroot + ": " + loc
-              + "\t" + smkey);
+      log.finest("I18N missing key with root " + keyroot + ": " + loc + "\t"
+              + smkey);
     }
     return name;
   }
index 139ee19..6713bbc 100644 (file)
@@ -153,8 +153,8 @@ public class ParseHtmlBodyAndLinks
     {
       // instead of parsing the html into plaintext
       // clean the description ready for embedding in html
-      sb = new StringBuilder(LEFT_ANGLE_BRACKET_PATTERN
-              .matcher(description).replaceAll("&lt;"));
+      sb = new StringBuilder(LEFT_ANGLE_BRACKET_PATTERN.matcher(description)
+              .replaceAll("&lt;"));
     }
     content = translateEntities(sb.toString());
   }
index 49dc7ff..2c74609 100644 (file)
@@ -30,7 +30,7 @@ import java.awt.event.MouseEvent;
  */
 public class Platform
 {
-  private static Boolean isAMac = null;
+  private static Boolean isAMac = null, isWindows = null;
 
   private static Boolean isHeadless = null;
 
@@ -45,10 +45,29 @@ public class Platform
     {
       isAMac = System.getProperty("os.name").indexOf("Mac") > -1;
     }
+
     return isAMac.booleanValue();
 
   }
 
+  /**
+   * Check if we are on a Microsoft plaform...
+   * 
+   * @return true if we have to cope with another platform variation
+   */
+  public static boolean isWindows()
+  {
+    if (isWindows == null)
+    {
+      isWindows = System.getProperty("os.name").indexOf("Win") > -1;
+    }
+    return isWindows.booleanValue();
+  }
+
+  /**
+   * 
+   * @return true if we are running in non-interactive no UI mode
+   */
   public static boolean isHeadless()
   {
     if (isHeadless == null)
@@ -121,8 +140,8 @@ public class Platform
       {
         return false;
       }
-      return (Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() & e
-              .getModifiers()) != 0;
+      return (Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()
+              & e.getModifiers()) != 0;
       // could we use e.isMetaDown() here?
     }
     return e.isControlDown();
index 62fd56e..0c0fabf 100755 (executable)
@@ -51,8 +51,8 @@ public class QuickSort
     @Override
     public int compare(Integer o1, Integer o2)
     {
-      return ascending ? Float.compare(values[o1], values[o2]) : Float
-              .compare(values[o2], values[o1]);
+      return ascending ? Float.compare(values[o1], values[o2])
+              : Float.compare(values[o2], values[o1]);
     }
   }
 
@@ -105,8 +105,8 @@ public class QuickSort
     @Override
     public int compare(Integer o1, Integer o2)
     {
-      return ascending ? Integer.compare(values[o1], values[o2]) : Integer
-              .compare(values[o2], values[o1]);
+      return ascending ? Integer.compare(values[o1], values[o2])
+              : Integer.compare(values[o2], values[o1]);
     }
   }
 
@@ -129,8 +129,8 @@ public class QuickSort
     @Override
     public int compare(Integer o1, Integer o2)
     {
-      return ascending ? values[o1].compareTo(values[o2]) : values[o2]
-              .compareTo(values[o1]);
+      return ascending ? values[o1].compareTo(values[o2])
+              : values[o2].compareTo(values[o1]);
     }
   }
 
@@ -475,10 +475,10 @@ public class QuickSort
     /*
      * Copy sorted positive values after the negatives and zeros
      */
-    System.arraycopy(nonZeroFloats, negativeCount, arr, negativeCount
-            + zerosCount, positiveCount);
-    System.arraycopy(nonZeroChars, negativeCount, s, negativeCount
-            + zerosCount, positiveCount);
+    System.arraycopy(nonZeroFloats, negativeCount, arr,
+            negativeCount + zerosCount, positiveCount);
+    System.arraycopy(nonZeroChars, negativeCount, s,
+            negativeCount + zerosCount, positiveCount);
   }
 
   /**
@@ -613,10 +613,10 @@ public class QuickSort
     /*
      * Copy sorted positive values after the negatives and zeros
      */
-    System.arraycopy(nonZeroInts, negativeCount, arr, negativeCount
-            + zerosCount, positiveCount);
-    System.arraycopy(nonZeroChars, negativeCount, s, negativeCount
-            + zerosCount, positiveCount);
+    System.arraycopy(nonZeroInts, negativeCount, arr,
+            negativeCount + zerosCount, positiveCount);
+    System.arraycopy(nonZeroChars, negativeCount, s,
+            negativeCount + zerosCount, positiveCount);
   }
 
   /**
diff --git a/src/jalview/util/RangeComparator.java b/src/jalview/util/RangeComparator.java
deleted file mode 100644 (file)
index f911a9b..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-package jalview.util;
-
-import java.util.Comparator;
-
-/**
- * A comparator to order [from, to] ranges into ascending or descending order of
- * their start position
- */
-public class RangeComparator implements Comparator<int[]>
-{
-  boolean forwards;
-
-  public RangeComparator(boolean forward)
-  {
-    forwards = forward;
-  }
-
-  @Override
-  public int compare(int[] o1, int[] o2)
-  {
-    int compared = Integer.compare(o1[0], o2[0]);
-    return forwards ? compared : -compared;
-  }
-
-}
\ No newline at end of file
index 381d9f6..06b627d 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.util;
 
 import java.util.Set;
index 7fd9792..2e9436b 100644 (file)
@@ -85,9 +85,11 @@ public class SparseCount
     }
     else
     {
-      try {
+      try
+      {
         newValue = shortProfile.add(key, value);
-      } catch (ArithmeticException e) {
+      } catch (ArithmeticException e)
+      {
         handleOverflow();
         newValue = intProfile.add(key, value);
       }
index b5ab40d..b3456aa 100644 (file)
@@ -138,7 +138,8 @@ public class StringUtils
    * @param delimiter
    * @return elements separated by separator
    */
-  public static String[] separatorListToArray(String input, String delimiter)
+  public static String[] separatorListToArray(String input,
+          String delimiter)
   {
     int seplen = delimiter.length();
     if (input == null || input.equals("") || input.equals(delimiter))
@@ -155,9 +156,8 @@ public class StringUtils
       if (wasescaped || wasquoted)
       {
         // append to previous pos
-        jv.set(jv.size() - 1,
-                lstitem = lstitem + delimiter
-                        + input.substring(cp, pos + escape));
+        jv.set(jv.size() - 1, lstitem = lstitem + delimiter
+                + input.substring(cp, pos + escape));
       }
       else
       {
@@ -201,8 +201,8 @@ public class StringUtils
     }
     if (DEBUG)
     {
-      System.err.println("Empty Array from '" + delimiter
-              + "' separated List");
+      System.err.println(
+              "Empty Array from '" + delimiter + "' separated List");
     }
     return null;
   }
@@ -235,16 +235,16 @@ public class StringUtils
       }
       if (DEBUG)
       {
-        System.err.println("Returning '" + separator
-                + "' separated List:\n");
+        System.err
+                .println("Returning '" + separator + "' separated List:\n");
         System.err.println(v);
       }
       return v.toString();
     }
     if (DEBUG)
     {
-      System.err.println("Returning empty '" + separator
-              + "' separated List\n");
+      System.err.println(
+              "Returning empty '" + separator + "' separated List\n");
     }
     return "" + separator;
   }
@@ -364,8 +364,8 @@ public class StringUtils
         }
       } catch (NumberFormatException e)
       {
-        System.err.println("Invalid version format found: "
-                + e.getMessage());
+        System.err
+                .println("Invalid version format found: " + e.getMessage());
         return 0;
       }
     }
index 666f945..e2a0aca 100755 (executable)
@@ -192,8 +192,8 @@ public class TableSorter extends AbstractTableModel
               .getDefaultRenderer();
       if (defaultRenderer instanceof SortableHeaderRenderer)
       {
-        this.tableHeader
-                .setDefaultRenderer(((SortableHeaderRenderer) defaultRenderer).tableCellRenderer);
+        this.tableHeader.setDefaultRenderer(
+                ((SortableHeaderRenderer) defaultRenderer).tableCellRenderer);
       }
     }
     this.tableHeader = tableHeader;
@@ -595,7 +595,8 @@ public class TableSorter extends AbstractTableModel
         JLabel l = (JLabel) c;
         l.setHorizontalTextPosition(JLabel.LEFT);
         int modelColumn = table.convertColumnIndexToModel(column);
-        l.setIcon(getHeaderRendererIcon(modelColumn, l.getFont().getSize()));
+        l.setIcon(
+                getHeaderRendererIcon(modelColumn, l.getFont().getSize()));
       }
       return c;
     }
index 3347cc7..e5cfaee 100644 (file)
@@ -55,7 +55,9 @@ public class UrlConstants
    * Default sequence URL link string for EMBL-EBI search
    */
   public static final String DEFAULT_STRING = DEFAULT_LABEL
-          + "|http://www.ebi.ac.uk/ebisearch/search.ebi?db=allebi&query=$SEQUENCE_ID$";
+          + "|https://www.ebi.ac.uk/ebisearch/search.ebi?db=allebi&query=$SEQUENCE_ID$";
+
+  private static final String COLON = ":";
 
   /*
    * not instantiable
@@ -63,4 +65,12 @@ public class UrlConstants
   private UrlConstants()
   {
   }
+
+  public static boolean isDefaultString(String link)
+  {
+    String sublink = link.substring(link.indexOf(COLON) + 1);
+    String subdefault = DEFAULT_STRING
+            .substring(DEFAULT_STRING.indexOf(COLON) + 1);
+    return sublink.equalsIgnoreCase(subdefault);
+  }
 }
index 0529c73..007da86 100644 (file)
@@ -176,8 +176,12 @@ public class UrlLink
     String var = (usesDBaccession ? DB_ACCESSION : SEQUENCE_ID);
 
     return urlPrefix
-            + (dynamic ? (DELIM + var + ((regexReplace != null) ? EQUALS
-                    + regexReplace + EQUALS + DELIM : DELIM)) : "")
+            + (dynamic
+                    ? (DELIM + var
+                            + ((regexReplace != null)
+                                    ? EQUALS + regexReplace + EQUALS + DELIM
+                                    : DELIM))
+                    : "")
             + ((urlSuffix == null) ? "" : urlSuffix);
   }
 
@@ -262,8 +266,8 @@ public class UrlLink
     {
       if (regexReplace != null)
       {
-        com.stevesoft.pat.Regex rg = com.stevesoft.pat.Regex.perlCode("/"
-                + regexReplace + "/");
+        com.stevesoft.pat.Regex rg = com.stevesoft.pat.Regex
+                .perlCode("/" + regexReplace + "/");
         if (rg.search(idstring))
         {
           int ns = rg.numSubs();
@@ -321,8 +325,8 @@ public class UrlLink
                 if (rg.matchedFrom(s) > -1)
                 {
                   subs.addElement(rg.stringMatched(s));
-                  subs.addElement(urlPrefix + rg.stringMatched(s)
-                          + urlSuffix);
+                  subs.addElement(
+                          urlPrefix + rg.stringMatched(s) + urlSuffix);
                 }
                 s++;
               }
@@ -470,8 +474,8 @@ public class UrlLink
       regexReplace = link.substring(sqidPos + startLength, p);
       try
       {
-        com.stevesoft.pat.Regex rg = com.stevesoft.pat.Regex.perlCode("/"
-                + regexReplace + "/");
+        com.stevesoft.pat.Regex rg = com.stevesoft.pat.Regex
+                .perlCode("/" + regexReplace + "/");
         if (rg == null)
         {
           invalidMessage = "Invalid Regular Expression : '" + regexReplace
@@ -573,7 +577,8 @@ public class UrlLink
     {
       // collect matching db-refs
       DBRefEntry[] dbr = DBRefUtils.selectRefs(seq.getDBRefs(),
-              new String[] { target });
+              new String[]
+              { target });
 
       // if there are any dbrefs which match up with the link
       if (dbr != null)
index 2881e81..a0cbff4 100644 (file)
@@ -22,6 +22,7 @@ package jalview.viewmodel;
 
 import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
 import jalview.analysis.Conservation;
+import jalview.analysis.TreeModel;
 import jalview.api.AlignCalcManagerI;
 import jalview.api.AlignViewportI;
 import jalview.api.AlignmentViewPanel;
@@ -33,7 +34,6 @@ import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.AlignmentView;
 import jalview.datamodel.Annotation;
-import jalview.datamodel.CigarArray;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.HiddenSequences;
@@ -77,10 +77,10 @@ import java.util.Map;
  * @author jimp
  * 
  */
-public abstract class AlignmentViewport implements AlignViewportI,
-        CommandListener, VamsasSource
+public abstract class AlignmentViewport
+        implements AlignViewportI, CommandListener, VamsasSource
 {
-  final protected ViewportRanges ranges;
+  protected ViewportRanges ranges;
 
   protected ViewStyleI viewStyle = new ViewStyle();
 
@@ -568,8 +568,6 @@ public abstract class AlignmentViewport implements AlignViewportI,
     viewStyle.setSeqNameItalics(default1);
   }
 
-
-
   @Override
   public AlignmentI getAlignment()
   {
@@ -666,8 +664,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
         sg.setColourScheme(cs);
         if (cs != null)
         {
-          sg.getGroupColourScheme()
-                  .alignmentChanged(sg, hiddenRepSequences);
+          sg.getGroupColourScheme().alignmentChanged(sg,
+                  hiddenRepSequences);
         }
       }
     }
@@ -676,8 +674,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
   @Override
   public ColourSchemeI getGlobalColourScheme()
   {
-    return residueShading == null ? null : residueShading
-            .getColourScheme();
+    return residueShading == null ? null : residueShading.getColourScheme();
   }
 
   @Override
@@ -825,11 +822,11 @@ public abstract class AlignmentViewport implements AlignViewportI,
     {
       return;
     }
-    if (calculator
-            .getRegisteredWorkersOfClass(jalview.workers.ConservationThread.class) == null)
+    if (calculator.getRegisteredWorkersOfClass(
+            jalview.workers.ConservationThread.class) == null)
     {
-      calculator.registerWorker(new jalview.workers.ConservationThread(
-              this, ap));
+      calculator.registerWorker(
+              new jalview.workers.ConservationThread(this, ap));
     }
   }
 
@@ -843,7 +840,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
     {
       return;
     }
-    if (calculator.getRegisteredWorkersOfClass(ConsensusThread.class) == null)
+    if (calculator
+            .getRegisteredWorkersOfClass(ConsensusThread.class) == null)
     {
       calculator.registerWorker(new ConsensusThread(this, ap));
     }
@@ -874,8 +872,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
       }
       if (doConsensus)
       {
-        if (calculator
-                .getRegisteredWorkersOfClass(ComplementConsensusThread.class) == null)
+        if (calculator.getRegisteredWorkersOfClass(
+                ComplementConsensusThread.class) == null)
         {
           calculator
                   .registerWorker(new ComplementConsensusThread(this, ap));
@@ -899,7 +897,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
     {
       return;
     }
-    if (calculator.getRegisteredWorkersOfClass(StrucConsensusThread.class) == null)
+    if (calculator.getRegisteredWorkersOfClass(
+            StrucConsensusThread.class) == null)
     {
       calculator.registerWorker(new StrucConsensusThread(this, ap));
     }
@@ -949,11 +948,15 @@ public abstract class AlignmentViewport implements AlignViewportI,
     groupConsensus = null;
     groupConservation = null;
     hconsensus = null;
+    hconservation = null;
     hcomplementConsensus = null;
-    // colour scheme may hold reference to consensus
-    residueShading = null;
-    // TODO remove listeners from changeSupport?
+    gapcounts = null;
+    calculator = null;
+    residueShading = null; // may hold a reference to Consensus
     changeSupport = null;
+    ranges = null;
+    currentTree = null;
+    selectionGroup = null;
     setAlignment(null);
   }
 
@@ -1188,8 +1191,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
   {
     if (sequenceSetID != null)
     {
-      System.err
-              .println("Warning - overwriting a sequenceSetId for a viewport!");
+      System.err.println(
+              "Warning - overwriting a sequenceSetId for a viewport!");
     }
     sequenceSetID = new String(newid);
   }
@@ -1335,7 +1338,10 @@ public abstract class AlignmentViewport implements AlignViewportI,
   public void removePropertyChangeListener(
           java.beans.PropertyChangeListener listener)
   {
-    changeSupport.removePropertyChangeListener(listener);
+    if (changeSupport != null)
+    {
+      changeSupport.removePropertyChangeListener(listener);
+    }
   }
 
   /**
@@ -1406,8 +1412,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
         selectionGroup = new SequenceGroup();
         selectionGroup.setEndRes(alignment.getWidth() - 1);
       }
-      List<SequenceI> tmp = alignment.getHiddenSequences().showAll(
-              hiddenRepSequences);
+      List<SequenceI> tmp = alignment.getHiddenSequences()
+              .showAll(hiddenRepSequences);
       for (SequenceI seq : tmp)
       {
         selectionGroup.addSequence(seq, false);
@@ -1430,8 +1436,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
     int startSeq = ranges.getStartSeq();
     int endSeq = ranges.getEndSeq();
 
-    List<SequenceI> tmp = alignment.getHiddenSequences().showSequence(
-            index, hiddenRepSequences);
+    List<SequenceI> tmp = alignment.getHiddenSequences().showSequence(index,
+            hiddenRepSequences);
     if (tmp.size() > 0)
     {
       if (selectionGroup == null)
@@ -1511,8 +1517,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
     }
 
     int gsize = selectionGroup.getSize();
-    SequenceI[] hseqs = selectionGroup.getSequences().toArray(
-            new SequenceI[gsize]);
+    SequenceI[] hseqs = selectionGroup.getSequences()
+            .toArray(new SequenceI[gsize]);
 
     hideSequence(hseqs);
     setSelectionGroup(null);
@@ -1602,8 +1608,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
    */
   public boolean isHiddenRepSequence(SequenceI seq)
   {
-    return (hiddenRepSequences != null && hiddenRepSequences
-            .containsKey(seq));
+    return (hiddenRepSequences != null
+            && hiddenRepSequences.containsKey(seq));
   }
 
   /**
@@ -1621,8 +1627,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
   @Override
   public int adjustForHiddenSeqs(int alignmentIndex)
   {
-    return alignment.getHiddenSequences().adjustForHiddenSeqs(
-            alignmentIndex);
+    return alignment.getHiddenSequences()
+            .adjustForHiddenSeqs(alignmentIndex);
   }
 
   @Override
@@ -1674,13 +1680,6 @@ public abstract class AlignmentViewport implements AlignViewportI,
   }
 
   @Override
-  public CigarArray getViewAsCigars(boolean selectedRegionOnly)
-  {
-    return new CigarArray(alignment, alignment.getHiddenColumns(),
-            (selectedRegionOnly ? selectionGroup : null));
-  }
-
-  @Override
   public jalview.datamodel.AlignmentView getAlignmentView(
           boolean selectedOnly)
   {
@@ -1692,10 +1691,10 @@ public abstract class AlignmentViewport implements AlignViewportI,
           boolean selectedOnly, boolean markGroups)
   {
     return new AlignmentView(alignment, alignment.getHiddenColumns(),
-            selectionGroup, alignment.getHiddenColumns() != null
+            selectionGroup,
+            alignment.getHiddenColumns() != null
                     && alignment.getHiddenColumns().hasHiddenColumns(),
-            selectedOnly,
-            markGroups);
+            selectedOnly, markGroups);
   }
 
   @Override
@@ -1741,8 +1740,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
     if (alignment.getHiddenColumns() != null
             && alignment.getHiddenColumns().hasHiddenColumns())
     {
-      selection = alignment.getHiddenColumns().getVisibleSequenceStrings(
-              start, end, seqs);
+      selection = alignment.getHiddenColumns()
+              .getVisibleSequenceStrings(start, end, seqs);
     }
     else
     {
@@ -1811,8 +1810,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
         if (selectedOnly && selectionGroup != null)
         {
           alignment.getHiddenColumns().makeVisibleAnnotation(
-                  selectionGroup.getStartRes(),
-                  selectionGroup.getEndRes(), clone);
+                  selectionGroup.getStartRes(), selectionGroup.getEndRes(),
+                  clone);
         }
         else
         {
@@ -2001,8 +2000,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
     {
       gapcounts = new AlignmentAnnotation("Occupancy",
               MessageManager.getString("label.occupancy_descr"),
-              new Annotation[1], 0f,
-              alignment.getHeight(), AlignmentAnnotation.BAR_GRAPH);
+              new Annotation[1], 0f, alignment.getHeight(),
+              AlignmentAnnotation.BAR_GRAPH);
       gapcounts.hasText = true;
       gapcounts.autoCalculated = true;
       gapcounts.scaleColLabel = true;
@@ -2020,8 +2019,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
       {
         conservation = new AlignmentAnnotation("Conservation",
                 MessageManager.formatMessage("label.conservation_descr",
-                        getConsPercGaps()), new Annotation[1],
-                0f, 11f, AlignmentAnnotation.BAR_GRAPH);
+                        getConsPercGaps()),
+                new Annotation[1], 0f, 11f, AlignmentAnnotation.BAR_GRAPH);
         conservation.hasText = true;
         conservation.autoCalculated = true;
         alignment.addAnnotation(conservation);
@@ -2501,8 +2500,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
     viewStyle = new ViewStyle(settingsForView);
     if (residueShading != null)
     {
-      residueShading.setConservationApplied(settingsForView
-              .isConservationColourSelected());
+      residueShading.setConservationApplied(
+              settingsForView.isConservationColourSelected());
     }
   }
 
@@ -2670,7 +2669,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
     return sortAnnotationsBy;
   }
 
-  public void setSortAnnotationsBy(SequenceAnnotationOrder sortAnnotationsBy)
+  public void setSortAnnotationsBy(
+          SequenceAnnotationOrder sortAnnotationsBy)
   {
     this.sortAnnotationsBy = sortAnnotationsBy;
   }
@@ -2748,8 +2748,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
       return 0;
     }
     boolean iAmProtein = !getAlignment().isNucleotide();
-    AlignmentI proteinAlignment = iAmProtein ? getAlignment() : complement
-            .getAlignment();
+    AlignmentI proteinAlignment = iAmProtein ? getAlignment()
+            : complement.getAlignment();
     if (proteinAlignment == null)
     {
       return 0;
@@ -2780,7 +2780,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
      */
     int lastSeq = alignment.getHeight() - 1;
     List<AlignedCodonFrame> seqMappings = null;
-    for (int seqNo = ranges.getStartSeq(); seqNo < lastSeq; seqNo++, seqOffset++)
+    for (int seqNo = ranges
+            .getStartSeq(); seqNo < lastSeq; seqNo++, seqOffset++)
     {
       sequence = getAlignment().getSequenceAt(seqNo);
       if (hiddenSequences != null && hiddenSequences.isHidden(sequence))
@@ -2791,9 +2792,9 @@ public abstract class AlignmentViewport implements AlignViewportI,
       {
         continue;
       }
-      seqMappings = MappingUtils
-              .findMappingsForSequenceAndOthers(sequence, mappings,
-                      getCodingComplement().getAlignment().getSequences());
+      seqMappings = MappingUtils.findMappingsForSequenceAndOthers(sequence,
+              mappings,
+              getCodingComplement().getAlignment().getSequences());
       if (!seqMappings.isEmpty())
       {
         break;
@@ -2876,6 +2877,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
    */
   private SearchResultsI searchResults = null;
 
+  protected TreeModel currentTree = null;
+
   @Override
   public boolean hasSearchResults()
   {
@@ -2928,10 +2931,22 @@ public abstract class AlignmentViewport implements AlignViewportI,
         }
       }
     }
-  
+
     SequenceI sq = new Sequence("Consensus", seqs.toString());
     sq.setDescription("Percentage Identity Consensus "
             + ((ignoreGapsInConsensusCalculation) ? " without gaps" : ""));
     return sq;
   }
+
+  @Override
+  public void setCurrentTree(TreeModel tree)
+  {
+    currentTree = tree;
+  }
+
+  @Override
+  public TreeModel getCurrentTree()
+  {
+    return currentTree;
+  }
 }
index f54c1eb..170f4e9 100644 (file)
@@ -301,7 +301,8 @@ public abstract class OverviewDimensions
   /*
    * Given the centre x position, calculate the box's left x position
    */
-  protected abstract int getLeftXFromCentreX(int mousex, HiddenColumns hidden);
+  protected abstract int getLeftXFromCentreX(int mousex,
+          HiddenColumns hidden);
 
   /*
    * Given the centre y position, calculate the box's top y position
index c78b8a3..c158ce7 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.viewmodel;
 
 import jalview.api.AlignmentColsCollectionI;
@@ -112,9 +132,7 @@ public class OverviewDimensionsHideHidden extends OverviewDimensions
       }
     }
 
-    // update viewport
-    ranges.setStartRes(xAsRes);
-    ranges.setStartSeq(yAsSeq);
+    ranges.setStartResAndSeq(xAsRes, yAsSeq);
   }
 
   @Override
index 681d43d..9dde16e 100644 (file)
@@ -104,9 +104,7 @@ public class OverviewDimensionsShowHidden extends OverviewDimensions
     int visYAsRes = hiddenSeqs.findIndexWithoutHiddenSeqs(vpy) + ydiff;
 
     // update viewport accordingly
-    updateViewportFromTopLeft(visXAsRes, visYAsRes,
-            hiddenSeqs,
-            hiddenCols);
+    updateViewportFromTopLeft(visXAsRes, visYAsRes, hiddenSeqs, hiddenCols);
   }
 
   @Override
@@ -168,8 +166,8 @@ public class OverviewDimensionsShowHidden extends OverviewDimensions
       // went past the end of the alignment, adjust backwards
       if (ranges.getEndSeq() < visAlignHeight)
       {
-        visYAsSeq = hiddenSeqs.findIndexWithoutHiddenSeqs(hiddenSeqs
-                .subtractVisibleRows(vpheight - 1, alheight - 1));
+        visYAsSeq = hiddenSeqs.findIndexWithoutHiddenSeqs(
+                hiddenSeqs.subtractVisibleRows(vpheight - 1, alheight - 1));
       }
       else
       {
@@ -178,8 +176,7 @@ public class OverviewDimensionsShowHidden extends OverviewDimensions
     }
 
     // update viewport
-    ranges.setStartRes(visXAsRes);
-    ranges.setStartSeq(visYAsSeq);
+    ranges.setStartResAndSeq(visXAsRes, visYAsSeq);
   }
 
   /**
@@ -205,22 +202,21 @@ public class OverviewDimensionsShowHidden extends OverviewDimensions
     int startSeq = hiddenSeqs.adjustForHiddenSeqs(ranges.getStartSeq());
     int endSeq = hiddenSeqs.adjustForHiddenSeqs(ranges.getEndSeq());
 
-    setBoxPosition(startRes, startSeq, endRes - startRes + 1, endSeq
-            - startSeq + 1);
+    setBoxPosition(startRes, startSeq, endRes - startRes + 1,
+            endSeq - startSeq + 1);
   }
 
   @Override
   public AlignmentColsCollectionI getColumns(AlignmentI al)
   {
-    return new AllColsCollection(0,
-            ranges.getAbsoluteAlignmentWidth() - 1, al);
+    return new AllColsCollection(0, ranges.getAbsoluteAlignmentWidth() - 1,
+            al);
   }
 
   @Override
   public AlignmentRowsCollectionI getRows(AlignmentI al)
   {
-    return new AllRowsCollection(0,
-            ranges.getAbsoluteAlignmentHeight() - 1,
+    return new AllRowsCollection(0, ranges.getAbsoluteAlignmentHeight() - 1,
             al);
   }
 
index 928d35e..5e7fca2 100644 (file)
@@ -62,8 +62,7 @@ public class PCAModel
    * @param params
    */
   public PCAModel(AlignmentView seqData, SequenceI[] sqs, boolean nuc,
-          ScoreModelI modelName,
-          SimilarityParamsI params)
+          ScoreModelI modelName, SimilarityParamsI params)
   {
     seqstrings = seqData;
     seqs = sqs;
index 555089e..dba4621 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.viewmodel;
 
 import java.beans.PropertyChangeListener;
index 10cf583..c7a3fa1 100644 (file)
@@ -24,11 +24,10 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.HiddenColumns;
 
 /**
- * Slightly less embryonic class which: Supplies and updates viewport properties
- * relating to position such as: start and end residues and sequences; ideally
- * will serve hidden columns/rows too. Intention also to support calculations
- * for positioning, scrolling etc. such as finding the middle of the viewport,
- * checking for scrolls off screen
+ * Supplies and updates viewport properties relating to position such as: start
+ * and end residues and sequences; ideally will serve hidden columns/rows too.
+ * Intention also to support calculations for positioning, scrolling etc. such
+ * as finding the middle of the viewport, checking for scrolls off screen
  */
 public class ViewportRanges extends ViewportProperties
 {
@@ -40,6 +39,10 @@ public class ViewportRanges extends ViewportProperties
 
   public static final String ENDSEQ = "endseq";
 
+  public static final String STARTRESANDSEQ = "startresandseq";
+
+  public static final String MOVE_VIEWPORT = "move_viewport";
+
   private boolean wrappedMode = false;
 
   // start residue of viewport
@@ -130,6 +133,31 @@ public class ViewportRanges extends ViewportProperties
    */
   public void setStartEndRes(int start, int end)
   {
+    int[] oldvalues = updateStartEndRes(start, end);
+    int oldstartres = oldvalues[0];
+    int oldendres = oldvalues[1];
+
+    changeSupport.firePropertyChange(STARTRES, oldstartres, startRes);
+    if (oldstartres == startRes)
+    {
+      // event won't be fired if start positions are same
+      // fire an event for the end positions in case they changed
+      changeSupport.firePropertyChange(ENDRES, oldendres, endRes);
+    }
+  }
+
+  /**
+   * Update start and end residue values, adjusting for width constraints if
+   * necessary
+   * 
+   * @param start
+   *          start residue
+   * @param end
+   *          end residue
+   * @return array containing old start and end residue values
+   */
+  private int[] updateStartEndRes(int start, int end)
+  {
     int oldstartres = this.startRes;
 
     /*
@@ -162,14 +190,7 @@ public class ViewportRanges extends ViewportProperties
     {
       endRes = end;
     }
-
-    changeSupport.firePropertyChange(STARTRES, oldstartres, startRes);
-    if (oldstartres == startRes)
-    {
-      // event won't be fired if start positions are same
-      // fire an event for the end positions in case they changed
-      changeSupport.firePropertyChange(ENDRES, oldendres, endRes);
-    }
+    return new int[] { oldstartres, oldendres };
   }
 
   /**
@@ -203,6 +224,31 @@ public class ViewportRanges extends ViewportProperties
    */
   public void setStartEndSeq(int start, int end)
   {
+    int[] oldvalues = updateStartEndSeq(start, end);
+    int oldstartseq = oldvalues[0];
+    int oldendseq = oldvalues[1];
+
+    changeSupport.firePropertyChange(STARTSEQ, oldstartseq, startSeq);
+    if (oldstartseq == startSeq)
+    {
+      // event won't be fired if start positions are the same
+      // fire in case the end positions changed
+      changeSupport.firePropertyChange(ENDSEQ, oldendseq, endSeq);
+    }
+  }
+
+  /**
+   * Update start and end sequence values, adjusting for height constraints if
+   * necessary
+   * 
+   * @param start
+   *          start sequence
+   * @param end
+   *          end sequence
+   * @return array containing old start and end sequence values
+   */
+  private int[] updateStartEndSeq(int start, int end)
+  {
     int oldstartseq = this.startSeq;
     int visibleHeight = getVisibleAlignmentHeight();
     if (start > visibleHeight - 1)
@@ -231,14 +277,7 @@ public class ViewportRanges extends ViewportProperties
     {
       endSeq = end;
     }
-
-    changeSupport.firePropertyChange(STARTSEQ, oldstartseq, startSeq);
-    if (oldstartseq == startSeq)
-    {
-      // event won't be fired if start positions are the same
-      // fire in case the end positions changed
-      changeSupport.firePropertyChange(ENDSEQ, oldendseq, endSeq);
-    }
+    return new int[] { oldstartseq, oldendseq };
   }
 
   /**
@@ -255,6 +294,34 @@ public class ViewportRanges extends ViewportProperties
   }
 
   /**
+   * Set start residue and start sequence together (fires single event). The
+   * event supplies a pair of old values and a pair of new values: [old start
+   * residue, old start sequence] and [new start residue, new start sequence]
+   * 
+   * @param res
+   *          the start residue
+   * @param seq
+   *          the start sequence
+   */
+  public void setStartResAndSeq(int res, int seq)
+  {
+    int width = getViewportWidth();
+    int[] oldresvalues = updateStartEndRes(res, res + width - 1);
+
+    int startseq = seq;
+    int height = getViewportHeight();
+    if (startseq + height - 1 > getVisibleAlignmentHeight() - 1)
+    {
+      startseq = getVisibleAlignmentHeight() - height;
+    }
+    int[] oldseqvalues = updateStartEndSeq(startseq, startseq + height - 1);
+
+    int[] old = new int[] { oldresvalues[0], oldseqvalues[0] };
+    int[] newresseq = new int[] { startRes, startSeq };
+    changeSupport.firePropertyChange(STARTRESANDSEQ, old, newresseq);
+  }
+
+  /**
    * Get start residue of viewport
    */
   public int getStartRes()
@@ -402,23 +469,39 @@ public class ViewportRanges extends ViewportProperties
    */
   public boolean scrollUp(boolean up)
   {
+    /*
+     * if in unwrapped mode, scroll up or down one sequence row;
+     * if in wrapped mode, scroll by one visible width of columns
+     */
     if (up)
     {
-      if (startSeq < 1)
+      if (wrappedMode)
       {
-        return false;
+        pageUp();
+      }
+      else
+      {
+        if (startSeq < 1)
+        {
+          return false;
+        }
+        setStartSeq(startSeq - 1);
       }
-
-      setStartSeq(startSeq - 1);
     }
     else
     {
-      if (endSeq >= getVisibleAlignmentHeight() - 1)
+      if (wrappedMode)
       {
-        return false;
+        pageDown();
+      }
+      else
+      {
+        if (endSeq >= getVisibleAlignmentHeight() - 1)
+        {
+          return false;
+        }
+        setStartSeq(startSeq + 1);
       }
-
-      setStartSeq(startSeq + 1);
     }
     return true;
   }
@@ -456,27 +539,63 @@ public class ViewportRanges extends ViewportProperties
   }
 
   /**
-   * Scroll a wrapped alignment so that the specified residue is visible. Fires
-   * a property change event.
+   * Scroll a wrapped alignment so that the specified residue is in the first
+   * repeat of the wrapped view. Fires a property change event. Answers true if
+   * the startRes changed, else false.
    * 
    * @param res
-   *          residue position to scroll to
+   *          residue position to scroll to NB visible position not absolute
+   *          alignment position
+   * @return
    */
-  public void scrollToWrappedVisible(int res)
+  public boolean scrollToWrappedVisible(int res)
   {
-    // get the start residue of the wrapped row which res is in
-    // and set that as our start residue
+    int newStartRes = calcWrappedStartResidue(res);
+    if (newStartRes == startRes)
+    {
+      return false;
+    }
+    setStartRes(newStartRes);
+
+    return true;
+  }
+
+  /**
+   * Calculate wrapped start residue from visible start residue
+   * 
+   * @param res
+   *          visible start residue
+   * @return left column of panel res will be located in
+   */
+  private int calcWrappedStartResidue(int res)
+  {
+    int oldStartRes = startRes;
     int width = getViewportWidth();
-    setStartRes((res / width) * width);
+
+    boolean up = res < oldStartRes;
+    int widthsToScroll = Math.abs((res - oldStartRes) / width);
+    if (up)
+    {
+      widthsToScroll++;
+    }
+
+    int residuesToScroll = width * widthsToScroll;
+    int newStartRes = up ? oldStartRes - residuesToScroll : oldStartRes
+            + residuesToScroll;
+    if (newStartRes < 0)
+    {
+      newStartRes = 0;
+    }
+    return newStartRes;
   }
 
   /**
    * Scroll so that (x,y) is visible. Fires a property change event.
    * 
    * @param x
-   *          x position in alignment
+   *          x position in alignment (absolute position)
    * @param y
-   *          y position in alignment
+   *          y position in alignment (absolute position)
    */
   public void scrollToVisible(int x, int y)
   {
@@ -488,7 +607,7 @@ public class ViewportRanges extends ViewportProperties
     {
       scrollUp(false);
     }
-
+    
     HiddenColumns hidden = al.getHiddenColumns();
     while (x < hidden.adjustForHiddenColumns(startRes))
     {
@@ -505,7 +624,63 @@ public class ViewportRanges extends ViewportProperties
       }
     }
   }
-  
+
+  /**
+   * Set the viewport location so that a position is visible
+   * 
+   * @param x
+   *          column to be visible: absolute position in alignment
+   * @param y
+   *          row to be visible: absolute position in alignment
+   */
+  public boolean setViewportLocation(int x, int y)
+  {
+    boolean changedLocation = false;
+
+    // convert the x,y location to visible coordinates
+    int visX = al.getHiddenColumns().findColumnPosition(x);
+    int visY = al.getHiddenSequences().findIndexWithoutHiddenSeqs(y);
+
+    // if (vis_x,vis_y) is already visible don't do anything
+    if (startRes > visX || visX > endRes
+            || startSeq > visY && visY > endSeq)
+    {
+      int[] old = new int[] { startRes, startSeq };
+      int[] newresseq;
+      if (wrappedMode)
+      {
+        int newstartres = calcWrappedStartResidue(visX);
+        setStartRes(newstartres);
+        newresseq = new int[] { startRes, startSeq };
+      }
+      else
+      {
+        // set the viewport x location to contain vis_x
+        int newstartres = visX;
+        int width = getViewportWidth();
+        if (newstartres + width - 1 > getVisibleAlignmentWidth() - 1)
+        {
+          newstartres = getVisibleAlignmentWidth() - width;
+        }
+        updateStartEndRes(newstartres, newstartres + width - 1);
+
+        // set the viewport y location to contain vis_y
+        int newstartseq = visY;
+        int height = getViewportHeight();
+        if (newstartseq + height - 1 > getVisibleAlignmentHeight() - 1)
+        {
+          newstartseq = getVisibleAlignmentHeight() - height;
+        }
+        updateStartEndSeq(newstartseq, newstartseq + height - 1);
+
+        newresseq = new int[] { startRes, startSeq };
+      }
+      changedLocation = true;
+      changeSupport.firePropertyChange(MOVE_VIEWPORT, old, newresseq);
+    }
+    return changedLocation;
+  }
+
   /**
    * Adjust sequence position for page up. Fires a property change event.
    */
@@ -521,7 +696,7 @@ public class ViewportRanges extends ViewportProperties
               getViewportHeight());
     }
   }
-  
+
   /**
    * Adjust sequence position for page down. Fires a property change event.
    */
index 2149c57..7acac3c 100644 (file)
@@ -84,7 +84,8 @@ public class AnnotationFilterParameter
     return regexSearchFields;
   }
 
-  public void addRegexSearchField(SearchableAnnotationField regexSearchField)
+  public void addRegexSearchField(
+          SearchableAnnotationField regexSearchField)
   {
     this.regexSearchFields.add(regexSearchField);
   }
index 40f38b6..2f30e94 100644 (file)
@@ -26,6 +26,7 @@ import jalview.api.FeaturesDisplayedI;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
+import jalview.datamodel.features.SequenceFeatures;
 import jalview.renderer.seqfeatures.FeatureRenderer;
 import jalview.schemes.FeatureColour;
 import jalview.util.ColorUtils;
@@ -44,8 +45,8 @@ import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
-public abstract class FeatureRendererModel implements
-        jalview.api.FeatureRenderer
+public abstract class FeatureRendererModel
+        implements jalview.api.FeatureRenderer
 {
 
   /**
@@ -116,11 +117,10 @@ public abstract class FeatureRendererModel implements
           synchronized (fd)
           {
             fd.clear();
-            java.util.Iterator<String> fdisp = _fr.getFeaturesDisplayed()
-                    .getVisibleFeatures();
-            while (fdisp.hasNext())
+            for (String type : _fr.getFeaturesDisplayed()
+                    .getVisibleFeatures())
             {
-              fd.setVisible(fdisp.next());
+              fd.setVisible(type);
             }
           }
         }
@@ -215,7 +215,8 @@ public abstract class FeatureRendererModel implements
       if (r[0] != 0 || mm[0] < 0.0)
       {
         r[0] = 1;
-        r[1] = (byte) ((int) 128.0 + 127.0 * (sequenceFeature.score / mm[1]));
+        r[1] = (byte) ((int) 128.0
+                + 127.0 * (sequenceFeature.score / mm[1]));
       }
       else
       {
@@ -264,50 +265,40 @@ public abstract class FeatureRendererModel implements
   }
 
   @Override
-  public List<SequenceFeature> findFeaturesAtRes(SequenceI sequence, int res)
+  public List<SequenceFeature> findFeaturesAtColumn(SequenceI sequence, int column)
   {
-    ArrayList<SequenceFeature> tmp = new ArrayList<SequenceFeature>();
-    SequenceFeature[] features = sequence.getSequenceFeatures();
-
-    if (features != null)
+    /*
+     * include features at the position provided their feature type is 
+     * displayed, and feature group is null or marked for display
+     */
+    List<SequenceFeature> result = new ArrayList<SequenceFeature>();
+    if (!av.areFeaturesDisplayed() || getFeaturesDisplayed() == null)
     {
-      for (int i = 0; i < features.length; i++)
-      {
-        if (!av.areFeaturesDisplayed()
-                || !av.getFeaturesDisplayed().isVisible(
-                        features[i].getType()))
-        {
-          continue;
-        }
+      return result;
+    }
 
-        if (features[i].featureGroup != null
-                && featureGroups != null
-                && featureGroups.containsKey(features[i].featureGroup)
-                && !featureGroups.get(features[i].featureGroup)
-                        .booleanValue())
-        {
-          continue;
-        }
+    Set<String> visibleFeatures = getFeaturesDisplayed()
+            .getVisibleFeatures();
+    String[] visibleTypes = visibleFeatures
+            .toArray(new String[visibleFeatures.size()]);
+    List<SequenceFeature> features = sequence.findFeatures(column, column,
+            visibleTypes);
 
-        // check if start/end are at res, and if not a contact feature, that res
-        // lies between start and end
-        if ((features[i].getBegin() == res || features[i].getEnd() == res)
-                || (!features[i].isContactFeature()
-                        && (features[i].getBegin() < res) && (features[i]
-                        .getEnd() >= res)))
-        {
-          tmp.add(features[i]);
-        }
+    for (SequenceFeature sf : features)
+    {
+      if (!featureGroupNotShown(sf))
+      {
+        result.add(sf);
       }
     }
-    return tmp;
+    return result;
   }
 
   /**
    * Searches alignment for all features and updates colours
    * 
    * @param newMadeVisible
-   *          if true newly added feature types will be rendered immediatly
+   *          if true newly added feature types will be rendered immediately
    *          TODO: check to see if this method should actually be proxied so
    *          repaint events can be propagated by the renderer code
    */
@@ -329,8 +320,7 @@ public abstract class FeatureRendererModel implements
     }
     FeaturesDisplayedI featuresDisplayed = av.getFeaturesDisplayed();
 
-    ArrayList<String> allfeatures = new ArrayList<String>();
-    ArrayList<String> oldfeatures = new ArrayList<String>();
+    Set<String> oldfeatures = new HashSet<String>();
     if (renderOrder != null)
     {
       for (int i = 0; i < renderOrder.length; i++)
@@ -341,107 +331,110 @@ public abstract class FeatureRendererModel implements
         }
       }
     }
-    if (minmax == null)
-    {
-      minmax = new Hashtable<String, float[][]>();
-    }
 
-    Set<String> oldGroups = new HashSet<String>(featureGroups.keySet());
     AlignmentI alignment = av.getAlignment();
+    List<String> allfeatures = new ArrayList<String>();
+
     for (int i = 0; i < alignment.getHeight(); i++)
     {
       SequenceI asq = alignment.getSequenceAt(i);
-      SequenceFeature[] features = asq.getSequenceFeatures();
-
-      if (features == null)
-      {
-        continue;
-      }
-
-      int index = 0;
-      while (index < features.length)
+      for (String group : asq.getFeatures().getFeatureGroups(true))
       {
-        String fgrp = features[index].getFeatureGroup();
-        oldGroups.remove(fgrp);
-        if (!featuresDisplayed.isRegistered(features[index].getType()))
+        boolean groupDisplayed = true;
+        if (group != null)
         {
-          if (fgrp != null)
+          if (featureGroups.containsKey(group))
           {
-            Boolean groupDisplayed = featureGroups.get(fgrp);
-            if (groupDisplayed == null)
-            {
-              groupDisplayed = Boolean.valueOf(newMadeVisible);
-              featureGroups.put(fgrp, groupDisplayed);
-            }
-            if (!groupDisplayed.booleanValue())
-            {
-              index++;
-              continue;
-            }
+            groupDisplayed = featureGroups.get(group);
           }
-          if (!(features[index].begin == 0 && features[index].end == 0))
+          else
           {
-            // If beginning and end are 0, the feature is for the whole sequence
-            // and we don't want to render the feature in the normal way
-
-            if (newMadeVisible
-                    && !oldfeatures.contains(features[index].getType()))
-            {
-              // this is a new feature type on the alignment. Mark it for
-              // display.
-              featuresDisplayed.setVisible(features[index].getType());
-              setOrder(features[index].getType(), 0);
-            }
+            groupDisplayed = newMadeVisible;
+            featureGroups.put(group, groupDisplayed);
           }
         }
-        if (!allfeatures.contains(features[index].getType()))
+        if (groupDisplayed)
         {
-          allfeatures.add(features[index].getType());
-        }
-        if (!Float.isNaN(features[index].score))
-        {
-          int nonpos = features[index].getBegin() >= 1 ? 0 : 1;
-          float[][] mm = minmax.get(features[index].getType());
-          if (mm == null)
-          {
-            mm = new float[][] { null, null };
-            minmax.put(features[index].getType(), mm);
-          }
-          if (mm[nonpos] == null)
-          {
-            mm[nonpos] = new float[] { features[index].score,
-                features[index].score };
-
-          }
-          else
+          Set<String> types = asq.getFeatures().getFeatureTypesForGroups(
+                  true, group);
+          for (String type : types)
           {
-            if (mm[nonpos][0] > features[index].score)
+            if (!allfeatures.contains(type)) // or use HashSet and no test?
             {
-              mm[nonpos][0] = features[index].score;
-            }
-            if (mm[nonpos][1] < features[index].score)
-            {
-              mm[nonpos][1] = features[index].score;
+              allfeatures.add(type);
             }
+            updateMinMax(asq, type, true); // todo: for all features?
           }
         }
-        index++;
       }
     }
 
-    /*
-     * oldGroups now consists of groups that no longer 
-     * have any feature in them - remove these
-     */
-    for (String grp : oldGroups)
+    // uncomment to add new features in alphebetical order (but JAL-2575)
+    // Collections.sort(allfeatures, String.CASE_INSENSITIVE_ORDER);
+    if (newMadeVisible)
     {
-      featureGroups.remove(grp);
+      for (String type : allfeatures)
+      {
+        if (!oldfeatures.contains(type))
+        {
+          featuresDisplayed.setVisible(type);
+          setOrder(type, 0);
+        }
+      }
     }
 
     updateRenderOrder(allfeatures);
     findingFeatures = false;
   }
 
+  /**
+   * Updates the global (alignment) min and max values for a feature type from
+   * the score for a sequence, if the score is not NaN. Values are stored
+   * separately for positional and non-positional features.
+   * 
+   * @param seq
+   * @param featureType
+   * @param positional
+   */
+  protected void updateMinMax(SequenceI seq, String featureType,
+          boolean positional)
+  {
+    float min = seq.getFeatures().getMinimumScore(featureType, positional);
+    if (Float.isNaN(min))
+    {
+      return;
+    }
+
+    float max = seq.getFeatures().getMaximumScore(featureType, positional);
+
+    /*
+     * stored values are 
+     * { {positionalMin, positionalMax}, {nonPositionalMin, nonPositionalMax} }
+     */
+    if (minmax == null)
+    {
+      minmax = new Hashtable<String, float[][]>();
+    }
+    synchronized (minmax)
+    {
+      float[][] mm = minmax.get(featureType);
+      int index = positional ? 0 : 1;
+      if (mm == null)
+      {
+        mm = new float[][] { null, null };
+        minmax.put(featureType, mm);
+      }
+      if (mm[index] == null)
+      {
+        mm[index] = new float[] { min, max };
+      }
+      else
+      {
+        mm[index][0] = Math.min(mm[index][0], min);
+        mm[index][1] = Math.max(mm[index][1], max);
+      }
+    }
+  }
   protected Boolean firing = Boolean.FALSE;
 
   /**
@@ -470,7 +463,8 @@ public abstract class FeatureRendererModel implements
         {
           if (initOrders)
           {
-            setOrder(oldRender[j], (1 - (1 + (float) j) / oldRender.length));
+            setOrder(oldRender[j],
+                    (1 - (1 + (float) j) / oldRender.length));
           }
           if (allfeatures.contains(oldRender[j]))
           {
@@ -567,7 +561,8 @@ public abstract class FeatureRendererModel implements
    * Returns the configured colour for a particular feature instance. This
    * includes calculation of 'colour by label', or of a graduated score colour,
    * if applicable. It does not take into account feature visibility or colour
-   * transparency.
+   * transparency. Returns null for a score feature whose score value lies
+   * outside any colour threshold.
    * 
    * @param feature
    * @return
@@ -575,21 +570,7 @@ public abstract class FeatureRendererModel implements
   public Color getColour(SequenceFeature feature)
   {
     FeatureColourI fc = getFeatureStyle(feature.getType());
-    return fc.isColored(feature) ? fc.getColor(feature) : null;
-  }
-
-  /**
-   * Answers true unless the feature has a score value which lies outside a
-   * minimum or maximum threshold configured for colouring. This method does not
-   * check feature type or group visibility.
-   * 
-   * @param sequenceFeature
-   * @return
-   */
-  protected boolean showFeature(SequenceFeature sequenceFeature)
-  {
-    FeatureColourI fc = getFeatureStyle(sequenceFeature.type);
-    return fc.isColored(sequenceFeature);
+    return fc.getColor(feature);
   }
 
   /**
@@ -679,7 +660,8 @@ public abstract class FeatureRendererModel implements
   }
 
   /**
-   * Sets the priority order for features
+   * Sets the priority order for features, with the highest priority (displayed
+   * on top) at the start of the data array
    * 
    * @param data
    *          { String(Type), Colour(Type), Boolean(Displayed) }
@@ -706,7 +688,8 @@ public abstract class FeatureRendererModel implements
       }
       else
       {
-        av.setFeaturesDisplayed(av_featuresdisplayed = new FeaturesDisplayed());
+        av.setFeaturesDisplayed(
+                av_featuresdisplayed = new FeaturesDisplayed());
       }
     }
     else
@@ -818,11 +801,12 @@ public abstract class FeatureRendererModel implements
   {
     // conflict between applet and desktop - featureGroups returns the map in
     // the desktop featureRenderer
-    return (featureGroups == null) ? Arrays.asList(new String[0]) : Arrays
-            .asList(featureGroups.keySet().toArray(new String[0]));
+    return (featureGroups == null) ? Arrays.asList(new String[0])
+            : Arrays.asList(featureGroups.keySet().toArray(new String[0]));
   }
 
-  public boolean checkGroupVisibility(String group, boolean newGroupsVisible)
+  public boolean checkGroupVisibility(String group,
+          boolean newGroupsVisible)
   {
     if (featureGroups == null)
     {
@@ -903,11 +887,10 @@ public abstract class FeatureRendererModel implements
     {
       return fcols;
     }
-    Iterator<String> features = getViewport().getFeaturesDisplayed()
+    Set<String> features = getViewport().getFeaturesDisplayed()
             .getVisibleFeatures();
-    while (features.hasNext())
+    for (String feature : features)
     {
-      String feature = features.next();
       fcols.put(feature, getFeatureStyle(feature));
     }
     return fcols;
@@ -949,25 +932,117 @@ public abstract class FeatureRendererModel implements
   public List<String> getDisplayedFeatureGroups()
   {
     List<String> _gps = new ArrayList<String>();
-    boolean valid = false;
     for (String gp : getFeatureGroups())
     {
       if (checkGroupVisibility(gp, false))
       {
-        valid = true;
         _gps.add(gp);
       }
-      if (!valid)
+    }
+    return _gps;
+  }
+
+  /**
+   * Answers true if the feature belongs to a feature group which is not
+   * currently displayed, else false
+   * 
+   * @param sequenceFeature
+   * @return
+   */
+  protected boolean featureGroupNotShown(final SequenceFeature sequenceFeature)
+  {
+    return featureGroups != null
+            && sequenceFeature.featureGroup != null
+            && sequenceFeature.featureGroup.length() != 0
+            && featureGroups.containsKey(sequenceFeature.featureGroup)
+            && !featureGroups.get(sequenceFeature.featureGroup)
+                    .booleanValue();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public List<SequenceFeature> findFeaturesAtResidue(SequenceI sequence,
+          int resNo)
+  {
+    List<SequenceFeature> result = new ArrayList<SequenceFeature>();
+    if (!av.areFeaturesDisplayed() || getFeaturesDisplayed() == null)
+    {
+      return result;
+    }
+
+    /*
+     * include features at the position provided their feature type is 
+     * displayed, and feature group is null or the empty string
+     * or marked for display
+     */
+    Set<String> visibleFeatures = getFeaturesDisplayed()
+            .getVisibleFeatures();
+    String[] visibleTypes = visibleFeatures
+            .toArray(new String[visibleFeatures.size()]);
+    List<SequenceFeature> features = sequence.getFeatures().findFeatures(
+            resNo, resNo, visibleTypes);
+  
+    for (SequenceFeature sf : features)
+    {
+      if (!featureGroupNotShown(sf))
       {
-        return null;
+        result.add(sf);
       }
-      else
+    }
+    return result;
+  }
+
+  /**
+   * Removes from the list of features any that have a feature group that is not
+   * displayed, or duplicate the location of a feature of the same type (unless
+   * a graduated colour scheme or colour by label is applied). Should be used
+   * only for features of the same feature colour (which normally implies the
+   * same feature type).
+   * 
+   * @param features
+   * @param fc
+   */
+  public void filterFeaturesForDisplay(List<SequenceFeature> features,
+          FeatureColourI fc)
+  {
+    if (features.isEmpty())
+    {
+      return;
+    }
+    SequenceFeatures.sortFeatures(features, true);
+    boolean simpleColour = fc == null || fc.isSimpleColour();
+    SequenceFeature lastFeature = null;
+
+    Iterator<SequenceFeature> it = features.iterator();
+    while (it.hasNext())
+    {
+      SequenceFeature sf = it.next();
+      if (featureGroupNotShown(sf))
       {
-        // gps = new String[_gps.size()];
-        // _gps.toArray(gps);
+        it.remove();
+        continue;
       }
+
+      /*
+       * a feature is redundant for rendering purposes if it has the
+       * same extent as another (so would just redraw the same colour);
+       * (checking type and isContactFeature as a fail-safe here, although
+       * currently they are guaranteed to match in this context)
+       */
+      if (simpleColour)
+      {
+        if (lastFeature != null && sf.getBegin() == lastFeature.getBegin()
+                && sf.getEnd() == lastFeature.getEnd()
+                && sf.isContactFeature() == lastFeature.isContactFeature()
+                && sf.getType().equals(lastFeature.getType()))
+        {
+          it.remove();
+        }
+      }
+      lastFeature = sf;
     }
-    return _gps;
   }
 
 }
index 4c7e3c4..f44a2d1 100644 (file)
@@ -23,22 +23,21 @@ package jalview.viewmodel.seqfeatures;
 import jalview.api.FeaturesDisplayedI;
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashSet;
-import java.util.Iterator;
+import java.util.Set;
 
 public class FeaturesDisplayed implements FeaturesDisplayedI
 {
-  private HashSet<String> featuresDisplayed = new HashSet<String>();
+  private Set<String> featuresDisplayed = new HashSet<String>();
 
-  private HashSet<String> featuresRegistered = new HashSet<String>();
+  private Set<String> featuresRegistered = new HashSet<String>();
 
   public FeaturesDisplayed(FeaturesDisplayedI featuresDisplayed2)
   {
-    Iterator<String> fdisp = featuresDisplayed2.getVisibleFeatures();
-    String ftype;
-    while (fdisp.hasNext())
+    Set<String> fdisp = featuresDisplayed2.getVisibleFeatures();
+    for (String ftype : fdisp)
     {
-      ftype = fdisp.next();
       featuresDisplayed.add(ftype);
       featuresRegistered.add(ftype);
     }
@@ -46,13 +45,12 @@ public class FeaturesDisplayed implements FeaturesDisplayedI
 
   public FeaturesDisplayed()
   {
-    // TODO Auto-generated constructor stub
   }
 
   @Override
-  public Iterator<String> getVisibleFeatures()
+  public Set<String> getVisibleFeatures()
   {
-    return featuresDisplayed.iterator();
+    return Collections.unmodifiableSet(featuresDisplayed);
   }
 
   @Override
index f01047d..16aa580 100644 (file)
@@ -280,21 +280,18 @@ public class ViewStyle implements ViewStyleI
             && getThreshold() == vs.getThreshold()
             && getThresholdTextColour() == vs.getThresholdTextColour()
             && isUpperCasebold() == vs.isUpperCasebold()
-            && getWrapAlignment() == vs.getWrapAlignment() && getWrappedWidth() == vs
-            .getWrappedWidth());
+            && getWrapAlignment() == vs.getWrapAlignment()
+            && getWrappedWidth() == vs.getWrappedWidth());
     /*
      * and compare non-primitive types; syntax below will match null with null
      * values
      */
-    match = match
-            && String.valueOf(getFontName()).equals(
-                    String.valueOf(vs.getFontName()));
-    match = match
-            && String.valueOf(getTextColour()).equals(
-                    String.valueOf(vs.getTextColour()));
-    match = match
-            && String.valueOf(getTextColour2()).equals(
-                    String.valueOf(vs.getTextColour2()));
+    match = match && String.valueOf(getFontName())
+            .equals(String.valueOf(vs.getFontName()));
+    match = match && String.valueOf(getTextColour())
+            .equals(String.valueOf(vs.getTextColour()));
+    match = match && String.valueOf(getTextColour2())
+            .equals(String.valueOf(vs.getTextColour2()));
     return match;
     // return equivalent(this, (ViewStyle) other);
   }
index addb372..08ef3a2 100644 (file)
@@ -68,12 +68,12 @@ public class AlignCalcManager implements AlignCalcManagerI
   {
     restartable = Collections
             .synchronizedList(new ArrayList<AlignCalcWorkerI>());
-    blackList = Collections
-            .synchronizedList(new ArrayList<Class<? extends AlignCalcWorkerI>>());
+    blackList = Collections.synchronizedList(
+            new ArrayList<Class<? extends AlignCalcWorkerI>>());
     inProgress = Collections
             .synchronizedList(new ArrayList<AlignCalcWorkerI>());
-    updating = Collections
-            .synchronizedMap(new Hashtable<Class<? extends AlignCalcWorkerI>, List<AlignCalcWorkerI>>());
+    updating = Collections.synchronizedMap(
+            new Hashtable<Class<? extends AlignCalcWorkerI>, List<AlignCalcWorkerI>>());
     canUpdate = new HashSet<AlignCalcWorkerI>();
   }
 
@@ -85,10 +85,8 @@ public class AlignCalcManager implements AlignCalcManagerI
       List<AlignCalcWorkerI> upd = updating.get(worker.getClass());
       if (upd == null)
       {
-        updating.put(
-                worker.getClass(),
-                upd = Collections
-                        .synchronizedList(new ArrayList<AlignCalcWorkerI>()));
+        updating.put(worker.getClass(), upd = Collections
+                .synchronizedList(new ArrayList<AlignCalcWorkerI>()));
       }
       synchronized (upd)
       {
@@ -235,7 +233,8 @@ public class AlignCalcManager implements AlignCalcManagerI
   }
 
   @Override
-  public boolean workingInvolvedWith(AlignmentAnnotation alignmentAnnotation)
+  public boolean workingInvolvedWith(
+          AlignmentAnnotation alignmentAnnotation)
   {
     synchronized (inProgress)
     {
index b0392d4..2507bb5 100644 (file)
@@ -31,11 +31,13 @@ import java.awt.Color;
 
 /**
  * Factory class with methods which allow clients (including external scripts
- * such as Groovy) to 'register and forget' an alignment annotation calculator. <br>
+ * such as Groovy) to 'register and forget' an alignment annotation calculator.
+ * <br>
  * Currently supports two flavours of calculator:
  * <ul>
  * <li>a simple 'feature counter' which counts any desired score derivable from
- * residue value and any sequence features at each position of the alignment</li>
+ * residue value and any sequence features at each position of the
+ * alignment</li>
  * <li>a 'general purpose' calculator which computes one or more complete
  * AlignmentAnnotation objects</li>
  * </ul>
@@ -50,11 +52,12 @@ public class AlignmentAnnotationFactory
    */
   public static void newCalculator(FeatureSetCounterI counter)
   {
-    AlignmentViewPanel currentAlignFrame = Jalview.getCurrentAlignFrame().alignPanel;
+    AlignmentViewPanel currentAlignFrame = Jalview
+            .getCurrentAlignFrame().alignPanel;
     if (currentAlignFrame == null)
     {
-      System.err
-              .println("Can't register calculator as no alignment window has focus");
+      System.err.println(
+              "Can't register calculator as no alignment window has focus");
       return;
     }
     new ColumnCounterSetWorker(currentAlignFrame.getAlignViewport(),
@@ -79,8 +82,8 @@ public class AlignmentAnnotationFactory
     }
     else
     {
-      System.err
-              .println("Can't register calculator as no alignment window has focus");
+      System.err.println(
+              "Can't register calculator as no alignment window has focus");
     }
   }
 
@@ -111,7 +114,8 @@ public class AlignmentAnnotationFactory
   public static Annotation newAnnotation(String displayChar, String desc,
           char secondaryStructure, float val, Color color)
   {
-    return new Annotation(displayChar, desc, secondaryStructure, val, color);
+    return new Annotation(displayChar, desc, secondaryStructure, val,
+            color);
   }
 
   /**
index 4d81307..8f37f15 100644 (file)
@@ -47,11 +47,11 @@ class AnnotationWorker extends AlignCalcWorker
    * @param af
    * @param counter
    */
-  public AnnotationWorker(AlignViewportI viewport,
-          AlignmentViewPanel panel, AnnotationProviderI counter)
+  public AnnotationWorker(AlignViewportI viewport, AlignmentViewPanel panel,
+          AnnotationProviderI counter)
   {
     super(viewport, panel);
-    ourAnnots = new ArrayList<AlignmentAnnotation>();
+    ourAnnots = new ArrayList<>();
     this.counter = counter;
     calcMan.registerWorker(this);
   }
@@ -121,7 +121,10 @@ class AnnotationWorker extends AlignCalcWorker
     if (ap != null)
     {
       ap.adjustAnnotationHeight();
-      ap.paintAlignment(true);
+      // TODO: only need to update colour and geometry if panel height changes
+      // and view is coloured by annotation, and the annotation is actually
+      // changed!
+      ap.paintAlignment(true, true);
     }
   }
 
index 2422748..74695fe 100644 (file)
@@ -57,7 +57,7 @@ class ColumnCounterSetWorker extends AlignCalcWorker
           AlignmentViewPanel panel, FeatureSetCounterI counter)
   {
     super(viewport, panel);
-    ourAnnots = new ArrayList<AlignmentAnnotation>();
+    ourAnnots = new ArrayList<>();
     this.counter = counter;
     calcMan.registerWorker(this);
   }
@@ -116,7 +116,7 @@ class ColumnCounterSetWorker extends AlignCalcWorker
       {
         ap.adjustAnnotationHeight();
       }
-      ap.paintAlignment(true);
+      ap.paintAlignment(true, true);
     }
 
   }
@@ -229,6 +229,7 @@ class ColumnCounterSetWorker extends AlignCalcWorker
    * 
    * @param alignment
    * @param col
+   *          (0..)
    * @param row
    * @param fr
    */
@@ -249,14 +250,12 @@ class ColumnCounterSetWorker extends AlignCalcWorker
     {
       return null;
     }
-    int pos = seq.findPosition(col);
 
     /*
      * compute a count for any displayed features at residue
      */
-    // NB have to adjust pos if using AlignmentView.getVisibleAlignment
     // see JAL-2075
-    List<SequenceFeature> features = fr.findFeaturesAtRes(seq, pos);
+    List<SequenceFeature> features = fr.findFeaturesAtColumn(seq, col + 1);
     int[] count = this.counter.count(String.valueOf(res), features);
     return count;
   }
index 284f1a1..335529c 100644 (file)
@@ -58,12 +58,13 @@ public class ConsensusThread extends AlignCalcWorker
       }
       while (!calcMan.notifyWorking(this))
       {
-        // System.err.println("Thread (Consensus"+Thread.currentThread().getName()+") Waiting around.");
+        // System.err.println("Thread
+        // (Consensus"+Thread.currentThread().getName()+") Waiting around.");
         try
         {
           if (ap != null)
           {
-            ap.paintAlignment(false);
+            ap.paintAlignment(false, false);
           }
           Thread.sleep(200);
         } catch (Exception ex)
@@ -92,7 +93,7 @@ public class ConsensusThread extends AlignCalcWorker
 
       if (ap != null)
       {
-        ap.paintAlignment(true);
+        ap.paintAlignment(true, true);
       }
     } catch (OutOfMemoryError error)
     {
index 571234c..54b0191 100644 (file)
@@ -75,7 +75,7 @@ public class ConservationThread extends AlignCalcWorker
         abortAndDestroy();
         return;
       }
-      List<AlignmentAnnotation> ourAnnot = new ArrayList<AlignmentAnnotation>();
+      List<AlignmentAnnotation> ourAnnot = new ArrayList<>();
       AlignmentI alignment = alignViewport.getAlignment();
       conservation = alignViewport.getAlignmentConservationAnnotation();
       quality = alignViewport.getAlignmentQualityAnnot();
@@ -123,7 +123,7 @@ public class ConservationThread extends AlignCalcWorker
     }
     if (ap != null)
     {
-      ap.paintAlignment(true);
+      ap.paintAlignment(true, true);
     }
 
   }
index 5ed2885..61ec3d0 100644 (file)
@@ -139,7 +139,7 @@ public class StrucConsensusThread extends AlignCalcWorker
       calcMan.workerComplete(this);
       if (ap != null)
       {
-        ap.paintAlignment(true);
+        ap.paintAlignment(true, true);
       }
     }
 
index 2ef5256..80918f9 100644 (file)
@@ -134,8 +134,8 @@ public abstract class AWSThread extends Thread
           {
             // Deal with Transaction exceptions
             wsInfo.appendProgressText(jobs[j].jobnum, MessageManager
-                    .formatMessage("info.server_exception", new Object[] {
-                        WebServiceName, ex.getMessage() }));
+                    .formatMessage("info.server_exception", new Object[]
+                    { WebServiceName, ex.getMessage() }));
             // always output the exception's stack trace to the log
             Cache.log.warn(WebServiceName + " job(" + jobs[j].jobnum
                     + ") Server exception.");
@@ -169,8 +169,8 @@ public abstract class AWSThread extends Thread
                     WebserviceInfo.STATE_STOPPED_ERROR);
             Cache.log.error("Out of memory when retrieving Job " + j
                     + " id:" + WsUrl + "/" + jobs[j].jobId, er);
-            new jalview.gui.OOMWarning("retrieving result for "
-                    + WebServiceName, er);
+            new jalview.gui.OOMWarning(
+                    "retrieving result for " + WebServiceName, er);
             System.gc();
           }
         }
@@ -185,8 +185,8 @@ public abstract class AWSThread extends Thread
           Thread.sleep(5000);
         } catch (InterruptedException e)
         {
-          Cache.log
-                  .debug("Interrupted sleep waiting for next job poll.", e);
+          Cache.log.debug("Interrupted sleep waiting for next job poll.",
+                  e);
         }
         // System.out.println("I'm alive "+alTitle);
       }
@@ -197,11 +197,11 @@ public abstract class AWSThread extends Thread
     }
     else
     {
-      Cache.log
-              .debug("WebServiceJob poll loop finished with no jobs created.");
+      Cache.log.debug(
+              "WebServiceJob poll loop finished with no jobs created.");
       wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
-      wsInfo.appendProgressText(MessageManager
-              .getString("info.no_jobs_ran"));
+      wsInfo.appendProgressText(
+              MessageManager.getString("info.no_jobs_ran"));
       wsInfo.setFinishedNoResults();
     }
   }
index fd511dc..fb8864d 100644 (file)
@@ -26,7 +26,6 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.DBRefSource;
 import jalview.datamodel.Mapping;
-import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.gui.CutAndPasteTransfer;
 import jalview.gui.DasSourceBrowser;
@@ -165,9 +164,9 @@ public class DBRefFetcher implements Runnable
     // af.featureSettings_actionPerformed(null);
     String[] defdb = null;
     List<DbSourceProxy> selsources = new ArrayList<DbSourceProxy>();
-    Vector<jalviewSourceI> dasselsrc = (featureSettings != null) ? featureSettings
-            .getSelectedSources() : new DasSourceBrowser()
-            .getSelectedSources();
+    Vector<jalviewSourceI> dasselsrc = (featureSettings != null)
+            ? featureSettings.getSelectedSources()
+            : new DasSourceBrowser().getSelectedSources();
 
     for (jalviewSourceI src : dasselsrc)
     {
@@ -251,7 +250,8 @@ public class DBRefFetcher implements Runnable
       DbSourceProxy[] newsrc = new DbSourceProxy[dbSources.length
               + otherdb.length];
       System.arraycopy(dbSources, 0, newsrc, 0, dbSources.length);
-      System.arraycopy(otherdb, 0, newsrc, dbSources.length, otherdb.length);
+      System.arraycopy(otherdb, 0, newsrc, dbSources.length,
+              otherdb.length);
       dbSources = newsrc;
     }
   }
@@ -331,9 +331,8 @@ public class DBRefFetcher implements Runnable
   {
     if (dbSources == null)
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_error_must_init_dbsources"));
+      throw new Error(MessageManager
+              .getString("error.implementation_error_must_init_dbsources"));
     }
     running = true;
     long startTime = System.currentTimeMillis();
@@ -398,8 +397,8 @@ public class DBRefFetcher implements Runnable
             String query = queries.elementAt(0);
             if (dbsource.isValidReference(query))
             {
-              queryString.append((numq == 0) ? "" : dbsource
-                      .getAccessionSeparator());
+              queryString.append(
+                      (numq == 0) ? "" : dbsource.getAccessionSeparator());
               queryString.append(query);
               numq++;
             }
@@ -433,12 +432,13 @@ public class DBRefFetcher implements Runnable
         else
         {
           // make some more strings for use as queries
-          for (int i = 0; (seqIndex < dataset.length) && (i < 50); seqIndex++, i++)
+          for (int i = 0; (seqIndex < dataset.length)
+                  && (i < 50); seqIndex++, i++)
           {
             SequenceI sequence = dataset[seqIndex];
-            DBRefEntry[] uprefs = DBRefUtils.selectRefs(
-                    sequence.getDBRefs(),
-                    new String[] { dbsource.getDbSource() }); // jalview.datamodel.DBRefSource.UNIPROT
+            DBRefEntry[] uprefs = DBRefUtils
+                    .selectRefs(sequence.getDBRefs(), new String[]
+                    { dbsource.getDbSource() }); // jalview.datamodel.DBRefSource.UNIPROT
             // });
             // check for existing dbrefs to use
             if (uprefs != null && uprefs.length > 0)
@@ -446,7 +446,8 @@ public class DBRefFetcher implements Runnable
               for (int j = 0; j < uprefs.length; j++)
               {
                 addSeqId(sequence, uprefs[j].getAccessionId());
-                queries.addElement(uprefs[j].getAccessionId().toUpperCase());
+                queries.addElement(
+                        uprefs[j].getAccessionId().toUpperCase());
               }
             }
             else
@@ -463,14 +464,13 @@ public class DBRefFetcher implements Runnable
                   // resolve the string against PICR to recover valid IDs
                   try
                   {
-                    presp = picrClient
-                            .getUPIForAccession(token, null,
-                                    picrClient.getMappedDatabaseNames(),
-                                    null, true);
+                    presp = picrClient.getUPIForAccession(token, null,
+                            picrClient.getMappedDatabaseNames(), null,
+                            true);
                   } catch (Exception e)
                   {
-                    System.err.println("Exception with Picr for '" + token
-                            + "'\n");
+                    System.err.println(
+                            "Exception with Picr for '" + token + "'\n");
                     e.printStackTrace();
                   }
                 }
@@ -482,8 +482,8 @@ public class DBRefFetcher implements Runnable
                     // present, and do a transferReferences
                     // otherwise transfer non sequence x-references directly.
                   }
-                  System.out
-                          .println("Validated ID against PICR... (for what its worth):"
+                  System.out.println(
+                          "Validated ID against PICR... (for what its worth):"
                                   + token);
                   addSeqId(sequence, token);
                   queries.addElement(token.toUpperCase());
@@ -491,7 +491,8 @@ public class DBRefFetcher implements Runnable
                 else
                 {
                   // if ()
-                  // System.out.println("Not querying source with token="+token+"\n");
+                  // System.out.println("Not querying source with
+                  // token="+token+"\n");
                   addSeqId(sequence, token);
                   queries.addElement(token.toUpperCase());
                 }
@@ -515,7 +516,8 @@ public class DBRefFetcher implements Runnable
       output.setText(sb.toString());
 
       Desktop.addInternalFrame(output,
-              MessageManager.getString("label.sequences_updated"), 600, 300);
+              MessageManager.getString("label.sequences_updated"), 600,
+              300);
       // The above is the dataset, we must now find out the index
       // of the viewed sequence
 
@@ -562,8 +564,8 @@ public class DBRefFetcher implements Runnable
     }
 
     boolean modified = false;
-    SequenceI[] retrieved = recoverDbSequences(retrievedAl
-            .getSequencesArray());
+    SequenceI[] retrieved = recoverDbSequences(
+            retrievedAl.getSequencesArray());
     SequenceI sequence = null;
 
     for (SequenceI retrievedSeq : retrieved)
@@ -572,8 +574,9 @@ public class DBRefFetcher implements Runnable
       // taking into account all accessionIds and names in the file
       Vector<SequenceI> sequenceMatches = new Vector<SequenceI>();
       // look for corresponding accession ids
-      DBRefEntry[] entryRefs = DBRefUtils.selectRefs(
-              retrievedSeq.getDBRefs(), new String[] { dbSource });
+      DBRefEntry[] entryRefs = DBRefUtils
+              .selectRefs(retrievedSeq.getDBRefs(), new String[]
+              { dbSource });
       if (entryRefs == null)
       {
         System.err
@@ -650,8 +653,9 @@ public class DBRefFetcher implements Runnable
         final int sequenceStart = sequence.getStart();
 
         boolean remoteEnclosesLocal = false;
-        String nonGapped = AlignSeq.extractGaps("-. ",
-                sequence.getSequenceAsString()).toUpperCase();
+        String nonGapped = AlignSeq
+                .extractGaps("-. ", sequence.getSequenceAsString())
+                .toUpperCase();
         int absStart = entrySeq.indexOf(nonGapped);
         if (absStart == -1)
         {
@@ -681,10 +685,14 @@ public class DBRefFetcher implements Runnable
            * So create a mapping to the external entry from the matching region of 
            * the local sequence, and leave local start/end untouched. 
            */
-          mp = new Mapping(null, new int[] { sequenceStart + absStart,
-              sequenceStart + absStart + entrySeq.length() - 1 }, new int[]
-          { retrievedSeq.getStart(),
-              retrievedSeq.getStart() + entrySeq.length() - 1 }, 1, 1);
+          mp = new Mapping(null,
+                  new int[]
+                  { sequenceStart + absStart,
+                      sequenceStart + absStart + entrySeq.length() - 1 },
+                  new int[]
+                  { retrievedSeq.getStart(),
+                      retrievedSeq.getStart() + entrySeq.length() - 1 },
+                  1, 1);
           updateRefFrame = false;
         }
         else
@@ -697,28 +705,13 @@ public class DBRefFetcher implements Runnable
 
           if (updateRefFrame)
           {
-            SequenceFeature[] sfs = sequence.getSequenceFeatures();
-            if (sfs != null)
+            /*
+             * relocate existing sequence features by offset
+             */
+            int startShift = absStart - sequenceStart + 1;
+            if (startShift != 0)
             {
-              /*
-               * relocate existing sequence features by offset
-               */
-              int start = sequenceStart;
-              int end = sequence.getEnd();
-              int startShift = 1 - absStart - start;
-
-              if (startShift != 0)
-              {
-                for (SequenceFeature sf : sfs)
-                {
-                  if (sf.getBegin() >= start && sf.getEnd() <= end)
-                  {
-                    sf.setBegin(sf.getBegin() + startShift);
-                    sf.setEnd(sf.getEnd() + startShift);
-                    modified = true;
-                  }
-                }
-              }
+              modified |= sequence.getFeatures().shiftFeatures(startShift);
             }
           }
         }
@@ -741,8 +734,8 @@ public class DBRefFetcher implements Runnable
             sequence.setSequence(retrievedSeqString);
             modified = true;
             addWarningMessage(warningMessages,
-                    "Sequence for " + sequence.getName()
-                            + " expanded from " + retrievedSeq.getName());
+                    "Sequence for " + sequence.getName() + " expanded from "
+                            + retrievedSeq.getName());
           }
           if (sequence.getStart() != retrievedSeq.getStart())
           {
@@ -750,9 +743,9 @@ public class DBRefFetcher implements Runnable
             modified = true;
             if (absStart != sequenceStart)
             {
-              addWarningMessage(warningMessages, "Start/end position for "
-                      + sequence.getName() + " updated from "
-                      + retrievedSeq.getName());
+              addWarningMessage(warningMessages,
+                      "Start/end position for " + sequence.getName()
+                              + " updated from " + retrievedSeq.getName());
             }
           }
         }
@@ -768,9 +761,9 @@ public class DBRefFetcher implements Runnable
               sequence.setStart(absStart);
               sequence.setEnd(absEnd);
               modified = true;
-              addWarningMessage(warningMessages, "Start/end for "
-                      + sequence.getName() + " updated from "
-                      + retrievedSeq.getName());
+              addWarningMessage(warningMessages,
+                      "Start/end for " + sequence.getName()
+                              + " updated from " + retrievedSeq.getName());
             }
           }
           // search for alignment sequences to update coordinate frame for
@@ -778,16 +771,17 @@ public class DBRefFetcher implements Runnable
           {
             if (alseqs[alsq].getDatasetSequence() == sequence)
             {
-              String ngAlsq = AlignSeq.extractGaps("-. ",
-                      alseqs[alsq].getSequenceAsString()).toUpperCase();
+              String ngAlsq = AlignSeq
+                      .extractGaps("-. ",
+                              alseqs[alsq].getSequenceAsString())
+                      .toUpperCase();
               int oldstrt = alseqs[alsq].getStart();
               alseqs[alsq].setStart(sequence.getSequenceAsString()
-                      .toUpperCase().indexOf(ngAlsq)
-                      + sequence.getStart());
+                      .toUpperCase().indexOf(ngAlsq) + sequence.getStart());
               if (oldstrt != alseqs[alsq].getStart())
               {
-                alseqs[alsq].setEnd(ngAlsq.length()
-                        + alseqs[alsq].getStart() - 1);
+                alseqs[alsq].setEnd(
+                        ngAlsq.length() + alseqs[alsq].getStart() - 1);
                 modified = true;
               }
             }
@@ -831,7 +825,8 @@ public class DBRefFetcher implements Runnable
   private SequenceI[] recoverDbSequences(SequenceI[] sequencesArray)
   {
     Vector<SequenceI> nseq = new Vector<SequenceI>();
-    for (int i = 0; sequencesArray != null && i < sequencesArray.length; i++)
+    for (int i = 0; sequencesArray != null
+            && i < sequencesArray.length; i++)
     {
       nseq.addElement(sequencesArray[i]);
       DBRefEntry[] dbr = sequencesArray[i].getDBRefs();
index 4d3dd2f..c661e2c 100644 (file)
@@ -135,7 +135,7 @@ public class DasSequenceFeatureFetcher
           boolean useJDasMultiThread)
   {
     this.useJDASMultiThread = useJDasMultiThread;
-    this.selectedSources = new ArrayList<jalviewSourceI>();
+    this.selectedSources = new ArrayList<>();
     // filter both sequences and sources to eliminate duplicates
     for (jalviewSourceI src : selectedSources2)
     {
@@ -202,15 +202,12 @@ public class DasSequenceFeatureFetcher
       int reply = JvOptionPane.YES_OPTION;
       if (promptFetchDbrefs)
       {
-        reply = JvOptionPane
-                .showInternalConfirmDialog(
-                        Desktop.desktop,
-                        MessageManager
-                                .getString("info.you_want_jalview_to_find_uniprot_accessions"),
-                        MessageManager
-                                .getString("label.find_uniprot_accession_ids"),
-                        JvOptionPane.YES_NO_OPTION,
-                        JvOptionPane.QUESTION_MESSAGE);
+        reply = JvOptionPane.showInternalConfirmDialog(Desktop.desktop,
+                MessageManager.getString(
+                        "info.you_want_jalview_to_find_uniprot_accessions"),
+                MessageManager
+                        .getString("label.find_uniprot_accession_ids"),
+                JvOptionPane.YES_NO_OPTION, JvOptionPane.QUESTION_MESSAGE);
       }
 
       if (reply == JvOptionPane.YES_OPTION)
@@ -271,9 +268,8 @@ public class DasSequenceFeatureFetcher
     startTime = System.currentTimeMillis();
     if (af != null)
     {
-      af.setProgressBar(MessageManager
-              .getString("status.fetching_das_sequence_features"),
-              startTime);
+      af.setProgressBar(MessageManager.getString(
+              "status.fetching_das_sequence_features"), startTime);
     }
     if (sourceRegistry == null)
     {
@@ -283,8 +279,8 @@ public class DasSequenceFeatureFetcher
     {
       try
       {
-        jalviewSourceI[] sources = sourceRegistry.getSources().toArray(
-                new jalviewSourceI[0]);
+        jalviewSourceI[] sources = sourceRegistry.getSources()
+                .toArray(new jalviewSourceI[0]);
         String active = Cache.getDefault("DAS_ACTIVE_SOURCE", "uniprot");
         StringTokenizer st = new StringTokenizer(active, "\t");
         selectedSources = new Vector();
@@ -320,17 +316,17 @@ public class DasSequenceFeatureFetcher
     FeaturesClientMultipleSources fc = new FeaturesClientMultipleSources();
     fc.setConnProps(sourceRegistry.getSessionHandler());
     // Now sending requests one at a time to each server
-    ArrayList<jalviewSourceI> srcobj = new ArrayList<jalviewSourceI>();
-    ArrayList<String> src = new ArrayList<String>();
-    List<List<String>> ids = new ArrayList<List<String>>();
-    List<List<DBRefEntry>> idobj = new ArrayList<List<DBRefEntry>>();
-    List<Map<String, SequenceI>> sqset = new ArrayList<Map<String, SequenceI>>();
+    ArrayList<jalviewSourceI> srcobj = new ArrayList<>();
+    ArrayList<String> src = new ArrayList<>();
+    List<List<String>> ids = new ArrayList<>();
+    List<List<DBRefEntry>> idobj = new ArrayList<>();
+    List<Map<String, SequenceI>> sqset = new ArrayList<>();
     for (jalviewSourceI _sr : selectedSources)
     {
 
-      Map<String, SequenceI> slist = new HashMap<String, SequenceI>();
-      List<DBRefEntry> idob = new ArrayList<DBRefEntry>();
-      List<String> qset = new ArrayList<String>();
+      Map<String, SequenceI> slist = new HashMap<>();
+      List<DBRefEntry> idob = new ArrayList<>();
+      List<String> qset = new ArrayList<>();
 
       for (SequenceI seq : sequences)
       {
@@ -372,8 +368,8 @@ public class DasSequenceFeatureFetcher
         sqset.add(slist);
       }
     }
-    Map<String, Map<List<String>, Exception>> errors = new HashMap<String, Map<List<String>, Exception>>();
-    Map<String, Map<List<String>, DasGFFAdapter>> results = new HashMap<String, Map<List<String>, DasGFFAdapter>>();
+    Map<String, Map<List<String>, Exception>> errors = new HashMap<>();
+    Map<String, Map<List<String>, DasGFFAdapter>> results = new HashMap<>();
     if (!useJDASMultiThread)
     {
       Iterator<String> sources = src.iterator();
@@ -381,9 +377,9 @@ public class DasSequenceFeatureFetcher
       for (List<String> idl : ids)
       {
         String source = sources.next();
-        FeaturesClient featuresc = new FeaturesClient(sourceRegistry
-                .getSessionHandler().getConnectionPropertyProviderFor(
-                        source));
+        FeaturesClient featuresc = new FeaturesClient(
+                sourceRegistry.getSessionHandler()
+                        .getConnectionPropertyProviderFor(source));
         for (String id : idl)
         {
           List<String> qid = Arrays.asList(new String[] { id });
@@ -394,7 +390,7 @@ public class DasSequenceFeatureFetcher
             if (ers == null)
             {
               results.put(source,
-                      ers = new HashMap<List<String>, DasGFFAdapter>());
+                      ers = new HashMap<>());
             }
             ers.put(qid, dga);
           } catch (Exception ex)
@@ -403,7 +399,7 @@ public class DasSequenceFeatureFetcher
             if (ers == null)
             {
               errors.put(source,
-                      ers = new HashMap<List<String>, Exception>());
+                      ers = new HashMap<>());
             }
             ers.put(qid, ex);
           }
@@ -438,11 +434,11 @@ public class DasSequenceFeatureFetcher
   }
 
   private void processResponse(Map<String, SequenceI> sequencemap,
-          jalviewSourceI jvsource, List<String> ids,
-          List<DBRefEntry> idobj, Map<List<String>, DasGFFAdapter> results,
+          jalviewSourceI jvsource, List<String> ids, List<DBRefEntry> idobj,
+          Map<List<String>, DasGFFAdapter> results,
           Map<List<String>, Exception> errors)
   {
-    Set<SequenceI> sequences = new HashSet<SequenceI>();
+    Set<SequenceI> sequences = new HashSet<>();
     String source = jvsource.getSourceURL();
     // process features
     DasGFFAdapter result = (results == null) ? null : results.get(ids);
@@ -502,8 +498,8 @@ public class DasSequenceFeatureFetcher
                   vf = dbref.getMap().locateFeature(f);
                 } catch (Exception ex)
                 {
-                  Cache.log
-                          .warn("Error in 'experimental' mapping of features. Please try to reproduce and then report info to jalview-discuss@jalview.org.");
+                  Cache.log.warn(
+                          "Error in 'experimental' mapping of features. Please try to reproduce and then report info to jalview-discuss@jalview.org.");
                   Cache.log.warn("Mapping feature from " + f.getBegin()
                           + " to " + f.getEnd() + " in dbref "
                           + dbref.getAccessionId() + " in "
@@ -576,9 +572,8 @@ public class DasSequenceFeatureFetcher
   {
     if (af != null)
     {
-      af.setProgressBar(MessageManager
-              .getString("status.das_feature_fetching_cancelled"),
-              startTime);
+      af.setProgressBar(MessageManager.getString(
+              "status.das_feature_fetching_cancelled"), startTime);
     }
     cancelled = true;
   }
@@ -593,8 +588,8 @@ public class DasSequenceFeatureFetcher
     if (!cancelled && af != null)
     {
       // only update the progress bar if we've completed the fetch normally
-      af.setProgressBar(MessageManager
-              .getString("status.das_feature_fetching_complete"), startTime);
+      af.setProgressBar(MessageManager.getString(
+              "status.das_feature_fetching_complete"), startTime);
     }
 
     if (af != null && af.featureSettings != null)
@@ -627,7 +622,7 @@ public class DasSequenceFeatureFetcher
         if (seq == af.getViewport().getAlignment().getSequenceAt(index)
                 .getDatasetSequence())
         {
-          af.alignPanel.paintAlignment(true);
+          af.alignPanel.paintAlignment(true, true);
           index = end;
           break;
         }
@@ -642,17 +637,18 @@ public class DasSequenceFeatureFetcher
       return null;
     }
     DBRefEntry[] uprefs = DBRefUtils.selectRefs(seq.getDBRefs(),
-            new String[] {
-            // jalview.datamodel.DBRefSource.PDB,
-            DBRefSource.UNIPROT,
+            new String[]
+            {
+                // jalview.datamodel.DBRefSource.PDB,
+                DBRefSource.UNIPROT,
             // jalview.datamodel.DBRefSource.EMBL - not tested on any EMBL coord
             // sys sources
             });
     // TODO: minimal list of DAS queries to make by querying with untyped ID if
     // distinct from any typed IDs
 
-    List<DBRefEntry> ids = new ArrayList<DBRefEntry>();
-    List<String> qstring = new ArrayList<String>();
+    List<DBRefEntry> ids = new ArrayList<>();
+    List<String> qstring = new ArrayList<>();
     boolean dasCoordSysFound = false;
 
     if (uprefs != null)
@@ -672,9 +668,9 @@ public class DasSequenceFeatureFetcher
             // - the start/end for the DBRefEntry may not be the same as the
             // sequence's start/end
 
-            System.out.println(seq.getName() + " "
-                    + (seq.getDatasetSequence() == null) + " "
-                    + csys.getUri());
+            System.out.println(
+                    seq.getName() + " " + (seq.getDatasetSequence() == null)
+                            + " " + csys.getUri());
 
             dasCoordSysFound = true; // break's out of the loop
             ids.add(uprefs[j]);
@@ -884,9 +880,8 @@ public class DasSequenceFeatureFetcher
       {
       }
 
-      SequenceFeature f = new SequenceFeature(
-              getTypeString(feat.getTYPE()), desc, start, end, score,
-              nickname);
+      SequenceFeature f = new SequenceFeature(getTypeString(feat.getTYPE()),
+              desc, start, end, score, nickname);
 
       if (feat.getLINK() != null)
       {
index 2cc3d8d..b19d606 100644 (file)
@@ -75,8 +75,8 @@ public class HttpClientUtils
             HttpVersion.HTTP_1_1);
     if (connectionTimeoutMs > 0)
     {
-      HttpConnectionParams
-              .setConnectionTimeout(params, connectionTimeoutMs);
+      HttpConnectionParams.setConnectionTimeout(params,
+              connectionTimeoutMs);
     }
     if (readTimeoutMs > 0)
     {
@@ -91,8 +91,8 @@ public class HttpClientUtils
 
     if (resEntity != null)
     {
-      BufferedReader r = new BufferedReader(new InputStreamReader(
-              resEntity.getContent()));
+      BufferedReader r = new BufferedReader(
+              new InputStreamReader(resEntity.getContent()));
       return r;
     }
     else
@@ -114,8 +114,8 @@ public class HttpClientUtils
       mpe.addPart(nvp.getName(), new StringBody(nvp.getValue()));
     }
 
-    FileBody fb = new FileBody(file, mtype != null ? mtype
-            : "application/octet-stream");
+    FileBody fb = new FileBody(file,
+            mtype != null ? mtype : "application/octet-stream");
     mpe.addPart(fparm, fb);
     UrlEncodedFormEntity ue = new UrlEncodedFormEntity(vals, "UTF-8");
     httppost.setEntity(ue);
@@ -124,8 +124,8 @@ public class HttpClientUtils
 
     if (resEntity != null)
     {
-      BufferedReader r = new BufferedReader(new InputStreamReader(
-              resEntity.getContent()));
+      BufferedReader r = new BufferedReader(
+              new InputStreamReader(resEntity.getContent()));
       return r;
     }
     else
@@ -136,8 +136,8 @@ public class HttpClientUtils
 
   public static BufferedReader doHttpMpartInputstreamPost(String postUrl,
           List<NameValuePair> vals, String fparm, String fname,
-          InputStream is, String mtype) throws ClientProtocolException,
-          IOException
+          InputStream is, String mtype)
+          throws ClientProtocolException, IOException
   {
     HttpClient httpclient = new DefaultHttpClient();
     HttpPost httppost = new HttpPost(postUrl);
@@ -147,8 +147,9 @@ public class HttpClientUtils
       mpe.addPart(nvp.getName(), new StringBody(nvp.getValue()));
     }
 
-    InputStreamBody fb = (mtype != null) ? new InputStreamBody(is, fname,
-            mtype) : new InputStreamBody(is, fname);
+    InputStreamBody fb = (mtype != null)
+            ? new InputStreamBody(is, fname, mtype)
+            : new InputStreamBody(is, fname);
     mpe.addPart(fparm, fb);
     UrlEncodedFormEntity ue = new UrlEncodedFormEntity(vals, "UTF-8");
     httppost.setEntity(ue);
@@ -157,8 +158,8 @@ public class HttpClientUtils
 
     if (resEntity != null)
     {
-      BufferedReader r = new BufferedReader(new InputStreamReader(
-              resEntity.getContent()));
+      BufferedReader r = new BufferedReader(
+              new InputStreamReader(resEntity.getContent()));
       return r;
     }
     else
index 4d3db58..6b86775 100644 (file)
@@ -119,7 +119,8 @@ public class JobStateSummary
       {
         serror++;
         j.subjobComplete = true;
-        wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_SERVERERROR);
+        wsInfo.setStatus(j.jobnum,
+                WebserviceInfo.STATE_STOPPED_SERVERERROR);
       }
       else if (j.isBroken())
       {
@@ -152,7 +153,8 @@ public class JobStateSummary
         }
         // } catch (OutOfMemoryError e)
         // {
-        // System.err.println("Out of memory when displaying status. Squashing error.");
+        // System.err.println("Out of memory when displaying status. Squashing
+        // error.");
         // wsInfo.appendProgressText(j.jobnum,
         // "..\n(Out of memory when displaying status)\n");
         // }
index 37946b1..a0b77de 100644 (file)
@@ -78,7 +78,8 @@ public class SequenceFetcher extends ASequenceFetcher
   public String[] getOrderedSupportedSources()
   {
     String[] srcs = this.getSupportedDb();
-    ArrayList<String> dassrc = new ArrayList<String>(), nondas = new ArrayList<String>();
+    ArrayList<String> dassrc = new ArrayList<String>(),
+            nondas = new ArrayList<String>();
     for (int i = 0; i < srcs.length; i++)
     {
       boolean das = false, skip = false;
@@ -94,7 +95,8 @@ public class SequenceFetcher extends ASequenceFetcher
         else
         {
           nm = dbs.getDbName();
-          if (getSourceProxy(srcs[i]) instanceof jalview.ws.dbsources.das.datamodel.DasSequenceSource)
+          if (getSourceProxy(
+                  srcs[i]) instanceof jalview.ws.dbsources.das.datamodel.DasSequenceSource)
           {
             if (nm.startsWith("das:"))
             {
@@ -118,8 +120,8 @@ public class SequenceFetcher extends ASequenceFetcher
         nondas.add(srcs[i]);
       }
     }
-    String[] tosort = nondas.toArray(new String[0]), sorted = nondas
-            .toArray(new String[0]);
+    String[] tosort = nondas.toArray(new String[0]),
+            sorted = nondas.toArray(new String[0]);
     for (int j = 0, jSize = sorted.length; j < jSize; j++)
     {
       tosort[j] = tosort[j].toLowerCase();
index b2fb808..ca90d60 100644 (file)
@@ -69,8 +69,8 @@ public abstract class EmblXmlSource extends EbiFileRetrievedProxy
     {
       stopQuery();
       throw new Exception(MessageManager.formatMessage(
-              "exception.ebiembl_retrieval_failed_on", new String[] {
-                  emprefx.toLowerCase(), query.trim() }), e);
+              "exception.ebiembl_retrieval_failed_on", new String[]
+              { emprefx.toLowerCase(), query.trim() }), e);
     }
     return getEmblSequenceRecords(emprefx, query, reply);
   }
@@ -91,7 +91,7 @@ public abstract class EmblXmlSource extends EbiFileRetrievedProxy
           File reply) throws Exception
   {
     EmblFile efile = null;
-    List<SequenceI> seqs = new ArrayList<SequenceI>();
+    List<SequenceI> seqs = new ArrayList<>();
 
     if (reply != null && reply.exists())
     {
@@ -107,7 +107,7 @@ public abstract class EmblXmlSource extends EbiFileRetrievedProxy
      * EmbFile reads something like (e.g.) this ungrammatical phrase
      * Entry: <acc> display type is either not supported or entry is not found.
      */
-    List<SequenceI> peptides = new ArrayList<SequenceI>();
+    List<SequenceI> peptides = new ArrayList<>();
     if (efile != null && efile.getEntries() != null)
     {
       for (EmblEntry entry : efile.getEntries())
index 982c399..e4326d1 100644 (file)
@@ -165,8 +165,8 @@ public class Pdb extends EbiFileRetrievedProxy
       // todo get rid of Type and use FileFormatI instead?
       FileFormatI fileFormat = (pdbFileFormat == Type.PDB) ? FileFormat.PDB
               : FileFormat.MMCif;
-      pdbAlignment = new FormatAdapter().readFile(file,
-              DataSourceType.FILE, fileFormat);
+      pdbAlignment = new FormatAdapter().readFile(file, DataSourceType.FILE,
+              fileFormat);
       if (pdbAlignment != null)
       {
         List<SequenceI> toremove = new ArrayList<SequenceI>();
@@ -182,15 +182,14 @@ public class Pdb extends EbiFileRetrievedProxy
 
             }
           }
-          if (chain == null
-                  || (chid != null && (chid.equals(chain)
-                          || chid.trim().equals(chain.trim()) || (chain
-                          .trim().length() == 0 && chid.equals("_")))))
+          if (chain == null || (chid != null && (chid.equals(chain)
+                  || chid.trim().equals(chain.trim())
+                  || (chain.trim().length() == 0 && chid.equals("_")))))
           {
             // FIXME seems to result in 'PDB|1QIP|1qip|A' - 1QIP is redundant.
             // TODO: suggest simplify naming to 1qip|A as default name defined
-            pdbcs.setName(jalview.datamodel.DBRefSource.PDB + SEPARATOR
-                    + id + SEPARATOR + pdbcs.getName());
+            pdbcs.setName(jalview.datamodel.DBRefSource.PDB + SEPARATOR + id
+                    + SEPARATOR + pdbcs.getName());
             // Might need to add more metadata to the PDBEntry object
             // like below
             /*
@@ -236,8 +235,8 @@ public class Pdb extends EbiFileRetrievedProxy
       if (pdbAlignment == null || pdbAlignment.getHeight() < 1)
       {
         throw new Exception(MessageManager.formatMessage(
-                "exception.no_pdb_records_for_chain", new String[] { id,
-                    ((chain == null) ? "' '" : chain) }));
+                "exception.no_pdb_records_for_chain", new String[]
+                { id, ((chain == null) ? "' '" : chain) }));
       }
 
     } catch (Exception ex) // Problem parsing PDB file
index 12b193d..ec9fcbb 100644 (file)
@@ -48,6 +48,7 @@ public class PfamFull extends Pfam
   {
     return "/alignment/full";
   }
+
   /*
    * (non-Javadoc)
    * 
index 9f07e5d..33c39b1 100644 (file)
@@ -49,6 +49,7 @@ public class PfamSeed extends Pfam
   {
     return "/alignment/seed";
   }
+
   /*
    * (non-Javadoc)
    * 
index e263c4b..b2ca31a 100644 (file)
@@ -50,6 +50,7 @@ public class RfamFull extends Rfam
   {
     return "/alignment/full";
   }
+
   /*
    * (non-Javadoc)
    * 
index 3afe8ec..73775cf 100644 (file)
@@ -28,15 +28,16 @@ import jalview.datamodel.PDBEntry;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
-import jalview.datamodel.UniprotEntry;
-import jalview.datamodel.UniprotFile;
-import jalview.ws.ebi.EBIFetchClient;
+import jalview.datamodel.xdb.uniprot.UniprotEntry;
+import jalview.datamodel.xdb.uniprot.UniprotFeature;
+import jalview.datamodel.xdb.uniprot.UniprotFile;
 import jalview.ws.seqfetcher.DbSourceProxyImpl;
 
-import java.io.File;
-import java.io.FileReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.Reader;
 import java.net.URL;
+import java.net.URLConnection;
 import java.util.ArrayList;
 import java.util.Vector;
 
@@ -161,16 +162,21 @@ public class Uniprot extends DbSourceProxyImpl
       queries = queries.toUpperCase().replaceAll(
               "(UNIPROT\\|?|UNIPROT_|UNIREF\\d+_|UNIREF\\d+\\|?)", "");
       AlignmentI al = null;
-      EBIFetchClient ebi = new EBIFetchClient();
-      // uniprotxml parameter required since december 2007
-      // uniprotkb dbname changed introduced december 2008
-      File file = ebi.fetchDataAsFile("uniprotkb:" + queries, "uniprotxml",
-              "xml");
-      Vector<UniprotEntry> entries = getUniprotEntries(new FileReader(file));
+
+      String downloadstring = "http://www.uniprot.org/uniprot/" + queries
+              + ".xml";
+      URL url = null;
+      URLConnection urlconn = null;
+
+      url = new URL(downloadstring);
+      urlconn = url.openConnection();
+      InputStream istr = urlconn.getInputStream();
+      Vector<UniprotEntry> entries = getUniprotEntries(
+              new InputStreamReader(istr, "UTF-8"));
 
       if (entries != null)
       {
-        ArrayList<SequenceI> seqs = new ArrayList<SequenceI>();
+        ArrayList<SequenceI> seqs = new ArrayList<>();
         for (UniprotEntry entry : entries)
         {
           seqs.add(uniprotEntryToSequenceI(entry));
@@ -182,8 +188,10 @@ public class Uniprot extends DbSourceProxyImpl
       return al;
     } catch (Exception e)
     {
-      stopQuery();
       throw (e);
+    } finally
+    {
+      stopQuery();
     }
   }
 
@@ -196,12 +204,12 @@ public class Uniprot extends DbSourceProxyImpl
   public SequenceI uniprotEntryToSequenceI(UniprotEntry entry)
   {
     String id = getUniprotEntryId(entry);
-    SequenceI sequence = new Sequence(id, entry.getUniprotSequence()
-            .getContent());
+    SequenceI sequence = new Sequence(id,
+            entry.getUniprotSequence().getContent());
     sequence.setDescription(getUniprotEntryDescription(entry));
 
     final String dbVersion = getDbVersion();
-    ArrayList<DBRefEntry> dbRefs = new ArrayList<DBRefEntry>();
+    ArrayList<DBRefEntry> dbRefs = new ArrayList<>();
     for (String accessionId : entry.getAccession())
     {
       DBRefEntry dbRef = new DBRefEntry(DBRefSource.UNIPROT, dbVersion,
@@ -211,7 +219,7 @@ public class Uniprot extends DbSourceProxyImpl
       dbRefs.add(dbRef);
     }
 
-    Vector<PDBEntry> onlyPdbEntries = new Vector<PDBEntry>();
+    Vector<PDBEntry> onlyPdbEntries = new Vector<>();
     for (PDBEntry pdb : entry.getDbReference())
     {
       DBRefEntry dbr = new DBRefEntry();
@@ -248,22 +256,23 @@ public class Uniprot extends DbSourceProxyImpl
         String cdsId = (String) pdb.getProperty("protein sequence ID");
         if (cdsId != null && cdsId.trim().length() > 0)
         {
-          dbr = new DBRefEntry(DBRefSource.ENSEMBL, DBRefSource.UNIPROT
-                  + ":" + dbVersion, cdsId.trim());
+          dbr = new DBRefEntry(DBRefSource.ENSEMBL,
+                  DBRefSource.UNIPROT + ":" + dbVersion, cdsId.trim());
           dbRefs.add(dbr);
 
         }
       }
-
     }
 
     sequence.setPDBId(onlyPdbEntries);
     if (entry.getFeature() != null)
     {
-      for (SequenceFeature sf : entry.getFeature())
+      for (UniprotFeature uf : entry.getFeature())
       {
-        sf.setFeatureGroup("Uniprot");
-        sequence.addSequenceFeature(sf);
+        SequenceFeature copy = new SequenceFeature(uf.getType(),
+                uf.getDescription(), uf.getBegin(), uf.getEnd(), "Uniprot");
+        copy.setStatus(uf.getStatus());
+        sequence.addSequenceFeature(copy);
       }
     }
     for (DBRefEntry dbr : dbRefs)
@@ -301,23 +310,18 @@ public class Uniprot extends DbSourceProxyImpl
   /**
    *
    * @param entry
-   *          UniportEntry
+   *          UniprotEntry
    * @return The accession id(s) and name(s) delimited by '|'.
    */
   public static String getUniprotEntryId(UniprotEntry entry)
   {
     StringBuilder name = new StringBuilder(32);
-    // name.append("UniProt/Swiss-Prot");
-    // use 'canonicalised' name for optimal id matching
-    name.append(DBRefSource.UNIPROT);
-    for (String accessionId : entry.getAccession())
-    {
-      name.append(BAR_DELIMITER);
-      name.append(accessionId);
-    }
     for (String n : entry.getName())
     {
-      name.append(BAR_DELIMITER);
+      if (name.length() > 0)
+      {
+        name.append(BAR_DELIMITER);
+      }
       name.append(n);
     }
     return name.toString();
index b0bea88..26291eb 100644 (file)
@@ -57,27 +57,26 @@ public abstract class Xfam extends DbSourceProxyImpl
     // retrieved.
     startQuery();
     // TODO: trap HTTP 404 exceptions and return null
-    String xfamUrl = getXFAMURL()
-            + queries.trim().toUpperCase() + getXFAMURLSUFFIX();
+    String xfamUrl = getXFAMURL() + queries.trim().toUpperCase()
+            + getXFAMURLSUFFIX();
 
     if (Cache.log != null)
     {
       Cache.log.debug("XFAM URL for retrieval is: " + xfamUrl);
     }
 
-    AlignmentI rcds = new FormatAdapter().readFile(xfamUrl  ,
+    AlignmentI rcds = new FormatAdapter().readFile(xfamUrl,
             DataSourceType.URL, FileFormat.Stockholm);
 
     for (int s = 0, sNum = rcds.getHeight(); s < sNum; s++)
     {
       rcds.getSequenceAt(s).addDBRef(new DBRefEntry(getXfamSource(),
-      // getDbSource(),
+              // getDbSource(),
               getDbVersion(), queries.trim().toUpperCase()));
       if (!getDbSource().equals(getXfamSource()))
       { // add the specific ref too
-        rcds.getSequenceAt(s).addDBRef(
-                new DBRefEntry(getDbSource(), getDbVersion(), queries
-                        .trim().toUpperCase()));
+        rcds.getSequenceAt(s).addDBRef(new DBRefEntry(getDbSource(),
+                getDbVersion(), queries.trim().toUpperCase()));
       }
     }
     stopQuery();
index 32e4f3e..84f6d4d 100644 (file)
@@ -57,8 +57,8 @@ import com.stevesoft.pat.Regex;
  * @author JimP
  * 
  */
-public class DasSequenceSource extends DbSourceProxyImpl implements
-        DbSourceProxy
+public class DasSequenceSource extends DbSourceProxyImpl
+        implements DbSourceProxy
 {
   private jalviewSourceI jsrc;
 
@@ -104,7 +104,8 @@ public class DasSequenceSource extends DbSourceProxyImpl implements
     {
       throw new Exception(MessageManager.formatMessage(
               "exception.das_source_doesnt_support_sequence_command",
-              new String[] { source.getTitle() }));
+              new String[]
+              { source.getTitle() }));
     }
     this.tier = 1 + ((jsrc.isLocal() || jsrc.isReferenceSource()) ? 0 : 1);
     this.source = source;
@@ -147,7 +148,8 @@ public class DasSequenceSource extends DbSourceProxyImpl implements
   public AlignmentI getSequenceRecords(String queries) throws Exception
   {
     StringTokenizer st = new StringTokenizer(queries, "\t");
-    List<String> toks = new ArrayList<String>(), src = new ArrayList<String>(), acIds = new ArrayList<String>();
+    List<String> toks = new ArrayList<String>(),
+            src = new ArrayList<String>(), acIds = new ArrayList<String>();
     while (st.hasMoreTokens())
     {
       String t;
@@ -168,9 +170,8 @@ public class DasSequenceSource extends DbSourceProxyImpl implements
         // slow, fetch one at a time.
         for (String sr : src)
         {
-          System.err
-                  .println("Retrieving IDs individually from das source: "
-                          + sr);
+          System.err.println(
+                  "Retrieving IDs individually from das source: " + sr);
           org.biodas.jdas.client.SequenceClient sq = new SequenceClient(
                   connprops.getConnectionPropertyProviderFor(sr));
           for (String q : toks)
@@ -182,9 +183,8 @@ public class DasSequenceSource extends DbSourceProxyImpl implements
               Map<List<String>, DasSequenceAdapter> dss = resultset.get(sr);
               if (dss == null)
               {
-                resultset
-                        .put(sr,
-                                dss = new HashMap<List<String>, DasSequenceAdapter>());
+                resultset.put(sr,
+                        dss = new HashMap<List<String>, DasSequenceAdapter>());
               }
               dss.put(qset, s);
             } catch (Exception x)
@@ -192,7 +192,8 @@ public class DasSequenceSource extends DbSourceProxyImpl implements
               Map<List<String>, Exception> ers = errors.get(sr);
               if (ers == null)
               {
-                errors.put(sr, ers = new HashMap<List<String>, Exception>());
+                errors.put(sr,
+                        ers = new HashMap<List<String>, Exception>());
               }
               ers.put(qset, x);
             }
@@ -246,8 +247,8 @@ public class DasSequenceSource extends DbSourceProxyImpl implements
 
             if (acIds.indexOf(lbl) == -1)
             {
-              System.err
-                      .println("Warning - received sequence event for strange accession code ("
+              System.err.println(
+                      "Warning - received sequence event for strange accession code ("
                               + lbl + ")");
             }
             else
@@ -256,11 +257,9 @@ public class DasSequenceSource extends DbSourceProxyImpl implements
               {
                 if (e.getContent().length() == 0)
                 {
-                  System.err
-                          .println("Empty sequence returned for accession code ("
-                                  + lbl
-                                  + ") from "
-                                  + resset.getKey()
+                  System.err.println(
+                          "Empty sequence returned for accession code ("
+                                  + lbl + ") from " + resset.getKey()
                                   + " (source is " + getDbName());
                   continue;
                 }
@@ -268,11 +267,11 @@ public class DasSequenceSource extends DbSourceProxyImpl implements
               seqs = new java.util.Vector<SequenceI>();
               // JDAS returns a sequence complete with any newlines and spaces
               // in the XML
-              Sequence sq = new Sequence(lbl, e.getContent().replaceAll(
-                      "\\s+", ""));
+              Sequence sq = new Sequence(lbl,
+                      e.getContent().replaceAll("\\s+", ""));
               sq.setStart(e.getStart().intValue());
-              sq.addDBRef(new DBRefEntry(getDbSource(), getDbVersion()
-                      + ":" + e.getVersion(), lbl));
+              sq.addDBRef(new DBRefEntry(getDbSource(),
+                      getDbVersion() + ":" + e.getVersion(), lbl));
               seqs.addElement(sq);
             }
           }
@@ -308,9 +307,9 @@ public class DasSequenceSource extends DbSourceProxyImpl implements
 
         } catch (Exception x)
         {
-          Cache.log
-                  .error("Couldn't retrieve features for sequence from its source.",
-                          x);
+          Cache.log.error(
+                  "Couldn't retrieve features for sequence from its source.",
+                  x);
         }
       }
 
index e0f7f70..de7f380 100644 (file)
@@ -46,8 +46,8 @@ import org.biodas.jdas.schema.sources.VERSION;
 /**
  *
  */
-public class DasSourceRegistry implements DasSourceRegistryI,
-        MultipleConnectionPropertyProviderI
+public class DasSourceRegistry
+        implements DasSourceRegistryI, MultipleConnectionPropertyProviderI
 {
   // private org.biodas.jdas.schema.sources.SOURCE[] dasSources = null;
   private List<jalviewSourceI> dasSources = null;
@@ -84,8 +84,7 @@ public class DasSourceRegistry implements DasSourceRegistryI,
     if (registry.lastIndexOf("sources.xml") == registry.length() - 11)
     {
       // no trailing sources.xml document for registry in JDAS
-      jalview.bin.Cache.setProperty(
-              jalview.bin.Cache.DAS_REGISTRY_URL,
+      jalview.bin.Cache.setProperty(jalview.bin.Cache.DAS_REGISTRY_URL,
               registry = registry.substring(0,
                       registry.lastIndexOf("sources.xml")));
     }
@@ -138,8 +137,8 @@ public class DasSourceRegistry implements DasSourceRegistryI,
           }
           else
           {
-            System.out.println("Debug: Ignored older source "
-                    + jsrc.getTitle());
+            System.out.println(
+                    "Debug: Ignored older source " + jsrc.getTitle());
           }
         }
         else
@@ -151,8 +150,8 @@ public class DasSourceRegistry implements DasSourceRegistryI,
       return dsrc;
     } catch (Exception ex)
     {
-      System.out.println("DAS1 registry at " + registryURL
-              + " no longer exists");
+      System.out.println(
+              "DAS1 registry at " + registryURL + " no longer exists");
       return new ArrayList<jalviewSourceI>();
     }
   }
@@ -193,8 +192,8 @@ public class DasSourceRegistry implements DasSourceRegistryI,
           int bar = token.indexOf("|");
           if (bar == -1)
           {
-            System.err
-                    .println("Warning: DAS user local source appears to have no nickname (expected a '|' followed by nickname)\nOffending definition: '"
+            System.err.println(
+                    "Warning: DAS user local source appears to have no nickname (expected a '|' followed by nickname)\nOffending definition: '"
                             + token + "'");
           }
           String url = token.substring(bar + 1);
@@ -218,8 +217,8 @@ public class DasSourceRegistry implements DasSourceRegistryI,
             }
           } catch (Exception q)
           {
-            System.err
-                    .println("Unexpected exception when creating local source from '"
+            System.err.println(
+                    "Unexpected exception when creating local source from '"
                             + token + "'");
             q.printStackTrace();
           }
@@ -373,8 +372,7 @@ public class DasSourceRegistry implements DasSourceRegistryI,
       {
         String token = en.nextElement().toString();
         jalviewSourceI srco = localSources.get(token);
-        sb.append(token + "|"
-                + (srco.isSequenceSource() ? "sequence:" : "")
+        sb.append(token + "|" + (srco.isSequenceSource() ? "sequence:" : "")
                 + srco.getUri() + "\t");
       }
       return sb.toString();
@@ -390,8 +388,8 @@ public class DasSourceRegistry implements DasSourceRegistryI,
     try
     {
       // TODO: allow same credentials for https and http
-      authStash.put(new URL(
-              "http://www.compbio.dundee.ac.uk/geneweb/das/myseq/"),
+      authStash.put(
+              new URL("http://www.compbio.dundee.ac.uk/geneweb/das/myseq/"),
               "Basic SmltOm1pSg==");
     } catch (MalformedURLException e)
     {
index 9cc4239..07ba027 100644 (file)
@@ -216,9 +216,8 @@ public class JalviewSource implements jalviewSourceI
   {
     for (CAPABILITY p : getVersion().getCAPABILITY())
     {
-      if (p.getType().equalsIgnoreCase(capability.getName())
-              || p.getType().equalsIgnoreCase(
-                      "das1:" + capability.getName()))
+      if (p.getType().equalsIgnoreCase(capability.getName()) || p.getType()
+              .equalsIgnoreCase("das1:" + capability.getName()))
       {
         return p;
       }
@@ -258,10 +257,9 @@ public class JalviewSource implements jalviewSourceI
       for (COORDINATES cs : v.getCOORDINATES())
       {
         COORDINATES ltst = latestc.get(cs.getUri());
-        if (ltst == null
-                || ltst.getVersion() == null
-                || (ltst.getVersion() != null && cs.getVersion() != null && isLaterThan(
-                        ltst.getVersion(), cs.getVersion())))
+        if (ltst == null || ltst.getVersion() == null
+                || (ltst.getVersion() != null && cs.getVersion() != null
+                        && isLaterThan(ltst.getVersion(), cs.getVersion())))
         {
           latestc.put(cs.getUri(), cs);
         }
@@ -279,10 +277,13 @@ public class JalviewSource implements jalviewSourceI
          */
         try
         {
-          seqsources.add(ds = new DasSequenceSource(getTitle() + " ("
-                  + cs.getAuthority() + " " + cs.getSource()
-                  + (cs.getVersion() != null ? " " + cs.getVersion() : "")
-                  + ")", cs.getAuthority(), source, v, cs, connprov));
+          seqsources.add(ds = new DasSequenceSource(
+                  getTitle() + " (" + cs.getAuthority() + " "
+                          + cs.getSource()
+                          + (cs.getVersion() != null ? " " + cs.getVersion()
+                                  : "")
+                          + ")",
+                  cs.getAuthority(), source, v, cs, connprov));
           if (seqsources.size() > 1)
           {
             System.err.println("Added another sequence DB source for "
@@ -301,8 +302,8 @@ public class JalviewSource implements jalviewSourceI
     {
       try
       {
-        seqsources.add(new DasSequenceSource(getTitle(), getTitle(),
-                source, getVersion(), null, connprov));
+        seqsources.add(new DasSequenceSource(getTitle(), getTitle(), source,
+                getVersion(), null, connprov));
       } catch (Exception e)
       {
         // TODO Auto-generated catch block
@@ -342,14 +343,14 @@ public class JalviewSource implements jalviewSourceI
 
       for (CAPABILITY cap : getVersion().getCAPABILITY())
       {
-        String capname = cap.getType().substring(
-                cap.getType().indexOf(":") + 1);
+        String capname = cap.getType()
+                .substring(cap.getType().indexOf(":") + 1);
         int p = cap.getQueryUri().lastIndexOf(capname);
         if (p < -1)
         {
           throw new Exception(MessageManager.formatMessage(
-                  "exception.invalid_das_source",
-                  new String[] { source.getUri() }));
+                  "exception.invalid_das_source", new String[]
+                  { source.getUri() }));
         }
         if (cap.getQueryUri().charAt(p) == '/')
         {
@@ -369,8 +370,8 @@ public class JalviewSource implements jalviewSourceI
   @Override
   public boolean isNewerThan(jalviewSourceI other)
   {
-    return isLaterThan(getVersion().getCreated(), other.getVersion()
-            .getCreated());
+    return isLaterThan(getVersion().getCreated(),
+            other.getVersion().getCreated());
   }
 
   @Override
index 3e8c55e..07a9df4 100644 (file)
@@ -29,6 +29,7 @@ import java.io.File;
 import java.io.FileOutputStream;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.List;
@@ -205,7 +206,14 @@ public class EBIFetchClient
     {
       URL rcall = new URL(url);
 
-      InputStream is = new BufferedInputStream(rcall.openStream());
+      HttpURLConnection conn = (HttpURLConnection) rcall.openConnection();
+      int responseCode = conn.getResponseCode();
+      if (responseCode != 200)
+      {
+        System.err.println("Warning: response code " + responseCode
+                + " for " + url);
+      }
+      InputStream is = new BufferedInputStream(conn.getInputStream());
       if (outFile != null)
       {
         FileOutputStream fio = new FileOutputStream(outFile);
@@ -267,12 +275,12 @@ public class EBIFetchClient
     if (database.equalsIgnoreCase(DBRefSource.EMBL)
             || database.equalsIgnoreCase(DBRefSource.EMBLCDS))
     {
-      url = "http://www.ebi.ac.uk/ena/data/view/" + ids.toLowerCase()
+      url = "https://www.ebi.ac.uk/ena/data/view/" + ids.toLowerCase()
               + (format != null ? "&" + format : "");
     }
     else
     {
-      url = "http://www.ebi.ac.uk/Tools/dbfetch/dbfetch/"
+      url = "https://www.ebi.ac.uk/Tools/dbfetch/dbfetch/"
               + database.toLowerCase() + "/" + ids.toLowerCase()
               + (format != null ? "/" + format : "");
     }
index bae0357..022ae6d 100644 (file)
@@ -86,7 +86,8 @@ public class Annotate3D
       AlignmentI al = null;
       while (r.hasNext())
       {
-        FileParse fp = new InputStreamParser(r.next(), source.getDataName());
+        FileParse fp = new InputStreamParser(r.next(),
+                source.getDataName());
         AlignmentI nal = new FormatAdapter().readFromFile(fp,
                 FileFormat.Rnaml);
         if (al == null)
@@ -107,9 +108,8 @@ public class Annotate3D
       }
       else
       {
-        throw new IOException(
-                MessageManager
-                        .getString("exception.unexpected_handling_rnaml_translation_for_pdb"),
+        throw new IOException(MessageManager.getString(
+                "exception.unexpected_handling_rnaml_translation_for_pdb"),
                 x);
       }
     }
@@ -180,8 +180,8 @@ public class Annotate3D
       URL url = new URL(
               "http://paradise-ibmc.u-strasbg.fr/webservices/annotate3d?data="
                       + content);
-      BufferedReader is = new BufferedReader(new InputStreamReader(
-              url.openStream()));
+      BufferedReader is = new BufferedReader(
+              new InputStreamReader(url.openStream()));
       String str4;
       while ((str4 = is.readLine()) != null)
       {
index ba4054e..ea883c8 100644 (file)
@@ -97,9 +97,9 @@ public class Discoverer implements Runnable
       // timeout
     } catch (Exception ex)
     {
-      jalview.bin.Cache.log
-              .error("Serious!  Service location failed\nfor URL :" + WsURL
-                      + "\n", ex);
+      jalview.bin.Cache.log.error(
+              "Serious!  Service location failed\nfor URL :" + WsURL + "\n",
+              ex);
 
       return null;
     }
@@ -126,9 +126,8 @@ public class Discoverer implements Runnable
   static private Vector getDiscoveryURLS()
   {
     Vector urls = new Vector();
-    String RootServiceURLs = jalview.bin.Cache
-            .getDefault("DISCOVERY_URLS",
-                    "http://www.compbio.dundee.ac.uk/JalviewWS/services/ServiceRegistry");
+    String RootServiceURLs = jalview.bin.Cache.getDefault("DISCOVERY_URLS",
+            "http://www.compbio.dundee.ac.uk/JalviewWS/services/ServiceRegistry");
 
     try
     {
@@ -153,17 +152,17 @@ public class Discoverer implements Runnable
           jalview.bin.Cache.log
                   .warn("Problem whilst trying to make a URL from '"
                           + ((url != null) ? url : "<null>") + "'");
-          jalview.bin.Cache.log
-                  .warn("This was probably due to a malformed comma separated list"
+          jalview.bin.Cache.log.warn(
+                  "This was probably due to a malformed comma separated list"
                           + " in the DISCOVERY_URLS entry of $(HOME)/.jalview_properties)");
           jalview.bin.Cache.log.debug("Exception was ", ex);
         }
       }
     } catch (Exception ex)
     {
-      jalview.bin.Cache.log
-              .warn("Error parsing comma separated list of urls in DISCOVERY_URLS.",
-                      ex);
+      jalview.bin.Cache.log.warn(
+              "Error parsing comma separated list of urls in DISCOVERY_URLS.",
+              ex);
     }
     if (urls.size() > 0)
     {
@@ -181,8 +180,8 @@ public class Discoverer implements Runnable
             .debug("(Re)-Initialising the discovery URL list.");
     try
     {
-      reallyDiscoverServices = jalview.bin.Cache.getDefault(
-              "DISCOVERY_START", false);
+      reallyDiscoverServices = jalview.bin.Cache
+              .getDefault("DISCOVERY_START", false);
       if (reallyDiscoverServices)
       {
         ServiceURLList = getDiscoveryURLS();
@@ -192,32 +191,27 @@ public class Discoverer implements Runnable
         jalview.bin.Cache.log.debug("Setting default services");
         services = new Hashtable();
         // Muscle, Clustal and JPred.
-        ServiceHandle[] defServices = {
-            new ServiceHandle(
-                    "MsaWS",
-                    "Edgar, Robert C. (2004), MUSCLE: multiple sequence alignment "
-                            + "with high accuracy and high throughput, Nucleic Acids Research 32(5), 1792-97.",
-                    "http://www.compbio.dundee.ac.uk/JalviewWS/services/MuscleWS",
-                    MessageManager
-                            .getString("label.muscle_multiple_protein_sequence_alignment")),
-            new ServiceHandle(
-                    "MsaWS",
+        ServiceHandle[] defServices = { new ServiceHandle("MsaWS",
+                "Edgar, Robert C. (2004), MUSCLE: multiple sequence alignment "
+                        + "with high accuracy and high throughput, Nucleic Acids Research 32(5), 1792-97.",
+                "http://www.compbio.dundee.ac.uk/JalviewWS/services/MuscleWS",
+                MessageManager.getString(
+                        "label.muscle_multiple_protein_sequence_alignment")),
+            new ServiceHandle("MsaWS",
                     "Katoh, K., K. Kuma, K., Toh, H.,  and Miyata, T. (2005) "
                             + "\"MAFFT version 5: improvement in accuracy of multiple sequence alignment.\""
                             + " Nucleic Acids Research, 33 511-518",
                     "http://www.compbio.dundee.ac.uk/JalviewWS/services/MafftWS",
-                    MessageManager
-                            .getString("label.mafft_multiple_sequence_alignment")),
-            new ServiceHandle(
-                    "MsaWS",
+                    MessageManager.getString(
+                            "label.mafft_multiple_sequence_alignment")),
+            new ServiceHandle("MsaWS",
                     "Thompson, J.D., Higgins, D.G. and Gibson, T.J. (1994) CLUSTAL W: improving the sensitivity of progressive multiple"
                             + " sequence alignment through sequence weighting, position specific gap penalties and weight matrix choice."
                             + " Nucleic Acids Research, 22 4673-4680",
                     "http://www.compbio.dundee.ac.uk/JalviewWS/services/ClustalWS",
-                    MessageManager
-                            .getString("label.clustalw_multiple_sequence_alignment")),
-            new ServiceHandle(
-                    "SecStrPred",
+                    MessageManager.getString(
+                            "label.clustalw_multiple_sequence_alignment")),
+            new ServiceHandle("SecStrPred",
                     "Drozdetskiy A, Cole C, Procter J & Barton GJ. (2015)\nJPred4: a protein secondary structure prediction server"
                             + "\nNucleic Acids Research, Web Server issue (first published 15th April 2015)"
                             + "\ndoi://10.1093/nar/gkv332",
@@ -230,8 +224,8 @@ public class Discoverer implements Runnable
 
     } catch (Exception e)
     {
-      System.err
-              .println("jalview.rootRegistry is not a proper url!\nWas set to "
+      System.err.println(
+              "jalview.rootRegistry is not a proper url!\nWas set to "
                       + RootServiceURL + "\n" + e);
     }
 
@@ -320,16 +314,15 @@ public class Discoverer implements Runnable
               disc_serv = new java.net.URL(sh[i].getEndpointURL());
               if (!ServiceURLList.contains(disc_serv))
               {
-                jalview.bin.Cache.log
-                        .debug("Adding new discovery service at "
-                                + disc_serv);
+                jalview.bin.Cache.log.debug(
+                        "Adding new discovery service at " + disc_serv);
                 ServiceURLList.add(disc_serv);
                 seenNewDiscovery = true;
               }
             } catch (Exception e)
             {
-              jalview.bin.Cache.log.debug(
-                      "Ignoring bad discovery service URL "
+              jalview.bin.Cache.log
+                      .debug("Ignoring bad discovery service URL "
                               + sh[i].getEndpointURL(), e);
             }
           }
@@ -353,17 +346,17 @@ public class Discoverer implements Runnable
     }
     while (s_url < ServiceURLList.size())
     {
-      if ((sh = getServices((java.net.URL) ServiceURLList.get(s_url))) != null)
+      if ((sh = getServices(
+              (java.net.URL) ServiceURLList.get(s_url))) != null)
       {
 
         buildServiceLists(sh, cat, sscat);
       }
       else
       {
-        jalview.bin.Cache.log
-                .warn("No services at "
-                        + (ServiceURLList.get(s_url))
-                        + " - check DISCOVERY_URLS property in .jalview_properties");
+        jalview.bin.Cache.log.warn("No services at "
+                + (ServiceURLList.get(s_url))
+                + " - check DISCOVERY_URLS property in .jalview_properties");
       }
       s_url++;
     }
@@ -413,12 +406,12 @@ public class Discoverer implements Runnable
       serviceClientBindings.put("SecStrPred", new JPredClient());
       serviceClientBindings.put("SeqSearch", new SeqSearchWSClient());
     }
-    WS1Client instance = (WS1Client) serviceClientBindings.get(sh
-            .getAbstractName());
+    WS1Client instance = (WS1Client) serviceClientBindings
+            .get(sh.getAbstractName());
     if (instance == null)
     {
-      System.err
-              .println("WARNING - POSSIBLE IMPLEMENTATION ERROR - cannot find WSClient implementation for "
+      System.err.println(
+              "WARNING - POSSIBLE IMPLEMENTATION ERROR - cannot find WSClient implementation for "
                       + sh.getAbstractName());
     }
     else
index 65847e6..3b7bdb6 100644 (file)
@@ -59,9 +59,8 @@ public class JPredClient extends WS1Client
    * @param viewonly
    *          TODO
    */
-  public JPredClient(ext.vamsas.ServiceHandle sh, String title,
-          boolean msa, AlignmentView alview, AlignFrame parentFrame,
-          boolean viewonly)
+  public JPredClient(ext.vamsas.ServiceHandle sh, String title, boolean msa,
+          AlignmentView alview, AlignFrame parentFrame, boolean viewonly)
   {
     super();
     wsInfo = setWebService(sh);
@@ -154,9 +153,8 @@ public class JPredClient extends WS1Client
     {
       if (!msa && msf.length > 1)
       {
-        throw new Error(
-                MessageManager
-                        .getString("error.implementation_error_multiple_single_sequence_prediction_jobs_not_supported"));
+        throw new Error(MessageManager.getString(
+                "error.implementation_error_multiple_single_sequence_prediction_jobs_not_supported"));
       }
 
       String altitle = getPredictionName(WebServiceName) + " for "
@@ -185,8 +183,8 @@ public class JPredClient extends WS1Client
 
   private String getPredictionName(String webServiceName)
   {
-    if (webServiceName.toLowerCase().indexOf(
-            "secondary structure prediction") > -1)
+    if (webServiceName.toLowerCase()
+            .indexOf("secondary structure prediction") > -1)
     {
       return webServiceName;
     }
@@ -243,7 +241,8 @@ public class JPredClient extends WS1Client
 
     wsInfo.setProgressText("Job details for MSA based prediction (" + title
             + ") on sequence :\n>" + seq.getName() + "\n"
-            + AlignSeq.extractGaps("-. ", seq.getSequenceAsString()) + "\n");
+            + AlignSeq.extractGaps("-. ", seq.getSequenceAsString())
+            + "\n");
     SequenceI aln[] = new SequenceI[msf.length];
     for (int i = 0, j = msf.length; i < j; i++)
     {
@@ -274,7 +273,8 @@ public class JPredClient extends WS1Client
     }
     wsInfo.setProgressText("Job details for prediction on sequence :\n>"
             + seq.getName() + "\n"
-            + AlignSeq.extractGaps("-. ", seq.getSequenceAsString()) + "\n");
+            + AlignSeq.extractGaps("-. ", seq.getSequenceAsString())
+            + "\n");
     String altitle = "JPred prediction for sequence " + seq.getName()
             + " from " + title;
 
@@ -323,21 +323,17 @@ public class JPredClient extends WS1Client
 
     } catch (Exception ex)
     {
-      JvOptionPane
-              .showMessageDialog(
-                      Desktop.desktop,
-                      MessageManager
-                              .formatMessage(
-                                      "label.secondary_structure_prediction_service_couldnt_be_located",
-                                      new String[] { WebServiceName, WsURL }),
-                      MessageManager
-                              .getString("label.internal_jalview_error"),
-                      JvOptionPane.WARNING_MESSAGE);
-      wsInfo.setProgressText(MessageManager
-              .formatMessage(
+      JvOptionPane.showMessageDialog(Desktop.desktop,
+              MessageManager.formatMessage(
                       "label.secondary_structure_prediction_service_couldnt_be_located",
-                      new String[] { WebServiceName, WsURL })
-              + "\n" + ex.getMessage());
+                      new String[]
+                      { WebServiceName, WsURL }),
+              MessageManager.getString("label.internal_jalview_error"),
+              JvOptionPane.WARNING_MESSAGE);
+      wsInfo.setProgressText(MessageManager.formatMessage(
+              "label.secondary_structure_prediction_service_couldnt_be_located",
+              new String[]
+              { WebServiceName, WsURL }) + "\n" + ex.getMessage());
       wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
 
     }
@@ -360,8 +356,8 @@ public class JPredClient extends WS1Client
         if (msa.getSequences().length == 1)
         {
           // Single Sequence prediction
-          new jalview.ws.jws1.JPredClient(sh, af.getTitle(), false, msa,
-                  af, true);
+          new jalview.ws.jws1.JPredClient(sh, af.getTitle(), false, msa, af,
+                  true);
         }
         else
         {
index b0210d8..a239625 100644 (file)
@@ -122,8 +122,8 @@ class JPredThread extends JWS1Thread implements WSClientI
       Cache.log.debug("Parsing output from JNet job.");
       // JPredFile prediction = new JPredFile("C:/JalviewX/files/jpred.txt",
       // "File");
-      JPredFile prediction = new JPredFile(
-              result.getPredfile(), DataSourceType.PASTE);
+      JPredFile prediction = new JPredFile(result.getPredfile(),
+              DataSourceType.PASTE);
       SequenceI[] preds = prediction.getSeqsAsArray();
       Cache.log.debug("Got prediction profile.");
 
@@ -132,8 +132,8 @@ class JPredThread extends JWS1Thread implements WSClientI
         Cache.log.debug("Getting associated alignment.");
         // we ignore the returned alignment if we only predicted on a single
         // sequence
-        FileFormatI format = new IdentifyFile().identify(
-                result.getAligfile(), DataSourceType.PASTE);
+        FileFormatI format = new IdentifyFile()
+                .identify(result.getAligfile(), DataSourceType.PASTE);
 
         if (format != null)
         {
@@ -158,9 +158,8 @@ class JPredThread extends JWS1Thread implements WSClientI
             }
             if (!SeqsetUtils.deuniquify(SequenceInfo, sqs))
             {
-              throw (new Exception(
-                      MessageManager
-                              .getString("exception.couldnt_recover_sequence_properties_for_alignment")));
+              throw (new Exception(MessageManager.getString(
+                      "exception.couldnt_recover_sequence_properties_for_alignment")));
             }
           }
           FirstSeq = 0;
@@ -173,15 +172,15 @@ class JPredThread extends JWS1Thread implements WSClientI
           {
             al.setDataset(null);
           }
-          JnetAnnotationMaker.add_annotation(prediction, al,
-                  FirstSeq, false, predMap);
+          JnetAnnotationMaker.add_annotation(prediction, al, FirstSeq,
+                  false, predMap);
 
         }
         else
         {
           throw (new Exception(MessageManager.formatMessage(
-                  "exception.unknown_format_for_file", new String[] { "",
-                      result.getAligfile() })));
+                  "exception.unknown_format_for_file", new String[]
+                  { "", result.getAligfile() })));
         }
       }
       else
@@ -195,9 +194,8 @@ class JPredThread extends JWS1Thread implements WSClientI
                   .getAlignmentAndHiddenColumns(gc)[0];
           if (this.msaIndex >= sqs.length)
           {
-            throw new Error(
-                    MessageManager
-                            .getString("error.implementation_error_invalid_msa_index_for_job"));
+            throw new Error(MessageManager.getString(
+                    "error.implementation_error_invalid_msa_index_for_job"));
           }
 
           // ///
@@ -205,7 +203,8 @@ class JPredThread extends JWS1Thread implements WSClientI
           // ///
           new jalview.commands.RemoveGapsCommand(
                   MessageManager.getString("label.remove_gaps"),
-                  new SequenceI[] { sqs[msaIndex] }, currentView);
+                  new SequenceI[]
+                  { sqs[msaIndex] }, currentView);
 
           SequenceI profileseq = al.getSequenceAt(FirstSeq);
           profileseq.setSequence(sqs[msaIndex].getSequenceAsString());
@@ -214,9 +213,8 @@ class JPredThread extends JWS1Thread implements WSClientI
         if (!jalview.analysis.SeqsetUtils.SeqCharacterUnhash(
                 al.getSequenceAt(FirstSeq), SequenceInfo))
         {
-          throw (new Exception(
-                  MessageManager
-                          .getString("exception.couldnt_recover_sequence_props_for_jnet_query")));
+          throw (new Exception(MessageManager.getString(
+                  "exception.couldnt_recover_sequence_props_for_jnet_query")));
         }
         else
         {
@@ -273,8 +271,8 @@ class JPredThread extends JWS1Thread implements WSClientI
         dsseq = dsseq.getDatasetSequence();
       }
       // look for same annotation on dataset and lift this one over
-      List<AlignmentAnnotation> dsan = dsseq.getAlignmentAnnotations(
-              calcId, typeName);
+      List<AlignmentAnnotation> dsan = dsseq.getAlignmentAnnotations(calcId,
+              typeName);
       if (dsan != null && dsan.size() > 0)
       {
         for (AlignmentAnnotation dssan : dsan)
@@ -319,17 +317,15 @@ class JPredThread extends JWS1Thread implements WSClientI
               sq = sq + sb;
               while ((diff = gapMap[r] - sq.length()) > 0)
               {
-                sq = sq
-                        + ((diff >= sb.length()) ? sb.toString() : sb
-                                .substring(0, diff));
+                sq = sq + ((diff >= sb.length()) ? sb.toString()
+                        : sb.substring(0, diff));
               }
               al.getSequenceAt(s).setSequence(sq);
             }
             else
             {
-              al.getSequenceAt(s).setSequence(
-                      sq.substring(0, gapMap[r]) + sb.toString()
-                              + sq.substring(gapMap[r]));
+              al.getSequenceAt(s).setSequence(sq.substring(0, gapMap[r])
+                      + sb.toString() + sq.substring(gapMap[r]));
             }
           }
         }
@@ -435,8 +431,8 @@ class JPredThread extends JWS1Thread implements WSClientI
     if (!(j instanceof JPredJob))
     {
       throw new Error(MessageManager.formatMessage(
-              "error.implementation_error_startjob_called",
-              new String[] { j.getClass().toString() }));
+              "error.implementation_error_startjob_called", new String[]
+              { j.getClass().toString() }));
     }
     try
     {
@@ -457,9 +453,9 @@ class JPredThread extends JWS1Thread implements WSClientI
         {
           job.result = new JpredResult();
           job.result.setInvalid(true);
-          job.result.setStatus(MessageManager.formatMessage(
-                  "label.submission_params", new String[] { job.getJobId()
-                          .toString() }));
+          job.result.setStatus(MessageManager
+                  .formatMessage("label.submission_params", new String[]
+                  { job.getJobId().toString() }));
           throw new Exception(job.getJobId());
         }
         else
@@ -471,9 +467,8 @@ class JPredThread extends JWS1Thread implements WSClientI
       }
       else
       {
-        throw new Exception(
-                MessageManager
-                        .getString("exception.server_timeout_try_later"));
+        throw new Exception(MessageManager
+                .getString("exception.server_timeout_try_later"));
       }
     } catch (Exception e)
     {
@@ -483,12 +478,11 @@ class JPredThread extends JWS1Thread implements WSClientI
       {
         wsInfo.setStatus(j.getJobnum(),
                 WebserviceInfo.STATE_STOPPED_SERVERERROR);
-        wsInfo.setProgressText(
-                j.getJobnum(),
+        wsInfo.setProgressText(j.getJobnum(),
                 "Failed to submit the prediction. (Just close the window)\n"
                         + "It is most likely that there is a problem with the server.\n");
-        System.err
-                .println("JPredWS Client: Failed to submit the prediction. Quite possibly because of a server error - see below)\n"
+        System.err.println(
+                "JPredWS Client: Failed to submit the prediction. Quite possibly because of a server error - see below)\n"
                         + e.getMessage() + "\n");
 
         jalview.bin.Cache.log.warn("Server Exception", e);
@@ -497,14 +491,13 @@ class JPredThread extends JWS1Thread implements WSClientI
       {
         wsInfo.setStatus(j.getJobnum(), WebserviceInfo.STATE_STOPPED_ERROR);
         // JBPNote - this could be a popup informing the user of the problem.
-        wsInfo.appendProgressText(j.getJobnum(), MessageManager
-                .formatMessage(
-                        "info.failed_to_submit_prediction",
-                        new String[] { e.getMessage(),
-                            wsInfo.getProgressText() }));
+        wsInfo.appendProgressText(j.getJobnum(),
+                MessageManager.formatMessage(
+                        "info.failed_to_submit_prediction", new String[]
+                        { e.getMessage(), wsInfo.getProgressText() }));
 
-        jalview.bin.Cache.log.debug(
-                "Failed Submission of job " + j.getJobnum(), e);
+        jalview.bin.Cache.log
+                .debug("Failed Submission of job " + j.getJobnum(), e);
 
       }
       j.setAllowedServerExceptions(-1);
@@ -531,8 +524,9 @@ class JPredThread extends JWS1Thread implements WSClientI
     } catch (Exception ex)
     {
 
-      Cache.log.error("Unexpected exception when processing results for "
-              + altitle, ex);
+      Cache.log.error(
+              "Unexpected exception when processing results for " + altitle,
+              ex);
       wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
     }
     if (results > 0)
@@ -594,20 +588,21 @@ class JPredThread extends JWS1Thread implements WSClientI
             else
             {
               // do merge with other job results
-              throw new Error(
-                      MessageManager
-                              .getString("error.multiple_jnet_subjob_merge_not_implemented"));
+              throw new Error(MessageManager.getString(
+                      "error.multiple_jnet_subjob_merge_not_implemented"));
             }
           } catch (Exception e)
           {
-            jalview.bin.Cache.log.error(
-                    "JNet Client: JPred Annotation Parse Error", e);
+            jalview.bin.Cache.log
+                    .error("JNet Client: JPred Annotation Parse Error", e);
             wsInfo.setStatus(j.getJobnum(),
                     WebserviceInfo.STATE_STOPPED_ERROR);
-            wsInfo.appendProgressText(j.getJobnum(), MessageManager
-                    .formatMessage("info.invalid_jnet_job_result_data",
-                            new String[] { OutputHeader.toString(),
-                                j.result.getStatus(), e.getMessage() }));
+            wsInfo.appendProgressText(j.getJobnum(),
+                    MessageManager.formatMessage(
+                            "info.invalid_jnet_job_result_data",
+                            new String[]
+                            { OutputHeader.toString(), j.result.getStatus(),
+                                e.getMessage() }));
             j.result.setBroken(true);
           }
         }
@@ -618,8 +613,8 @@ class JPredThread extends JWS1Thread implements WSClientI
         if (newWindow)
         {
           AlignFrame af;
-          ((AlignmentI) res[0]).setSeqrep(((AlignmentI) res[0])
-                  .getSequenceAt(0));
+          ((AlignmentI) res[0])
+                  .setSeqrep(((AlignmentI) res[0]).getSequenceAt(0));
           if (input == null)
           {
             if (res[1] != null)
@@ -650,10 +645,8 @@ class JPredThread extends JWS1Thread implements WSClientI
              * alandcolsel[0])[0].gapMap())); }
              */
 
-            af = new AlignFrame((Alignment) res[0],
- (HiddenColumns) res[1],
-                    AlignFrame.DEFAULT_WIDTH,
-                    AlignFrame.DEFAULT_HEIGHT);
+            af = new AlignFrame((Alignment) res[0], (HiddenColumns) res[1],
+                    AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
           }
           Desktop.addInternalFrame(af, altitle, AlignFrame.DEFAULT_WIDTH,
                   AlignFrame.DEFAULT_HEIGHT);
index 5ea553e..4a09625 100644 (file)
@@ -78,10 +78,12 @@ public class MsaWSClient extends WS1Client
     alignFrame = _alignFrame;
     if (!sh.getAbstractName().equals("MsaWS"))
     {
-      JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
-              .formatMessage("label.service_called_is_not_msa_service",
-                      new String[] { sh.getName() }), MessageManager
-              .getString("label.internal_jalview_error"),
+      JvOptionPane.showMessageDialog(Desktop.desktop,
+              MessageManager.formatMessage(
+                      "label.service_called_is_not_msa_service",
+                      new String[]
+                      { sh.getName() }),
+              MessageManager.getString("label.internal_jalview_error"),
               JvOptionPane.WARNING_MESSAGE);
 
       return;
@@ -90,9 +92,9 @@ public class MsaWSClient extends WS1Client
     if ((wsInfo = setWebService(sh)) == null)
     {
       JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
-              .formatMessage("label.msa_service_is_unknown",
-                      new String[] { sh.getName() }), MessageManager
-              .getString("label.internal_jalview_error"),
+              .formatMessage("label.msa_service_is_unknown", new String[]
+              { sh.getName() }),
+              MessageManager.getString("label.internal_jalview_error"),
               JvOptionPane.WARNING_MESSAGE);
 
       return;
@@ -120,9 +122,8 @@ public class MsaWSClient extends WS1Client
     String jobtitle = WebServiceName.toLowerCase();
     if (jobtitle.endsWith("alignment"))
     {
-      if (submitGaps
-              && (!jobtitle.endsWith("realignment") || jobtitle
-                      .indexOf("profile") == -1))
+      if (submitGaps && (!jobtitle.endsWith("realignment")
+              || jobtitle.indexOf("profile") == -1))
       {
         int pos = jobtitle.indexOf("alignment");
         jobtitle = WebServiceName.substring(0, pos) + "re-alignment of "
@@ -213,9 +214,10 @@ public class MsaWSClient extends WS1Client
       public void actionPerformed(ActionEvent e)
       {
         AlignmentView msa = alignFrame.gatherSequencesForAlignment();
-        new jalview.ws.jws1.MsaWSClient(serviceHandle, alignFrame
-                .getTitle(), msa, false, true, alignFrame.getViewport()
-                .getAlignment().getDataset(), alignFrame);
+        new jalview.ws.jws1.MsaWSClient(serviceHandle,
+                alignFrame.getTitle(), msa, false, true,
+                alignFrame.getViewport().getAlignment().getDataset(),
+                alignFrame);
 
       }
 
@@ -224,8 +226,8 @@ public class MsaWSClient extends WS1Client
     if (canSubmitGaps())
     {
       // We know that ClustalWS can accept partial alignments for refinement.
-      final JMenuItem methodR = new JMenuItem(serviceHandle.getName()
-              + " Realign");
+      final JMenuItem methodR = new JMenuItem(
+              serviceHandle.getName() + " Realign");
       methodR.setToolTipText(WsURL);
       methodR.addActionListener(new ActionListener()
       {
@@ -233,9 +235,10 @@ public class MsaWSClient extends WS1Client
         public void actionPerformed(ActionEvent e)
         {
           AlignmentView msa = alignFrame.gatherSequencesForAlignment();
-          new jalview.ws.jws1.MsaWSClient(serviceHandle, alignFrame
-                  .getTitle(), msa, true, true, alignFrame.getViewport()
-                  .getAlignment().getDataset(), alignFrame);
+          new jalview.ws.jws1.MsaWSClient(serviceHandle,
+                  alignFrame.getTitle(), msa, true, true,
+                  alignFrame.getViewport().getAlignment().getDataset(),
+                  alignFrame);
 
         }
 
index 72d41c9..006f014 100644 (file)
@@ -96,9 +96,8 @@ class MsaWSThread extends JWS1Thread implements WSClientI
       int nseqs = 0;
       if (minlen < 0)
       {
-        throw new Error(
-                MessageManager
-                        .getString("error.implementation_error_minlen_must_be_greater_zero"));
+        throw new Error(MessageManager.getString(
+                "error.implementation_error_minlen_must_be_greater_zero"));
       }
       for (int i = 0; i < seqs.length; i++)
       {
@@ -108,7 +107,8 @@ class MsaWSThread extends JWS1Thread implements WSClientI
         }
       }
       boolean valid = nseqs > 1; // need at least two seqs
-      vamsas.objects.simple.Sequence[] seqarray = (valid) ? new vamsas.objects.simple.Sequence[nseqs]
+      vamsas.objects.simple.Sequence[] seqarray = (valid)
+              ? new vamsas.objects.simple.Sequence[nseqs]
               : null;
       for (int i = 0, n = 0; i < seqs.length; i++)
       {
@@ -132,8 +132,8 @@ class MsaWSThread extends JWS1Thread implements WSClientI
           String empty = null;
           if (seqs[i].getEnd() >= seqs[i].getStart())
           {
-            empty = (submitGaps) ? seqs[i].getSequenceAsString() : AlignSeq
-                    .extractGaps(jalview.util.Comparison.GapChars,
+            empty = (submitGaps) ? seqs[i].getSequenceAsString()
+                    : AlignSeq.extractGaps(jalview.util.Comparison.GapChars,
                             seqs[i].getSequenceAsString());
           }
           emptySeqs.add(new String[] { newname, empty });
@@ -414,8 +414,8 @@ class MsaWSThread extends JWS1Thread implements WSClientI
                     "Exception whilst cancelling " + jobs[job].getJobId(),
                     exc);
           }
-          wsInfo.setProgressText(jobs[job].getJobnum(), OutputHeader
-                  + cancelledMessage + "\n");
+          wsInfo.setProgressText(jobs[job].getJobnum(),
+                  OutputHeader + cancelledMessage + "\n");
         }
       }
       if (cancelled)
@@ -447,16 +447,16 @@ class MsaWSThread extends JWS1Thread implements WSClientI
     if (!(job instanceof MsaWSJob))
     {
       throw new Error(MessageManager.formatMessage(
-              "error.implementation_error_msawbjob_called",
-              new String[] { job.getClass().toString() }));
+              "error.implementation_error_msawbjob_called", new String[]
+              { job.getClass().toString() }));
     }
     MsaWSJob j = (MsaWSJob) job;
     if (j.isSubmitted())
     {
       if (Cache.log.isDebugEnabled())
       {
-        Cache.log.debug("Tried to submit an already submitted job "
-                + j.getJobId());
+        Cache.log.debug(
+                "Tried to submit an already submitted job " + j.getJobId());
       }
       return;
     }
@@ -466,8 +466,8 @@ class MsaWSThread extends JWS1Thread implements WSClientI
       j.setSubmitted(true);
       j.result = new MsaResult();
       j.result.setFinished(true);
-      j.result.setStatus(MessageManager
-              .getString("label.empty_alignment_job"));
+      j.result.setStatus(
+              MessageManager.getString("label.empty_alignment_job"));
       ((MsaResult) j.result).setMsa(null);
     }
     try
@@ -487,7 +487,8 @@ class MsaWSThread extends JWS1Thread implements WSClientI
         {
           throw new Exception(MessageManager.formatMessage(
                   "exception.web_service_returned_null_try_later",
-                  new String[] { WsUrl }));
+                  new String[]
+                  { WsUrl }));
         }
 
         throw new Exception(jobsubmit.getJobId());
@@ -496,11 +497,10 @@ class MsaWSThread extends JWS1Thread implements WSClientI
     {
       // TODO: JBPNote catch timeout or other fault types explicitly
       // For unexpected errors
-      System.err
-              .println(WebServiceName
-                      + "Client: Failed to submit the sequences for alignment (probably a server side problem)\n"
-                      + "When contacting Server:" + WsUrl + "\n"
-                      + e.toString() + "\n");
+      System.err.println(WebServiceName
+              + "Client: Failed to submit the sequences for alignment (probably a server side problem)\n"
+              + "When contacting Server:" + WsUrl + "\n" + e.toString()
+              + "\n");
       j.setAllowedServerExceptions(0);
       wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
       wsInfo.setStatus(j.getJobnum(),
@@ -544,7 +544,8 @@ class MsaWSThread extends JWS1Thread implements WSClientI
           results++;
           // if (Cache.log.isDebugEnabled())
           // {
-          // System.out.println("Job lob for job "+jobs[j].getJobId()+":"+jobs[j].getJobnum());
+          // System.out.println("Job lob for job
+          // "+jobs[j].getJobId()+":"+jobs[j].getJobnum());
           // System.out.println(jobs[j].getStatus());
           // }
 
@@ -557,8 +558,8 @@ class MsaWSThread extends JWS1Thread implements WSClientI
             String[] lines = valign.getMethod();
             for (int line = 0; line < lines.length; line++)
             {
-              wsInfo.appendProgressText(jobs[j].getJobnum(), lines[line]
-                      + "\n");
+              wsInfo.appendProgressText(jobs[j].getJobnum(),
+                      lines[line] + "\n");
             }
             // JBPNote The returned files from a webservice could be
             // hidden behind icons in the monitor window that,
@@ -570,8 +571,9 @@ class MsaWSThread extends JWS1Thread implements WSClientI
     } catch (Exception ex)
     {
 
-      Cache.log.error("Unexpected exception when processing results for "
-              + alTitle, ex);
+      Cache.log.error(
+              "Unexpected exception when processing results for " + alTitle,
+              ex);
       wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
     }
     if (results > 0)
@@ -646,8 +648,8 @@ class MsaWSThread extends JWS1Thread implements WSClientI
 
     if (newFrame)
     {
-      AlignFrame af = new AlignFrame(al, hidden,
-              AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
+      AlignFrame af = new AlignFrame(al, hidden, AlignFrame.DEFAULT_WIDTH,
+              AlignFrame.DEFAULT_HEIGHT);
 
       // initialise with same renderer settings as in parent alignframe.
       af.getFeatureRenderer().transferSettings(this.featureSettings);
@@ -670,8 +672,8 @@ class MsaWSThread extends JWS1Thread implements WSClientI
 
             while (j < l)
             {
-              if (((AlignmentOrder) alorders.get(i)).equals((alorders
-                      .get(j))))
+              if (((AlignmentOrder) alorders.get(i))
+                      .equals((alorders.get(j))))
               {
                 alorders.remove(j);
                 l--;
index 92d17e8..53338d3 100644 (file)
@@ -84,11 +84,12 @@ public class SeqSearchWSClient extends WS1Client
     // name to service client name
     if (!sh.getAbstractName().equals(this.getServiceActionKey()))
     {
-      JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
-              .formatMessage(
+      JvOptionPane.showMessageDialog(Desktop.desktop,
+              MessageManager.formatMessage(
                       "label.service_called_is_not_seq_search_service",
-                      new String[] { sh.getName() }), MessageManager
-              .getString("label.internal_jalview_error"),
+                      new String[]
+                      { sh.getName() }),
+              MessageManager.getString("label.internal_jalview_error"),
               JvOptionPane.WARNING_MESSAGE);
 
       return;
@@ -96,10 +97,11 @@ public class SeqSearchWSClient extends WS1Client
 
     if ((wsInfo = setWebService(sh)) == null)
     {
-      JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
-              .formatMessage("label.seq_search_service_is_unknown",
-                      new String[] { sh.getName() }), MessageManager
-              .getString("label.internal_jalview_error"),
+      JvOptionPane.showMessageDialog(Desktop.desktop,
+              MessageManager.formatMessage(
+                      "label.seq_search_service_is_unknown", new String[]
+                      { sh.getName() }),
+              MessageManager.getString("label.internal_jalview_error"),
               JvOptionPane.WARNING_MESSAGE);
 
       return;
@@ -138,20 +140,21 @@ public class SeqSearchWSClient extends WS1Client
     // sequence db
     boolean profileSearch = msa.getSequences().length > 2 ? true : false;
     // single sequence or profile from alignment view
-    wsInfo.setProgressText("Searching "
-            + visdb
-            + (!profileSearch ? " with sequence "
-                    + msa.getSequences()[0].getRefSeq().getName()
-                    : " with profile") + " from " + altitle
-            + "\nJob details\n");
+    wsInfo.setProgressText("Searching " + visdb
+            + (!profileSearch
+                    ? " with sequence "
+                            + msa.getSequences()[0].getRefSeq().getName()
+                    : " with profile")
+            + " from " + altitle + "\nJob details\n");
 
     String jobtitle = WebServiceName
             + ((WebServiceName.indexOf("earch") > -1) ? " " : " search ")
-            + " of "
-            + visdb
-            + (!profileSearch ? " with sequence "
-                    + msa.getSequences()[0].getRefSeq().getName()
-                    : " with profile") + " from " + altitle;
+            + " of " + visdb
+            + (!profileSearch
+                    ? " with sequence "
+                            + msa.getSequences()[0].getRefSeq().getName()
+                    : " with profile")
+            + " from " + altitle;
     SeqSearchWSThread ssthread = new SeqSearchWSThread(server, WsURL,
             wsInfo, alignFrame, WebServiceName, jobtitle, msa, db,
             seqdataset);
@@ -220,8 +223,8 @@ public class SeqSearchWSClient extends WS1Client
     if (!locateWebService())
     {
       throw new Exception(MessageManager.formatMessage(
-              "exception.cannot_contact_service_endpoint_at",
-              new String[] { WsURL }));
+              "exception.cannot_contact_service_endpoint_at", new String[]
+              { WsURL }));
     }
     String database = server.getDatabase();
     if (database == null)
@@ -257,8 +260,8 @@ public class SeqSearchWSClient extends WS1Client
     JMenu defmenu = (JMenu) dbsrchs.get("Default Database");
     if (defmenu == null)
     {
-      dbsrchs.put("Default Database", defmenu = new JMenu(
-              "Default Database"));
+      dbsrchs.put("Default Database",
+              defmenu = new JMenu("Default Database"));
       newdbsrch.addElement(defmenu);
     }
 
@@ -271,7 +274,8 @@ public class SeqSearchWSClient extends WS1Client
     {
       jalview.bin.Cache.log.warn(
               "Database list request failed, so disabling SeqSearch Service client "
-                      + sh.getName() + " at " + sh.getEndpointURL(), e);
+                      + sh.getName() + " at " + sh.getEndpointURL(),
+              e);
       return;
     }
     JMenuItem method;
index edc9ae8..761b758 100644 (file)
@@ -95,9 +95,8 @@ class SeqSearchWSThread extends JWS1Thread implements WSClientI
       int nseqs = 0;
       if (minlen < 0)
       {
-        throw new Error(
-                MessageManager
-                        .getString("error.implementation_error_minlen_must_be_greater_zero"));
+        throw new Error(MessageManager.getString(
+                "error.implementation_error_minlen_must_be_greater_zero"));
       }
       for (int i = 0; i < seqs.length; i++)
       {
@@ -108,7 +107,8 @@ class SeqSearchWSThread extends JWS1Thread implements WSClientI
       }
       boolean valid = nseqs >= 1; // need at least one sequence for valid input
       // TODO: generalise
-      vamsas.objects.simple.Sequence[] seqarray = (valid) ? new vamsas.objects.simple.Sequence[nseqs]
+      vamsas.objects.simple.Sequence[] seqarray = (valid)
+              ? new vamsas.objects.simple.Sequence[nseqs]
               : null;
       boolean submitGaps = (nseqs == 1) ? false : true; // profile is submitted
       // with gaps
@@ -134,8 +134,8 @@ class SeqSearchWSThread extends JWS1Thread implements WSClientI
           String empty = null;
           if (seqs[i].getEnd() >= seqs[i].getStart())
           {
-            empty = (submitGaps) ? seqs[i].getSequenceAsString() : AlignSeq
-                    .extractGaps(jalview.util.Comparison.GapChars,
+            empty = (submitGaps) ? seqs[i].getSequenceAsString()
+                    : AlignSeq.extractGaps(jalview.util.Comparison.GapChars,
                             seqs[i].getSequenceAsString());
           }
           emptySeqs.add(new String[] { newname, empty });
@@ -157,11 +157,10 @@ class SeqSearchWSThread extends JWS1Thread implements WSClientI
     @Override
     public boolean hasResults()
     {
-      if (subjobComplete
-              && result != null
-              && result.isFinished()
+      if (subjobComplete && result != null && result.isFinished()
               && ((SeqSearchResult) result).getAlignment() != null
-              && ((SeqSearchResult) result).getAlignment().getSeqs() != null)
+              && ((SeqSearchResult) result).getAlignment()
+                      .getSeqs() != null)
       {
         return true;
       }
@@ -184,8 +183,8 @@ class SeqSearchWSThread extends JWS1Thread implements WSClientI
         // int alseq_l = 0;
         if (((SeqSearchResult) result).getAlignment() != null)
         {
-          alseqs = getVamsasAlignment(((SeqSearchResult) result)
-                  .getAlignment());
+          alseqs = getVamsasAlignment(
+                  ((SeqSearchResult) result).getAlignment());
           // alseq_gapchar = ( (SeqSearchResult)
           // result).getAlignment().getGapchar().charAt(0);
           // alseq_l = alseqs.length;
@@ -213,8 +212,8 @@ class SeqSearchWSThread extends JWS1Thread implements WSClientI
           }
         } catch (Exception e)
         {
-          System.err
-                  .println("Failed to parse the annotation file associated with the alignment.");
+          System.err.println(
+                  "Failed to parse the annotation file associated with the alignment.");
           System.err.println(">>>EOF" + inFile + "\n<<<EOF\n");
           e.printStackTrace(System.err);
         }
@@ -224,14 +223,14 @@ class SeqSearchWSThread extends JWS1Thread implements WSClientI
           inFile = ((SeqSearchResult) result).getFeatures();
           if (inFile != null && inFile.length() > 0)
           {
-            jalview.io.FeaturesFile ff = new jalview.io.FeaturesFile(
-                    inFile, jalview.io.DataSourceType.PASTE);
+            jalview.io.FeaturesFile ff = new jalview.io.FeaturesFile(inFile,
+                    jalview.io.DataSourceType.PASTE);
             ff.parse(al, featureColours, false);
           }
         } catch (Exception e)
         {
-          System.err
-                  .println("Failed to parse the Features file associated with the alignment.");
+          System.err.println(
+                  "Failed to parse the Features file associated with the alignment.");
           System.err.println(">>>EOF" + inFile + "\n<<<EOF\n");
           e.printStackTrace(System.err);
         }
@@ -251,8 +250,8 @@ class SeqSearchWSThread extends JWS1Thread implements WSClientI
           }
         } catch (Exception e)
         {
-          System.err
-                  .println("Failed to parse the treeFile associated with the alignment.");
+          System.err.println(
+                  "Failed to parse the treeFile associated with the alignment.");
           System.err.println(">>>EOF" + inFile + "\n<<<EOF\n");
           e.printStackTrace(System.err);
         }
@@ -430,8 +429,8 @@ class SeqSearchWSThread extends JWS1Thread implements WSClientI
                     "Exception whilst cancelling " + jobs[job].getJobId(),
                     exc);
           }
-          wsInfo.setProgressText(jobs[job].getJobnum(), OutputHeader
-                  + cancelledMessage + "\n");
+          wsInfo.setProgressText(jobs[job].getJobnum(),
+                  OutputHeader + cancelledMessage + "\n");
         }
       }
       if (cancelled)
@@ -454,8 +453,8 @@ class SeqSearchWSThread extends JWS1Thread implements WSClientI
   @Override
   public void pollJob(AWsJob job) throws Exception
   {
-    ((SeqSearchWSJob) job).result = server.getResult(((SeqSearchWSJob) job)
-            .getJobId());
+    ((SeqSearchWSJob) job).result = server
+            .getResult(((SeqSearchWSJob) job).getJobId());
   }
 
   @Override
@@ -464,16 +463,16 @@ class SeqSearchWSThread extends JWS1Thread implements WSClientI
     if (!(job instanceof SeqSearchWSJob))
     {
       throw new Error(MessageManager.formatMessage(
-              "error.implementation_error_msawbjob_called",
-              new String[] { job.getClass().toString() }));
+              "error.implementation_error_msawbjob_called", new String[]
+              { job.getClass().toString() }));
     }
     SeqSearchWSJob j = (SeqSearchWSJob) job;
     if (j.isSubmitted())
     {
       if (Cache.log.isDebugEnabled())
       {
-        Cache.log.debug("Tried to submit an already submitted job "
-                + j.getJobId());
+        Cache.log.debug(
+                "Tried to submit an already submitted job " + j.getJobId());
       }
       return;
     }
@@ -483,14 +482,14 @@ class SeqSearchWSThread extends JWS1Thread implements WSClientI
       j.setSubmitted(true);
       j.result = new MsaResult();
       j.result.setFinished(true);
-      j.result.setStatus(MessageManager
-              .getString("label.empty_alignment_job"));
+      j.result.setStatus(
+              MessageManager.getString("label.empty_alignment_job"));
       ((MsaResult) j.result).setMsa(null);
     }
     try
     {
-      vamsas.objects.simple.WsJobId jobsubmit = server.search(
-              j.seqs.getSeqs()[0], dbArg);
+      vamsas.objects.simple.WsJobId jobsubmit = server
+              .search(j.seqs.getSeqs()[0], dbArg);
 
       if ((jobsubmit != null) && (jobsubmit.getStatus() == 1))
       {
@@ -505,7 +504,8 @@ class SeqSearchWSThread extends JWS1Thread implements WSClientI
         {
           throw new Exception(MessageManager.formatMessage(
                   "exception.web_service_returned_null_try_later",
-                  new String[] { WsUrl }));
+                  new String[]
+                  { WsUrl }));
         }
 
         throw new Exception(jobsubmit.getJobId());
@@ -514,11 +514,10 @@ class SeqSearchWSThread extends JWS1Thread implements WSClientI
     {
       // TODO: JBPNote catch timeout or other fault types explicitly
       // For unexpected errors
-      System.err
-              .println(WebServiceName
-                      + "Client: Failed to submit the sequences for alignment (probably a server side problem)\n"
-                      + "When contacting Server:" + WsUrl + "\n"
-                      + e.toString() + "\n");
+      System.err.println(WebServiceName
+              + "Client: Failed to submit the sequences for alignment (probably a server side problem)\n"
+              + "When contacting Server:" + WsUrl + "\n" + e.toString()
+              + "\n");
       j.setAllowedServerExceptions(0);
       wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
       wsInfo.setStatus(j.getJobnum(),
@@ -568,8 +567,8 @@ class SeqSearchWSThread extends JWS1Thread implements WSClientI
             String[] lines = valign.getMethod();
             for (int line = 0; line < lines.length; line++)
             {
-              wsInfo.appendProgressText(jobs[j].getJobnum(), lines[line]
-                      + "\n");
+              wsInfo.appendProgressText(jobs[j].getJobnum(),
+                      lines[line] + "\n");
             }
             // JBPNote The returned files from a webservice could be
             // hidden behind icons in the monitor window that,
@@ -580,8 +579,9 @@ class SeqSearchWSThread extends JWS1Thread implements WSClientI
     } catch (Exception ex)
     {
 
-      Cache.log.error("Unexpected exception when processing results for "
-              + alTitle, ex);
+      Cache.log.error(
+              "Unexpected exception when processing results for " + alTitle,
+              ex);
       wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
     }
     if (results > 0)
@@ -662,12 +662,13 @@ class SeqSearchWSThread extends JWS1Thread implements WSClientI
        * propagateDatasetMappings(al); }
        */
 
-      AlignFrame af = new AlignFrame(al,// columnselection,
+      AlignFrame af = new AlignFrame(al, // columnselection,
               AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
       if (nf != null)
       {
-        af.showNewickTree(nf, MessageManager.formatMessage(
-                "label.tree_from", new String[] { this.alTitle }));
+        af.showNewickTree(nf,
+                MessageManager.formatMessage("label.tree_from", new String[]
+                { this.alTitle }));
       }
       // initialise with same renderer settings as in parent alignframe.
       af.getFeatureRenderer().transferSettings(this.featureSettings);
index f111760..6fa41fc 100644 (file)
@@ -36,8 +36,8 @@ import ext.vamsas.ServiceHandle;
  * @author JimP
  * 
  */
-public abstract class WS1Client extends WSClient implements
-        WSMenuEntryProviderI
+public abstract class WS1Client extends WSClient
+        implements WSMenuEntryProviderI
 {
 
   /**
@@ -111,9 +111,8 @@ public abstract class WS1Client extends WSClient implements
   {
     if (serviceHandle == null)
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_error_cannot_attach_ws_menu_entry"));
+      throw new Error(MessageManager.getString(
+              "error.implementation_error_cannot_attach_ws_menu_entry"));
     }
     attachWSMenuEntry(wsmenu, serviceHandle, alignFrame);
   }
index 001f6a8..9a2316c 100644 (file)
@@ -20,7 +20,6 @@
  */
 package jalview.ws.jws2;
 
-import jalview.api.AlignCalcWorkerI;
 import jalview.api.FeatureColourI;
 import jalview.bin.Cache;
 import jalview.datamodel.AlignmentAnnotation;
@@ -63,9 +62,9 @@ public class AADisorderClient extends JabawsCalcWorker
   AlignFrame af;
 
   public AADisorderClient(Jws2Instance sh, AlignFrame alignFrame,
-          WsParamSetI preset, List<Argument> paramset)
+          WsParamSetI thePreset, List<Argument> paramset)
   {
-    super(sh, alignFrame, preset, paramset);
+    super(sh, alignFrame, thePreset, paramset);
     af = alignFrame;
     typeName = sh.action;
     methodName = sh.serviceType;
@@ -100,29 +99,32 @@ public class AADisorderClient extends JabawsCalcWorker
   {
     // TODO: turn this into some kind of configuration file that's a bit easier
     // to edit
-    featureMap = new HashMap<String, Map<String, String[]>>();
+    featureMap = new HashMap<>();
     Map<String, String[]> fmap;
     featureMap.put(compbio.ws.client.Services.IUPredWS.toString(),
-            fmap = new HashMap<String, String[]>());
-    fmap.put("Glob", new String[] { "Globular Domain",
-        "Predicted globular domain" });
+            fmap = new HashMap<>());
+    fmap.put("Glob",
+            new String[]
+            { "Globular Domain", "Predicted globular domain" });
     featureMap.put(compbio.ws.client.Services.JronnWS.toString(),
-            fmap = new HashMap<String, String[]>());
+            fmap = new HashMap<>());
     featureMap.put(compbio.ws.client.Services.DisemblWS.toString(),
-            fmap = new HashMap<String, String[]>());
+            fmap = new HashMap<>());
     fmap.put("REM465", new String[] { "REM465", "Missing density" });
     fmap.put("HOTLOOPS", new String[] { "HOTLOOPS", "Flexible loops" });
     fmap.put("COILS", new String[] { "COILS", "Random coil" });
     featureMap.put(compbio.ws.client.Services.GlobPlotWS.toString(),
-            fmap = new HashMap<String, String[]>());
-    fmap.put("GlobDoms", new String[] { "Globular Domain",
-        "Predicted globular domain" });
-    fmap.put("Disorder", new String[] { "Protein Disorder",
-        "Probable unstructured peptide region" });
+            fmap = new HashMap<>());
+    fmap.put("GlobDoms",
+            new String[]
+            { "Globular Domain", "Predicted globular domain" });
+    fmap.put("Disorder",
+            new String[]
+            { "Protein Disorder", "Probable unstructured peptide region" });
     Map<String, Map<String, Object>> amap;
-    annotMap = new HashMap<String, Map<String, Map<String, Object>>>();
+    annotMap = new HashMap<>();
     annotMap.put(compbio.ws.client.Services.GlobPlotWS.toString(),
-            amap = new HashMap<String, Map<String, Object>>());
+            amap = new HashMap<>());
     amap.put("Dydx", new HashMap<String, Object>());
     amap.get("Dydx").put(DONTCOMBINE, DONTCOMBINE);
     amap.get("Dydx").put(THRESHOLD, new double[] { 1, 0 });
@@ -133,7 +135,7 @@ public class AADisorderClient extends JabawsCalcWorker
     amap.put("RawScore", new HashMap<String, Object>());
     amap.get("RawScore").put(INVISIBLE, INVISIBLE);
     annotMap.put(compbio.ws.client.Services.DisemblWS.toString(),
-            amap = new HashMap<String, Map<String, Object>>());
+            amap = new HashMap<>());
     amap.put("COILS", new HashMap<String, Object>());
     amap.put("HOTLOOPS", new HashMap<String, Object>());
     amap.put("REM465", new HashMap<String, Object>());
@@ -146,7 +148,7 @@ public class AADisorderClient extends JabawsCalcWorker
     amap.get("REM465").put(RANGE, new float[] { 0, 1 });
 
     annotMap.put(compbio.ws.client.Services.IUPredWS.toString(),
-            amap = new HashMap<String, Map<String, Object>>());
+            amap = new HashMap<>());
     amap.put("Long", new HashMap<String, Object>());
     amap.put("Short", new HashMap<String, Object>());
     amap.get("Long").put(THRESHOLD, new double[] { 1, 0.5 });
@@ -154,7 +156,7 @@ public class AADisorderClient extends JabawsCalcWorker
     amap.get("Short").put(THRESHOLD, new double[] { 1, 0.5 });
     amap.get("Short").put(RANGE, new float[] { 0, 1 });
     annotMap.put(compbio.ws.client.Services.JronnWS.toString(),
-            amap = new HashMap<String, Map<String, Object>>());
+            amap = new HashMap<>());
     amap.put("JRonn", new HashMap<String, Object>());
     amap.get("JRonn").put(THRESHOLD, new double[] { 1, 0.5 });
     amap.get("JRonn").put(RANGE, new float[] { 0, 1 });
@@ -171,8 +173,8 @@ public class AADisorderClient extends JabawsCalcWorker
       Map<String, Map<String, Object>> annotTypeMap = annotMap
               .get(service.serviceType);
       boolean dispFeatures = false;
-      Map<String, Object> fc = new Hashtable<String, Object>();
-      List<AlignmentAnnotation> ourAnnot = new ArrayList<AlignmentAnnotation>();
+      Map<String, Object> fc = new Hashtable<>();
+      List<AlignmentAnnotation> ourAnnot = new ArrayList<>();
       /**
        * grouping for any annotation rows created
        */
@@ -207,9 +209,7 @@ public class AADisorderClient extends JabawsCalcWorker
         {
           Cache.log
                   .info("Couldn't recover disorder prediction for sequence "
-                          + seq.getName()
-                          + "(Prediction name was "
-                          + seqId
+                          + seq.getName() + "(Prediction name was " + seqId
                           + ")"
                           + "\nSee http://issues.jalview.org/browse/JAL-1319 for one possible reason why disorder predictions might fail.");
         }
@@ -238,14 +238,14 @@ public class AADisorderClient extends JabawsCalcWorker
                 }
                 if (vals.hasNext())
                 {
+                  val = vals.next().floatValue();
                   sf = new SequenceFeature(type[0], type[1],
-                          base + rn.from, base + rn.to, val = vals.next()
-                                  .floatValue(), methodName);
+                          base + rn.from, base + rn.to, val, methodName);
                 }
                 else
                 {
-                  sf = new SequenceFeature(type[0], type[1], null, base
-                          + rn.from, base + rn.to, methodName);
+                  sf = new SequenceFeature(type[0], type[1],
+                          base + rn.from, base + rn.to, methodName);
                 }
                 dseq.addSequenceFeature(sf);
                 if (last != val && !Float.isNaN(last))
@@ -268,13 +268,15 @@ public class AADisorderClient extends JabawsCalcWorker
                       typename = service.serviceType + " ("
                               + scr.getMethod() + ")",
                       calcName = service.getServiceTypeURI() + "/"
-                              + scr.getMethod(), aseq, base + 1, scr);
+                              + scr.getMethod(),
+                      aseq, base + 1, scr);
               annot.graph = AlignmentAnnotation.LINE_GRAPH;
 
               Map<String, Object> styleMap = (annotTypeMap == null) ? null
                       : annotTypeMap.get(scr.getMethod());
 
-              annot.visible = (styleMap == null || styleMap.get(INVISIBLE) == null);
+              annot.visible = (styleMap == null
+                      || styleMap.get(INVISIBLE) == null);
               double[] thrsh = (styleMap == null) ? null
                       : (double[]) styleMap.get(THRESHOLD);
               float[] range = (styleMap == null) ? null
@@ -308,8 +310,8 @@ public class AADisorderClient extends JabawsCalcWorker
                 annot.description += "<br/>" + threshNote;
               }
               annot.description += "</html>";
-              Color col = ColorUtils.createColourFromName(typeName
-                      + scr.getMethod());
+              Color col = ColorUtils
+                      .createColourFromName(typeName + scr.getMethod());
               for (int p = 0, ps = annot.annotations.length; p < ps; p++)
               {
                 if (annot.annotations[p] != null)
@@ -356,7 +358,6 @@ public class AADisorderClient extends JabawsCalcWorker
             // only do this if the alignFrame is currently showing this view.
             af.setShowSeqFeatures(true);
           }
-          ap.paintAlignment(true);
         }
         if (ourAnnot.size() > 0)
         {
@@ -364,6 +365,7 @@ public class AADisorderClient extends JabawsCalcWorker
           // new alignment annotation rows created.
           updateOurAnnots(ourAnnot);
           ap.adjustAnnotationHeight();
+          ap.paintAlignment(true, true);
         }
       }
     }
index f2795d2..dd64e77 100644 (file)
@@ -30,6 +30,7 @@ import jalview.datamodel.AnnotatedCollectionI;
 import jalview.datamodel.SequenceI;
 import jalview.gui.AlignFrame;
 import jalview.gui.IProgressIndicator;
+import jalview.gui.IProgressIndicatorHandler;
 import jalview.schemes.ResidueProperties;
 import jalview.workers.AlignCalcWorker;
 import jalview.ws.jws2.dm.AAConSettings;
@@ -78,8 +79,10 @@ public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
       ((jalview.gui.AlignViewport) alignViewport).setCalcIdSettingsFor(
               getCalcId(),
               new AAConSettings(true, service, this.preset,
-                      (arguments != null) ? JabaParamStore
-                              .getJwsArgsfromJaba(arguments) : null), true);
+                      (arguments != null)
+                              ? JabaParamStore.getJwsArgsfromJaba(arguments)
+                              : null),
+              true);
     }
   }
 
@@ -164,8 +167,8 @@ public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
     super(alignViewport, alignPanel);
   }
 
-  public AbstractJabaCalcWorker(Jws2Instance service,
-          AlignFrame alignFrame, WsParamSetI preset, List<Argument> paramset)
+  public AbstractJabaCalcWorker(Jws2Instance service, AlignFrame alignFrame,
+          WsParamSetI preset, List<Argument> paramset)
   {
     this(alignFrame.getCurrentView(), alignFrame.alignPanel);
     this.guiProgress = alignFrame;
@@ -218,7 +221,26 @@ public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
                 progressId = System.currentTimeMillis());
       }
       rslt = submitToService(seqs);
+      if (guiProgress != null)
+      {
+        guiProgress.registerHandler(progressId,
+                new IProgressIndicatorHandler()
+                {
 
+                  @Override
+                  public boolean cancelActivity(long id)
+                  {
+                    cancelCurrentJob();
+                    return true;
+                  }
+
+                  @Override
+                  public boolean canCancel()
+                  {
+                    return true;
+                  }
+                });
+      }
       boolean finished = false;
       long rpos = 0;
       do
@@ -322,9 +344,8 @@ public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
         }
         if (collectAnnotationResultsFor(rslt))
         {
-          jalview.bin.Cache.log
-                  .debug("Updating result annotation from Job " + rslt
-                          + " at " + service.getUri());
+          jalview.bin.Cache.log.debug("Updating result annotation from Job "
+                  + rslt + " at " + service.getUri());
           updateResultAnnotation(true);
           ap.adjustAnnotationHeight();
         }
@@ -334,8 +355,8 @@ public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
     catch (JobSubmissionException x)
     {
 
-      System.err.println("submission error with " + getServiceActionText()
-              + " :");
+      System.err.println(
+              "submission error with " + getServiceActionText() + " :");
       x.printStackTrace();
       calcMan.disableWorker(this);
     } catch (ResultNotAvailableException x)
@@ -371,7 +392,8 @@ public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
         {
           guiProgress.setProgressBar("", progressId);
         }
-        ap.paintAlignment(true);
+        // TODO: may not need to paintAlignment again !
+        ap.paintAlignment(false, false);
       }
       if (msg.length() > 0)
       {
@@ -444,8 +466,9 @@ public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
           AnnotatedCollectionI inputSeqs)
   {
     if (alignment == null || alignment.getWidth() <= 0
-            || alignment.getSequences() == null || alignment.isNucleotide() ? !nucleotidesAllowed
-            : !proteinAllowed)
+            || alignment.getSequences() == null || alignment.isNucleotide()
+                    ? !nucleotidesAllowed
+                    : !proteinAllowed)
     {
       return null;
     }
@@ -470,9 +493,10 @@ public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
 
     for (SequenceI sq : (inputSeqs.getSequences()))
     {
-      if (bySequence ? sq.findPosition(end + 1)
-              - sq.findPosition(start + 1) > minlen - 1 : sq.getEnd()
-              - sq.getStart() > minlen - 1)
+      if (bySequence
+              ? sq.findPosition(end + 1)
+                      - sq.findPosition(start + 1) > minlen - 1
+              : sq.getEnd() - sq.getStart() > minlen - 1)
       {
         String newname = SeqsetUtils.unique_name(seqs.size() + 1);
         // make new input sequence with or without gaps
@@ -537,8 +561,8 @@ public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
         FastaSequence sq = seqs.get(p);
         int l = sq.getSequence().length();
         // strip gapped columns
-        char[] padded = new char[realw], orig = sq.getSequence()
-                .toCharArray();
+        char[] padded = new char[realw],
+                orig = sq.getSequence().toCharArray();
         for (int i = 0, pp = 0; i < realw; pp++)
         {
           if (gapMap[pp])
@@ -579,7 +603,7 @@ public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
   protected boolean checkDone()
   {
     calcMan.notifyStart(this);
-    ap.paintAlignment(false);
+    ap.paintAlignment(false, false);
     while (!calcMan.notifyWorking(this))
     {
       if (calcMan.isWorking(this))
@@ -590,7 +614,7 @@ public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
       {
         if (ap != null)
         {
-          ap.paintAlignment(false);
+          ap.paintAlignment(false, false);
         }
 
         Thread.sleep(200);
index 9482d1d..cd85d4a 100644 (file)
@@ -128,8 +128,9 @@ public abstract class JWs2Job extends AWsJob
   @Override
   public boolean isQueued()
   {
-    return status == null ? false : status.equals(status.SUBMITTED)
-            || status.equals(status.PENDING);
+    return status == null ? false
+            : status.equals(status.SUBMITTED)
+                    || status.equals(status.PENDING);
   }
 
   /*
@@ -141,9 +142,8 @@ public abstract class JWs2Job extends AWsJob
   public boolean isRunning()
   {
     // TODO Auto-generated method stub
-    return status != null
-            && (status.equals(status.RUNNING) || status
-                    .equals(status.STARTED));
+    return status != null && (status.equals(status.RUNNING)
+            || status.equals(status.STARTED));
   }
 
   /*
index 34b8a72..10ec812 100644 (file)
@@ -84,8 +84,8 @@ public class JabaParamStore implements ParamDatastoreI
           }
           else
           {
-            System.err
-                    .println("Warning: Ignoring parameter set instance of type "
+            System.err.println(
+                    "Warning: Ignoring parameter set instance of type "
                             + paramset.getClass()
                             + " : Bound but not applicable for service at "
                             + service.getUri());
@@ -168,7 +168,8 @@ public class JabaParamStore implements ParamDatastoreI
       {
         throw new Error(MessageManager.formatMessage(
                 "error.implementation_error_cannot_handle_jaba_param",
-                new String[] { rg.getClass().toString() }));
+                new String[]
+                { rg.getClass().toString() }));
       }
       else
       {
@@ -199,13 +200,15 @@ public class JabaParamStore implements ParamDatastoreI
     List rgs = new ArrayList();
     for (ArgumentI rg : jwsargs)
     {
-      Argument narg = (rg instanceof JabaOption) ? ((JabaOption) rg)
-              .getOption() : null;
+      Argument narg = (rg instanceof JabaOption)
+              ? ((JabaOption) rg).getOption()
+              : null;
       if (narg == null)
       {
         throw new Error(MessageManager.formatMessage(
                 "error.implementation_error_cannot_handle_jaba_param",
-                new String[] { rg.getClass().toString() }));
+                new String[]
+                { rg.getClass().toString() }));
       }
       else
       {
@@ -224,8 +227,8 @@ public class JabaParamStore implements ParamDatastoreI
   @Override
   public boolean presetExists(String name)
   {
-    return (editedParams.containsKey(name) || servicePresets
-            .containsKey(name));
+    return (editedParams.containsKey(name)
+            || servicePresets.containsKey(name));
   }
 
   @Override
@@ -243,9 +246,8 @@ public class JabaParamStore implements ParamDatastoreI
     }
     if (servicePresets.containsKey(name))
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_error_attempt_to_delete_service_preset"));
+      throw new Error(MessageManager.getString(
+              "error.implementation_error_attempt_to_delete_service_preset"));
     }
   }
 
@@ -266,15 +268,15 @@ public class JabaParamStore implements ParamDatastoreI
   public void updatePreset(String oldName, String presetName, String text,
           List<ArgumentI> jobParams)
   {
-    JabaWsParamSet jps = (JabaWsParamSet) ((oldName != null) ? getPreset(oldName)
+    JabaWsParamSet jps = (JabaWsParamSet) ((oldName != null)
+            ? getPreset(oldName)
             : getPreset(presetName));
     if (jps == null)
     {
-      throw new Error(
-              MessageManager
-                      .formatMessage(
-                              "error.implementation_error_cannot_locate_oldname_presetname",
-                              new String[] { oldName, presetName }));
+      throw new Error(MessageManager.formatMessage(
+              "error.implementation_error_cannot_locate_oldname_presetname",
+              new String[]
+              { oldName, presetName }));
     }
     jps.setName(presetName);
     jps.setDescription(text);
@@ -323,9 +325,8 @@ public class JabaParamStore implements ParamDatastoreI
   {
     if (!involves(urls))
     {
-      throw new IOException(
-              MessageManager
-                      .getString("error.implementation_error_cannot_find_service_url_in_given_set"));
+      throw new IOException(MessageManager.getString(
+              "error.implementation_error_cannot_find_service_url_in_given_set"));
 
     }
     JabaWsParamSet wsp = new JabaWsParamSet();
@@ -339,8 +340,8 @@ public class JabaParamStore implements ParamDatastoreI
     {
       lines.add(st.nextToken());
     }
-    wsp.setjabaArguments(ParameterUtils.processParameters(lines,
-            serviceOptions, " "));
+    wsp.setjabaArguments(
+            ParameterUtils.processParameters(lines, serviceOptions, " "));
     return wsp;
   }
 
@@ -350,17 +351,15 @@ public class JabaParamStore implements ParamDatastoreI
   {
     if (!involves(pset.getApplicableUrls()))
     {
-      throw new IOException(
-              MessageManager
-                      .formatMessage(
-                              "error.implementation_error_cannot_find_service_url_in_given_set_param_store",
-                              new String[] { service.getUri() }));
+      throw new IOException(MessageManager.formatMessage(
+              "error.implementation_error_cannot_find_service_url_in_given_set_param_store",
+              new String[]
+              { service.getUri() }));
     }
     if (!(pset instanceof JabaWsParamSet))
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_error_jabaws_param_set_only_handled_by"));
+      throw new Error(MessageManager.getString(
+              "error.implementation_error_jabaws_param_set_only_handled_by"));
     }
 
     StringBuffer rslt = new StringBuffer();
index 279a4f0..981b288 100644 (file)
@@ -74,9 +74,9 @@ public class JabaPreset implements WsParamSetI
   @Override
   public void setSourceFile(String newfile)
   {
-    throw new Error(MessageManager.formatMessage(
-            "error.cannot_set_source_file_for", new String[] { getClass()
-                    .toString() }));
+    throw new Error(MessageManager
+            .formatMessage("error.cannot_set_source_file_for", new String[]
+            { getClass().toString() }));
   }
 
   @Override
@@ -84,22 +84,20 @@ public class JabaPreset implements WsParamSetI
   {
     try
     {
-      return JabaParamStore.getJwsArgsfromJaba(p.getArguments(service
-              .getRunnerConfig()));
+      return JabaParamStore.getJwsArgsfromJaba(
+              p.getArguments(service.getRunnerConfig()));
     } catch (Exception e)
     {
       e.printStackTrace();
-      throw new Error(
-              MessageManager
-                      .getString("error.mismatch_service_instance_preset"));
+      throw new Error(MessageManager
+              .getString("error.mismatch_service_instance_preset"));
     }
   }
 
   @Override
   public void setArguments(List<ArgumentI> args)
   {
-    throw new Error(
-            MessageManager
-                    .getString("error.cannot_set_params_for_ws_preset"));
+    throw new Error(MessageManager
+            .getString("error.cannot_set_params_for_ws_preset"));
   }
 }
index a3ed47a..d06c3f0 100644 (file)
@@ -126,8 +126,8 @@ public class JabaWsServerQuery implements Runnable
             srv_set = registry.getSupportedServices();
 
             // dan test
-            System.out.println("registry.getSupportedServices: "
-                    + srv_set.toString());
+            System.out.println(
+                    "registry.getSupportedServices: " + srv_set.toString());
 
             svccategories = registry.getServiceCategories();
 
index 4388f6c..fc36205 100644 (file)
@@ -115,10 +115,8 @@ public abstract class JabawsCalcWorker extends AbstractJabaCalcWorker
         rslt = aaservice.customAnalize(seqs, getJabaArguments());
       } catch (WrongParameterException x)
       {
-        throw new JobSubmissionException(
-                MessageManager
-                        .getString("exception.jobsubmission_invalid_params_set"),
-                x);
+        throw new JobSubmissionException(MessageManager.getString(
+                "exception.jobsubmission_invalid_params_set"), x);
 
       }
     }
index 0baa767..ee36d4a 100644 (file)
@@ -43,8 +43,8 @@ import compbio.metadata.JobSubmissionException;
 import compbio.metadata.ResultNotAvailableException;
 import compbio.metadata.WrongParameterException;
 
-public abstract class JabawsMsaInterfaceAlignCalcWorker extends
-        AbstractJabaCalcWorker
+public abstract class JabawsMsaInterfaceAlignCalcWorker
+        extends AbstractJabaCalcWorker
 {
 
   @SuppressWarnings("unchecked")
@@ -59,7 +59,8 @@ public abstract class JabawsMsaInterfaceAlignCalcWorker extends
   }
 
   public JabawsMsaInterfaceAlignCalcWorker(Jws2Instance service,
-          AlignFrame alignFrame, WsParamSetI preset, List<Argument> paramset)
+          AlignFrame alignFrame, WsParamSetI preset,
+          List<Argument> paramset)
   {
     this(alignFrame.getCurrentView(), alignFrame.alignPanel);
     this.guiProgress = alignFrame;
@@ -129,10 +130,8 @@ public abstract class JabawsMsaInterfaceAlignCalcWorker extends
         rslt = msaservice.customAlign(seqs, getJabaArguments());
       } catch (WrongParameterException x)
       {
-        throw new JobSubmissionException(
-                MessageManager
-                        .getString("exception.jobsubmission_invalid_params_set"),
-                x);
+        throw new JobSubmissionException(MessageManager.getString(
+                "exception.jobsubmission_invalid_params_set"), x);
       }
     }
     return rslt;
index 8855d96..0f1a25e 100644 (file)
@@ -67,7 +67,8 @@ public abstract class Jws2Client extends jalview.ws.WSClient
     this.preset = preset;
     if (preset != null)
     {
-      if (!((preset instanceof JabaPreset) || preset instanceof JabaWsParamSet))
+      if (!((preset instanceof JabaPreset)
+              || preset instanceof JabaWsParamSet))
       {
         /*
          * { this.preset = ((JabaPreset) preset).p; } else if (preset instanceof
@@ -78,9 +79,8 @@ public abstract class Jws2Client extends jalview.ws.WSClient
          * arguments. for (Argument opt : arguments) { newargs.add(opt); } }
          * paramset = newargs; } else {
          */
-        throw new Error(
-                MessageManager
-                        .getString("error.implementation_error_can_only_instantiate_jaba_param_sets"));
+        throw new Error(MessageManager.getString(
+                "error.implementation_error_can_only_instantiate_jaba_param_sets"));
       }
     }
     else
@@ -106,9 +106,10 @@ public abstract class Jws2Client extends jalview.ws.WSClient
         sh.paramStore = new JabaParamStore(sh,
                 Desktop.getUserParameterStore());
       }
-      WsJobParameters jobParams = (preset == null && paramset != null && paramset
-              .size() > 0) ? new WsJobParameters(null, sh, null, paramset)
-              : new WsJobParameters(sh, preset);
+      WsJobParameters jobParams = (preset == null && paramset != null
+              && paramset.size() > 0)
+                      ? new WsJobParameters(null, sh, null, paramset)
+                      : new WsJobParameters(sh, preset);
       if (adjustingExisting)
       {
         jobParams.setName(MessageManager
@@ -121,8 +122,9 @@ public abstract class Jws2Client extends jalview.ws.WSClient
       WsParamSetI prset = jobParams.getPreset();
       if (prset == null)
       {
-        paramset = jobParams.isServiceDefaults() ? null : JabaParamStore
-                .getJabafromJwsArgs(jobParams.getJobParams());
+        paramset = jobParams.isServiceDefaults() ? null
+                : JabaParamStore
+                        .getJabafromJwsArgs(jobParams.getJobParams());
         this.preset = null;
       }
       else
@@ -149,9 +151,11 @@ public abstract class Jws2Client extends jalview.ws.WSClient
     WsURL = serv.hosturl;
     if (!b)
     {
-      return new WebserviceInfo(WebServiceJobTitle, WebServiceJobTitle
-              + " using service hosted at " + serv.hosturl + "\n"
-              + (serv.description != null ? serv.description : ""), false);
+      return new WebserviceInfo(WebServiceJobTitle,
+              WebServiceJobTitle + " using service hosted at "
+                      + serv.hosturl + "\n"
+                      + (serv.description != null ? serv.description : ""),
+              false);
     }
     return null;
   }
@@ -220,7 +224,7 @@ public abstract class Jws2Client extends jalview.ws.WSClient
               removeCurrentAAConWorkerFor(aaui, alignFrame);
               buildCurrentAAConWorkerFor(aaui, alignFrame, service);
             }
-          }// );
+          } // );
         }
       }
     }
@@ -232,8 +236,8 @@ public abstract class Jws2Client extends jalview.ws.WSClient
       final JCheckBoxMenuItem aaConEnabled = new JCheckBoxMenuItem(
               aaui.getAAconToggle());
 
-      aaConEnabled.setToolTipText(JvSwingUtils.wrapTooltip(true,
-              aaui.getAAconToggleTooltip()));
+      aaConEnabled.setToolTipText(
+              JvSwingUtils.wrapTooltip(true, aaui.getAAconToggleTooltip()));
       aaConEnabled.addActionListener(new ActionListener()
       {
         @Override
@@ -255,7 +259,8 @@ public abstract class Jws2Client extends jalview.ws.WSClient
 
       });
       wsmenu.add(aaConEnabled);
-      final JMenuItem modifyParams = new JMenuItem(aaui.getAAeditSettings());
+      final JMenuItem modifyParams = new JMenuItem(
+              aaui.getAAeditSettings());
       modifyParams.setToolTipText(JvSwingUtils.wrapTooltip(true,
               aaui.getAAeditSettingsTooltip()));
       modifyParams.addActionListener(new ActionListener()
@@ -275,8 +280,9 @@ public abstract class Jws2Client extends jalview.ws.WSClient
         public void menuSelected(MenuEvent arg0)
         {
           // TODO: refactor to the implementing class.
-          if (alignFrame.getViewport().getAlignment().isNucleotide() ? aaui
-                  .isNa() : aaui.isPr())
+          if (alignFrame.getViewport().getAlignment().isNucleotide()
+                  ? aaui.isNa()
+                  : aaui.isPr())
           {
             aaConEnabled.setEnabled(true);
             modifyParams.setEnabled(true);
@@ -380,11 +386,11 @@ public abstract class Jws2Client extends jalview.ws.WSClient
   {
     if (service != null)
     {
-      if (!service.serviceType.toString().equals(
-              compbio.ws.client.Services.AAConWS.toString()))
+      if (!service.serviceType.toString()
+              .equals(compbio.ws.client.Services.AAConWS.toString()))
       {
-        Cache.log
-                .warn("Ignoring invalid preferred service for AACon calculations (service type was "
+        Cache.log.warn(
+                "Ignoring invalid preferred service for AACon calculations (service type was "
                         + service.serviceType + ")");
         service = null;
       }
index 12a08a0..5319eab 100644 (file)
@@ -164,8 +164,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
       {
         try
         {
-          Cache.log
-                  .debug("Waiting around for old discovery thread to finish.");
+          Cache.log.debug(
+                  "Waiting around for old discovery thread to finish.");
           // wait around until old discoverer dies
           Thread.sleep(100);
         } catch (Exception e)
@@ -179,8 +179,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
 
     // first set up exclusion list if needed
     final Set<String> ignoredServices = new HashSet<String>();
-    for (String ignored : Cache.getDefault("IGNORED_JABAWS_SERVICETYPES",
-            "").split("\\|"))
+    for (String ignored : Cache
+            .getDefault("IGNORED_JABAWS_SERVICETYPES", "").split("\\|"))
     {
       ignoredServices.add(ignored);
     }
@@ -190,12 +190,12 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     oldthread = Thread.currentThread();
     try
     {
-      Class foo = getClass().getClassLoader().loadClass(
-              "compbio.ws.client.Jws2Client");
+      Class foo = getClass().getClassLoader()
+              .loadClass("compbio.ws.client.Jws2Client");
     } catch (ClassNotFoundException e)
     {
-      System.err
-              .println("Not enabling JABA Webservices : client jar is not available."
+      System.err.println(
+              "Not enabling JABA Webservices : client jar is not available."
                       + "\nPlease check that your webstart JNLP file is up to date!");
       running = false;
       return;
@@ -259,8 +259,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
       }
       if (aborted)
       {
-        Cache.log.debug("Aborting " + qrys.size()
-                + " JABAWS discovery threads.");
+        Cache.log.debug(
+                "Aborting " + qrys.size() + " JABAWS discovery threads.");
         for (JabaWsServerQuery squery : qrys)
         {
           squery.setQuit(true);
@@ -297,8 +297,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     }
     oldthread = null;
     running = false;
-    changeSupport.firePropertyChange("services",
-            new Vector<Jws2Instance>(), services);
+    changeSupport.firePropertyChange("services", new Vector<Jws2Instance>(),
+            services);
   }
 
   /**
@@ -314,8 +314,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     {
       services = new Vector<Jws2Instance>();
     }
-    System.out.println("Discovered service: " + jwsservers + " "
-            + service.toString());
+    System.out.println(
+            "Discovered service: " + jwsservers + " " + service.toString());
     // Jws2Instance service = new Jws2Instance(jwsservers, srv.toString(),
     // service2);
 
@@ -433,8 +433,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
       service.attachWSMenuEntry(atpoint, alignFrame);
       if (alternates.containsKey(service.serviceType))
       {
-        atpoint.add(hitm = new JMenu(MessageManager
-                .getString("label.switch_server")));
+        atpoint.add(hitm = new JMenu(
+                MessageManager.getString("label.switch_server")));
         hitm.setToolTipText(JvSwingUtils.wrapTooltip(false,
                 MessageManager.getString("label.choose_jabaws_server")));
         for (final Jws2Instance sv : alternates.get(service.serviceType))
@@ -472,10 +472,11 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
    * submenus to index by host and service program type
    */
   private void addEnumeratedServices(final JMenu jws2al,
-          final AlignFrame alignFrame, List<Jws2Instance> enumerableServices)
+          final AlignFrame alignFrame,
+          List<Jws2Instance> enumerableServices)
   {
-    boolean byhost = Cache.getDefault("WSMENU_BYHOST", false), bytype = Cache
-            .getDefault("WSMENU_BYTYPE", false);
+    boolean byhost = Cache.getDefault("WSMENU_BYHOST", false),
+            bytype = Cache.getDefault("WSMENU_BYTYPE", false);
     /**
      * eventually, JWS2 services will appear under the same align/etc submenus.
      * for moment we keep them separate.
@@ -500,8 +501,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     // now add hosts in order of the given array
     for (String host : hostlist)
     {
-      Jws2Instance orderedsvcs[] = hosts.get(host).toArray(
-              new Jws2Instance[1]);
+      Jws2Instance orderedsvcs[] = hosts.get(host)
+              .toArray(new Jws2Instance[1]);
       String sortbytype[] = new String[orderedsvcs.length];
       for (int i = 0; i < sortbytype.length; i++)
       {
@@ -517,8 +518,9 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
           atpoint = JvSwingUtils.findOrCreateMenu(atpoint, host);
           if (atpoint.getToolTipText() == null)
           {
-            atpoint.setToolTipText(MessageManager.formatMessage(
-                    "label.services_at", new String[] { host }));
+            atpoint.setToolTipText(MessageManager
+                    .formatMessage("label.services_at", new String[]
+                    { host }));
           }
         }
         if (bytype)
@@ -529,9 +531,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
             atpoint.setToolTipText(service.getActionText());
           }
         }
-        if (!byhost
-                && !hostLabels.contains(host + service.serviceType
-                        + service.getActionText()))
+        if (!byhost && !hostLabels.contains(
+                host + service.serviceType + service.getActionText()))
         // !hostLabels.contains(host + (bytype ?
         // service.serviceType+service.getActionText() : "")))
         {
@@ -562,12 +563,13 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
                 Desktop.showUrl(service.getHost());
               }
             });
-            hitm.setToolTipText(JvSwingUtils.wrapTooltip(true,
-                    MessageManager.getString("label.open_jabaws_web_page")));
+            hitm.setToolTipText(
+                    JvSwingUtils.wrapTooltip(true, MessageManager
+                            .getString("label.open_jabaws_web_page")));
             lasthostFor.put(service.action, host);
           }
-          hostLabels.add(host + service.serviceType
-                  + service.getActionText());
+          hostLabels.add(
+                  host + service.serviceType + service.getActionText());
         }
 
         service.attachWSMenuEntry(atpoint, alignFrame);
@@ -586,8 +588,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
       }
       ;
     }
-    Thread runner = getDiscoverer().startDiscoverer(
-            new PropertyChangeListener()
+    Thread runner = getDiscoverer()
+            .startDiscoverer(new PropertyChangeListener()
             {
 
               @Override
@@ -601,9 +603,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
                   for (Jws2Instance instance : getDiscoverer().services)
                   {
                     System.out.println("Service " + i++ + " "
-                            + instance.getClass() + "@"
-                            + instance.getHost() + ": "
-                            + instance.getActionText());
+                            + instance.getClass() + "@" + instance.getHost()
+                            + ": " + instance.getActionText());
                   }
 
                 }
@@ -715,10 +716,9 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
         {
           Cache.log.warn("Problem whilst trying to make a URL from '"
                   + ((url != null) ? url : "<null>") + "'");
-          Cache.log
-                  .warn("This was probably due to a malformed comma separated list"
-                          + " in the "
-                          + JWS2HOSTURLS
+          Cache.log.warn(
+                  "This was probably due to a malformed comma separated list"
+                          + " in the " + JWS2HOSTURLS
                           + " entry of $(HOME)/.jalview_properties)");
           Cache.log.debug("Exception was ", ex);
         }
@@ -748,7 +748,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     try
     {
       compbio.ws.client.WSTester
-              .main(new String[] { "-h=" + foo.toString() });
+              .main(new String[]
+              { "-h=" + foo.toString() });
     } catch (Exception e)
     {
       e.printStackTrace();
@@ -841,8 +842,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
       urlsWithoutServices = new Vector<String>();
     }
 
-    if ((invalidServiceUrls == null || !invalidServiceUrls
-            .contains(jwsservers))
+    if ((invalidServiceUrls == null
+            || !invalidServiceUrls.contains(jwsservers))
             && !urlsWithoutServices.contains(jwsservers))
     {
       urlsWithoutServices.add(jwsservers);
@@ -897,7 +898,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
       if (getUrlsWithoutServices() != null
               && getUrlsWithoutServices().size() > 0)
       {
-        ermsg.append(MessageManager.getString("warn.urls_no_jaba") + ": \n");
+        ermsg.append(
+                MessageManager.getString("warn.urls_no_jaba") + ": \n");
         for (String svcurl : getUrlsWithoutServices())
         {
           if (list)
@@ -1039,7 +1041,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
   public void setPreferredServiceFor(String serviceType,
           String serviceAction, Jws2Instance selectedServer)
   {
-    setPreferredServiceFor(null, serviceType, serviceAction, selectedServer);
+    setPreferredServiceFor(null, serviceType, serviceAction,
+            selectedServer);
   }
 
   /**
index b723059..7e68d3b 100644 (file)
@@ -107,10 +107,12 @@ public class MsaWSClient extends Jws2Client
     if (!(sh.service instanceof MsaWS))
     {
       // redundant at mo - but may change
-      JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
-              .formatMessage("label.service_called_is_not_msa_service",
-                      new String[] { sh.serviceType }), MessageManager
-              .getString("label.internal_jalview_error"),
+      JvOptionPane.showMessageDialog(Desktop.desktop,
+              MessageManager.formatMessage(
+                      "label.service_called_is_not_msa_service",
+                      new String[]
+                      { sh.serviceType }),
+              MessageManager.getString("label.internal_jalview_error"),
               JvOptionPane.WARNING_MESSAGE);
 
       return;
@@ -119,9 +121,9 @@ public class MsaWSClient extends Jws2Client
     if ((wsInfo = setWebService(sh, false)) == null)
     {
       JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
-              .formatMessage("label.msa_service_is_unknown",
-                      new String[] { sh.serviceType }), MessageManager
-              .getString("label.internal_jalview_error"),
+              .formatMessage("label.msa_service_is_unknown", new String[]
+              { sh.serviceType }),
+              MessageManager.getString("label.internal_jalview_error"),
               JvOptionPane.WARNING_MESSAGE);
 
       return;
@@ -150,9 +152,8 @@ public class MsaWSClient extends Jws2Client
     String jobtitle = WebServiceName.toLowerCase();
     if (jobtitle.endsWith("alignment"))
     {
-      if (submitGaps
-              && (!jobtitle.endsWith("realignment") || jobtitle
-                      .indexOf("profile") == -1))
+      if (submitGaps && (!jobtitle.endsWith("realignment")
+              || jobtitle.indexOf("profile") == -1))
       {
         int pos = jobtitle.indexOf("alignment");
         jobtitle = WebServiceName.substring(0, pos) + "re-alignment of "
@@ -169,9 +170,9 @@ public class MsaWSClient extends Jws2Client
               + "alignment of " + altitle;
     }
 
-    MsaWSThread msathread = new MsaWSThread(server, preset, paramset,
-            WsURL, wsInfo, alignFrame, WebServiceName, jobtitle, msa,
-            submitGaps, preserveOrder, seqdataset);
+    MsaWSThread msathread = new MsaWSThread(server, preset, paramset, WsURL,
+            wsInfo, alignFrame, WebServiceName, jobtitle, msa, submitGaps,
+            preserveOrder, seqdataset);
     if (msathread.hasValidInput())
     {
       wsInfo.setthisService(msathread);
@@ -247,8 +248,9 @@ public class MsaWSClient extends Jws2Client
       if (submitGaps == true)
       {
         action = "Realign ";
-        msawsmenu = new JMenu(MessageManager.formatMessage(
-                "label.realign_with_params", new String[] { svcname }));
+        msawsmenu = new JMenu(MessageManager
+                .formatMessage("label.realign_with_params", new String[]
+                { svcname }));
         msawsmenu.setToolTipText(MessageManager
                 .getString("label.align_sequences_to_existing_alignment"));
         rmsawsmenu.add(msawsmenu);
@@ -256,11 +258,11 @@ public class MsaWSClient extends Jws2Client
       final boolean withGaps = submitGaps;
 
       JMenuItem method = new JMenuItem(MessageManager.formatMessage(
-              "label.calcname_with_default_settings",
-              new String[] { calcName }));
-      method.setToolTipText(MessageManager
-              .formatMessage("label.action_with_default_settings",
-                      new String[] { action }));
+              "label.calcname_with_default_settings", new String[]
+              { calcName }));
+      method.setToolTipText(MessageManager.formatMessage(
+              "label.action_with_default_settings", new String[]
+              { action }));
 
       method.addActionListener(new ActionListener()
       {
@@ -272,8 +274,9 @@ public class MsaWSClient extends Jws2Client
           if (msa != null)
           {
             new MsaWSClient(service, alignFrame.getTitle(), msa, withGaps,
-                    true, alignFrame.getViewport().getAlignment()
-                            .getDataset(), alignFrame);
+                    true,
+                    alignFrame.getViewport().getAlignment().getDataset(),
+                    alignFrame);
           }
 
         }
@@ -285,8 +288,8 @@ public class MsaWSClient extends Jws2Client
         // arguments
         method = new JMenuItem(
                 MessageManager.getString("label.edit_settings_and_run"));
-        method.setToolTipText(MessageManager
-                .getString("label.view_and_change_parameters_before_alignment"));
+        method.setToolTipText(MessageManager.getString(
+                "label.view_and_change_parameters_before_alignment"));
 
         method.addActionListener(new ActionListener()
         {
@@ -296,9 +299,9 @@ public class MsaWSClient extends Jws2Client
             AlignmentView msa = alignFrame.gatherSequencesForAlignment();
             if (msa != null)
             {
-              new MsaWSClient(service, null, null, true, alignFrame
-                      .getTitle(), msa, withGaps, true, alignFrame
-                      .getViewport().getAlignment().getDataset(),
+              new MsaWSClient(service, null, null, true,
+                      alignFrame.getTitle(), msa, withGaps, true,
+                      alignFrame.getViewport().getAlignment().getDataset(),
                       alignFrame);
             }
 
@@ -308,10 +311,9 @@ public class MsaWSClient extends Jws2Client
         List<WsParamSetI> presets = service.getParamStore().getPresets();
         if (presets != null && presets.size() > 0)
         {
-          JMenu presetlist = new JMenu(
-                  MessageManager.formatMessage(
-                          "label.run_with_preset_params",
-                          new String[] { calcName }));
+          JMenu presetlist = new JMenu(MessageManager.formatMessage(
+                  "label.run_with_preset_params", new String[]
+                  { calcName }));
 
           final int showToolTipFor = ToolTipManager.sharedInstance()
                   .getDismissDelay();
@@ -326,28 +328,24 @@ public class MsaWSClient extends Jws2Client
               @Override
               public void mouseEntered(MouseEvent e)
               {
-                ToolTipManager.sharedInstance().setDismissDelay(
-                        QUICK_TOOLTIP);
+                ToolTipManager.sharedInstance()
+                        .setDismissDelay(QUICK_TOOLTIP);
               }
 
               @Override
               public void mouseExited(MouseEvent e)
               {
-                ToolTipManager.sharedInstance().setDismissDelay(
-                        showToolTipFor);
+                ToolTipManager.sharedInstance()
+                        .setDismissDelay(showToolTipFor);
               }
 
             });
-            String tooltip = JvSwingUtils
-                    .wrapTooltip(
-                            true,
-                            "<strong>"
-                                    + (preset.isModifiable() ? MessageManager
-                                            .getString("label.user_preset")
-                                            : MessageManager
-                                                    .getString("label.service_preset"))
-                                    + "</strong><br/>"
-                                    + preset.getDescription());
+            String tooltip = JvSwingUtils.wrapTooltip(true, "<strong>"
+                    + (preset.isModifiable()
+                            ? MessageManager.getString("label.user_preset")
+                            : MessageManager
+                                    .getString("label.service_preset"))
+                    + "</strong><br/>" + preset.getDescription());
             methodR.setToolTipText(tooltip);
             methodR.addActionListener(new ActionListener()
             {
@@ -362,7 +360,8 @@ public class MsaWSClient extends Jws2Client
                   MsaWSClient msac = new MsaWSClient(service, preset,
                           alignFrame.getTitle(), msa, false, true,
                           alignFrame.getViewport().getAlignment()
-                                  .getDataset(), alignFrame);
+                                  .getDataset(),
+                          alignFrame);
                 }
 
               }
index 2187f46..db6e03f 100644 (file)
@@ -125,9 +125,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI
       int nseqs = 0;
       if (minlen < 0)
       {
-        throw new Error(
-                MessageManager
-                        .getString("error.implementation_error_minlen_must_be_greater_zero"));
+        throw new Error(MessageManager.getString(
+                "error.implementation_error_minlen_must_be_greater_zero"));
       }
       for (int i = 0; i < seqs.length; i++)
       {
@@ -162,8 +161,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI
           String empty = null;
           if (seqs[i].getEnd() >= seqs[i].getStart())
           {
-            empty = (submitGaps) ? seqs[i].getSequenceAsString() : AlignSeq
-                    .extractGaps(jalview.util.Comparison.GapChars,
+            empty = (submitGaps) ? seqs[i].getSequenceAsString()
+                    : AlignSeq.extractGaps(jalview.util.Comparison.GapChars,
                             seqs[i].getSequenceAsString());
           }
           emptySeqs.add(new String[] { newname, empty });
@@ -179,10 +178,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI
     @Override
     public boolean hasResults()
     {
-      if (subjobComplete
-              && isFinished()
-              && (alignment != null || (emptySeqs != null && emptySeqs
-                      .size() > 0)))
+      if (subjobComplete && isFinished() && (alignment != null
+              || (emptySeqs != null && emptySeqs.size() > 0)))
       {
         return true;
       }
@@ -211,7 +208,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI
           for (compbio.data.sequence.FastaSequence seq : alignment
                   .getSequences())
           {
-            alseqs[alseq_l++] = new Sequence(seq.getId(), seq.getSequence());
+            alseqs[alseq_l++] = new Sequence(seq.getId(),
+                    seq.getSequence());
           }
           alseq_gapchar = alignment.getMetadata().getGapchar();
 
@@ -407,8 +405,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI
         {
           for (Argument opt : ((JabaWsParamSet) preset).getjabaArguments())
           {
-            jobProgress.append(opt.getName() + " " + opt.getDefaultValue()
-                    + "\n");
+            jobProgress.append(
+                    opt.getName() + " " + opt.getDefaultValue() + "\n");
           }
         }
       }
@@ -418,8 +416,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI
         // merge arguments with preset's own arguments.
         for (Argument opt : arguments)
         {
-          jobProgress.append(opt.getName() + " " + opt.getDefaultValue()
-                  + "\n");
+          jobProgress.append(
+                  opt.getName() + " " + opt.getDefaultValue() + "\n");
         }
       }
       jobProgress.append("\nJob Output:\n");
@@ -580,8 +578,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI
                     "Exception whilst cancelling " + jobs[job].getJobId(),
                     exc);
           }
-          wsInfo.setProgressText(jobs[job].getJobnum(), OutputHeader
-                  + cancelledMessage + "\n");
+          wsInfo.setProgressText(jobs[job].getJobnum(),
+                  OutputHeader + cancelledMessage + "\n");
         }
         else
         {
@@ -635,8 +633,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI
     do
     {
       j.setLastChunk(lastchunk);
-      ChunkHolder chunk = server
-              .pullExecStatistics(j.getJobId(), lastchunk);
+      ChunkHolder chunk = server.pullExecStatistics(j.getJobId(),
+              lastchunk);
       if (chunk != null)
       {
         changed |= chunk.getChunk().length() > 0;
@@ -663,16 +661,16 @@ class MsaWSThread extends AWS2Thread implements WSClientI
     if (!(job instanceof MsaWSJob))
     {
       throw new Error(MessageManager.formatMessage(
-              "error.implementation_error_msawbjob_called",
-              new String[] { job.getClass().toString() }));
+              "error.implementation_error_msawbjob_called", new String[]
+              { job.getClass().toString() }));
     }
     MsaWSJob j = (MsaWSJob) job;
     if (j.isSubmitted())
     {
       if (Cache.log.isDebugEnabled())
       {
-        Cache.log.debug("Tried to submit an already submitted job "
-                + j.getJobId());
+        Cache.log.debug(
+                "Tried to submit an already submitted job " + j.getJobId());
       }
       return;
     }
@@ -712,14 +710,16 @@ class MsaWSThread extends AWS2Thread implements WSClientI
       {
         throw new Exception(MessageManager.formatMessage(
                 "exception.web_service_returned_null_try_later",
-                new String[] { WsUrl }));
+                new String[]
+                { WsUrl }));
       }
     } catch (compbio.metadata.UnsupportedRuntimeException _lex)
     {
       lex = _lex;
       wsInfo.appendProgressText(MessageManager.formatMessage(
               "info.job_couldnt_be_run_server_doesnt_support_program",
-              new String[] { _lex.getMessage() }));
+              new String[]
+              { _lex.getMessage() }));
       wsInfo.warnUser(_lex.getMessage(),
               MessageManager.getString("warn.service_not_supported"));
       wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
@@ -729,8 +729,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI
     {
       lex = _lex;
       wsInfo.appendProgressText(MessageManager.formatMessage(
-              "info.job_couldnt_be_run_exceeded_hard_limit",
-              new String[] { _lex.getMessage() }));
+              "info.job_couldnt_be_run_exceeded_hard_limit", new String[]
+              { _lex.getMessage() }));
       wsInfo.warnUser(_lex.getMessage(),
               MessageManager.getString("warn.input_is_too_big"));
       wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
@@ -742,16 +742,16 @@ class MsaWSThread extends AWS2Thread implements WSClientI
               MessageManager.getString("warn.invalid_job_param_set"));
       wsInfo.appendProgressText(MessageManager.formatMessage(
               "info.job_couldnt_be_run_incorrect_param_setting",
-              new String[] { _lex.getMessage() }));
+              new String[]
+              { _lex.getMessage() }));
       wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
       wsInfo.setStatus(j.getJobnum(), WebserviceInfo.STATE_STOPPED_ERROR);
     } catch (Error e)
     {
       // For unexpected errors
-      System.err
-              .println(WebServiceName
-                      + "Client: Failed to submit the sequences for alignment (probably a server side problem)\n"
-                      + "When contacting Server:" + WsUrl + "\n");
+      System.err.println(WebServiceName
+              + "Client: Failed to submit the sequences for alignment (probably a server side problem)\n"
+              + "When contacting Server:" + WsUrl + "\n");
       e.printStackTrace(System.err);
       wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
       wsInfo.setStatus(j.getJobnum(),
@@ -759,10 +759,9 @@ class MsaWSThread extends AWS2Thread implements WSClientI
     } catch (Exception e)
     {
       // For unexpected errors
-      System.err
-              .println(WebServiceName
-                      + "Client: Failed to submit the sequences for alignment (probably a server side problem)\n"
-                      + "When contacting Server:" + WsUrl + "\n");
+      System.err.println(WebServiceName
+              + "Client: Failed to submit the sequences for alignment (probably a server side problem)\n"
+              + "When contacting Server:" + WsUrl + "\n");
       e.printStackTrace(System.err);
       wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
       wsInfo.setStatus(j.getJobnum(),
@@ -775,8 +774,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI
         // TODO: JBPNote catch timeout or other fault types explicitly
 
         j.setAllowedServerExceptions(0);
-        wsInfo.appendProgressText(j.getJobnum(), MessageManager
-                .getString("info.failed_to_submit_sequences_for_alignment"));
+        wsInfo.appendProgressText(j.getJobnum(), MessageManager.getString(
+                "info.failed_to_submit_sequences_for_alignment"));
       }
     }
   }
@@ -812,8 +811,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI
             } catch (Exception e)
             {
 
-              Cache.log
-                      .warn("Exception when retrieving remaining Job progress data for job "
+              Cache.log.warn(
+                      "Exception when retrieving remaining Job progress data for job "
                               + msjob.getJobId() + " on server " + WsUrl);
               e.printStackTrace();
               nexcept--;
@@ -851,11 +850,11 @@ class MsaWSThread extends AWS2Thread implements WSClientI
           {
             // job has failed for some reason - probably due to invalid
             // parameters
-            Cache.log
-                    .debug("Results not available for finished job - marking as broken job.",
-                            e);
-            msjob.jobProgress
-                    .append("\nResult not available. Probably due to invalid input or parameter settings. Server error message below:\n\n"
+            Cache.log.debug(
+                    "Results not available for finished job - marking as broken job.",
+                    e);
+            msjob.jobProgress.append(
+                    "\nResult not available. Probably due to invalid input or parameter settings. Server error message below:\n\n"
                             + e.getLocalizedMessage());
             msjob.setjobStatus(JobStatus.FAILED);
           } catch (Exception e)
@@ -877,7 +876,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI
             // wsInfo.appendProgressText(jobs[j].getJobnum(),
             // "\nAlignment Object Method Notes\n");
             // wsInfo.appendProgressText(jobs[j].getJobnum(),
-            // "Calculated with "+alignment.getMetadata().getProgram().toString());
+            // "Calculated with
+            // "+alignment.getMetadata().getProgram().toString());
             // JBPNote The returned files from a webservice could be
             // hidden behind icons in the monitor window that,
             // when clicked, pop up their corresponding data
@@ -887,8 +887,9 @@ class MsaWSThread extends AWS2Thread implements WSClientI
     } catch (Exception ex)
     {
 
-      Cache.log.error("Unexpected exception when processing results for "
-              + alTitle, ex);
+      Cache.log.error(
+              "Unexpected exception when processing results for " + alTitle,
+              ex);
       wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
     }
     if (results > 0)
@@ -1002,8 +1003,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI
   protected void displayInNewFrame(AlignmentI al,
           List<AlignmentOrder> alorders, HiddenColumns hidden)
   {
-    AlignFrame af = new AlignFrame(al, hidden,
-            AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
+    AlignFrame af = new AlignFrame(al, hidden, AlignFrame.DEFAULT_WIDTH,
+            AlignFrame.DEFAULT_HEIGHT);
 
     // initialise with same renderer settings as in parent alignframe.
     af.getFeatureRenderer().transferSettings(this.featureSettings);
@@ -1020,10 +1021,9 @@ class MsaWSThread extends AWS2Thread implements WSClientI
      * SplitFrame with the other pane similarly aligned.
      */
     AlignFrame requestedBy = getRequestingAlignFrame();
-    if (requestedBy != null
-            && requestedBy.getSplitViewContainer() != null
-            && requestedBy.getSplitViewContainer().getComplement(
-                    requestedBy) != null)
+    if (requestedBy != null && requestedBy.getSplitViewContainer() != null
+            && requestedBy.getSplitViewContainer()
+                    .getComplement(requestedBy) != null)
     {
       AlignmentI complement = requestedBy.getSplitViewContainer()
               .getComplement(requestedBy);
@@ -1045,8 +1045,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI
         af2.setTitle(complementTitle);
         String linkedTitle = MessageManager
                 .getString("label.linked_view_title");
-        JInternalFrame splitFrame = new SplitFrame(al.isNucleotide() ? af
-                : af2, al.isNucleotide() ? af2 : af);
+        JInternalFrame splitFrame = new SplitFrame(
+                al.isNucleotide() ? af : af2, al.isNucleotide() ? af2 : af);
         Desktop.addInternalFrame(splitFrame, linkedTitle, -1, -1);
         return;
       }
@@ -1108,8 +1108,9 @@ class MsaWSThread extends AWS2Thread implements WSClientI
       }
       for (int i = 0, l = alorders.size(); i < l; i++)
       {
-        af.addSortByOrderMenuItem(WebServiceName + (names.get(i))
-                + " Ordering", alorders.get(i));
+        af.addSortByOrderMenuItem(
+                WebServiceName + (names.get(i)) + " Ordering",
+                alorders.get(i));
       }
     }
   }
index 62ddd0a..c7fad05 100644 (file)
@@ -93,12 +93,13 @@ public class ParameterUtils
       {
         try
         {
-          o.setDefaultValue(isParameter(param, pseparator) ? getParamValue(
-                  param, pseparator) : param);
+          o.setDefaultValue(isParameter(param, pseparator)
+                  ? getParamValue(param, pseparator)
+                  : param);
         } catch (WrongParameterException e)
         {
-          System.out.println("Problem setting value for the parameter: "
-                  + param);
+          System.out.println(
+                  "Problem setting value for the parameter: " + param);
           e.printStackTrace();
         }
       }
@@ -185,9 +186,8 @@ public class ParameterUtils
     } catch (Exception e)
     {
       e.printStackTrace();
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_error_couldnt_copy_value_constraint"));
+      throw new Error(MessageManager.getString(
+              "error.implementation_error_couldnt_copy_value_constraint"));
     }
   }
 
index 9ca6d2e..80c9ce9 100644 (file)
@@ -189,8 +189,8 @@ public class RNAalifoldClient extends JabawsCalcWorker
       descriptionData = data;
     }
 
-    String[] typenameAndDescription = constructTypenameAndDescription(descriptionData
-            .first());
+    String[] typenameAndDescription = constructTypenameAndDescription(
+            descriptionData.first());
     String typename = typenameAndDescription[0];
     String description = typenameAndDescription[1];
 
@@ -219,15 +219,14 @@ public class RNAalifoldClient extends JabawsCalcWorker
   }
 
   private AlignmentAnnotation constructAnnotationFromScoreHolder(
-          AlignmentAnnotation annotation, String struct, TreeSet<Score> data)
+          AlignmentAnnotation annotation, String struct,
+          TreeSet<Score> data)
   {
     Annotation[] anns = new Annotation[gapMap != null ? gapMap.length + 1
             : struct.length()];
 
-    if (data != null
-            && data.size() > 1
-            && data.first().getMethod()
-                    .equals(AlifoldResult.contactProbabilities.toString()))
+    if (data != null && data.size() > 1 && data.first().getMethod()
+            .equals(AlifoldResult.contactProbabilities.toString()))
     {
 
       // The base pair probabilities are stored in a set in scoreholder. we want
@@ -237,8 +236,8 @@ public class RNAalifoldClient extends JabawsCalcWorker
       {
         // The Score objects contain a set of size one containing the range and
         // an ArrayList<float> of size one containing the probabilty
-        basePairs.put(score.getRanges().first(), new Float(score
-                .getScores().get(0)));
+        basePairs.put(score.getRanges().first(),
+                new Float(score.getScores().get(0)));
       }
 
       for (int i = 0, ri = 0, iEnd = struct.length(); i < iEnd; i++, ri++)
@@ -320,25 +319,24 @@ public class RNAalifoldClient extends JabawsCalcWorker
 
       description = MessageFormat.format(
               "Minimum Free Energy Structure. Energy: {0} = {1} + {2}",
-              score.getScores().get(0), score.getScores().get(1), score
-                      .getScores().get(2));
+              score.getScores().get(0), score.getScores().get(1),
+              score.getScores().get(2));
       typename = "MFE Structure";
     }
-    else if (datatype.equals(AlifoldResult.contactProbabilityStructure
-            .toString()))
+    else if (datatype
+            .equals(AlifoldResult.contactProbabilityStructure.toString()))
     {
-      description = MessageFormat
-              .format("Base Pair Contact Probabilities. "
-                      + "Energy of Ensemble: {0}  Frequency of Ensemble: {1}",
-                      score.getScores().get(0), score.getScores().get(1));
+      description = MessageFormat.format("Base Pair Contact Probabilities. "
+              + "Energy of Ensemble: {0}  Frequency of Ensemble: {1}",
+              score.getScores().get(0), score.getScores().get(1));
       typename = "Contact Probabilities";
     }
     else if (datatype.equals(AlifoldResult.centroidStructure.toString()))
     {
       description = MessageFormat.format(
-              "Centroid Structure. Energy: {0} = {1} + {2}", score
-                      .getScores().get(0), score.getScores().get(1), score
-                      .getScores().get(2));
+              "Centroid Structure. Energy: {0} = {1} + {2}",
+              score.getScores().get(0), score.getScores().get(1),
+              score.getScores().get(2));
       typename = "Centroid Structure";
     }
     else if (datatype.equals(AlifoldResult.stochBTStructure.toString()))
@@ -356,8 +354,8 @@ public class RNAalifoldClient extends JabawsCalcWorker
     else if (datatype.equals(AlifoldResult.MEAStucture.toString()))
     {
       description = MessageFormat.format(
-              "Maximum Expected Accuracy Values: '{' {0} MEA={1} '}", score
-                      .getScores().get(0), score.getScores().get(1));
+              "Maximum Expected Accuracy Values: '{' {0} MEA={1} '}",
+              score.getScores().get(0), score.getScores().get(1));
       typename = "MEA Structure";
     }
     else if (datatype.equals(AlifoldResult.consensusAlignment.toString()))
index 4702686..45bddac 100644 (file)
@@ -93,15 +93,17 @@ public class SequenceAnnotationWSClient extends Jws2Client
         try
         {
           worker = (AbstractJabaCalcWorker) (clientClass
-                  .getConstructor(new Class[] { Jws2Instance.class,
-                      AlignFrame.class, WsParamSetI.class, List.class })
-                  .newInstance(new Object[] { sh, alignFrame, this.preset,
-                      paramset }));
+                  .getConstructor(new Class[]
+                  { Jws2Instance.class, AlignFrame.class, WsParamSetI.class,
+                      List.class })
+                  .newInstance(new Object[]
+                  { sh, alignFrame, this.preset, paramset }));
         } catch (Exception x)
         {
           x.printStackTrace();
           throw new Error(
-                  MessageManager.getString("error.implementation_error"), x);
+                  MessageManager.getString("error.implementation_error"),
+                  x);
         }
         alignFrame.getViewport().getCalcManager().registerWorker(worker);
         alignFrame.getViewport().getCalcManager().startWorker(worker);
@@ -135,11 +137,8 @@ public class SequenceAnnotationWSClient extends Jws2Client
         return;
       }
 
-      alignFrame
-              .getViewport()
-              .getCalcManager()
-              .startWorker(
-                      new AADisorderClient(sh, alignFrame, preset, paramset));
+      alignFrame.getViewport().getCalcManager().startWorker(
+              new AADisorderClient(sh, alignFrame, preset, paramset));
     }
   }
 
@@ -171,8 +170,8 @@ public class SequenceAnnotationWSClient extends Jws2Client
             service.serviceType.length() - 2);
 
     JMenuItem annotservice = new JMenuItem(MessageManager.formatMessage(
-            "label.calcname_with_default_settings",
-            new String[] { calcName }));
+            "label.calcname_with_default_settings", new String[]
+            { calcName }));
     annotservice.addActionListener(new ActionListener()
     {
 
@@ -189,9 +188,8 @@ public class SequenceAnnotationWSClient extends Jws2Client
       // arguments
       annotservice = new JMenuItem(
               MessageManager.getString("label.edit_settings_and_run"));
-      annotservice
-              .setToolTipText(MessageManager
-                      .getString("label.view_and_change_parameters_before_running_calculation"));
+      annotservice.setToolTipText(MessageManager.getString(
+              "label.view_and_change_parameters_before_running_calculation"));
 
       annotservice.addActionListener(new ActionListener()
       {
@@ -204,20 +202,19 @@ public class SequenceAnnotationWSClient extends Jws2Client
       List<WsParamSetI> presets = service.getParamStore().getPresets();
       if (presets != null && presets.size() > 0)
       {
-        JMenu presetlist = new JMenu(MessageManager.formatMessage(
-                "label.run_with_preset", new String[] { calcName }));
+        JMenu presetlist = new JMenu(MessageManager
+                .formatMessage("label.run_with_preset", new String[]
+                { calcName }));
 
         for (final WsParamSetI preset : presets)
         {
           final JMenuItem methodR = new JMenuItem(preset.getName());
-          methodR.setToolTipText(JvSwingUtils.wrapTooltip(
-                  true,
-                  "<strong>"
-                          + (preset.isModifiable() ? MessageManager
-                                  .getString("label.user_preset")
-                                  : MessageManager
-                                          .getString("label.service_preset"))
-                          + "</strong><br/>" + preset.getDescription()));
+          methodR.setToolTipText(JvSwingUtils.wrapTooltip(true, "<strong>"
+                  + (preset.isModifiable()
+                          ? MessageManager.getString("label.user_preset")
+                          : MessageManager
+                                  .getString("label.service_preset"))
+                  + "</strong><br/>" + preset.getDescription()));
           methodR.addActionListener(new ActionListener()
           {
             public void actionPerformed(ActionEvent e)
@@ -248,9 +245,10 @@ public class SequenceAnnotationWSClient extends Jws2Client
             Desktop.instance.showUrl(service.docUrl);
           }
         });
-        annotservice.setToolTipText(JvSwingUtils.wrapTooltip(true,
-                MessageManager.formatMessage("label.view_service_doc_url",
-                        new String[] { service.docUrl, service.docUrl })));
+        annotservice.setToolTipText(
+                JvSwingUtils.wrapTooltip(true, MessageManager.formatMessage(
+                        "label.view_service_doc_url", new String[]
+                        { service.docUrl, service.docUrl })));
         wsmenu.add(annotservice);
       }
     }
index 5f068b0..708787e 100644 (file)
@@ -76,7 +76,8 @@ public class AAConSettings extends jalview.ws.params.AutoCalcSetting
         preset = pr;
         return;
       }
-      List<ArgumentI> oldargs = new ArrayList<ArgumentI>(), newargs = new ArrayList<ArgumentI>();
+      List<ArgumentI> oldargs = new ArrayList<ArgumentI>(),
+              newargs = new ArrayList<ArgumentI>();
       oldargs.addAll(preset.getArguments());
       // need to compare parameters
       for (ArgumentI newparg : pr.getArguments())
@@ -93,23 +94,22 @@ public class AAConSettings extends jalview.ws.params.AutoCalcSetting
         return;
       }
       // Try even harder to migrate arguments.
-      throw new Error(
-              MessageManager
-                      .getString("error.parameter_migration_not_implemented_yet"));
+      throw new Error(MessageManager
+              .getString("error.parameter_migration_not_implemented_yet"));
     }
   }
 
   public List<Argument> getJobArgset()
   {
-    return jobArgset == null ? null : JabaParamStore
-            .getJabafromJwsArgs(jobArgset);
+    return jobArgset == null ? null
+            : JabaParamStore.getJabafromJwsArgs(jobArgset);
   }
 
   public void setJobArgset(List<Argument> jobArgset)
   {
     // TODO: test if parameters valid for service
-    this.jobArgset = jobArgset == null ? null : JabaParamStore
-            .getJwsArgsfromJaba(jobArgset);
+    this.jobArgset = jobArgset == null ? null
+            : JabaParamStore.getJwsArgsfromJaba(jobArgset);
   }
 
   public String getWsParamFile()
index d9f8f46..cbfbd3b 100644 (file)
@@ -95,9 +95,8 @@ public class JabaOption implements jalview.ws.params.OptionI
     } catch (Exception e)
     {
       e.printStackTrace();
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_error_cannot_set_jaba_option"));
+      throw new Error(MessageManager.getString(
+              "error.implementation_error_cannot_set_jaba_option"));
     }
   }
 
index b99c381..df7df6f 100644 (file)
@@ -46,11 +46,10 @@ public class JabaValueConstrain implements ValueConstrainI
     {
       return ValueType.Integer;
     }
-    throw new Error(
-            MessageManager
-                    .formatMessage(
-                            "error.implementation_error_valuetype_doesnt_support_jabaws_type",
-                            new String[] { vc.toString() }));
+    throw new Error(MessageManager.formatMessage(
+            "error.implementation_error_valuetype_doesnt_support_jabaws_type",
+            new String[]
+            { vc.toString() }));
   }
 
   @Override
index 6d2b057..1bfd71d 100644 (file)
@@ -54,9 +54,8 @@ public class JabaWsParamSet implements WsParamSetI
       {
         if (!allJaba(jobParams))
         {
-          throw new Error(
-                  MessageManager
-                          .getString("error.cannot_create_jabaws_param_set"));
+          throw new Error(MessageManager
+                  .getString("error.cannot_create_jabaws_param_set"));
         }
         else
         {
@@ -179,9 +178,8 @@ public class JabaWsParamSet implements WsParamSetI
   {
     if (!allJaba(args))
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.cannot_set_arguments_to_jabaws_param_set"));
+      throw new Error(MessageManager
+              .getString("error.cannot_set_arguments_to_jabaws_param_set"));
     }
     jabaArguments = new ArrayList<Option>();
     for (ArgumentI rg : args)
index 61ff7eb..2f3c298 100644 (file)
@@ -159,7 +159,8 @@ public class Jws2Instance
     }
     throw new Error(MessageManager.formatMessage(
             "error.implementation_error_runner_config_not_available",
-            new String[] { serviceType, service.getClass().toString() }));
+            new String[]
+            { serviceType, service.getClass().toString() }));
   }
 
   @Override
@@ -169,13 +170,11 @@ public class Jws2Instance
     {
       try
       {
-        Closeable svc = (Closeable) service;
-        service = null;
-        svc.close();
-      } catch (Exception e)
+        ((Closeable) service).close();
+      } catch (Throwable t)
       {
+        // ignore
       }
-      ;
     }
     super.finalize();
   }
@@ -204,7 +203,8 @@ public class Jws2Instance
     // this is only valid for Jaba 1.0 - this formula might have to change!
     return hosturl
             + (hosturl.lastIndexOf("/") == (hosturl.length() - 1) ? ""
-                    : "/") + serviceType;
+                    : "/")
+            + serviceType;
   }
 
   private boolean hasParams = false, lookedForParams = false;
index 671b5f1..623b8de 100644 (file)
@@ -37,7 +37,8 @@ public class Jws2InstanceFactory
 
   private static String category_rewrite(String cat_name)
   {
-    return (cat_name != null && cat_name.equals("Prediction")) ? "Secondary Structure Prediction"
+    return (cat_name != null && cat_name.equals("Prediction"))
+            ? "Secondary Structure Prediction"
             : cat_name;
   }
 
index d629f67..515f8f4 100644 (file)
@@ -67,6 +67,7 @@ public interface ParamManager
    * @param hosturl
    * @param jabaParamStore
    */
-  public void registerParser(String hosturl, ParamDatastoreI paramdataStore);
+  public void registerParser(String hosturl,
+          ParamDatastoreI paramdataStore);
 
 }
index eea8f9f..f80ff77 100644 (file)
@@ -33,7 +33,8 @@ public class BooleanOption extends Option implements OptionI
   {
 
     super(name, descr, required, (defVal ? name : ""), (val ? name : ""),
-            Arrays.asList(new String[] { name }), link);
+            Arrays.asList(new String[]
+            { name }), link);
   }
 
 }
index 2f50c6b..fb34e89 100644 (file)
@@ -79,21 +79,21 @@ public class IntegerParameter extends Option implements ParameterI
     min = parm.min;
   }
 
-  public IntegerParameter(String name, String description,
-          boolean required, int defValue, int min, int max)
+  public IntegerParameter(String name, String description, boolean required,
+          int defValue, int min, int max)
   {
-    super(name, description, required, String.valueOf(defValue), null,
-            null, null);
+    super(name, description, required, String.valueOf(defValue), null, null,
+            null);
     defval = defValue;
     this.min = min;
     this.max = max;
   }
 
-  public IntegerParameter(String name, String description,
-          boolean required, int defValue, int value, int min, int max)
+  public IntegerParameter(String name, String description, boolean required,
+          int defValue, int value, int min, int max)
   {
-    super(name, description, required, String.valueOf(defValue), String
-            .valueOf(value), null, null);
+    super(name, description, required, String.valueOf(defValue),
+            String.valueOf(value), null, null);
     defval = defValue;
     this.min = min;
     this.max = max;
index 79b1b30..e2c81a6 100644 (file)
@@ -24,8 +24,8 @@ import jalview.ws.params.OptionI;
 import jalview.ws.params.ParameterI;
 import jalview.ws.params.ValueConstrainI;
 
-public abstract class Parameter extends Option implements OptionI,
-        ParameterI
+public abstract class Parameter extends Option
+        implements OptionI, ParameterI
 {
   ValueConstrainI validator;
 
index d682da1..4d5a2aa 100644 (file)
@@ -111,9 +111,8 @@ public class HttpResultSet extends FileParse
 
     if (en == null)
     {
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_error_need_to_have_httpresponse"));
+      throw new Error(MessageManager.getString(
+              "error.implementation_error_need_to_have_httpresponse"));
     }
     jalview.io.packed.JalviewDataset ds = restJob.newJalviewDataset();
     // Decide how we deal with content.
@@ -155,8 +154,8 @@ public class HttpResultSet extends FileParse
     if (!(en instanceof MultipartEntity))
     {
       // assume content is simple text stream that can be read from
-      String enc = (en.getContentEncoding() == null) ? null : en
-              .getContentEncoding().getValue();
+      String enc = (en.getContentEncoding() == null) ? null
+              : en.getContentEncoding().getValue();
       if (en.getContentType() != null)
       {
         Cache.log.debug("Result Type: " + en.getContentType().toString());
index 69f1d95..88431a6 100644 (file)
@@ -130,13 +130,13 @@ public abstract class InputType
     {
       if (type == null)
       {
-        return new StringBody(utf8.encode(content).asCharBuffer()
-                .toString());
+        return new StringBody(
+                utf8.encode(content).asCharBuffer().toString());
       }
       else
       {
-        return new StringBody(utf8.encode(content).asCharBuffer()
-                .toString(), type, utf8);
+        return new StringBody(
+                utf8.encode(content).asCharBuffer().toString(), type, utf8);
       }
     } catch (Exception ex)
     {
@@ -307,9 +307,10 @@ public abstract class InputType
       {
         // TODO: revise architecture - this is counter intuitive - options with
         // different values to their names are actually parameters
-        rg = (arg.getValue().length() > 0) ? (arg.getValue().equals(
-                arg.getName()) ? arg.getName() : arg.getName() + "='"
-                + arg.getValue() + "'") : arg.getName();
+        rg = (arg.getValue().length() > 0)
+                ? (arg.getValue().equals(arg.getName()) ? arg.getName()
+                        : arg.getName() + "='" + arg.getValue() + "'")
+                : arg.getName();
       }
       if (rg.length() > 0)
       {
@@ -317,7 +318,8 @@ public abstract class InputType
       }
     }
     StringBuffer warnings;
-    if (!configureFromURLtokenString(urltoks, warnings = new StringBuffer()))
+    if (!configureFromURLtokenString(urltoks,
+            warnings = new StringBuffer()))
     {
       throw new InvalidArgumentException(warnings.toString());
     }
@@ -326,8 +328,8 @@ public abstract class InputType
   protected OptionI createMolTypeOption(String name, String descr,
           boolean req, molType curType, molType defType)
   {
-    return new Option(name, descr, req, defType == null ? ""
-            : defType.toString(),
+    return new Option(name, descr, req,
+            defType == null ? "" : defType.toString(),
             curType == null ? "" : curType.toString(),
             molType.toStringValues(), null);
   }
index 27f5271..a71b70d 100644 (file)
@@ -48,8 +48,8 @@ import javax.swing.event.MenuListener;
  * @author JimP
  * 
  */
-public class RestClient extends WSClient implements WSClientI,
-        WSMenuEntryProviderI
+public class RestClient extends WSClient
+        implements WSClientI, WSMenuEntryProviderI
 {
   RestServiceDescription service;
 
@@ -97,9 +97,9 @@ public class RestClient extends WSClient implements WSClientI,
 
   public void setWebserviceInfo(boolean headless)
   {
-    WebServiceJobTitle = MessageManager.formatMessage(
-            "label.webservice_job_title", new String[] {
-                service.details.Action, service.details.Name });
+    WebServiceJobTitle = MessageManager
+            .formatMessage("label.webservice_job_title", new String[]
+            { service.details.Action, service.details.Name });
     WebServiceName = service.details.Name;
     WebServiceReference = "No reference - go to url for more info";
     if (service.details.description != null)
@@ -108,8 +108,8 @@ public class RestClient extends WSClient implements WSClientI,
     }
     if (!headless)
     {
-      wsInfo = new WebserviceInfo(WebServiceJobTitle, WebServiceName + "\n"
-              + WebServiceReference, true);
+      wsInfo = new WebserviceInfo(WebServiceJobTitle,
+              WebServiceName + "\n" + WebServiceReference, true);
       wsInfo.setRenderAsHtml(true);
     }
 
@@ -142,9 +142,9 @@ public class RestClient extends WSClient implements WSClientI,
           final AlignFrame alignFrame)
   {
     JMenuItem submit = new JMenuItem(service.details.Name);
-    submit.setToolTipText(MessageManager.formatMessage(
-            "label.rest_client_submit", new String[] {
-                service.details.Action, service.details.Name }));
+    submit.setToolTipText(MessageManager
+            .formatMessage("label.rest_client_submit", new String[]
+            { service.details.Action, service.details.Name }));
     submit.addActionListener(new ActionListener()
     {
 
@@ -259,43 +259,42 @@ public class RestClient extends WSClient implements WSClientI,
         {
           // intersect groups with selected region
           _input = new AlignmentView(av.getAlignment(),
- av.getAlignment()
-                  .getHiddenColumns(), av.getSelectionGroup(),
-                  av.hasHiddenColumns(), true, true);
+                  av.getAlignment().getHiddenColumns(),
+                  av.getSelectionGroup(), av.hasHiddenColumns(), true,
+                  true);
           viewTitle = MessageManager.formatMessage(
-                  "label.select_visible_region_of",
-                  new String[] {
-                      (av.hasHiddenColumns() ? MessageManager
-                              .getString("label.visible") : ""),
+                  "label.select_visible_region_of", new String[]
+                  { (av.hasHiddenColumns()
+                          ? MessageManager.getString("label.visible")
+                          : ""),
                       af.getTitle() });
         }
         else
         {
           // use selected region to partition alignment
           _input = new AlignmentView(av.getAlignment(),
- av.getAlignment()
-                  .getHiddenColumns(), av.getSelectionGroup(),
-                  av.hasHiddenColumns(), false, true);
+                  av.getAlignment().getHiddenColumns(),
+                  av.getSelectionGroup(), av.hasHiddenColumns(), false,
+                  true);
         }
         viewTitle = MessageManager.formatMessage(
-                "label.select_unselect_visible_regions_from",
-                new String[] {
-                    (av.hasHiddenColumns() ? MessageManager
-                            .getString("label.visible") : ""),
+                "label.select_unselect_visible_regions_from", new String[]
+                { (av.hasHiddenColumns()
+                        ? MessageManager.getString("label.visible")
+                        : ""),
                     af.getTitle() });
       }
       else
       {
         // just take selected region intersection
         _input = new AlignmentView(av.getAlignment(),
- av.getAlignment()
-                .getHiddenColumns(), av.getSelectionGroup(),
-                av.hasHiddenColumns(), true, true);
+                av.getAlignment().getHiddenColumns(),
+                av.getSelectionGroup(), av.hasHiddenColumns(), true, true);
         viewTitle = MessageManager.formatMessage(
-                "label.select_visible_region_of",
-                new String[] {
-                    (av.hasHiddenColumns() ? MessageManager
-                            .getString("label.visible") : ""),
+                "label.select_visible_region_of", new String[]
+                { (av.hasHiddenColumns()
+                        ? MessageManager.getString("label.visible")
+                        : ""),
                     af.getTitle() });
       }
     }
@@ -303,14 +302,16 @@ public class RestClient extends WSClient implements WSClientI,
     {
       // standard alignment view without selection present
       _input = new AlignmentView(av.getAlignment(),
- av.getAlignment()
-              .getHiddenColumns(), null, av.hasHiddenColumns(), false,
-              true);
+              av.getAlignment().getHiddenColumns(), null,
+              av.hasHiddenColumns(), false, true);
       viewTitle = ""
-              + (av.hasHiddenColumns() ? (new StringBuffer(" ")
-                      .append(MessageManager
-                              .getString("label.visible_region_of"))
-                      .toString()) : "") + af.getTitle();
+              + (av.hasHiddenColumns()
+                      ? (new StringBuffer(" ")
+                              .append(MessageManager
+                                      .getString("label.visible_region_of"))
+                              .toString())
+                      : "")
+              + af.getTitle();
     }
 
     RestJobThread jobsthread = new RestJobThread(this);
@@ -328,22 +329,21 @@ public class RestClient extends WSClient implements WSClientI,
     else
     {
       // TODO: try to tell the user why the job couldn't be started.
-      JvOptionPane
-              .showMessageDialog(
-                      Desktop.desktop,
-                      (jobsthread.hasWarnings() ? jobsthread.getWarnings()
-                              : MessageManager
-                                      .getString("label.job_couldnt_be_started_check_input")),
-                      MessageManager
-                              .getString("label.unable_start_web_service_analysis"),
-                      JvOptionPane.WARNING_MESSAGE);
+      JvOptionPane.showMessageDialog(Desktop.desktop,
+              (jobsthread.hasWarnings() ? jobsthread.getWarnings()
+                      : MessageManager.getString(
+                              "label.job_couldnt_be_started_check_input")),
+              MessageManager
+                      .getString("label.unable_start_web_service_analysis"),
+              JvOptionPane.WARNING_MESSAGE);
     }
   }
 
   public static RestClient makeShmmrRestClient()
   {
-    String action = "Analysis", description = "Sequence Harmony and Multi-Relief (Brandt et al. 2010)", name = MessageManager
-            .getString("label.multiharmony");
+    String action = "Analysis",
+            description = "Sequence Harmony and Multi-Relief (Brandt et al. 2010)",
+            name = MessageManager.getString("label.multiharmony");
     Hashtable<String, InputType> iparams = new Hashtable<String, InputType>();
     jalview.ws.rest.params.JobConstant toolp;
     // toolp = new jalview.ws.rest.JobConstant("tool","jalview");
@@ -370,11 +370,9 @@ public class RestClient extends WSClient implements WSClientI,
     iparams.put("groups", sgroups);
     sgroups.token = "groups";
     sgroups.sep = " ";
-    RestServiceDescription shmrService = new RestServiceDescription(
-            action,
-            description,
-            name,
-            "http://zeus.few.vu.nl/programs/shmrwww/index.php?tool=jalview",// ?tool=jalview&mbjob[method]=shmr&mbjob[description]=step1",
+    RestServiceDescription shmrService = new RestServiceDescription(action,
+            description, name,
+            "http://zeus.few.vu.nl/programs/shmrwww/index.php?tool=jalview", // ?tool=jalview&mbjob[method]=shmr&mbjob[description]=step1",
             "?tool=jalview", iparams, true, false, '-');
     // a priori knowledge of the data returned from the service
     shmrService.addResultDatatype(JvDataType.ANNOTATION);
@@ -413,16 +411,16 @@ public class RestClient extends WSClient implements WSClientI,
       try
       {
         for (RestServiceDescription descr : RestServiceDescription
-                .parseDescriptions(jalview.bin.Cache.getDefault(
-                        RSBS_SERVICES,
-                        makeShmmrRestClient().service.toString())))
+                .parseDescriptions(
+                        jalview.bin.Cache.getDefault(RSBS_SERVICES,
+                                makeShmmrRestClient().service.toString())))
         {
           services.add(descr.toString());
         }
       } catch (Exception ex)
       {
-        System.err
-                .println("Serious - RSBS descriptions in user preferences are corrupt!");
+        System.err.println(
+                "Serious - RSBS descriptions in user preferences are corrupt!");
         ex.printStackTrace();
       }
 
index 5fbc303..824af90 100644 (file)
@@ -77,8 +77,8 @@ public class RestJob extends AWsJob
    * @param viscontigs
    *          visible contigs of an alignment view from which _input was derived
    */
-  public RestJob(int jobNum, RestJobThread restJobThread,
-          AlignmentI _input, int[] viscontigs)
+  public RestJob(int jobNum, RestJobThread restJobThread, AlignmentI _input,
+          int[] viscontigs)
   {
     rsd = restJobThread.restClient.service;
     jobnum = jobNum;
@@ -90,8 +90,8 @@ public class RestJob extends AWsJob
     // get sequences for the alignmentI
     // get groups trimmed to alignment columns
     // get any annotation trimmed to start/end columns, too.
-    squniq = jalview.analysis.SeqsetUtils.uniquify(
-            _input.getSequencesArray(), true);
+    squniq = jalview.analysis.SeqsetUtils
+            .uniquify(_input.getSequencesArray(), true);
     // prepare input
     // form alignment+groups+annotation,preprocess and then record references
     // for formatters
@@ -122,8 +122,8 @@ public class RestJob extends AWsJob
           }
           else
           {
-            statMessage = ("Not enough groups defined on the alignment - need at least " + prm
-                    .getValue().min);
+            statMessage = ("Not enough groups defined on the alignment - need at least "
+                    + prm.getValue().min);
           }
         }
       }
index 0592426..acb7904 100644 (file)
@@ -90,8 +90,8 @@ public class RestJobThread extends AWSThread
     {
       jobs = new RestJob[1];
       jobs[0] = new RestJob(0, this,
-              restClient._input.getVisibleAlignment(restClient.service
-                      .getGapCharacter()),
+              restClient._input.getVisibleAlignment(
+                      restClient.service.getGapCharacter()),
               restClient._input.getVisibleContigs());
       // need a function to get a range on a view/alignment and return both
       // annotation, groups and selection subsetted to just that region.
@@ -101,8 +101,8 @@ public class RestJobThread extends AWSThread
     {
       int[] viscontig = restClient._input.getVisibleContigs();
       AlignmentI[] viscontigals = restClient._input
-              .getVisibleContigAlignments(restClient.service
-                      .getGapCharacter());
+              .getVisibleContigAlignments(
+                      restClient.service.getGapCharacter());
       if (viscontigals != null && viscontigals.length > 0)
       {
         jobs = new RestJob[viscontigals.length];
@@ -233,8 +233,8 @@ public class RestJobThread extends AWSThread
       {
         if (input.getValue().validFor(rj))
         {
-          postentity.addPart(input.getKey(), input.getValue()
-                  .formatForInput(rj));
+          postentity.addPart(input.getKey(),
+                  input.getValue().formatForInput(rj));
         }
         else
         {
@@ -289,10 +289,7 @@ public class RestJobThread extends AWSThread
         break;
       case 202:
         rj.statMessage = "<br>Job submitted successfully. Results available at this URL:\n"
-                + "<a href="
-                + rj.getJobId()
-                + "\">"
-                + rj.getJobId()
+                + "<a href=" + rj.getJobId() + "\">" + rj.getJobId()
                 + "</a><br>";
         rj.running = true;
         break;
@@ -305,11 +302,9 @@ public class RestJobThread extends AWSThread
         {
           if (loc.length > 1)
           {
-            Cache.log
-                    .warn("Ignoring additional "
-                            + (loc.length - 1)
-                            + " location(s) provided in response header ( next one is '"
-                            + loc[1].getValue() + "' )");
+            Cache.log.warn("Ignoring additional " + (loc.length - 1)
+                    + " location(s) provided in response header ( next one is '"
+                    + loc[1].getValue() + "' )");
           }
           rj.setJobId(loc[0].getValue());
           rj.setSubmitted(true);
@@ -323,8 +318,8 @@ public class RestJobThread extends AWSThread
         rj.setSubjobComplete(true);
         rj.error = true;
         rj.running = false;
-        completeStatus(rj, response, "" + getStage(stg)
-                + "failed. Reason below:\n");
+        completeStatus(rj, response,
+                "" + getStage(stg) + "failed. Reason below:\n");
         break;
       default:
         // Some other response. Probably need to pop up the content in a window.
@@ -337,16 +332,10 @@ public class RestJobThread extends AWSThread
         rj.setSubmitted(true);
         try
         {
-          completeStatus(
-                  rj,
-                  response,
-                  ""
-                          + getStage(stg)
-                          + " resulted in an unexpected server response.<br/>Url concerned was <a href=\""
-                          + request.getURI()
-                          + "\">"
-                          + request.getURI()
-                          + "</a><br/>Filtered response content below:<br/>");
+          completeStatus(rj, response, "" + getStage(stg)
+                  + " resulted in an unexpected server response.<br/>Url concerned was <a href=\""
+                  + request.getURI() + "\">" + request.getURI()
+                  + "</a><br/>Filtered response content below:<br/>");
         } catch (IOException e)
         {
           Cache.log.debug("IOException when consuming unhandled response",
@@ -484,21 +473,19 @@ public class RestJobThread extends AWSThread
 
         } catch (Error ex)
         {
-          Cache.log.warn("Failed to finish parsing data for job "
-                  + rj.getJobId());
+          Cache.log.warn(
+                  "Failed to finish parsing data for job " + rj.getJobId());
           ex.printStackTrace();
         } catch (Exception ex)
         {
-          Cache.log.warn("Failed to finish parsing data for job "
-                  + rj.getJobId());
+          Cache.log.warn(
+                  "Failed to finish parsing data for job " + rj.getJobId());
           ex.printStackTrace();
         } finally
         {
           rj.error = true;
           rj.statMessage = "Error whilst parsing data for this job.<br>URL for job response is :<a href=\""
-                  + rj.resSet.getUrl()
-                  + "\">"
-                  + rj.resSet.getUrl()
+                  + rj.resSet.getUrl() + "\">" + rj.resSet.getUrl()
                   + "</a><br>";
         }
       }
@@ -736,9 +723,9 @@ public class RestJobThread extends AWSThread
               {
                 destAl = restClient.av.getAlignment();
                 destHCs = restClient.av.getAlignment().getHiddenColumns();
-                resultDest
-                        .add(restClient.isShowResultsInNewView() ? AddDataTo.newView
-                                : AddDataTo.currentView);
+                resultDest.add(restClient.isShowResultsInNewView()
+                        ? AddDataTo.newView
+                        : AddDataTo.currentView);
                 destPanels.add(restClient.recoverAlignPanelForView());
               }
               else
@@ -767,8 +754,8 @@ public class RestJobThread extends AWSThread
               {
                 // TODO: decide if multiple multiple alignments returned by
                 // non-vseparable services are allowed.
-                Cache.log
-                        .warn("dealing with multiple alignment products returned by non-vertically separable service.");
+                Cache.log.warn(
+                        "dealing with multiple alignment products returned by non-vertically separable service.");
               }
               // recover reference to last alignment created for this rest frame
               // ready for extension
@@ -810,8 +797,7 @@ public class RestJobThread extends AWSThread
               destColsel.add(destHCs);
               resultDest.add(AddDataTo.newAlignment);
               throw new Error(
-                      MessageManager
-                              .getString("error.implementation_error")
+                      MessageManager.getString("error.implementation_error")
                               + "TODO: ");
             }
           }
@@ -882,8 +868,8 @@ public class RestJobThread extends AWSThread
                     }
                     else
                     {
-                      Cache.log
-                              .warn("Couldn't resolve original sequence for new sequence.");
+                      Cache.log.warn(
+                              "Couldn't resolve original sequence for new sequence.");
                     }
                   }
                   if (sg.hasSeqrep())
@@ -905,8 +891,8 @@ public class RestJobThread extends AWSThread
                 {
                   // adjust boundaries of recovered group w.r.t. new group being
                   // merged on to original alignment.
-                  int start = sg.getStartRes() + contigs[ncnt], end = sg
-                          .getEndRes() + contigs[ncnt];
+                  int start = sg.getStartRes() + contigs[ncnt],
+                          end = sg.getEndRes() + contigs[ncnt];
                   if (start < exsg.getStartRes())
                   {
                     exsg.setStartRes(start);
@@ -960,8 +946,8 @@ public class RestJobThread extends AWSThread
                   grass = groupNames.get(alan[nrj][an].groupRef.getName());
                   if (grass == null)
                   {
-                    Cache.log
-                            .error("Couldn't relocate group referemce for group "
+                    Cache.log.error(
+                            "Couldn't relocate group referemce for group "
                                     + alan[nrj][an].groupRef.getName());
                   }
                 }
@@ -987,7 +973,8 @@ public class RestJobThread extends AWSThread
                   visan.sequenceRef = sqass;
                   visAlAn.add(visan);
                 }
-                if (contigs[ncnt] + alan[nrj][an].annotations.length > visan.annotations.length)
+                if (contigs[ncnt]
+                        + alan[nrj][an].annotations.length > visan.annotations.length)
                 {
                   // increase width of annotation row
                   Annotation[] newannv = new Annotation[contigs[ncnt]
@@ -1010,8 +997,8 @@ public class RestJobThread extends AWSThread
               {
                 // TODO: process each newick file, lifting over sequence refs to
                 // current alignment, if necessary.
-                Cache.log
-                        .error("Tree recovery from restjob not yet implemented.");
+                Cache.log.error(
+                        "Tree recovery from restjob not yet implemented.");
               }
             }
           }
@@ -1048,9 +1035,9 @@ public class RestJobThread extends AWSThread
     {
       AlignmentI destal;
       HiddenColumns destcs;
-      String alTitle = MessageManager.formatMessage(
-              "label.webservice_job_title_on", new String[] {
-                  restClient.service.details.Action,
+      String alTitle = MessageManager
+              .formatMessage("label.webservice_job_title_on", new String[]
+              { restClient.service.details.Action,
                   restClient.service.details.Name, restClient.viewTitle });
       switch (action)
       {
@@ -1059,8 +1046,8 @@ public class RestJobThread extends AWSThread
         destcs = destColsel.get(als);
         destaf = new AlignFrame(destal, destcs, AlignFrame.DEFAULT_WIDTH,
                 AlignFrame.DEFAULT_HEIGHT);
-        PaintRefresher.Refresh(destaf, destaf.getViewport()
-                .getSequenceSetId());
+        PaintRefresher.Refresh(destaf,
+                destaf.getViewport().getSequenceSetId());
         // todo transfer any feature settings and colouring
         /*
          * destaf.getFeatureRenderer().transferSettings(this.featureSettings);
@@ -1188,8 +1175,8 @@ public class RestJobThread extends AWSThread
           {
             if (start + width < end)
             {
-              blocks[c][s] = sequenceIs[s].getSubSequence(start, start
-                      + width);
+              blocks[c][s] = sequenceIs[s].getSubSequence(start,
+                      start + width);
             }
             else
             {
index 34a1224..5533406 100644 (file)
@@ -92,8 +92,9 @@ public class RestServiceDescription
     boolean diff = (gapCharacter != other.gapCharacter);
     diff |= vseparable != other.vseparable;
     diff |= hseparable != other.hseparable;
-    diff |= !(urlSuffix == null && other.urlSuffix == null || (urlSuffix != null
-            && other.urlSuffix != null && urlSuffix.equals(other.urlSuffix)));
+    diff |= !(urlSuffix == null && other.urlSuffix == null
+            || (urlSuffix != null && other.urlSuffix != null
+                    && urlSuffix.equals(other.urlSuffix)));
     // TODO - robust diff that includes constants and reordering of URL
     // diff |= !(postUrl.equals(other.postUrl));
     // diff |= !inputParams.equals(other.inputParams);
@@ -462,8 +463,8 @@ public class RestServiceDescription
         resultData.add(JvDataType.valueOf(tok = st.nextToken()));
       } catch (NoSuchElementException x)
       {
-        warnings.append("Invalid result type: '" + tok
-                + "' (must be one of: ");
+        warnings.append(
+                "Invalid result type: '" + tok + "' (must be one of: ");
         String sep = "";
         for (JvDataType vl : JvDataType.values())
         {
@@ -491,8 +492,8 @@ public class RestServiceDescription
     ;
     vls.add(new String("gapCharacter='" + gapCharacter + "'"));
     vls.add(new String("returns='" + _genOutputFormatString() + "'"));
-    return StringUtils
-            .arrayToSeparatorList(vls.toArray(new String[0]), ",");
+    return StringUtils.arrayToSeparatorList(vls.toArray(new String[0]),
+            ",");
   }
 
   public String toString()
@@ -557,7 +558,8 @@ public class RestServiceDescription
    * @param p
    * @return
    */
-  protected int parseServiceList(String[] list, StringBuffer warnings, int p)
+  protected int parseServiceList(String[] list, StringBuffer warnings,
+          int p)
   {
     boolean invalid = false;
     // look for the first non-empty position - expect it to be service name
@@ -582,7 +584,8 @@ public class RestServiceDescription
               && list[p + 4].trim().length() > 5)
       {
         urlSuffix = null;
-        invalid |= !configureFromInputParamEncodedUrl(list[p + 4], warnings);
+        invalid |= !configureFromInputParamEncodedUrl(list[p + 4],
+                warnings);
         p += 5;
       }
     }
@@ -683,8 +686,8 @@ public class RestServiceDescription
         iprmparams = iprm.substring(colon + 1);
         iprm = iprm.substring(0, colon);
       }
-      valid = parseTypeString(prms.group(0), tok, iprm, iprmparams,
-              iparams, warnings);
+      valid = parseTypeString(prms.group(0), tok, iprm, iprmparams, iparams,
+              warnings);
     }
     if (valid)
     {
@@ -707,8 +710,7 @@ public class RestServiceDescription
     // TODO - find a better way of maintaining this classlist
     return new Class[] { jalview.ws.rest.params.Alignment.class,
         jalview.ws.rest.params.AnnotationFile.class,
-        SeqGroupIndexVector.class,
-        jalview.ws.rest.params.SeqIdVector.class,
+        SeqGroupIndexVector.class, jalview.ws.rest.params.SeqIdVector.class,
         jalview.ws.rest.params.SeqVector.class,
         jalview.ws.rest.params.Tree.class };
   }
@@ -801,7 +803,8 @@ public class RestServiceDescription
   /**
    * search the input types for an instance of the given class
    * 
-   * @param <validInput.inputType> class1
+   * @param <validInput.inputType>
+   *          class1
    * @return
    */
   public boolean inputInvolves(Class<?> class1)
index b85073f..4426c5f 100644 (file)
@@ -79,11 +79,11 @@ public class Alignment extends InputType
       try
       {
         File fa = File.createTempFile("jvmime", ".fa");
-        PrintWriter pw = new PrintWriter(
-                new OutputStreamWriter(new BufferedOutputStream(
-                        new FileOutputStream(fa)), "UTF-8"));
-        pw.append(new FormatAdapter().formatSequences(format,
-                alignment, jvsuffix));
+        PrintWriter pw = new PrintWriter(new OutputStreamWriter(
+                new BufferedOutputStream(new FileOutputStream(fa)),
+                "UTF-8"));
+        pw.append(new FormatAdapter().formatSequences(format, alignment,
+                jvsuffix));
         pw.close();
         return new FileBody(fa, "text/plain");
       } catch (Exception ex)
@@ -156,8 +156,8 @@ public class Alignment extends InputType
           return true;
         }
       }
-      warnings.append("Invalid alignment format '" + val
-              + "'. Must be one of (");
+      warnings.append(
+              "Invalid alignment format '" + val + "'. Must be one of (");
       for (String fmt : FileFormats.getInstance().getWritableFormats(true))
       {
         warnings.append(" ").append(fmt);
@@ -172,8 +172,8 @@ public class Alignment extends InputType
         return true;
       } catch (Exception x)
       {
-        warnings.append("Invalid molecule type '" + val
-                + "'. Must be one of (");
+        warnings.append(
+                "Invalid molecule type '" + val + "'. Must be one of (");
         for (molType v : molType.values())
         {
           warnings.append(" " + v);
@@ -195,12 +195,12 @@ public class Alignment extends InputType
             "Append jalview style /start-end suffix to ID", false, false,
             writeAsFile, null));
 
-    List<String> writable = FileFormats
-            .getInstance().getWritableFormats(true);
+    List<String> writable = FileFormats.getInstance()
+            .getWritableFormats(true);
     lst.add(new Option("format", "Alignment upload format", true,
-            FileFormat.Fasta.toString(), format.getName(), writable,
+            FileFormat.Fasta.toString(), format.getName(), writable, null));
+    lst.add(createMolTypeOption("type", "Sequence type", false, type,
             null));
-    lst.add(createMolTypeOption("type", "Sequence type", false, type, null));
 
     return lst;
   }
index 5962a91..b610fca 100644 (file)
@@ -71,9 +71,8 @@ public class AnnotationFile extends InputType
     AlignmentI al = rj.getAlignmentForInput(token, molType.MIX);
     if (format.equals(JVANNOT))
     {
-      return new StringBody(
-              new jalview.io.AnnotationFile()
-                      .printAnnotationsForAlignment(al));
+      return new StringBody(new jalview.io.AnnotationFile()
+              .printAnnotationsForAlignment(al));
     }
     else
     {
@@ -83,9 +82,8 @@ public class AnnotationFile extends InputType
                 "Unrecognised format for exporting Annotation (" + format
                         + ")");
       }
-      return new StringBody(
-              new jalview.io.AnnotationFile().printCSVAnnotations(al
-                      .getAlignmentAnnotation()));
+      return new StringBody(new jalview.io.AnnotationFile()
+              .printCSVAnnotations(al.getAlignmentAnnotation()));
     }
   }
 
@@ -135,9 +133,9 @@ public class AnnotationFile extends InputType
   {
     // TODO - consider disregarding base options here.
     List<OptionI> lst = getBaseOptions();
-    lst.add(new Option("format", "Alignment annotation upload format",
-            true, JVANNOT, format, Arrays.asList(new String[] { JVANNOT,
-                CSVANNOT }), null));
+    lst.add(new Option("format", "Alignment annotation upload format", true,
+            JVANNOT, format, Arrays.asList(new String[]
+            { JVANNOT, CSVANNOT }), null));
     return lst;
   }
 }
index 568df7c..1c2cb42 100644 (file)
@@ -80,8 +80,9 @@ public class JobConstant extends InputType
         prm.add(URLEncoder.encode(value, "UTF-8"));
       } catch (UnsupportedEncodingException ex)
       {
-        throw new Error(MessageManager.formatMessage(
-                "error.couldnt_encode_as_utf8", new String[] { value }), ex);
+        throw new Error(MessageManager
+                .formatMessage("error.couldnt_encode_as_utf8", new String[]
+                { value }), ex);
 
       }
     }
@@ -100,7 +101,8 @@ public class JobConstant extends InputType
   {
     if (tokenstring.size() > 1)
     {
-      warnings.append("IMPLEMENTATION ERROR: Constant POST parameters cannot have more than one value.");
+      warnings.append(
+              "IMPLEMENTATION ERROR: Constant POST parameters cannot have more than one value.");
       return false;
     }
     if (tokenstring.size() == 1)
@@ -114,7 +116,8 @@ public class JobConstant extends InputType
   public boolean configureProperty(String tok, String val,
           StringBuffer warnings)
   {
-    warnings.append("IMPLEMENTATION ERROR: No Properties to configure for a Constant parameter.");
+    warnings.append(
+            "IMPLEMENTATION ERROR: No Properties to configure for a Constant parameter.");
     return false;
   }
 
index 8306873..dcb7fab 100644 (file)
@@ -48,8 +48,8 @@ import org.apache.http.entity.mime.content.StringBody;
  * @author JimP
  * 
  */
-public class SeqGroupIndexVector extends InputType implements
-        AlignmentProcessor
+public class SeqGroupIndexVector extends InputType
+        implements AlignmentProcessor
 {
   public SeqGroupIndexVector()
   {
@@ -99,12 +99,10 @@ public class SeqGroupIndexVector extends InputType implements
       {
         if (sg.getSize() < minsize)
         {
-          throw new NoValidInputDataException(
-                  MessageManager
-                          .formatMessage(
-                                  "exception.notvaliddata_group_contains_less_than_min_seqs",
-                                  new String[] { Integer.valueOf(minsize)
-                                          .toString() }));
+          throw new NoValidInputDataException(MessageManager.formatMessage(
+                  "exception.notvaliddata_group_contains_less_than_min_seqs",
+                  new String[]
+                  { Integer.valueOf(minsize).toString() }));
         }
         // TODO: refactor to sequenceGroup for efficiency -
         // getAlignmentRowInterval(AlignmentI al)
@@ -261,8 +259,8 @@ public class SeqGroupIndexVector extends InputType implements
         return true;
       } catch (Exception x)
       {
-        warnings.append("Invalid molecule type '" + val
-                + "'. Must be one of (");
+        warnings.append(
+                "Invalid molecule type '" + val + "'. Must be one of (");
         for (molType v : molType.values())
         {
           warnings.append(" " + v);
@@ -279,8 +277,8 @@ public class SeqGroupIndexVector extends InputType implements
     List<OptionI> lst = getBaseOptions();
     lst.add(new Option("sep",
             "Separator character between elements of vector", true, ",",
-            sep, Arrays.asList(new String[] { " ", ",", ";", "\t", "|" }),
-            null));
+            sep, Arrays.asList(new String[]
+            { " ", ",", ";", "\t", "|" }), null));
     lst.add(new IntegerParameter("minsize",
             "Minimum size of partition allowed by service", true, 1,
             minsize, 1, 0));
index ba573a6..0b19629 100644 (file)
@@ -109,8 +109,8 @@ public class SeqIdVector extends InputType
         return true;
       } catch (Exception x)
       {
-        warnings.append("Invalid molecule type '" + val
-                + "'. Must be one of (");
+        warnings.append(
+                "Invalid molecule type '" + val + "'. Must be one of (");
         for (molType v : molType.values())
         {
           warnings.append(" " + v);
@@ -127,9 +127,10 @@ public class SeqIdVector extends InputType
     List<OptionI> lst = getBaseOptions();
     lst.add(new Option("sep",
             "Separator character between elements of vector", true, ",",
-            sep, Arrays.asList(new String[] { " ", ",", ";", "\t", "|" }),
+            sep, Arrays.asList(new String[]
+            { " ", ",", ";", "\t", "|" }), null));
+    lst.add(createMolTypeOption("type", "Sequence type", false, type,
             null));
-    lst.add(createMolTypeOption("type", "Sequence type", false, type, null));
     return lst;
   }
 }
index cbd73dd..55ca3ff 100644 (file)
@@ -65,7 +65,7 @@ public class SeqVector extends InputType
       {
         idvector.append(sep);
       }
-      idvector.append(seq.getSequence());
+      idvector.append(seq.getSequenceAsString());
     }
     return new StringBody(idvector.toString());
   }
@@ -107,8 +107,8 @@ public class SeqVector extends InputType
         return true;
       } catch (Exception x)
       {
-        warnings.append("Invalid molecule type '" + val
-                + "'. Must be one of (");
+        warnings.append(
+                "Invalid molecule type '" + val + "'. Must be one of (");
         for (molType v : molType.values())
         {
           warnings.append(" " + v);
@@ -125,8 +125,8 @@ public class SeqVector extends InputType
     List<OptionI> lst = getBaseOptions();
     lst.add(new Option("sep",
             "Separator character between elements of vector", true, ",",
-            sep, Arrays.asList(new String[] { " ", ",", ";", "\t", "|" }),
-            null));
+            sep, Arrays.asList(new String[]
+            { " ", ",", ";", "\t", "|" }), null));
     lst.add(createMolTypeOption("type", "Sequence type", false, type,
             molType.MIX));
 
index 5baa61f..af8881c 100644 (file)
@@ -53,9 +53,8 @@ public class Tree extends InputType
     /*
      * rj.getTreeForInput(token); return new StringBody(new )
      */
-    throw new Error(
-            MessageManager
-                    .getString("error.tree_inputtype_not_yet_implemented"));
+    throw new Error(MessageManager
+            .getString("error.tree_inputtype_not_yet_implemented"));
     // return null;
   }
 
index 31168b4..9284f82 100644 (file)
@@ -98,8 +98,8 @@ public class ASequenceFetcher
     {
       return null;
     }
-    String[] sf = fetchableDbs.keySet().toArray(
-            new String[fetchableDbs.size()]);
+    String[] sf = fetchableDbs.keySet()
+            .toArray(new String[fetchableDbs.size()]);
     return sf;
   }
 
@@ -126,15 +126,16 @@ public class ASequenceFetcher
    */
   public SequenceI[] getSequences(List<DBRefEntry> refs, boolean dna)
   {
-    Vector<SequenceI> rseqs = new Vector<SequenceI>();
-    Hashtable<String, List<String>> queries = new Hashtable<String, List<String>>();
+    Vector<SequenceI> rseqs = new Vector<>();
+    Hashtable<String, List<String>> queries = new Hashtable<>();
     for (DBRefEntry ref : refs)
     {
-      if (!queries.containsKey(ref.getSource()))
+      String canonical = DBRefUtils.getCanonicalName(ref.getSource());
+      if (!queries.containsKey(canonical))
       {
-        queries.put(ref.getSource(), new ArrayList<String>());
+        queries.put(canonical, new ArrayList<String>());
       }
-      List<String> qset = queries.get(ref.getSource());
+      List<String> qset = queries.get(canonical);
       if (!qset.contains(ref.getAccessionId()))
       {
         qset.add(ref.getAccessionId());
@@ -154,14 +155,14 @@ public class ASequenceFetcher
         continue;
       }
 
-      Stack<String> queriesLeft = new Stack<String>();
+      Stack<String> queriesLeft = new Stack<>();
       queriesLeft.addAll(query);
 
       List<DbSourceProxy> proxies = getSourceProxy(db);
       for (DbSourceProxy fetcher : proxies)
       {
-        List<String> queriesMade = new ArrayList<String>();
-        HashSet<String> queriesFound = new HashSet<String>();
+        List<String> queriesMade = new ArrayList<>();
+        HashSet<String> queriesFound = new HashSet<>();
         try
         {
           if (fetcher.isDnaCoding() != dna)
@@ -190,8 +191,8 @@ public class ASequenceFetcher
               seqset = fetcher.getSequenceRecords(qsb.toString());
             } catch (Exception ex)
             {
-              System.err.println("Failed to retrieve the following from "
-                      + db);
+              System.err.println(
+                      "Failed to retrieve the following from " + db);
               System.err.println(qsb);
               ex.printStackTrace(System.err);
             }
@@ -204,8 +205,9 @@ public class ASequenceFetcher
                 for (int is = 0; is < seqs.length; is++)
                 {
                   rseqs.addElement(seqs[is]);
-                  List<DBRefEntry> frefs = DBRefUtils.searchRefs(seqs[is]
-                          .getDBRefs(), new DBRefEntry(db, null, null));
+                  List<DBRefEntry> frefs = DBRefUtils.searchRefs(
+                          seqs[is].getDBRefs(),
+                          new DBRefEntry(db, null, null));
                   for (DBRefEntry dbr : frefs)
                   {
                     queriesFound.add(dbr.getAccessionId());
@@ -218,8 +220,8 @@ public class ASequenceFetcher
               {
                 if (fetcher.getRawRecords() != null)
                 {
-                  System.out.println("# Retrieved from " + db + ":"
-                          + qsb.toString());
+                  System.out.println(
+                          "# Retrieved from " + db + ":" + qsb.toString());
                   StringBuffer rrb = fetcher.getRawRecords();
                   /*
                    * for (int rr = 0; rr<rrb.length; rr++) {
@@ -275,8 +277,8 @@ public class ASequenceFetcher
           Exception ex)
   {
 
-    System.err.println("Failed to retrieve the following references from "
-            + db);
+    System.err.println(
+            "Failed to retrieve the following references from " + db);
     int n = 0;
     for (String qv : queriesMade)
     {
@@ -305,13 +307,13 @@ public class ASequenceFetcher
     Map<String, DbSourceProxy> dblist = fetchableDbs.get(db);
     if (dblist == null)
     {
-      return new ArrayList<DbSourceProxy>();
+      return new ArrayList<>();
     }
 
     /*
      * sort so that primary sources precede secondary
      */
-    List<DbSourceProxy> dbs = new ArrayList<DbSourceProxy>(dblist.values());
+    List<DbSourceProxy> dbs = new ArrayList<>(dblist.values());
     Collections.sort(dbs, proxyComparator);
     return dbs;
   }
@@ -338,10 +340,8 @@ public class ASequenceFetcher
     } catch (Exception e)
     {
       // Serious problems if this happens.
-      throw new Error(
-              MessageManager
-                      .getString("error.dbrefsource_implementation_exception"),
-              e);
+      throw new Error(MessageManager
+              .getString("error.dbrefsource_implementation_exception"), e);
     }
     addDbRefSourceImpl(proxy);
   }
@@ -358,14 +358,14 @@ public class ASequenceFetcher
     {
       if (fetchableDbs == null)
       {
-        fetchableDbs = new Hashtable<String, Map<String, DbSourceProxy>>();
+        fetchableDbs = new Hashtable<>();
       }
-      Map<String, DbSourceProxy> slist = fetchableDbs.get(proxy
-              .getDbSource());
+      Map<String, DbSourceProxy> slist = fetchableDbs
+              .get(proxy.getDbSource());
       if (slist == null)
       {
         fetchableDbs.put(proxy.getDbSource(),
-                slist = new Hashtable<String, DbSourceProxy>());
+                slist = new Hashtable<>());
       }
       slist.put(proxy.getDbName(), proxy);
     }
@@ -374,25 +374,25 @@ public class ASequenceFetcher
   /**
    * select sources which are implemented by instances of the given class
    * 
-   * @param class that implements DbSourceProxy
+   * @param class
+   *          that implements DbSourceProxy
    * @return null or vector of source names for fetchers
    */
   public String[] getDbInstances(Class class1)
   {
     if (!DbSourceProxy.class.isAssignableFrom(class1))
     {
-      throw new Error(
-              MessageManager
-                      .formatMessage(
-                              "error.implementation_error_dbinstance_must_implement_interface",
-                              new String[] { class1.toString() }));
+      throw new Error(MessageManager.formatMessage(
+              "error.implementation_error_dbinstance_must_implement_interface",
+              new String[]
+              { class1.toString() }));
     }
     if (fetchableDbs == null)
     {
       return null;
     }
     String[] sources = null;
-    Vector<String> src = new Vector<String>();
+    Vector<String> src = new Vector<>();
     Enumeration<String> dbs = fetchableDbs.keys();
     while (dbs.hasMoreElements())
     {
@@ -414,7 +414,7 @@ public class ASequenceFetcher
 
   public DbSourceProxy[] getDbSourceProxyInstances(Class class1)
   {
-    List<DbSourceProxy> prlist = new ArrayList<DbSourceProxy>();
+    List<DbSourceProxy> prlist = new ArrayList<>();
     for (String fetchable : getSupportedDb())
     {
       for (DbSourceProxy pr : getSourceProxy(fetchable))
index 2fcf501..ab4644e 100644 (file)
@@ -99,8 +99,7 @@ public abstract class DbSourceProxyImpl implements DbSourceProxy
     if (format != null)
     {
       sequences = new FormatAdapter().readFile(result.toString(),
-              DataSourceType.PASTE,
-              format);
+              DataSourceType.PASTE, format);
     }
     return sequences;
   }
index 4675fb7..f7cedf0 100644 (file)
@@ -49,8 +49,9 @@ public class MappingOutputPojo
 
   public void setSeqName(String seqName)
   {
-    this.seqName = (seqName.length() > MAX_ID_LENGTH) ? seqName.substring(
-            0, MAX_ID_LENGTH) : seqName;
+    this.seqName = (seqName.length() > MAX_ID_LENGTH)
+            ? seqName.substring(0, MAX_ID_LENGTH)
+            : seqName;
   }
 
   public String getSeqResidue()
@@ -90,8 +91,9 @@ public class MappingOutputPojo
 
   public void setStrName(String strName)
   {
-    this.strName = (strName.length() > MAX_ID_LENGTH) ? strName.substring(
-            0, MAX_ID_LENGTH) : strName;
+    this.strName = (strName.length() > MAX_ID_LENGTH)
+            ? strName.substring(0, MAX_ID_LENGTH)
+            : strName;
   }
 
   public String getStrResidue()
index 2ff4a8b..68af7c3 100644 (file)
@@ -128,8 +128,8 @@ public class SiftsClient implements SiftsClientI
 
   private enum ResidueDetailType
   {
-    NAME_SEC_STRUCTURE("nameSecondaryStructure"), CODE_SEC_STRUCTURE(
-            "codeSecondaryStructure"), ANNOTATION("Annotation");
+    NAME_SEC_STRUCTURE("nameSecondaryStructure"),
+    CODE_SEC_STRUCTURE("codeSecondaryStructure"), ANNOTATION("Annotation");
     private String code;
 
     private ResidueDetailType(String code)
@@ -261,8 +261,9 @@ public class SiftsClient implements SiftsClientI
     try
     {
       attr = Files.readAttributes(filePath, BasicFileAttributes.class);
-      diffInDays = (int) ((new Date().getTime() - attr.lastModifiedTime()
-              .toMillis()) / (1000 * 60 * 60 * 24));
+      diffInDays = (int) ((new Date().getTime()
+              - attr.lastModifiedTime().toMillis())
+              / (1000 * 60 * 60 * 24));
       // System.out.println("Diff in days : " + diffInDays);
     } catch (IOException e)
     {
@@ -279,8 +280,8 @@ public class SiftsClient implements SiftsClientI
    * @throws SiftsException
    * @throws IOException
    */
-  public static File downloadSiftsFile(String pdbId) throws SiftsException,
-          IOException
+  public static File downloadSiftsFile(String pdbId)
+          throws SiftsException, IOException
   {
     if (pdbId.contains(".cif"))
     {
@@ -311,8 +312,8 @@ public class SiftsClient implements SiftsClientI
     }
     outputStream.close();
     inputStream.close();
-//    System.out.println(">>> File downloaded : " + downloadedSiftsFile
-//            + " took " + (System.currentTimeMillis() - now) + "ms");
+    // System.out.println(">>> File downloaded : " + downloadedSiftsFile
+    // + " took " + (System.currentTimeMillis() - now) + "ms");
     return new File(downloadedSiftsFile);
   }
 
@@ -360,11 +361,11 @@ public class SiftsClient implements SiftsClientI
       {
         continue;
       }
-      String canonicalSource = DBRefUtils.getCanonicalName(dbRef
-              .getSource());
+      String canonicalSource = DBRefUtils
+              .getCanonicalName(dbRef.getSource());
       if (isValidDBRefEntry(dbRef)
-              && (canonicalSource.equalsIgnoreCase(DBRefSource.UNIPROT) || canonicalSource
-                      .equalsIgnoreCase(DBRefSource.PDB)))
+              && (canonicalSource.equalsIgnoreCase(DBRefSource.UNIPROT)
+                      || canonicalSource.equalsIgnoreCase(DBRefSource.PDB)))
       {
         return dbRef;
       }
@@ -511,8 +512,9 @@ public class SiftsClient implements SiftsClientI
       int orignalSeqStart = seq.getStart();
       if (orignalSeqStart >= 1)
       {
-        int subSeqStart = (seqStart >= orignalSeqStart) ? seqStart
-                - orignalSeqStart : 0;
+        int subSeqStart = (seqStart >= orignalSeqStart)
+                ? seqStart - orignalSeqStart
+                : 0;
         int subSeqEnd = seqEnd - (orignalSeqStart - 1);
         subSeqEnd = originalSeq.length() < subSeqEnd ? originalSeq.length()
                 : subSeqEnd;
@@ -573,12 +575,11 @@ public class SiftsClient implements SiftsClientI
           {
             pdbRefDb = cRefDb;
           }
-          if (cRefDb.getDbCoordSys()
-                  .equalsIgnoreCase(seqCoordSys.getName())
+          if (cRefDb.getDbCoordSys().equalsIgnoreCase(seqCoordSys.getName())
                   && isAccessionMatched(cRefDb.getDbAccessionId()))
           {
-            currSeqIndex = getLeadingIntegerValue(
-                    cRefDb.getDbResNum(), UNASSIGNED);
+            currSeqIndex = getLeadingIntegerValue(cRefDb.getDbResNum(),
+                    UNASSIGNED);
             if (pdbRefDb != null)
             {
               break;// exit loop if pdb and uniprot are already found
@@ -592,8 +593,9 @@ public class SiftsClient implements SiftsClientI
         if (currSeqIndex >= seq.getStart() && currSeqIndex <= seq.getEnd())
         {
 
-          int resNum = (pdbRefDb == null) ? getLeadingIntegerValue(
-                  residue.getDbResNum(), UNASSIGNED)
+          int resNum = (pdbRefDb == null)
+                  ? getLeadingIntegerValue(residue.getDbResNum(),
+                          UNASSIGNED)
                   : getLeadingIntegerValue(pdbRefDb.getDbResNum(),
                           UNASSIGNED);
 
@@ -610,8 +612,9 @@ public class SiftsClient implements SiftsClientI
             omitNonObserved.add(currSeqIndex);
             ++nonObservedShiftIndex;
           }
-          mapping.put(currSeqIndex - nonObservedShiftIndex, new int[] {
-              Integer.valueOf(resNum), UNASSIGNED });
+          mapping.put(currSeqIndex - nonObservedShiftIndex,
+                  new int[]
+                  { Integer.valueOf(resNum), UNASSIGNED });
         }
       }
     }
@@ -640,7 +643,6 @@ public class SiftsClient implements SiftsClientI
     return failValue;
   }
 
-
   /**
    * 
    * @param chainId
@@ -815,7 +817,8 @@ public class SiftsClient implements SiftsClientI
    */
   public Entity getEntityByMostOptimalMatchedId(String chainId)
   {
-    // System.out.println("---> advanced greedy entityId matching block entered..");
+    // System.out.println("---> advanced greedy entityId matching block
+    // entered..");
     List<Entity> entities = siftsEntry.getEntity();
     SiftsEntitySortPojo[] sPojo = new SiftsEntitySortPojo[entities.size()];
     int count = 0;
@@ -871,8 +874,8 @@ public class SiftsClient implements SiftsClientI
     return null;
   }
 
-  private class SiftsEntitySortPojo implements
-          Comparable<SiftsEntitySortPojo>
+  private class SiftsEntitySortPojo
+          implements Comparable<SiftsEntitySortPojo>
   {
     public String entityId;
 
@@ -901,8 +904,7 @@ public class SiftsClient implements SiftsClientI
 
     private int nonObservedShiftIndex;
 
-    public SegmentHelperPojo(SequenceI seq,
-            HashMap<Integer, int[]> mapping,
+    public SegmentHelperPojo(SequenceI seq, HashMap<Integer, int[]> mapping,
             TreeMap<Integer, String> resNumMap,
             List<Integer> omitNonObserved, int nonObservedShiftIndex)
     {
@@ -989,8 +991,8 @@ public class SiftsClient implements SiftsClientI
     // output mappings
     StringBuilder output = new StringBuilder(512);
     output.append(NEWLINE);
-    output.append("Sequence \u27f7 Structure mapping details").append(
-            NEWLINE);
+    output.append("Sequence \u27f7 Structure mapping details")
+            .append(NEWLINE);
     output.append("Method: SIFTS");
     output.append(NEWLINE).append(NEWLINE);
 
@@ -1013,8 +1015,8 @@ public class SiftsClient implements SiftsClientI
     for (int j = 0; j < nochunks; j++)
     {
       // Print the first aligned sequence
-      output.append(new Format("%" + (maxid) + "s").form(seqName)).append(
-              " ");
+      output.append(new Format("%" + (maxid) + "s").form(seqName))
+              .append(" ");
 
       for (int i = 0; i < len; i++)
       {
@@ -1086,8 +1088,8 @@ public class SiftsClient implements SiftsClientI
     {
       throw new SiftsException(">>> Low PID detected for SIFTs mapping...");
     }
-    output.append("Length of alignment = " + seqRes.length()).append(
-            NEWLINE);
+    output.append("Length of alignment = " + seqRes.length())
+            .append(NEWLINE);
     output.append(new Format("Percentage ID = %2.2f").form(pid));
     return output;
   }
index dcd861a..448edd9 100644 (file)
@@ -79,8 +79,8 @@ public class UrlDownloadClient
         }
       } catch (IOException e)
       {
-        System.out
-                .println("Exception while closing download file output stream: "
+        System.out.println(
+                "Exception while closing download file output stream: "
                         + e.getMessage());
       }
       try
@@ -92,7 +92,7 @@ public class UrlDownloadClient
       } catch (IOException e)
       {
         System.out.println("Exception while closing download channel: "
-                        + e.getMessage());
+                + e.getMessage());
       }
       try
       {
@@ -103,7 +103,7 @@ public class UrlDownloadClient
       } catch (IOException e)
       {
         System.out.println("Exception while deleting download temp file: "
-                        + e.getMessage());
+                + e.getMessage());
       }
     }
   }
index 7132939..defcdbc 100644 (file)
@@ -36,6 +36,7 @@ import jalview.schemes.TaylorColourScheme;
 import jalview.structure.StructureImportSettings;
 
 import java.awt.Color;
+import java.util.List;
 import java.util.Vector;
 
 import org.testng.annotations.BeforeClass;
@@ -258,19 +259,19 @@ public class PDBChainTest
     /*
      * check sequence features
      */
-    SequenceFeature[] sfs = c.sequence.getSequenceFeatures();
-    assertEquals(3, sfs.length);
-    assertEquals("RESNUM", sfs[0].type);
-    assertEquals("MET:4 1gaqA", sfs[0].description);
-    assertEquals(4, sfs[0].begin);
-    assertEquals(4, sfs[0].end);
-    assertEquals("RESNUM", sfs[0].type);
-    assertEquals("LYS:5 1gaqA", sfs[1].description);
-    assertEquals(5, sfs[1].begin);
-    assertEquals(5, sfs[1].end);
-    assertEquals("LEU:6 1gaqA", sfs[2].description);
-    assertEquals(6, sfs[2].begin);
-    assertEquals(6, sfs[2].end);
+    List<SequenceFeature> sfs = c.sequence.getSequenceFeatures();
+    assertEquals(3, sfs.size());
+    assertEquals("RESNUM", sfs.get(0).type);
+    assertEquals("MET:4 1gaqA", sfs.get(0).description);
+    assertEquals(4, sfs.get(0).begin);
+    assertEquals(4, sfs.get(0).end);
+    assertEquals("RESNUM", sfs.get(0).type);
+    assertEquals("LYS:5 1gaqA", sfs.get(1).description);
+    assertEquals(5, sfs.get(1).begin);
+    assertEquals(5, sfs.get(1).end);
+    assertEquals("LEU:6 1gaqA", sfs.get(2).description);
+    assertEquals(6, sfs.get(2).begin);
+    assertEquals(6, sfs.get(2).end);
   }
 
   private Atom makeAtom(int resnum, String name, String resname)
index 3187fd9..9d3877c 100644 (file)
@@ -27,39 +27,25 @@ import jalview.datamodel.SequenceI;
 import jalview.gui.JvOptionPane;
 import jalview.io.FastaFile;
 
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintStream;
 import java.util.Arrays;
 import java.util.Random;
 
 import org.testng.annotations.BeforeClass;
 
 /**
- * Generates, and outputs in Fasta format, a random DNA alignment for given
+ * Generates, and outputs in Fasta format, a random peptide or nucleotide alignment for given
  * sequence length and count. Will regenerate the same alignment each time if
  * the same random seed is used (so may be used for reproducible unit tests).
  * Not guaranteed to reproduce the same results between versions, as the rules
  * may get tweaked to produce more 'realistic' results.
  * 
- * Arguments:
- * <ul>
- * <li>length (number of bases in each sequence)</li>
- * <li>height (number of sequences)</li>
- * <li>a whole number random seed</li>
- * <li>percentage of gaps to include (0-100)</li>
- * <li>percentage chance of variation of each position (0-100)</li>
- * </ul>
- * 
  * @author gmcarstairs
- *
  */
 public class AlignmentGenerator
 {
-  @BeforeClass(alwaysRun = true)
-  public void setUpJvOptionPane()
-  {
-    JvOptionPane.setInteractiveMode(false);
-    JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
-  }
-
   private static final char GAP = '-';
 
   private static final char ZERO = '0';
@@ -72,51 +58,76 @@ public class AlignmentGenerator
 
   private Random random;
 
+  private PrintStream ps;
 
   /**
-   * Outputs a DNA 'alignment' where each position is a random choice from
-   * 'GTCA-'.
+   * Outputs a pseudo-randomly generated nucleotide or peptide alignment
+   * Arguments:
+   * <ul>
+   * <li>n (for nucleotide) or p (for peptide)</li>
+   * <li>length (number of bases in each sequence)</li>
+   * <li>height (number of sequences)</li>
+   * <li>a whole number random seed</li>
+   * <li>percentage of gaps to include (0-100)</li>
+   * <li>percentage chance of variation of each position (0-100)</li>
+   * <li>(optional) path to a file to write the alignment to</li>
+   * </ul>
+   * 
    * 
    * @param args
+   * @throws FileNotFoundException
    */
-  public static void main(String[] args)
+  public static void main(String[] args) throws FileNotFoundException
   {
-    if (args.length != 6)
+    if (args.length != 6 && args.length != 7)
     {
       usage();
       return;
     }
+
+    PrintStream ps = System.out;
+    if (args.length == 7)
+    {
+      ps = new PrintStream(new File(args[6]));
+    }
+
     boolean nucleotide = args[0].toLowerCase().startsWith("n");
     int width = Integer.parseInt(args[1]);
     int height = Integer.parseInt(args[2]);
     long randomSeed = Long.valueOf(args[3]);
     int gapPercentage = Integer.valueOf(args[4]);
     int changePercentage = Integer.valueOf(args[5]);
-    AlignmentI al = new AlignmentGenerator(nucleotide).generate(width,
-            height,
-            randomSeed, gapPercentage, changePercentage);
 
-    System.out.println("; " + height + " sequences of " + width
+    ps.println("; " + height + " sequences of " + width
             + " bases with " + gapPercentage + "% gaps and "
             + changePercentage + "% mutations (random seed = " + randomSeed
             + ")");
-    System.out.println(new FastaFile().print(al.getSequencesArray(), true));
+
+    new AlignmentGenerator(nucleotide, ps).generate(width, height,
+            randomSeed, gapPercentage, changePercentage);
+
+    if (ps != System.out)
+    {
+      ps.close();
+    }
   }
 
   /**
-   * Print parameter help.
+   * Prints parameter help
    */
   private static void usage()
   {
     System.out.println("Usage:");
     System.out.println("arg0: n (for nucleotide) or p (for peptide)");
     System.out.println("arg1: number of (non-gap) bases per sequence");
-    System.out.println("arg2: number sequences");
+    System.out.println("arg2: number of sequences");
     System.out
             .println("arg3: an integer as random seed (same seed = same results)");
     System.out.println("arg4: percentage of gaps to (randomly) generate");
     System.out
             .println("arg5: percentage of 'mutations' to (randomly) generate");
+    System.out
+            .println("arg6: (optional) path to output file (default is sysout)");
     System.out.println("Example: AlignmentGenerator n 12 15 387 10 5");
     System.out
             .println("- 15 nucleotide sequences of 12 bases each, approx 10% gaps and 5% mutations, random seed = 387");
@@ -124,16 +135,28 @@ public class AlignmentGenerator
   }
 
   /**
-   * Constructor that sets nucleotide or peptide symbol set
+   * Constructor that sets nucleotide or peptide symbol set, and also writes the
+   * generated alignment to sysout
    */
   public AlignmentGenerator(boolean nuc)
   {
-    BASES = nuc ? NUCS : PEPS;
+    this(nuc, System.out);
+  }
+
+  /**
+   * Constructor that sets nucleotide or peptide symbol set, and also writes the
+   * generated alignment to the specified output stream (if not null). This can
+   * be used to write the alignment to a file or sysout.
+   */
+  public AlignmentGenerator(boolean nucleotide, PrintStream printStream)
+  {
+    BASES = nucleotide ? NUCS : PEPS;
+    ps = printStream;
   }
 
   /**
-   * Outputs a DNA 'alignment' of given width and height, where each position is
-   * a random choice from 'GTCA-'.
+   * Outputs an 'alignment' of given width and height, where each position is a
+   * random choice from the symbol alphabet, or - for gap
    * 
    * @param width
    * @param height
@@ -153,6 +176,12 @@ public class AlignmentGenerator
               seqno + 1, width, changePercentage);
     }
     AlignmentI al = new Alignment(seqs);
+
+    if (ps != null)
+    {
+      ps.println(new FastaFile().print(al.getSequencesArray(), true));
+    }
+
     return al;
   }
 
index 088611e..3b9be23 100644 (file)
@@ -31,10 +31,9 @@ public class AlignmentSorterTest
     /*
      * sort with no score features does nothing
      */
-    PA.setValue(AlignmentSorter.class, "lastSortByFeatureScore", null);
+    PA.setValue(AlignmentSorter.class, "sortByFeatureCriteria", null);
 
-    AlignmentSorter.sortByFeature((String) null, null, 0, al.getWidth(),
-            al,
+    AlignmentSorter.sortByFeature(null, null, 0, al.getWidth(), al,
             AlignmentSorter.FEATURE_SCORE);
     assertSame(al.getSequenceAt(0), seq1);
     assertSame(al.getSequenceAt(1), seq2);
@@ -65,9 +64,9 @@ public class AlignmentSorterTest
      * sort by ascending score, no filter on feature type or group
      * NB sort order for the same feature set (none) gets toggled, so descending
      */
-    PA.setValue(AlignmentSorter.class, "sortByFeatureScoreAscending", true);
-    AlignmentSorter.sortByFeature((String) null, null, 0, al.getWidth(),
-            al, AlignmentSorter.FEATURE_SCORE);
+    PA.setValue(AlignmentSorter.class, "sortByFeatureAscending", true);
+    AlignmentSorter.sortByFeature(null, null, 0, al.getWidth(), al,
+            AlignmentSorter.FEATURE_SCORE);
     assertSame(al.getSequenceAt(3), seq3); // -0.5
     assertSame(al.getSequenceAt(2), seq2); // 2.5
     assertSame(al.getSequenceAt(1), seq1); // 3.0
@@ -76,8 +75,8 @@ public class AlignmentSorterTest
     /*
      * repeat sort toggles order - now ascending
      */
-    AlignmentSorter.sortByFeature((String) null, null, 0, al.getWidth(),
-            al, AlignmentSorter.FEATURE_SCORE);
+    AlignmentSorter.sortByFeature(null, null, 0, al.getWidth(), al,
+            AlignmentSorter.FEATURE_SCORE);
     assertSame(al.getSequenceAt(0), seq3); // -0.5
     assertSame(al.getSequenceAt(1), seq2); // 2.5
     assertSame(al.getSequenceAt(2), seq1); // 3.0
@@ -116,7 +115,7 @@ public class AlignmentSorterTest
      */
     // fails because seq1.findPosition(4) returns 4
     // although residue 4 is in column 5! - JAL-2544
-    AlignmentSorter.sortByFeature((String) null, null, 0, 4, al,
+    AlignmentSorter.sortByFeature(null, null, 0, 4, al,
             AlignmentSorter.FEATURE_SCORE);
     assertSame(al.getSequenceAt(0), seq3); // -4
     assertSame(al.getSequenceAt(1), seq1); // 2.0
index bada3ca..06b51e6 100644 (file)
@@ -40,6 +40,7 @@ import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
+import jalview.datamodel.features.SequenceFeatures;
 import jalview.gui.JvOptionPane;
 import jalview.io.AppletFormatAdapter;
 import jalview.io.DataSourceType;
@@ -1179,12 +1180,12 @@ public class AlignmentUtilsTests
     /*
      * check cds2 acquired a variant feature in position 5
      */
-    SequenceFeature[] sfs = cds2Dss.getSequenceFeatures();
+    List<SequenceFeature> sfs = cds2Dss.getSequenceFeatures();
     assertNotNull(sfs);
-    assertEquals(1, sfs.length);
-    assertEquals("variant", sfs[0].type);
-    assertEquals(5, sfs[0].begin);
-    assertEquals(5, sfs[0].end);
+    assertEquals(1, sfs.size());
+    assertEquals("variant", sfs.get(0).type);
+    assertEquals(5, sfs.get(0).begin);
+    assertEquals(5, sfs.get(0).end);
   }
 
   /**
@@ -1489,39 +1490,39 @@ public class AlignmentUtilsTests
      * that partially overlap 5' or 3' (start or end) of target sequence
      */
     AlignmentUtils.transferFeatures(dna, cds, map, null);
-    SequenceFeature[] sfs = cds.getSequenceFeatures();
-    assertEquals(6, sfs.length);
+    List<SequenceFeature> sfs = cds.getSequenceFeatures();
+    assertEquals(6, sfs.size());
 
-    SequenceFeature sf = sfs[0];
+    SequenceFeature sf = sfs.get(0);
     assertEquals("type2", sf.getType());
     assertEquals("desc2", sf.getDescription());
     assertEquals(2f, sf.getScore());
     assertEquals(1, sf.getBegin());
     assertEquals(1, sf.getEnd());
 
-    sf = sfs[1];
+    sf = sfs.get(1);
     assertEquals("type3", sf.getType());
     assertEquals("desc3", sf.getDescription());
     assertEquals(3f, sf.getScore());
     assertEquals(1, sf.getBegin());
     assertEquals(3, sf.getEnd());
 
-    sf = sfs[2];
+    sf = sfs.get(2);
     assertEquals("type4", sf.getType());
     assertEquals(2, sf.getBegin());
     assertEquals(5, sf.getEnd());
 
-    sf = sfs[3];
+    sf = sfs.get(3);
     assertEquals("type5", sf.getType());
     assertEquals(1, sf.getBegin());
     assertEquals(6, sf.getEnd());
 
-    sf = sfs[4];
+    sf = sfs.get(4);
     assertEquals("type8", sf.getType());
     assertEquals(6, sf.getBegin());
     assertEquals(6, sf.getEnd());
 
-    sf = sfs[5];
+    sf = sfs.get(5);
     assertEquals("type9", sf.getType());
     assertEquals(6, sf.getBegin());
     assertEquals(6, sf.getEnd());
@@ -1551,10 +1552,10 @@ public class AlignmentUtilsTests
 
     // desc4 and desc8 are the 'omit these' varargs
     AlignmentUtils.transferFeatures(dna, cds, map, null, "type4", "type8");
-    SequenceFeature[] sfs = cds.getSequenceFeatures();
-    assertEquals(1, sfs.length);
+    List<SequenceFeature> sfs = cds.getSequenceFeatures();
+    assertEquals(1, sfs.size());
 
-    SequenceFeature sf = sfs[0];
+    SequenceFeature sf = sfs.get(0);
     assertEquals("type5", sf.getType());
     assertEquals(1, sf.getBegin());
     assertEquals(6, sf.getEnd());
@@ -1584,10 +1585,10 @@ public class AlignmentUtilsTests
 
     // "type5" is the 'select this type' argument
     AlignmentUtils.transferFeatures(dna, cds, map, "type5");
-    SequenceFeature[] sfs = cds.getSequenceFeatures();
-    assertEquals(1, sfs.length);
+    List<SequenceFeature> sfs = cds.getSequenceFeatures();
+    assertEquals(1, sfs.size());
 
-    SequenceFeature sf = sfs[0];
+    SequenceFeature sf = sfs.get(0);
     assertEquals("type5", sf.getType());
     assertEquals(1, sf.getBegin());
     assertEquals(6, sf.getEnd());
@@ -2078,24 +2079,29 @@ public class AlignmentUtilsTests
      * var6 P -> H COSMIC
      * var6 P -> R COSMIC
      */
-    SequenceFeature[] sfs = peptide.getSequenceFeatures();
-    assertEquals(5, sfs.length);
+    List<SequenceFeature> sfs = peptide.getSequenceFeatures();
+    SequenceFeatures.sortFeatures(sfs, true);
+    assertEquals(5, sfs.size());
 
-    SequenceFeature sf = sfs[0];
+    /*
+     * features are sorted by start position ascending, but in no
+     * particular order where start positions match; asserts here
+     * simply match the data returned (the order is not important)
+     */
+    SequenceFeature sf = sfs.get(0);
     assertEquals(1, sf.getBegin());
     assertEquals(1, sf.getEnd());
-    assertEquals("p.Lys1Glu", sf.getDescription());
-    assertEquals("var1.125A>G", sf.getValue("ID"));
-    assertNull(sf.getValue("clinical_significance"));
-    assertEquals("ID=var1.125A>G", sf.getAttributes());
+    assertEquals("p.Lys1Asn", sf.getDescription());
+    assertEquals("var4", sf.getValue("ID"));
+    assertEquals("Benign", sf.getValue("clinical_significance"));
+    assertEquals("ID=var4;clinical_significance=Benign", sf.getAttributes());
     assertEquals(1, sf.links.size());
-    // link to variation is urlencoded
     assertEquals(
-            "p.Lys1Glu var1.125A>G|http://www.ensembl.org/Homo_sapiens/Variation/Summary?v=var1.125A%3EG",
+            "p.Lys1Asn var4|http://www.ensembl.org/Homo_sapiens/Variation/Summary?v=var4",
             sf.links.get(0));
     assertEquals(ensembl, sf.getFeatureGroup());
 
-    sf = sfs[1];
+    sf = sfs.get(1);
     assertEquals(1, sf.getBegin());
     assertEquals(1, sf.getEnd());
     assertEquals("p.Lys1Gln", sf.getDescription());
@@ -2108,43 +2114,44 @@ public class AlignmentUtilsTests
             sf.links.get(0));
     assertEquals(dbSnp, sf.getFeatureGroup());
 
-    sf = sfs[2];
+    sf = sfs.get(2);
     assertEquals(1, sf.getBegin());
     assertEquals(1, sf.getEnd());
-    assertEquals("p.Lys1Asn", sf.getDescription());
-    assertEquals("var4", sf.getValue("ID"));
-    assertEquals("Benign", sf.getValue("clinical_significance"));
-    assertEquals("ID=var4;clinical_significance=Benign", sf.getAttributes());
+    assertEquals("p.Lys1Glu", sf.getDescription());
+    assertEquals("var1.125A>G", sf.getValue("ID"));
+    assertNull(sf.getValue("clinical_significance"));
+    assertEquals("ID=var1.125A>G", sf.getAttributes());
     assertEquals(1, sf.links.size());
+    // link to variation is urlencoded
     assertEquals(
-            "p.Lys1Asn var4|http://www.ensembl.org/Homo_sapiens/Variation/Summary?v=var4",
+            "p.Lys1Glu var1.125A>G|http://www.ensembl.org/Homo_sapiens/Variation/Summary?v=var1.125A%3EG",
             sf.links.get(0));
     assertEquals(ensembl, sf.getFeatureGroup());
 
-    // var5 generates two distinct protein variant features
-    sf = sfs[3];
+    sf = sfs.get(3);
     assertEquals(3, sf.getBegin());
     assertEquals(3, sf.getEnd());
-    assertEquals("p.Pro3His", sf.getDescription());
+    assertEquals("p.Pro3Arg", sf.getDescription());
     assertEquals("var6", sf.getValue("ID"));
     assertEquals("Good", sf.getValue("clinical_significance"));
     assertEquals("ID=var6;clinical_significance=Good", sf.getAttributes());
     assertEquals(1, sf.links.size());
     assertEquals(
-            "p.Pro3His var6|http://www.ensembl.org/Homo_sapiens/Variation/Summary?v=var6",
+            "p.Pro3Arg var6|http://www.ensembl.org/Homo_sapiens/Variation/Summary?v=var6",
             sf.links.get(0));
     assertEquals(cosmic, sf.getFeatureGroup());
 
-    sf = sfs[4];
+    // var5 generates two distinct protein variant features
+    sf = sfs.get(4);
     assertEquals(3, sf.getBegin());
     assertEquals(3, sf.getEnd());
-    assertEquals("p.Pro3Arg", sf.getDescription());
+    assertEquals("p.Pro3His", sf.getDescription());
     assertEquals("var6", sf.getValue("ID"));
     assertEquals("Good", sf.getValue("clinical_significance"));
     assertEquals("ID=var6;clinical_significance=Good", sf.getAttributes());
     assertEquals(1, sf.links.size());
     assertEquals(
-            "p.Pro3Arg var6|http://www.ensembl.org/Homo_sapiens/Variation/Summary?v=var6",
+            "p.Pro3His var6|http://www.ensembl.org/Homo_sapiens/Variation/Summary?v=var6",
             sf.links.get(0));
     assertEquals(cosmic, sf.getFeatureGroup());
   }
@@ -2526,4 +2533,71 @@ public class AlignmentUtilsTests
     assertEquals(s_as3, uas3.getSequenceAsString());
   }
 
+  /**
+   * Tests for the method that maps nucleotide to protein based on CDS features
+   */
+  @Test(groups = "Functional")
+  public void testMapCdsToProtein()
+  {
+    SequenceI peptide = new Sequence("pep", "KLQ");
+
+    /*
+     * Case 1: CDS 3 times length of peptide
+     * NB method only checks lengths match, not translation
+     */
+    SequenceI dna = new Sequence("dna", "AACGacgtCTCCT");
+    dna.createDatasetSequence();
+    dna.addSequenceFeature(new SequenceFeature("CDS", "", 1, 4, null));
+    dna.addSequenceFeature(new SequenceFeature("CDS", "", 9, 13, null));
+    MapList ml = AlignmentUtils.mapCdsToProtein(dna, peptide);
+    assertEquals(3, ml.getFromRatio());
+    assertEquals(1, ml.getToRatio());
+    assertEquals("[[1, 3]]",
+            Arrays.deepToString(ml.getToRanges().toArray()));
+    assertEquals("[[1, 4], [9, 13]]",
+            Arrays.deepToString(ml.getFromRanges().toArray()));
+
+    /*
+     * Case 2: CDS 3 times length of peptide + stop codon
+     * (note code does not currently check trailing codon is a stop codon)
+     */
+    dna = new Sequence("dna", "AACGacgtCTCCTTGA");
+    dna.createDatasetSequence();
+    dna.addSequenceFeature(new SequenceFeature("CDS", "", 1, 4, null));
+    dna.addSequenceFeature(new SequenceFeature("CDS", "", 9, 16, null));
+    ml = AlignmentUtils.mapCdsToProtein(dna, peptide);
+    assertEquals(3, ml.getFromRatio());
+    assertEquals(1, ml.getToRatio());
+    assertEquals("[[1, 3]]",
+            Arrays.deepToString(ml.getToRanges().toArray()));
+    assertEquals("[[1, 4], [9, 13]]",
+            Arrays.deepToString(ml.getFromRanges().toArray()));
+
+    /*
+     * Case 3: CDS not 3 times length of peptide - no mapping is made
+     */
+    dna = new Sequence("dna", "AACGacgtCTCCTTG");
+    dna.createDatasetSequence();
+    dna.addSequenceFeature(new SequenceFeature("CDS", "", 1, 4, null));
+    dna.addSequenceFeature(new SequenceFeature("CDS", "", 9, 15, null));
+    ml = AlignmentUtils.mapCdsToProtein(dna, peptide);
+    assertNull(ml);
+
+    /*
+     * Case 4: incomplete start codon corresponding to X in peptide
+     */
+    dna = new Sequence("dna", "ACGacgtCTCCTTGG");
+    dna.createDatasetSequence();
+    SequenceFeature sf = new SequenceFeature("CDS", "", 1, 3, null);
+    sf.setPhase("2"); // skip 2 positions (AC) to start of next codon (GCT)
+    dna.addSequenceFeature(sf);
+    dna.addSequenceFeature(new SequenceFeature("CDS", "", 8, 15, null));
+    peptide = new Sequence("pep", "XLQ");
+    ml = AlignmentUtils.mapCdsToProtein(dna, peptide);
+    assertEquals("[[2, 3]]",
+            Arrays.deepToString(ml.getToRanges().toArray()));
+    assertEquals("[[3, 3], [8, 12]]",
+            Arrays.deepToString(ml.getFromRanges().toArray()));
+  }
+
 }
index 814d2d4..1faf3f2 100644 (file)
@@ -27,9 +27,10 @@ import static org.testng.AssertJUnit.assertTrue;
 import static org.testng.AssertJUnit.fail;
 
 import jalview.analysis.SecStrConsensus.SimpleBP;
+import jalview.datamodel.SequenceFeature;
 import jalview.gui.JvOptionPane;
 
-import java.util.Vector;
+import java.util.List;
 
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
@@ -48,7 +49,7 @@ public class RnaTest
   public void testGetSimpleBPs() throws WUSSParseException
   {
     String rna = "([{})]"; // JAL-1081 example
-    Vector<SimpleBP> bps = Rna.getSimpleBPs(rna);
+    List<SimpleBP> bps = Rna.getSimpleBPs(rna);
     assertEquals(3, bps.size());
 
     /*
@@ -313,4 +314,54 @@ public class RnaTest
               .valueOf((char) i) + " "));
     }
   }
+
+  @Test(groups = "Functional")
+  public void testGetHelixMap_oneHelix() throws WUSSParseException
+  {
+    String rna = ".(..[{.<..>}..].)";
+    SequenceFeature[] sfs = Rna.getHelixMap(rna);
+    assertEquals(4, sfs.length);
+
+    /*
+     * pairs are added in the order in which the closing bracket is found
+     * (see testGetSimpleBPs)
+     */
+    assertEquals(7, sfs[0].getBegin());
+    assertEquals(10, sfs[0].getEnd());
+    assertEquals("0", sfs[0].getFeatureGroup());
+    assertEquals(5, sfs[1].getBegin());
+    assertEquals(11, sfs[1].getEnd());
+    assertEquals("0", sfs[1].getFeatureGroup());
+    assertEquals(4, sfs[2].getBegin());
+    assertEquals(14, sfs[2].getEnd());
+    assertEquals("0", sfs[2].getFeatureGroup());
+    assertEquals(1, sfs[3].getBegin());
+    assertEquals(16, sfs[3].getEnd());
+    assertEquals("0", sfs[3].getFeatureGroup());
+  }
+
+  @Test(groups = "Functional")
+  public void testGetHelixMap_twoHelices() throws WUSSParseException
+  {
+    String rna = ".([.)]..{.<}.>";
+    SequenceFeature[] sfs = Rna.getHelixMap(rna);
+    assertEquals(4, sfs.length);
+  
+    /*
+     * pairs are added in the order in which the closing bracket is found
+     * (see testGetSimpleBPs)
+     */
+    assertEquals(1, sfs[0].getBegin());
+    assertEquals(4, sfs[0].getEnd());
+    assertEquals("0", sfs[0].getFeatureGroup());
+    assertEquals(2, sfs[1].getBegin());
+    assertEquals(5, sfs[1].getEnd());
+    assertEquals("0", sfs[1].getFeatureGroup());
+    assertEquals(8, sfs[2].getBegin());
+    assertEquals(11, sfs[2].getEnd());
+    assertEquals("1", sfs[2].getFeatureGroup());
+    assertEquals(10, sfs[3].getBegin());
+    assertEquals(13, sfs[3].getEnd());
+    assertEquals("1", sfs[3].getFeatureGroup());
+  }
 }
index 11cb10c..9839ba0 100644 (file)
@@ -62,26 +62,25 @@ public class SeqsetUtilsTest
     AlignmentI al = new Alignment(sqset);
     al.setDataset(null);
     AlignmentI ds = al.getDataset();
-    SequenceFeature sf1 = new SequenceFeature("f1", "foo", "bleh", 2, 3,
-            "far"), sf2 = new SequenceFeature("f2", "foo", "bleh", 2, 3,
-            "far");
+    SequenceFeature sf1 = new SequenceFeature("f1", "foo", 2, 3, "far");
+    SequenceFeature sf2 = new SequenceFeature("f2", "foo", 2, 3, "far");
     ds.getSequenceAt(0).addSequenceFeature(sf1);
     Hashtable unq = SeqsetUtils.uniquify(sqset, true);
     SequenceI[] sqset2 = new SequenceI[] {
         new Sequence(sqset[0].getName(), sqset[0].getSequenceAsString()),
         new Sequence(sqset[1].getName(), sqset[1].getSequenceAsString()) };
-    Assert.assertTrue(sqset[0].getSequenceFeatures()[0] == sf1);
-    Assert.assertEquals(sqset2[0].getSequenceFeatures(), null);
+    Assert.assertSame(sqset[0].getSequenceFeatures().get(0), sf1);
+    Assert.assertTrue(sqset2[0].getSequenceFeatures().isEmpty());
     ds.getSequenceAt(0).addSequenceFeature(sf2);
-    Assert.assertEquals(sqset[0].getSequenceFeatures().length, 2);
+    Assert.assertEquals(sqset[0].getSequenceFeatures().size(), 2);
     SeqsetUtils.deuniquify(unq, sqset2);
     // explicitly test that original sequence features still exist because they
     // are on the shared dataset sequence
-    Assert.assertEquals(sqset[0].getSequenceFeatures().length, 2);
-    Assert.assertEquals(sqset2[0].getSequenceFeatures().length, 2);
-    Assert.assertTrue(sqset[0].getSequenceFeatures()[0] == sqset2[0]
-            .getSequenceFeatures()[0]);
-    Assert.assertTrue(sqset[0].getSequenceFeatures()[1] == sqset2[0]
-            .getSequenceFeatures()[1]);
+    Assert.assertEquals(sqset[0].getSequenceFeatures().size(), 2);
+    Assert.assertEquals(sqset2[0].getSequenceFeatures().size(), 2);
+    Assert.assertSame(sqset[0].getSequenceFeatures().get(0), sqset2[0]
+            .getSequenceFeatures().get(0));
+    Assert.assertSame(sqset[0].getSequenceFeatures().get(1), sqset2[0]
+            .getSequenceFeatures().get(1));
   }
 }
index 70e59c5..e2e5594 100644 (file)
@@ -64,7 +64,7 @@ public class TestAlignSeq
     s2 = new Sequence("Seq2", "ASDFA");
     s2.setStart(5);
     s2.setEnd(9);
-    s3 = new Sequence("Seq1", "SDFAQQQSSS");
+    s3 = new Sequence("Seq3", "SDFAQQQSSS");
 
   }
 
@@ -125,10 +125,10 @@ public class TestAlignSeq
     };
 
     as.printAlignment(ps);
-    String expected = "Score = 320.0\nLength of alignment = 10\nSequence Seq1 :  3 - 18 (Sequence length = 14)\nSequence Seq1 :  1 - 10 (Sequence length = 10)\n\n"
-            + "Seq1 SDFAQQQRRR\n"
-            + "     |||||||   \n"
-            + "Seq1 SDFAQQQSSS\n\n" + "Percentage ID = 70.00\n";
+    String expected = "Score = 320.0\nLength of alignment = 10\nSequence Seq1/4-13 (Sequence length = 14)\nSequence Seq3/1-10 (Sequence length = 10)\n\n"
+            + "Seq1/4-13 SDFAQQQRRR\n"
+            + "          |||||||   \n"
+            + "Seq3/1-10 SDFAQQQSSS\n\n" + "Percentage ID = 70.00\n\n";
     assertEquals(expected, baos.toString());
   }
 }
index 0577fae..16ca70d 100644 (file)
@@ -23,6 +23,7 @@ package jalview.analysis.scoremodels;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
 
+import jalview.api.analysis.ScoreModelI;
 import jalview.api.analysis.SimilarityParamsI;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentI;
@@ -84,18 +85,18 @@ public class FeatureDistanceModelTest
       SequenceI ds = al.getSequenceAt(i).getDatasetSequence();
       if (sf1[i * 2] > 0)
       {
-        ds.addSequenceFeature(new SequenceFeature("sf1", "sf1", "sf1",
-                sf1[i * 2], sf1[i * 2 + 1], "sf1"));
+        ds.addSequenceFeature(new SequenceFeature("sf1", "sf1", sf1[i * 2],
+                sf1[i * 2 + 1], "sf1"));
       }
       if (sf2[i * 2] > 0)
       {
-        ds.addSequenceFeature(new SequenceFeature("sf2", "sf2", "sf2",
-                sf2[i * 2], sf2[i * 2 + 1], "sf2"));
+        ds.addSequenceFeature(new SequenceFeature("sf2", "sf2", sf2[i * 2],
+                sf2[i * 2 + 1], "sf2"));
       }
       if (sf3[i * 2] > 0)
       {
-        ds.addSequenceFeature(new SequenceFeature("sf3", "sf3", "sf3",
-                sf3[i * 2], sf3[i * 2 + 1], "sf3"));
+        ds.addSequenceFeature(new SequenceFeature("sf3", "sf3", sf3[i * 2],
+                sf3[i * 2 + 1], "sf3"));
       }
     }
     alf.setShowSeqFeatures(true);
@@ -113,12 +114,12 @@ public class FeatureDistanceModelTest
   public void testFeatureScoreModel() throws Exception
   {
     AlignFrame alf = getTestAlignmentFrame();
-    FeatureDistanceModel fsm = new FeatureDistanceModel();
-    assertTrue(fsm.configureFromAlignmentView(alf.getCurrentView()
-            .getAlignPanel()));
+    ScoreModelI sm = new FeatureDistanceModel();
+    sm = ScoreModels.getInstance().getScoreModel(sm.getName(),
+            alf.getCurrentView().getAlignPanel());
     alf.selectAllSequenceMenuItem_actionPerformed(null);
 
-    MatrixI dm = fsm.findDistances(
+    MatrixI dm = sm.findDistances(
             alf.getViewport().getAlignmentView(true),
             SimilarityParams.Jalview);
     assertEquals(dm.getValue(0, 2), 0d,
@@ -133,11 +134,11 @@ public class FeatureDistanceModelTest
     AlignFrame alf = getTestAlignmentFrame();
     // hiding first two columns shouldn't affect the tree
     alf.getViewport().hideColumns(0, 1);
-    FeatureDistanceModel fsm = new FeatureDistanceModel();
-    assertTrue(fsm.configureFromAlignmentView(alf.getCurrentView()
-            .getAlignPanel()));
+    ScoreModelI sm = new FeatureDistanceModel();
+    sm = ScoreModels.getInstance().getScoreModel(sm.getName(),
+            alf.getCurrentView().getAlignPanel());
     alf.selectAllSequenceMenuItem_actionPerformed(null);
-    MatrixI dm = fsm.findDistances(
+    MatrixI dm = sm.findDistances(
             alf.getViewport().getAlignmentView(true),
             SimilarityParams.Jalview);
     assertEquals(dm.getValue(0, 2), 0d,
@@ -153,11 +154,12 @@ public class FeatureDistanceModelTest
     // hide columns and check tree changes
     alf.getViewport().hideColumns(3, 4);
     alf.getViewport().hideColumns(0, 1);
-    FeatureDistanceModel fsm = new FeatureDistanceModel();
-    assertTrue(fsm.configureFromAlignmentView(alf.getCurrentView()
-            .getAlignPanel()));
+    // getName() can become static in Java 8
+    ScoreModelI sm = new FeatureDistanceModel();
+    sm = ScoreModels.getInstance().getScoreModel(sm.getName(),
+            alf.getCurrentView().getAlignPanel());
     alf.selectAllSequenceMenuItem_actionPerformed(null);
-    MatrixI dm = fsm.findDistances(
+    MatrixI dm = sm.findDistances(
             alf.getViewport().getAlignmentView(true),
             SimilarityParams.Jalview);
     assertEquals(
@@ -197,22 +199,22 @@ public class FeatureDistanceModelTest
     Assert.assertEquals(af.getFeatureRenderer().getDisplayedFeatureTypes()
             .size(), 1, "Should be just one feature type displayed");
     // step through and check for pointwise feature presence/absence
-    Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtRes(aseq, 1)
+    Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtColumn(aseq, 1)
             .size(), 0);
     // step through and check for pointwise feature presence/absence
-    Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtRes(aseq, 2)
+    Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtColumn(aseq, 2)
             .size(), 1);
     // step through and check for pointwise feature presence/absence
-    Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtRes(aseq, 3)
+    Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtColumn(aseq, 3)
             .size(), 0);
     // step through and check for pointwise feature presence/absence
-    Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtRes(aseq, 4)
+    Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtColumn(aseq, 4)
             .size(), 0);
     // step through and check for pointwise feature presence/absence
-    Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtRes(aseq, 5)
+    Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtColumn(aseq, 5)
             .size(), 1);
     // step through and check for pointwise feature presence/absence
-    Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtRes(aseq, 6)
+    Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtColumn(aseq, 6)
             .size(), 0);
   }
 
@@ -252,13 +254,15 @@ public class FeatureDistanceModelTest
     alf.setShowSeqFeatures(true);
     alf.getFeatureRenderer().findAllFeatures(true);
 
-    FeatureDistanceModel fsm = new FeatureDistanceModel();
-    assertTrue(fsm.configureFromAlignmentView(alf.getCurrentView()
-            .getAlignPanel()));
+    ScoreModelI sm = new FeatureDistanceModel();
+    sm = ScoreModels.getInstance().getScoreModel(sm.getName(),
+            alf.getCurrentView().getAlignPanel());
     alf.selectAllSequenceMenuItem_actionPerformed(null);
 
-    MatrixI distances = fsm.findDistances(alf.getViewport()
-            .getAlignmentView(true), SimilarityParams.Jalview);
+    AlignmentView alignmentView = alf.getViewport()
+            .getAlignmentView(true);
+    MatrixI distances = sm.findDistances(alignmentView,
+            SimilarityParams.Jalview);
     assertEquals(distances.width(), 2);
     assertEquals(distances.height(), 2);
     assertEquals(distances.getValue(0, 0), 0d);
@@ -279,9 +283,10 @@ public class FeatureDistanceModelTest
     AlignViewport viewport = af.getViewport();
     AlignmentView view = viewport.getAlignmentView(false);
 
-    FeatureDistanceModel sm = new FeatureDistanceModel();
-    sm.configureFromAlignmentView(af.alignPanel);
-  
+    ScoreModelI sm = new FeatureDistanceModel();
+    sm = ScoreModels.getInstance().getScoreModel(sm.getName(),
+            af.alignPanel);
+
     /*
      * feature distance model always normalises by region width
      * gap-gap is always included (but scores zero)
index 3223042..155f00e 100644 (file)
@@ -21,6 +21,7 @@
 package jalview.commands;
 
 import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNull;
 import static org.testng.AssertJUnit.assertSame;
 
 import jalview.commands.EditCommand.Action;
@@ -28,11 +29,15 @@ import jalview.commands.EditCommand.Edit;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
+import jalview.datamodel.features.SequenceFeatures;
 import jalview.gui.JvOptionPane;
 
+import java.util.List;
 import java.util.Map;
 
+import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
@@ -45,6 +50,14 @@ import org.testng.annotations.Test;
  */
 public class EditCommandTest
 {
+  /*
+   * compute n(n+1)/2 e.g. 
+   * func(5) = 5 + 4 + 3 + 2 + 1 = 15
+   */
+  private static int func(int i)
+  {
+    return i * (i + 1) / 2;
+  }
 
   @BeforeClass(alwaysRun = true)
   public void setUpJvOptionPane()
@@ -639,4 +652,222 @@ public class EditCommandTest
     assertEquals(ds2, unwound.get(ds2).getDatasetSequence());
     assertEquals(ds3, unwound.get(ds3).getDatasetSequence());
   }
+
+  /**
+   * Test a cut action's relocation of sequence features
+   */
+  @Test(groups = { "Functional" })
+  public void testCut_withFeatures()
+  {
+    /*
+     * create sequence features before, after and overlapping
+     * a cut of columns/residues 4-7
+     */
+    SequenceI seq0 = seqs[0];
+    seq0.addSequenceFeature(new SequenceFeature("before", "", 1, 3, 0f,
+            null));
+    seq0.addSequenceFeature(new SequenceFeature("overlap left", "", 2, 6,
+            0f, null));
+    seq0.addSequenceFeature(new SequenceFeature("internal", "", 5, 6, 0f,
+            null));
+    seq0.addSequenceFeature(new SequenceFeature("overlap right", "", 7, 8,
+            0f, null));
+    seq0.addSequenceFeature(new SequenceFeature("after", "", 8, 10, 0f,
+            null));
+
+    Edit ec = testee.new Edit(Action.CUT, seqs, 3, 4, al); // cols 3-6 base 0
+    EditCommand.cut(ec, new AlignmentI[] { al });
+
+    List<SequenceFeature> sfs = seq0.getSequenceFeatures();
+    SequenceFeatures.sortFeatures(sfs, true);
+
+    assertEquals(4, sfs.size()); // feature internal to cut has been deleted
+    SequenceFeature sf = sfs.get(0);
+    assertEquals("before", sf.getType());
+    assertEquals(1, sf.getBegin());
+    assertEquals(3, sf.getEnd());
+    sf = sfs.get(1);
+    assertEquals("overlap left", sf.getType());
+    assertEquals(2, sf.getBegin());
+    assertEquals(3, sf.getEnd()); // truncated by cut
+    sf = sfs.get(2);
+    assertEquals("overlap right", sf.getType());
+    assertEquals(4, sf.getBegin()); // shifted left by cut
+    assertEquals(5, sf.getEnd()); // truncated by cut
+    sf = sfs.get(3);
+    assertEquals("after", sf.getType());
+    assertEquals(4, sf.getBegin()); // shifted left by cut
+    assertEquals(6, sf.getEnd()); // shifted left by cut
+  }
+
+  /**
+   * Test a cut action's relocation of sequence features, with full coverage of
+   * all possible feature and cut locations for a 5-position ungapped sequence
+   */
+  @Test(groups = { "Functional" })
+  public void testCut_withFeatures_exhaustive()
+  {
+    /*
+     * create a sequence features on each subrange of 1-5
+     */
+    SequenceI seq0 = new Sequence("seq", "ABCDE");
+    AlignmentI alignment = new Alignment(new SequenceI[] { seq0 });
+    alignment.setDataset(null);
+    for (int from = 1; from <= seq0.getLength(); from++)
+    {
+      for (int to = from; to <= seq0.getLength(); to++)
+      {
+        String desc = String.format("%d-%d", from, to);
+        SequenceFeature sf = new SequenceFeature("test", desc, from, to,
+                0f,
+                null);
+        sf.setValue("from", Integer.valueOf(from));
+        sf.setValue("to", Integer.valueOf(to));
+        seq0.addSequenceFeature(sf);
+      }
+    }
+    // sanity check
+    List<SequenceFeature> sfs = seq0.getSequenceFeatures();
+    assertEquals(func(5), sfs.size());
+
+    /*
+     * now perform all possible cuts of subranges of 1-5 (followed by Undo)
+     * and validate the resulting remaining sequence features!
+     */
+    SequenceI[] sqs = new SequenceI[] { seq0 };
+
+    // goal is to have this passing for all from/to values!!
+    // for (int from = 0; from < seq0.getLength(); from++)
+    // {
+    // for (int to = from; to < seq0.getLength(); to++)
+    for (int from = 1; from < 3; from++)
+    {
+      for (int to = 2; to < 3; to++)
+      {
+        testee.appendEdit(Action.CUT, sqs, from, (to - from + 1),
+                alignment, true);
+
+        sfs = seq0.getSequenceFeatures();
+
+        /*
+         * confirm the number of features has reduced by the
+         * number of features within the cut region i.e. by
+         * func(length of cut)
+         */
+        String msg = String.format("Cut %d-%d ", from, to);
+        if (to - from == 4)
+        {
+          // all columns cut
+          assertNull(sfs);
+        }
+        else
+        {
+          assertEquals(msg + "wrong number of features left", func(5)
+                  - func(to - from + 1), sfs.size());
+        }
+
+        /*
+         * inspect individual features
+         */
+        if (sfs != null)
+        {
+          for (SequenceFeature sf : sfs)
+          {
+            checkFeatureRelocation(sf, from + 1, to + 1);
+          }
+        }
+        /*
+         * undo ready for next cut
+         */
+        testee.undoCommand(new AlignmentI[] { alignment });
+        assertEquals(func(5), seq0.getSequenceFeatures().size());
+      }
+    }
+  }
+
+  /**
+   * Helper method to check a feature has been correctly relocated after a cut
+   * 
+   * @param sf
+   * @param from
+   *          start of cut (first residue cut)
+   * @param to
+   *          end of cut (last residue cut)
+   */
+  private void checkFeatureRelocation(SequenceFeature sf, int from, int to)
+  {
+    // TODO handle the gapped sequence case as well
+    int cutSize = to - from + 1;
+    int oldFrom = ((Integer) sf.getValue("from")).intValue();
+    int oldTo = ((Integer) sf.getValue("to")).intValue();
+
+    String msg = String.format(
+            "Feature %s relocated to %d-%d after cut of %d-%d",
+            sf.getDescription(), sf.getBegin(), sf.getEnd(), from, to);
+    if (oldTo < from)
+    {
+      // before cut region so unchanged
+      assertEquals("1: " + msg, oldFrom, sf.getBegin());
+      assertEquals("2: " + msg, oldTo, sf.getEnd());
+    }
+    else if (oldFrom > to)
+    {
+      // follows cut region - shift by size of cut
+      assertEquals("3: " + msg, oldFrom - cutSize, sf.getBegin());
+      assertEquals("4: " + msg, oldTo - cutSize, sf.getEnd());
+    }
+    else if (oldFrom < from && oldTo > to)
+    {
+      // feature encloses cut region - shrink it right
+      assertEquals("5: " + msg, oldFrom, sf.getBegin());
+      assertEquals("6: " + msg, oldTo - cutSize, sf.getEnd());
+    }
+    else if (oldFrom < from)
+    {
+      // feature overlaps left side of cut region - truncated right
+      assertEquals("7: " + msg, from - 1, sf.getEnd());
+    }
+    else if (oldTo > to)
+    {
+      // feature overlaps right side of cut region - truncated left
+      assertEquals("8: " + msg, from, sf.getBegin());
+      assertEquals("9: " + msg, from + oldTo - to - 1, sf.getEnd());
+    }
+    else
+    {
+      // feature internal to cut - should have been deleted!
+      Assert.fail(msg + " - should have been deleted");
+    }
+  }
+
+  /**
+   * Test a cut action's relocation of sequence features
+   */
+  @Test(groups = { "Functional" })
+  public void testCut_gappedWithFeatures()
+  {
+    /*
+     * create sequence features before, after and overlapping
+     * a cut of columns/residues 4-7
+     */
+    SequenceI seq0 = new Sequence("seq", "A-BCC");
+    seq0.addSequenceFeature(new SequenceFeature("", "", 3, 4, 0f,
+            null));
+    AlignmentI alignment = new Alignment(new SequenceI[] { seq0 });
+    // cut columns of A-B
+    Edit ec = testee.new Edit(Action.CUT, seqs, 0, 3, alignment); // cols 0-3
+                                                                  // base 0
+    EditCommand.cut(ec, new AlignmentI[] { alignment });
+  
+    /*
+     * feature on CC(3-4) should now be on CC(1-2)
+     */
+    List<SequenceFeature> sfs = seq0.getSequenceFeatures();
+    assertEquals(1, sfs.size());
+    SequenceFeature sf = sfs.get(0);
+    assertEquals(1, sf.getBegin());
+    assertEquals(2, sf.getEnd());
+
+    // TODO add further cases including Undo - see JAL-2541
+  }
 }
index 1cfa771..4b5d096 100644 (file)
@@ -1300,4 +1300,25 @@ public class AlignmentTest
     AlignmentI alignment = new Alignment(new SequenceI[] { seq });
     alignment.setDataset(alignment);
   }
+
+  @Test(groups = "Functional")
+  public void testAppend()
+  {
+    SequenceI seq = new Sequence("seq1", "FRMLPSRT-A--L-");
+    AlignmentI alignment = new Alignment(new SequenceI[] { seq });
+    alignment.setGapCharacter('-');
+    SequenceI seq2 = new Sequence("seq1", "KP..L.FQII.");
+    AlignmentI alignment2 = new Alignment(new SequenceI[] { seq2 });
+    alignment2.setGapCharacter('.');
+
+    alignment.append(alignment2);
+
+    assertEquals('-', alignment.getGapCharacter());
+    assertSame(seq, alignment.getSequenceAt(0));
+    assertEquals("KP--L-FQII-", alignment.getSequenceAt(1)
+            .getSequenceAsString());
+
+    // todo test coverage for annotations, mappings, groups,
+    // hidden sequences, properties
+  }
 }
diff --git a/test/jalview/datamodel/CigarArrayTest.java b/test/jalview/datamodel/CigarArrayTest.java
new file mode 100644 (file)
index 0000000..7bee423
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.gui.JvOptionPane;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class CigarArrayTest
+{
+  @BeforeClass(alwaysRun = true)
+  public void setUpJvOptionPane()
+  {
+    JvOptionPane.setInteractiveMode(false);
+    JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
+  }
+
+  @Test(groups = "Functional")
+  public void testConstructor()
+  {
+    SequenceI seq1 = new Sequence("sq1",
+            "ASFDDABACBACBACBACBACBACBABCABCBACBABCAB");
+    Sequence seq2 = new Sequence("sq2",
+            "TTTTTTACBCBABCABCABCABCBACBACBABCABCABCBA");
+
+    // construct alignment
+    AlignmentI al = new Alignment(new SequenceI[] { seq1, seq2 });
+
+    // hide columns
+    HiddenColumns hc = new HiddenColumns();
+    hc.hideColumns(3, 6);
+    hc.hideColumns(16, 20);
+
+    // select group
+    SequenceGroup sg1 = new SequenceGroup();
+    sg1.addSequence(seq1, false);
+    sg1.setStartRes(2);
+    sg1.setEndRes(23);
+
+    // Cigar array meanings:
+    // M = match
+    // D = deletion
+    // I = insertion
+    // number preceding M/D/I is the number of residues which
+    // match/are deleted/are inserted
+    // In the CigarArray constructor only matches or deletions are created, as
+    // we are comparing a sequence to its own subsequence (the group) + hidden
+    // columns.
+
+    // no hidden columns case
+    CigarArray cig = new CigarArray(al, null, sg1);
+    String result = cig.getCigarstring();
+    assertEquals(result, "22M");
+
+    cig = new CigarArray(al, hc, sg1);
+    result = cig.getCigarstring();
+    assertEquals(result, "1M4D9M5D3M");
+
+    // group starts at hidden cols
+    sg1.setStartRes(3);
+    cig = new CigarArray(al, hc, sg1);
+    result = cig.getCigarstring();
+    assertEquals(result, "4D9M5D3M");
+
+    // group starts at last but 1 hidden col
+    sg1.setStartRes(5);
+    cig = new CigarArray(al, hc, sg1);
+    result = cig.getCigarstring();
+    assertEquals(result, "2D9M5D3M");
+
+    // group starts at last hidden col
+    sg1.setStartRes(6);
+    cig = new CigarArray(al, hc, sg1);
+    result = cig.getCigarstring();
+    assertEquals(result, "1D9M5D3M");
+
+    // group starts just after hidden region
+    sg1.setStartRes(7);
+    cig = new CigarArray(al, hc, sg1);
+    result = cig.getCigarstring();
+    assertEquals(result, "9M5D3M");
+
+    // group ends just before start of hidden region
+    sg1.setStartRes(5);
+    sg1.setEndRes(15);
+    cig = new CigarArray(al, hc, sg1);
+    result = cig.getCigarstring();
+    assertEquals(result, "2D9M");
+
+    // group ends at start of hidden region
+    sg1.setEndRes(16);
+    cig = new CigarArray(al, hc, sg1);
+    result = cig.getCigarstring();
+    assertEquals(result, "2D9M1D");
+
+    // group ends 1 after start of hidden region
+    sg1.setEndRes(17);
+    cig = new CigarArray(al, hc, sg1);
+    result = cig.getCigarstring();
+    assertEquals(result, "2D9M2D");
+
+    // group ends at end of hidden region
+    sg1.setEndRes(20);
+    cig = new CigarArray(al, hc, sg1);
+    result = cig.getCigarstring();
+    assertEquals(result, "2D9M5D");
+
+    // group ends just after end of hidden region
+    sg1.setEndRes(21);
+    cig = new CigarArray(al, hc, sg1);
+    result = cig.getCigarstring();
+    assertEquals(result, "2D9M5D1M");
+
+    // group ends 2 after end of hidden region
+    sg1.setEndRes(22);
+    cig = new CigarArray(al, hc, sg1);
+    result = cig.getCigarstring();
+    assertEquals(result, "2D9M5D2M");
+  }
+}
index ab25aa6..89169d6 100644 (file)
@@ -121,7 +121,7 @@ public class SeqCigarTest
     /*
      * TODO: can we add assertions to the sysouts that follow?
      */
-    System.out.println("Original sequence align:\n" + sub_gapped_s
+    System.out.println("\nOriginal sequence align:\n" + sub_gapped_s
             + "\nReconstructed window from 8 to 48\n" + "XXXXXXXX"
             + sub_se_gp.getSequenceString('-') + "..." + "\nCigar String:"
             + sub_se_gp.getCigarstring() + "\n");
@@ -193,7 +193,8 @@ public class SeqCigarTest
     SequenceI gen_sgapped_s = gen_sgapped.getSeq('-');
     // assertEquals("Couldn't reconstruct sequence", s_gapped.getSequence(),
     // gen_sgapped_s);
-    if (!gen_sgapped_s.getSequence().equals(s_gapped.getSequence()))
+    if (!gen_sgapped_s.getSequenceAsString().equals(
+            s_gapped.getSequenceAsString()))
     {
       // TODO: investigate errors reported here, to allow full conversion to
       // passing JUnit assertion form
index 2da8918..fbeb365 100644 (file)
@@ -42,7 +42,7 @@ public class SequenceFeatureTest
   }
 
   @Test(groups = { "Functional" })
-  public void testCopyConstructor()
+  public void testCopyConstructors()
   {
     SequenceFeature sf1 = new SequenceFeature("type", "desc", 22, 33,
             12.5f, "group");
@@ -56,10 +56,41 @@ public class SequenceFeatureTest
     assertEquals("desc", sf2.getDescription());
     assertEquals(22, sf2.getBegin());
     assertEquals(33, sf2.getEnd());
+    assertEquals(12.5f, sf2.getScore());
     assertEquals("+", sf2.getValue("STRAND"));
     assertEquals("Testing", sf2.getValue("Note"));
     // shallow clone of otherDetails map - contains the same object values!
     assertSame(count, sf2.getValue("Count"));
+
+    /*
+     * copy constructor modifying begin/end/group/score
+     */
+    SequenceFeature sf3 = new SequenceFeature(sf1, 11, 14, "group2", 17.4f);
+    assertEquals("type", sf3.getType());
+    assertEquals("desc", sf3.getDescription());
+    assertEquals(11, sf3.getBegin());
+    assertEquals(14, sf3.getEnd());
+    assertEquals(17.4f, sf3.getScore());
+    assertEquals("+", sf3.getValue("STRAND"));
+    assertEquals("Testing", sf3.getValue("Note"));
+    // shallow clone of otherDetails map - contains the same object values!
+    assertSame(count, sf3.getValue("Count"));
+
+    /*
+     * copy constructor modifying type/begin/end/group/score
+     */
+    SequenceFeature sf4 = new SequenceFeature(sf1, "Disulfide bond", 12,
+            15, "group3", -9.1f);
+    assertEquals("Disulfide bond", sf4.getType());
+    assertTrue(sf4.isContactFeature());
+    assertEquals("desc", sf4.getDescription());
+    assertEquals(12, sf4.getBegin());
+    assertEquals(15, sf4.getEnd());
+    assertEquals(-9.1f, sf4.getScore());
+    assertEquals("+", sf4.getValue("STRAND"));
+    assertEquals("Testing", sf4.getValue("Note"));
+    // shallow clone of otherDetails map - contains the same object values!
+    assertSame(count, sf4.getValue("Count"));
   }
 
   /**
@@ -123,51 +154,61 @@ public class SequenceFeatureTest
     assertEquals(sf1.hashCode(), sf2.hashCode());
 
     // changing type breaks equals:
-    String restores = sf2.getType();
-    sf2.setType("Type");
-    assertFalse(sf1.equals(sf2));
-    sf2.setType(restores);
+    SequenceFeature sf3 = new SequenceFeature("type", "desc", 22, 33,
+            12.5f, "group");
+    SequenceFeature sf4 = new SequenceFeature("Type", "desc", 22, 33,
+            12.5f, "group");
+    assertFalse(sf3.equals(sf4));
 
     // changing description breaks equals:
-    restores = sf2.getDescription();
+    String restores = sf2.getDescription();
     sf2.setDescription("Desc");
     assertFalse(sf1.equals(sf2));
     sf2.setDescription(restores);
 
     // changing score breaks equals:
     float restoref = sf2.getScore();
-    sf2.setScore(12.4f);
+    sf2 = new SequenceFeature(sf2, sf2.getBegin(), sf2.getEnd(),
+            sf2.getFeatureGroup(), 10f);
     assertFalse(sf1.equals(sf2));
-    sf2.setScore(restoref);
+    sf2 = new SequenceFeature(sf2, sf2.getBegin(), sf2.getEnd(),
+            sf2.getFeatureGroup(), restoref);
 
     // NaN doesn't match a number
     restoref = sf2.getScore();
-    sf2.setScore(Float.NaN);
+    sf2 = new SequenceFeature(sf2, sf2.getBegin(), sf2.getEnd(),
+            sf2.getFeatureGroup(), Float.NaN);
     assertFalse(sf1.equals(sf2));
 
     // NaN matches NaN
-    sf1.setScore(Float.NaN);
+    sf1 = new SequenceFeature(sf1, sf1.getBegin(), sf1.getEnd(),
+            sf1.getFeatureGroup(), Float.NaN);
     assertTrue(sf1.equals(sf2));
-    sf1.setScore(restoref);
-    sf2.setScore(restoref);
+    sf1 = new SequenceFeature(sf1, sf1.getBegin(), sf1.getEnd(),
+            sf1.getFeatureGroup(), restoref);
+    sf2 = new SequenceFeature(sf2, sf2.getBegin(), sf2.getEnd(),
+            sf2.getFeatureGroup(), restoref);
 
     // changing start position breaks equals:
     int restorei = sf2.getBegin();
-    sf2.setBegin(21);
+    sf2 = new SequenceFeature(sf2, 21, sf2.getEnd(), sf2.getFeatureGroup(), sf2.getScore());
     assertFalse(sf1.equals(sf2));
-    sf2.setBegin(restorei);
+    sf2 = new SequenceFeature(sf2, restorei, sf2.getEnd(),
+            sf2.getFeatureGroup(), sf2.getScore());
 
     // changing end position breaks equals:
     restorei = sf2.getEnd();
-    sf2.setEnd(32);
+    sf2 = new SequenceFeature(sf2, sf2.getBegin(), 32,
+            sf2.getFeatureGroup(), sf2.getScore());
     assertFalse(sf1.equals(sf2));
-    sf2.setEnd(restorei);
+    sf2 = new SequenceFeature(sf2, sf2.getBegin(), restorei,
+            sf2.getFeatureGroup(), sf2.getScore());
 
     // changing feature group breaks equals:
     restores = sf2.getFeatureGroup();
-    sf2.setFeatureGroup("Group");
+    sf2 = new SequenceFeature(sf2, sf2.getBegin(), sf2.getEnd(), "Group", sf2.getScore());
     assertFalse(sf1.equals(sf2));
-    sf2.setFeatureGroup(restores);
+    sf2 = new SequenceFeature(sf2, sf2.getBegin(), sf2.getEnd(), restores, sf2.getScore());
 
     // changing ID breaks equals:
     restores = (String) sf2.getValue("ID");
@@ -215,17 +256,21 @@ public class SequenceFeatureTest
     SequenceFeature sf = new SequenceFeature("type", "desc", 22, 33, 12.5f,
             "group");
     assertFalse(sf.isContactFeature());
-    sf.setType("");
+    sf = new SequenceFeature("", "desc", 22, 33, 12.5f, "group");
     assertFalse(sf.isContactFeature());
-    sf.setType(null);
+    sf = new SequenceFeature(null, "desc", 22, 33, 12.5f, "group");
     assertFalse(sf.isContactFeature());
-    sf.setType("Disulfide Bond");
+    sf = new SequenceFeature("Disulfide Bond", "desc", 22, 33, 12.5f,
+            "group");
     assertTrue(sf.isContactFeature());
-    sf.setType("disulfide bond");
+    sf = new SequenceFeature("disulfide bond", "desc", 22, 33, 12.5f,
+            "group");
     assertTrue(sf.isContactFeature());
-    sf.setType("Disulphide Bond");
+    sf = new SequenceFeature("Disulphide Bond", "desc", 22, 33, 12.5f,
+            "group");
     assertTrue(sf.isContactFeature());
-    sf.setType("disulphide bond");
+    sf = new SequenceFeature("disulphide bond", "desc", 22, 33, 12.5f,
+            "group");
     assertTrue(sf.isContactFeature());
   }
 }
index a52f0a2..a084a8e 100644 (file)
@@ -23,11 +23,13 @@ package jalview.datamodel;
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertFalse;
 import static org.testng.AssertJUnit.assertNotNull;
+import static org.testng.AssertJUnit.assertNotSame;
 import static org.testng.AssertJUnit.assertNull;
 import static org.testng.AssertJUnit.assertSame;
 import static org.testng.AssertJUnit.assertTrue;
-import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
 
+import jalview.commands.EditCommand;
+import jalview.commands.EditCommand.Action;
 import jalview.datamodel.PDBEntry.Type;
 import jalview.gui.JvOptionPane;
 import jalview.util.MapList;
@@ -39,6 +41,8 @@ import java.util.BitSet;
 import java.util.List;
 import java.util.Vector;
 
+import junit.extensions.PA;
+
 import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
@@ -102,15 +106,6 @@ public class SequenceTest
     // change sequence, should trigger an update of cached result
     sq.setSequence("ASDFASDFADSF");
     assertTrue(sq.isProtein());
-    /*
-     * in situ change of sequence doesn't change hashcode :-O
-     * (sequence should not expose internal implementation)
-     */
-    for (int i = 0; i < sq.getSequence().length; i++)
-    {
-      sq.getSequence()[i] = "acgtu".charAt(i % 5);
-    }
-    assertTrue(sq.isProtein()); // but it isn't
   }
 
   @Test(groups = { "Functional" })
@@ -235,82 +230,353 @@ public class SequenceTest
   @Test(groups = { "Functional" })
   public void testFindIndex()
   {
+    /* 
+     * call sequenceChanged() after each test to invalidate any cursor,
+     * forcing the 1-arg findIndex to be executed
+     */
     SequenceI sq = new Sequence("test", "ABCDEF");
     assertEquals(0, sq.findIndex(0));
+    sq.sequenceChanged();
     assertEquals(1, sq.findIndex(1));
+    sq.sequenceChanged();
     assertEquals(5, sq.findIndex(5));
+    sq.sequenceChanged();
     assertEquals(6, sq.findIndex(6));
+    sq.sequenceChanged();
     assertEquals(6, sq.findIndex(9));
 
-    sq = new Sequence("test", "-A--B-C-D-E-F--");
-    assertEquals(2, sq.findIndex(1));
-    assertEquals(5, sq.findIndex(2));
-    assertEquals(7, sq.findIndex(3));
+    sq = new Sequence("test/8-13", "-A--B-C-D-E-F--");
+    assertEquals(2, sq.findIndex(8));
+    sq.sequenceChanged();
+    assertEquals(5, sq.findIndex(9));
+    sq.sequenceChanged();
+    assertEquals(7, sq.findIndex(10));
 
     // before start returns 0
+    sq.sequenceChanged();
     assertEquals(0, sq.findIndex(0));
+    sq.sequenceChanged();
     assertEquals(0, sq.findIndex(-1));
 
     // beyond end returns last residue column
+    sq.sequenceChanged();
     assertEquals(13, sq.findIndex(99));
-
   }
 
   /**
-   * Tests for the method that returns a dataset sequence position (base 1) for
+   * Tests for the method that returns a dataset sequence position (start..) for
    * an aligned column position (base 0).
    */
   @Test(groups = { "Functional" })
   public void testFindPosition()
   {
-    SequenceI sq = new Sequence("test", "ABCDEF");
-    assertEquals(1, sq.findPosition(0));
-    assertEquals(6, sq.findPosition(5));
+    /* 
+     * call sequenceChanged() after each test to invalidate any cursor,
+     * forcing the 1-arg findPosition to be executed
+     */
+    SequenceI sq = new Sequence("test/8-13", "ABCDEF");
+    assertEquals(8, sq.findPosition(0));
+    // Sequence should now hold a cursor at [8, 0]
+    assertEquals("test:Pos8:Col1:startCol1:endCol0:tok0",
+            PA.getValue(sq, "cursor").toString());
+    SequenceCursor cursor = (SequenceCursor) PA.getValue(sq, "cursor");
+    int token = (int) PA.getValue(sq, "changeCount");
+    assertEquals(new SequenceCursor(sq, 8, 1, token), cursor);
+
+    sq.sequenceChanged();
+
+    /*
+     * find F13 at column offset 5, cursor should update to [13, 6]
+     * endColumn is found and saved in cursor
+     */
+    assertEquals(13, sq.findPosition(5));
+    cursor = (SequenceCursor) PA.getValue(sq, "cursor");
+    assertEquals(++token, (int) PA.getValue(sq, "changeCount"));
+    assertEquals(new SequenceCursor(sq, 13, 6, token), cursor);
+    assertEquals("test:Pos13:Col6:startCol1:endCol6:tok1",
+            PA.getValue(sq, "cursor").toString());
+
     // assertEquals(-1, seq.findPosition(6)); // fails
 
-    sq = new Sequence("test", "AB-C-D--");
-    assertEquals(1, sq.findPosition(0));
-    assertEquals(2, sq.findPosition(1));
+    sq = new Sequence("test/8-11", "AB-C-D--");
+    token = (int) PA.getValue(sq, "changeCount"); // 0
+    assertEquals(8, sq.findPosition(0));
+    cursor = (SequenceCursor) PA.getValue(sq, "cursor");
+    assertEquals(new SequenceCursor(sq, 8, 1, token), cursor);
+    assertEquals("test:Pos8:Col1:startCol1:endCol0:tok0",
+            PA.getValue(sq, "cursor").toString());
+
+    sq.sequenceChanged();
+    assertEquals(9, sq.findPosition(1));
+    cursor = (SequenceCursor) PA.getValue(sq, "cursor");
+    assertEquals(new SequenceCursor(sq, 9, 2, ++token), cursor);
+    assertEquals("test:Pos9:Col2:startCol1:endCol0:tok1",
+            PA.getValue(sq, "cursor").toString());
+
+    sq.sequenceChanged();
     // gap position 'finds' residue to the right (not the left as per javadoc)
-    assertEquals(3, sq.findPosition(2));
-    assertEquals(3, sq.findPosition(3));
-    assertEquals(4, sq.findPosition(4));
-    assertEquals(4, sq.findPosition(5));
+    // cursor is set to the last residue position found [B 2]
+    assertEquals(10, sq.findPosition(2));
+    cursor = (SequenceCursor) PA.getValue(sq, "cursor");
+    assertEquals(new SequenceCursor(sq, 9, 2, ++token), cursor);
+    assertEquals("test:Pos9:Col2:startCol1:endCol0:tok2",
+            PA.getValue(sq, "cursor").toString());
+
+    sq.sequenceChanged();
+    assertEquals(10, sq.findPosition(3));
+    cursor = (SequenceCursor) PA.getValue(sq, "cursor");
+    assertEquals(new SequenceCursor(sq, 10, 4, ++token), cursor);
+    assertEquals("test:Pos10:Col4:startCol1:endCol0:tok3",
+            PA.getValue(sq, "cursor").toString());
+
+    sq.sequenceChanged();
+    // column[4] is the gap after C - returns D11
+    // cursor is set to [C 4]
+    assertEquals(11, sq.findPosition(4));
+    cursor = (SequenceCursor) PA.getValue(sq, "cursor");
+    assertEquals(new SequenceCursor(sq, 10, 4, ++token), cursor);
+    assertEquals("test:Pos10:Col4:startCol1:endCol0:tok4",
+            PA.getValue(sq, "cursor").toString());
+
+    sq.sequenceChanged();
+    assertEquals(11, sq.findPosition(5)); // D
+    cursor = (SequenceCursor) PA.getValue(sq, "cursor");
+    assertEquals(new SequenceCursor(sq, 11, 6, ++token), cursor);
+    // lastCol has been found and saved in the cursor
+    assertEquals("test:Pos11:Col6:startCol1:endCol6:tok5",
+            PA.getValue(sq, "cursor").toString());
+
+    sq.sequenceChanged();
     // returns 1 more than sequence length if off the end ?!?
-    assertEquals(5, sq.findPosition(6));
-    assertEquals(5, sq.findPosition(7));
+    assertEquals(12, sq.findPosition(6));
 
-    sq = new Sequence("test", "--AB-C-DEF--");
-    assertEquals(1, sq.findPosition(0));
-    assertEquals(1, sq.findPosition(1));
-    assertEquals(1, sq.findPosition(2));
-    assertEquals(2, sq.findPosition(3));
-    assertEquals(3, sq.findPosition(4));
-    assertEquals(3, sq.findPosition(5));
-    assertEquals(4, sq.findPosition(6));
-    assertEquals(4, sq.findPosition(7));
-    assertEquals(5, sq.findPosition(8));
-    assertEquals(6, sq.findPosition(9));
-    assertEquals(7, sq.findPosition(10));
-    assertEquals(7, sq.findPosition(11));
+    sq.sequenceChanged();
+    assertEquals(12, sq.findPosition(7));
+
+    /*
+     * first findPosition should also set firstResCol in cursor
+     */
+    sq = new Sequence("test/8-13", "--AB-C-DEF--");
+    assertEquals(8, sq.findPosition(0));
+    assertNull(PA.getValue(sq, "cursor"));
+
+    sq.sequenceChanged();
+    assertEquals(8, sq.findPosition(1));
+    assertNull(PA.getValue(sq, "cursor"));
+
+    sq.sequenceChanged();
+    assertEquals(8, sq.findPosition(2));
+    assertEquals("test:Pos8:Col3:startCol3:endCol0:tok2",
+            PA.getValue(sq, "cursor").toString());
+
+    sq.sequenceChanged();
+    assertEquals(9, sq.findPosition(3));
+    assertEquals("test:Pos9:Col4:startCol3:endCol0:tok3",
+            PA.getValue(sq, "cursor").toString());
+
+    sq.sequenceChanged();
+    // column[4] is a gap, returns next residue pos (C10)
+    // cursor is set to last residue found [B]
+    assertEquals(10, sq.findPosition(4));
+    assertEquals("test:Pos9:Col4:startCol3:endCol0:tok4",
+            PA.getValue(sq, "cursor").toString());
+
+    sq.sequenceChanged();
+    assertEquals(10, sq.findPosition(5));
+    assertEquals("test:Pos10:Col6:startCol3:endCol0:tok5",
+            PA.getValue(sq, "cursor").toString());
+
+    sq.sequenceChanged();
+    // column[6] is a gap, returns next residue pos (D11)
+    // cursor is set to last residue found [C]
+    assertEquals(11, sq.findPosition(6));
+    assertEquals("test:Pos10:Col6:startCol3:endCol0:tok6",
+            PA.getValue(sq, "cursor").toString());
+
+    sq.sequenceChanged();
+    assertEquals(11, sq.findPosition(7));
+    assertEquals("test:Pos11:Col8:startCol3:endCol0:tok7",
+            PA.getValue(sq, "cursor").toString());
+
+    sq.sequenceChanged();
+    assertEquals(12, sq.findPosition(8));
+    assertEquals("test:Pos12:Col9:startCol3:endCol0:tok8",
+            PA.getValue(sq, "cursor").toString());
+
+    /*
+     * when the last residue column is found, it is set in the cursor
+     */
+    sq.sequenceChanged();
+    assertEquals(13, sq.findPosition(9));
+    assertEquals("test:Pos13:Col10:startCol3:endCol10:tok9",
+            PA.getValue(sq, "cursor").toString());
+
+    sq.sequenceChanged();
+    assertEquals(14, sq.findPosition(10));
+    assertEquals("test:Pos13:Col10:startCol3:endCol10:tok10",
+            PA.getValue(sq, "cursor").toString());
+
+    /*
+     * findPosition for column beyond sequence length
+     * returns 1 more than last residue position
+     */
+    sq.sequenceChanged();
+    assertEquals(14, sq.findPosition(11));
+    assertEquals("test:Pos13:Col10:startCol3:endCol10:tok11",
+            PA.getValue(sq, "cursor").toString());
+
+    sq.sequenceChanged();
+    assertEquals(14, sq.findPosition(99));
+    assertEquals("test:Pos13:Col10:startCol3:endCol10:tok12",
+            PA.getValue(sq, "cursor").toString());
+
+    /*
+     * gapped sequence ending in non-gap
+     */
+    sq = new Sequence("test/8-13", "--AB-C-DEF");
+    assertEquals(13, sq.findPosition(9));
+    assertEquals("test:Pos13:Col10:startCol3:endCol10:tok0",
+            PA.getValue(sq, "cursor").toString());
+    sq.sequenceChanged();
+    assertEquals(12, sq.findPosition(8));
+    cursor = (SequenceCursor) PA.getValue(sq, "cursor");
+    // sequenceChanged() invalidates cursor.lastResidueColumn
+    cursor = (SequenceCursor) PA.getValue(sq, "cursor");
+    assertEquals("test:Pos12:Col9:startCol3:endCol0:tok1",
+            cursor.toString());
+    // findPosition with cursor accepts base 1 column values
+    assertEquals(13, ((Sequence) sq).findPosition(10, cursor));
+    assertEquals(13, sq.findPosition(9)); // F13
+    // lastResidueColumn has now been found and saved in cursor
+    assertEquals("test:Pos13:Col10:startCol3:endCol10:tok1",
+            PA.getValue(sq, "cursor").toString());
   }
 
   @Test(groups = { "Functional" })
   public void testDeleteChars()
   {
+    /*
+     * internal delete
+     */
     SequenceI sq = new Sequence("test", "ABCDEF");
+    assertNull(PA.getValue(sq, "datasetSequence"));
     assertEquals(1, sq.getStart());
     assertEquals(6, sq.getEnd());
     sq.deleteChars(2, 3);
     assertEquals("ABDEF", sq.getSequenceAsString());
     assertEquals(1, sq.getStart());
     assertEquals(5, sq.getEnd());
+    assertNull(PA.getValue(sq, "datasetSequence"));
 
+    /*
+     * delete at start
+     */
     sq = new Sequence("test", "ABCDEF");
     sq.deleteChars(0, 2);
     assertEquals("CDEF", sq.getSequenceAsString());
     assertEquals(3, sq.getStart());
     assertEquals(6, sq.getEnd());
+    assertNull(PA.getValue(sq, "datasetSequence"));
+
+    /*
+     * delete at end
+     */
+    sq = new Sequence("test", "ABCDEF");
+    sq.deleteChars(4, 6);
+    assertEquals("ABCD", sq.getSequenceAsString());
+    assertEquals(1, sq.getStart());
+    assertEquals(4, sq.getEnd());
+    assertNull(PA.getValue(sq, "datasetSequence"));
+  }
+
+  @Test(groups = { "Functional" })
+  public void testDeleteChars_withDbRefsAndFeatures()
+  {
+    /*
+     * internal delete - new dataset sequence created
+     * gets a copy of any dbrefs
+     */
+    SequenceI sq = new Sequence("test", "ABCDEF");
+    sq.createDatasetSequence();
+    DBRefEntry dbr1 = new DBRefEntry("Uniprot", "0", "a123");
+    sq.addDBRef(dbr1);
+    Object ds = PA.getValue(sq, "datasetSequence");
+    assertNotNull(ds);
+    assertEquals(1, sq.getStart());
+    assertEquals(6, sq.getEnd());
+    sq.deleteChars(2, 3);
+    assertEquals("ABDEF", sq.getSequenceAsString());
+    assertEquals(1, sq.getStart());
+    assertEquals(5, sq.getEnd());
+    Object newDs = PA.getValue(sq, "datasetSequence");
+    assertNotNull(newDs);
+    assertNotSame(ds, newDs);
+    assertNotNull(sq.getDBRefs());
+    assertEquals(1, sq.getDBRefs().length);
+    assertNotSame(dbr1, sq.getDBRefs()[0]);
+    assertEquals(dbr1, sq.getDBRefs()[0]);
+
+    /*
+     * internal delete with sequence features
+     * (failure case for JAL-2541)
+     */
+    sq = new Sequence("test", "ABCDEF");
+    sq.createDatasetSequence();
+    SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 2, 4, 2f,
+            "CathGroup");
+    sq.addSequenceFeature(sf1);
+    ds = PA.getValue(sq, "datasetSequence");
+    assertNotNull(ds);
+    assertEquals(1, sq.getStart());
+    assertEquals(6, sq.getEnd());
+    sq.deleteChars(2, 4);
+    assertEquals("ABEF", sq.getSequenceAsString());
+    assertEquals(1, sq.getStart());
+    assertEquals(4, sq.getEnd());
+    newDs = PA.getValue(sq, "datasetSequence");
+    assertNotNull(newDs);
+    assertNotSame(ds, newDs);
+    List<SequenceFeature> sfs = sq.getSequenceFeatures();
+    assertEquals(1, sfs.size());
+    assertNotSame(sf1, sfs.get(0));
+    assertEquals(sf1, sfs.get(0));
+
+    /*
+     * delete at start - no new dataset sequence created
+     * any sequence features remain as before
+     */
+    sq = new Sequence("test", "ABCDEF");
+    sq.createDatasetSequence();
+    ds = PA.getValue(sq, "datasetSequence");
+    sf1 = new SequenceFeature("Cath", "desc", 2, 4, 2f, "CathGroup");
+    sq.addSequenceFeature(sf1);
+    sq.deleteChars(0, 2);
+    assertEquals("CDEF", sq.getSequenceAsString());
+    assertEquals(3, sq.getStart());
+    assertEquals(6, sq.getEnd());
+    assertSame(ds, PA.getValue(sq, "datasetSequence"));
+    sfs = sq.getSequenceFeatures();
+    assertNotNull(sfs);
+    assertEquals(1, sfs.size());
+    assertSame(sf1, sfs.get(0));
+
+    /*
+     * delete at end - no new dataset sequence created
+     * any dbrefs remain as before
+     */
+    sq = new Sequence("test", "ABCDEF");
+    sq.createDatasetSequence();
+    ds = PA.getValue(sq, "datasetSequence");
+    dbr1 = new DBRefEntry("Uniprot", "0", "a123");
+    sq.addDBRef(dbr1);
+    sq.deleteChars(4, 6);
+    assertEquals("ABCD", sq.getSequenceAsString());
+    assertEquals(1, sq.getStart());
+    assertEquals(4, sq.getEnd());
+    assertSame(ds, PA.getValue(sq, "datasetSequence"));
+    assertNotNull(sq.getDBRefs());
+    assertEquals(1, sq.getDBRefs().length);
+    assertSame(dbr1, sq.getDBRefs()[0]);
   }
 
   @Test(groups = { "Functional" })
@@ -348,16 +614,16 @@ public class SequenceTest
     SequenceI sq = new Sequence("test", "GATCAT");
     sq.createDatasetSequence();
 
-    assertNull(sq.getSequenceFeatures());
+    assertTrue(sq.getSequenceFeatures().isEmpty());
 
     /*
      * SequenceFeature on sequence
      */
-    SequenceFeature sf = new SequenceFeature();
+    SequenceFeature sf = new SequenceFeature("Cath", "desc", 2, 4, 2f, null);
     sq.addSequenceFeature(sf);
-    SequenceFeature[] sfs = sq.getSequenceFeatures();
-    assertEquals(1, sfs.length);
-    assertSame(sf, sfs[0]);
+    List<SequenceFeature> sfs = sq.getSequenceFeatures();
+    assertEquals(1, sfs.size());
+    assertSame(sf, sfs.get(0));
 
     /*
      * SequenceFeature on sequence and dataset sequence; returns that on
@@ -366,18 +632,19 @@ public class SequenceTest
      * Note JAL-2046: spurious: we have no use case for this at the moment.
      * This test also buggy - as sf2.equals(sf), no new feature is added
      */
-    SequenceFeature sf2 = new SequenceFeature();
+    SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 2, 4, 2f,
+            null);
     sq.getDatasetSequence().addSequenceFeature(sf2);
     sfs = sq.getSequenceFeatures();
-    assertEquals(1, sfs.length);
-    assertSame(sf, sfs[0]);
+    assertEquals(1, sfs.size());
+    assertSame(sf, sfs.get(0));
 
     /*
      * SequenceFeature on dataset sequence only
      * Note JAL-2046: spurious: we have no use case for setting a non-dataset sequence's feature array to null at the moment.
      */
     sq.setSequenceFeatures(null);
-    assertNull(sq.getDatasetSequence().getSequenceFeatures());
+    assertTrue(sq.getDatasetSequence().getSequenceFeatures().isEmpty());
 
     /*
      * Corrupt case - no SequenceFeature, dataset's dataset is the original
@@ -398,7 +665,7 @@ public class SequenceTest
       assertTrue(e.getMessage().toLowerCase()
               .contains("implementation error"));
     }
-    assertNull(sq.getSequenceFeatures());
+    assertTrue(sq.getSequenceFeatures().isEmpty());
   }
 
   /**
@@ -448,11 +715,23 @@ public class SequenceTest
   public void testCreateDatasetSequence()
   {
     SequenceI sq = new Sequence("my", "ASDASD");
+    sq.addSequenceFeature(new SequenceFeature("type", "desc", 1, 10, 1f,
+            "group"));
+    sq.addDBRef(new DBRefEntry("source", "version", "accession"));
     assertNull(sq.getDatasetSequence());
+    assertNotNull(PA.getValue(sq, "sequenceFeatureStore"));
+    assertNotNull(PA.getValue(sq, "dbrefs"));
+
     SequenceI rds = sq.createDatasetSequence();
     assertNotNull(rds);
     assertNull(rds.getDatasetSequence());
-    assertEquals(sq.getDatasetSequence(), rds);
+    assertSame(sq.getDatasetSequence(), rds);
+
+    // sequence features and dbrefs transferred to dataset sequence
+    assertNull(PA.getValue(sq, "sequenceFeatureStore"));
+    assertNull(PA.getValue(sq, "dbrefs"));
+    assertNotNull(PA.getValue(rds, "sequenceFeatureStore"));
+    assertNotNull(PA.getValue(rds, "dbrefs"));
   }
 
   /**
@@ -559,12 +838,9 @@ public class SequenceTest
     assertEquals("CD", derived.getSequenceAsString());
     assertSame(sq.getDatasetSequence(), derived.getDatasetSequence());
 
-    assertNull(sq.sequenceFeatures);
-    assertNull(derived.sequenceFeatures);
     // derived sequence should access dataset sequence features
     assertNotNull(sq.getSequenceFeatures());
-    assertArrayEquals(sq.getSequenceFeatures(),
-            derived.getSequenceFeatures());
+    assertEquals(sq.getSequenceFeatures(), derived.getSequenceFeatures());
 
     /*
      *  verify we have primary db refs *just* for PDB IDs with associated
@@ -694,18 +970,18 @@ public class SequenceTest
     assertEquals(anns[0].score, seq1.getAnnotation()[0].score);
 
     // copy has a copy of the sequence feature:
-    SequenceFeature[] sfs = copy.getSequenceFeatures();
-    assertEquals(1, sfs.length);
+    List<SequenceFeature> sfs = copy.getSequenceFeatures();
+    assertEquals(1, sfs.size());
     if (seq1.getDatasetSequence() != null
             && copy.getDatasetSequence() == seq1.getDatasetSequence())
     {
-      assertTrue(sfs[0] == seq1.getSequenceFeatures()[0]);
+      assertSame(sfs.get(0), seq1.getSequenceFeatures().get(0));
     }
     else
     {
-      assertFalse(sfs[0] == seq1.getSequenceFeatures()[0]);
+      assertNotSame(sfs.get(0), seq1.getSequenceFeatures().get(0));
     }
-    assertTrue(sfs[0].equals(seq1.getSequenceFeatures()[0]));
+    assertEquals(sfs.get(0), seq1.getSequenceFeatures().get(0));
 
     // copy has a copy of the PDB entry
     Vector<PDBEntry> pdbs = copy.getAllPDBEntries();
@@ -724,6 +1000,36 @@ public class SequenceTest
     assertEquals(' ', sq.getCharAt(-1));
   }
 
+  @Test(groups = { "Functional" })
+  public void testAddSequenceFeatures()
+  {
+    SequenceI sq = new Sequence("", "abcde");
+    // type may not be null
+    assertFalse(sq.addSequenceFeature(new SequenceFeature(null, "desc", 4,
+            8, 0f, null)));
+    assertTrue(sq.addSequenceFeature(new SequenceFeature("Cath", "desc", 4,
+            8, 0f, null)));
+    // can't add a duplicate feature
+    assertFalse(sq.addSequenceFeature(new SequenceFeature("Cath", "desc",
+            4, 8, 0f, null)));
+    // can add a different feature
+    assertTrue(sq.addSequenceFeature(new SequenceFeature("Scop", "desc", 4,
+            8, 0f, null))); // different type
+    assertTrue(sq.addSequenceFeature(new SequenceFeature("Cath",
+            "description", 4, 8, 0f, null)));// different description
+    assertTrue(sq.addSequenceFeature(new SequenceFeature("Cath", "desc", 3,
+            8, 0f, null))); // different start position
+    assertTrue(sq.addSequenceFeature(new SequenceFeature("Cath", "desc", 4,
+            9, 0f, null))); // different end position
+    assertTrue(sq.addSequenceFeature(new SequenceFeature("Cath", "desc", 4,
+            8, 1f, null))); // different score
+    assertTrue(sq.addSequenceFeature(new SequenceFeature("Cath", "desc", 4,
+            8, Float.NaN, null))); // score NaN
+    assertTrue(sq.addSequenceFeature(new SequenceFeature("Cath", "desc", 4,
+            8, 0f, "Metal"))); // different group
+    assertEquals(8, sq.getFeatures().getAllFeatures().size());
+  }
+
   /**
    * Tests for adding (or updating) dbrefs
    * 
@@ -1023,4 +1329,556 @@ public class SequenceTest
     seq2.createDatasetSequence();
     seq.setDatasetSequence(seq2);
   }
+
+  @Test(groups = { "Functional" })
+  public void testFindFeatures()
+  {
+    SequenceI sq = new Sequence("test/8-16", "-ABC--DEF--GHI--");
+    sq.createDatasetSequence();
+
+    assertTrue(sq.findFeatures(1, 99).isEmpty());
+
+    // add non-positional feature
+    SequenceFeature sf0 = new SequenceFeature("Cath", "desc", 0, 0, 2f,
+            null);
+    sq.addSequenceFeature(sf0);
+    // add feature on BCD
+    SequenceFeature sfBCD = new SequenceFeature("Cath", "desc", 9, 11, 2f,
+            null);
+    sq.addSequenceFeature(sfBCD);
+    // add feature on DE
+    SequenceFeature sfDE = new SequenceFeature("Cath", "desc", 11, 12, 2f,
+            null);
+    sq.addSequenceFeature(sfDE);
+    // add contact feature at [B, H]
+    SequenceFeature sfContactBH = new SequenceFeature("Disulphide bond",
+            "desc", 9, 15, 2f, null);
+    sq.addSequenceFeature(sfContactBH);
+    // add contact feature at [F, G]
+    SequenceFeature sfContactFG = new SequenceFeature("Disulfide Bond",
+            "desc", 13, 14, 2f, null);
+    sq.addSequenceFeature(sfContactFG);
+    // add single position feature at [I]
+    SequenceFeature sfI = new SequenceFeature("Disulfide Bond",
+            "desc", 16, 16, null);
+    sq.addSequenceFeature(sfI);
+
+    // no features in columns 1-2 (-A)
+    List<SequenceFeature> found = sq.findFeatures(1, 2);
+    assertTrue(found.isEmpty());
+
+    // columns 1-6 (-ABC--) includes BCD and B/H feature but not DE
+    found = sq.findFeatures(1, 6);
+    assertEquals(2, found.size());
+    assertTrue(found.contains(sfBCD));
+    assertTrue(found.contains(sfContactBH));
+
+    // columns 5-6 (--) includes (enclosing) BCD but not (contact) B/H feature
+    found = sq.findFeatures(5, 6);
+    assertEquals(1, found.size());
+    assertTrue(found.contains(sfBCD));
+
+    // columns 7-10 (DEF-) includes BCD, DE, F/G but not B/H feature
+    found = sq.findFeatures(7, 10);
+    assertEquals(3, found.size());
+    assertTrue(found.contains(sfBCD));
+    assertTrue(found.contains(sfDE));
+    assertTrue(found.contains(sfContactFG));
+
+    // columns 10-11 (--) should find nothing
+    found = sq.findFeatures(10, 11);
+    assertEquals(0, found.size());
+
+    // columns 14-14 (I) should find variant feature
+    found = sq.findFeatures(14, 14);
+    assertEquals(1, found.size());
+    assertTrue(found.contains(sfI));
+  }
+
+  @Test(groups = { "Functional" })
+  public void testFindIndex_withCursor()
+  {
+    Sequence sq = new Sequence("test/8-13", "-A--BCD-EF--");
+
+    // find F given A
+    assertEquals(10, sq.findIndex(13, new SequenceCursor(sq, 8, 2, 0)));
+
+    // find A given F
+    assertEquals(2, sq.findIndex(8, new SequenceCursor(sq, 13, 10, 0)));
+
+    // find C given C
+    assertEquals(6, sq.findIndex(10, new SequenceCursor(sq, 10, 6, 0)));
+  }
+
+  @Test(groups = { "Functional" })
+  public void testFindPosition_withCursor()
+  {
+    Sequence sq = new Sequence("test/8-13", "-A--BCD-EF--");
+  
+    // find F pos given A - lastCol gets set in cursor
+    assertEquals(13, sq.findPosition(10, new SequenceCursor(sq, 8, 2, 0)));
+    assertEquals("test:Pos13:Col10:startCol0:endCol10:tok0",
+            PA.getValue(sq, "cursor").toString());
+
+    // find A pos given F - first residue column is saved in cursor
+    assertEquals(8, sq.findPosition(2, new SequenceCursor(sq, 13, 10, 0)));
+    assertEquals("test:Pos8:Col2:startCol2:endCol10:tok0",
+            PA.getValue(sq, "cursor").toString());
+  
+    // find C pos given C (neither startCol nor endCol is set)
+    assertEquals(10, sq.findPosition(6, new SequenceCursor(sq, 10, 6, 0)));
+    assertEquals("test:Pos10:Col6:startCol0:endCol0:tok0",
+            PA.getValue(sq, "cursor").toString());
+
+    // now the grey area - what residue position for a gapped column? JAL-2562
+
+    // find 'residue' for column 3 given cursor for D (so working left)
+    // returns B9; cursor is updated to [B 5]
+    assertEquals(9, sq.findPosition(3, new SequenceCursor(sq, 11, 7, 0)));
+    assertEquals("test:Pos9:Col5:startCol0:endCol0:tok0",
+            PA.getValue(sq, "cursor").toString());
+
+    // find 'residue' for column 8 given cursor for D (so working right)
+    // returns E12; cursor is updated to [D 7]
+    assertEquals(12, sq.findPosition(8, new SequenceCursor(sq, 11, 7, 0)));
+    assertEquals("test:Pos11:Col7:startCol0:endCol0:tok0",
+            PA.getValue(sq, "cursor").toString());
+
+    // find 'residue' for column 12 given cursor for B
+    // returns 1 more than last residue position; cursor is updated to [F 10]
+    // lastCol position is saved in cursor
+    assertEquals(14, sq.findPosition(12, new SequenceCursor(sq, 9, 5, 0)));
+    assertEquals("test:Pos13:Col10:startCol0:endCol10:tok0",
+            PA.getValue(sq, "cursor").toString());
+
+    /*
+     * findPosition for column beyond length of sequence
+     * returns 1 more than the last residue position
+     * cursor is set to last real residue position [F 10]
+     */
+    assertEquals(14, sq.findPosition(99, new SequenceCursor(sq, 8, 2, 0)));
+    assertEquals("test:Pos13:Col10:startCol0:endCol10:tok0",
+            PA.getValue(sq, "cursor").toString());
+
+    /*
+     * and the case without a trailing gap
+     */
+    sq = new Sequence("test/8-13", "-A--BCD-EF");
+    // first find C from A
+    assertEquals(10, sq.findPosition(6, new SequenceCursor(sq, 8, 2, 0)));
+    SequenceCursor cursor = (SequenceCursor) PA.getValue(sq, "cursor");
+    assertEquals("test:Pos10:Col6:startCol0:endCol0:tok0",
+            cursor.toString());
+    // now 'find' 99 from C
+    // cursor is set to [F 10] and saved lastCol
+    assertEquals(14, sq.findPosition(99, cursor));
+    assertEquals("test:Pos13:Col10:startCol0:endCol10:tok0",
+            PA.getValue(sq, "cursor").toString());
+  }
+
+  @Test
+  public void testIsValidCursor()
+  {
+    Sequence sq = new Sequence("Seq", "ABC--DE-F", 8, 13);
+    assertFalse(sq.isValidCursor(null));
+
+    /*
+     * cursor is valid if it has valid sequence ref and changeCount token
+     * and positions within the range of the sequence
+     */
+    int changeCount = (int) PA.getValue(sq, "changeCount");
+    SequenceCursor cursor = new SequenceCursor(sq, 13, 1, changeCount);
+    assertTrue(sq.isValidCursor(cursor));
+
+    /*
+     * column position outside [0 - length] is rejected
+     */
+    cursor = new SequenceCursor(sq, 13, -1, changeCount);
+    assertFalse(sq.isValidCursor(cursor));
+    cursor = new SequenceCursor(sq, 13, 10, changeCount);
+    assertFalse(sq.isValidCursor(cursor));
+    cursor = new SequenceCursor(sq, 7, 8, changeCount);
+    assertFalse(sq.isValidCursor(cursor));
+    cursor = new SequenceCursor(sq, 14, 2, changeCount);
+    assertFalse(sq.isValidCursor(cursor));
+
+    /*
+     * wrong sequence is rejected
+     */
+    cursor = new SequenceCursor(null, 13, 1, changeCount);
+    assertFalse(sq.isValidCursor(cursor));
+    cursor = new SequenceCursor(new Sequence("Seq", "abc"), 13, 1,
+            changeCount);
+    assertFalse(sq.isValidCursor(cursor));
+
+    /*
+     * wrong token value is rejected
+     */
+    cursor = new SequenceCursor(sq, 13, 1, changeCount + 1);
+    assertFalse(sq.isValidCursor(cursor));
+    cursor = new SequenceCursor(sq, 13, 1, changeCount - 1);
+    assertFalse(sq.isValidCursor(cursor));
+  }
+
+  @Test(groups = { "Functional" })
+  public void testFindPosition_withCursorAndEdits()
+  {
+    Sequence sq = new Sequence("test/8-13", "-A--BCD-EF--");
+  
+    // find F pos given A
+    assertEquals(13, sq.findPosition(10, new SequenceCursor(sq, 8, 2, 0)));
+    int token = (int) PA.getValue(sq, "changeCount"); // 0
+    SequenceCursor cursor = (SequenceCursor) PA.getValue(sq, "cursor");
+    assertEquals(new SequenceCursor(sq, 13, 10, token), cursor);
+
+    /*
+     * setSequence should invalidate the cursor cached by the sequence
+     */
+    sq.setSequence("-A-BCD-EF---"); // one gap removed
+    assertEquals(8, sq.getStart()); // sanity check
+    assertEquals(11, sq.findPosition(5)); // D11
+    // cursor should now be at [D 6]
+    cursor = (SequenceCursor) PA.getValue(sq, "cursor");
+    assertEquals(new SequenceCursor(sq, 11, 6, ++token), cursor);
+
+    /*
+     * deleteChars should invalidate the cached cursor
+     */
+    sq.deleteChars(2, 5); // delete -BC
+    assertEquals("-AD-EF---", sq.getSequenceAsString());
+    assertEquals(8, sq.getStart()); // sanity check
+    assertEquals(10, sq.findPosition(4)); // E10
+    // cursor should now be at [E 5]
+    cursor = (SequenceCursor) PA.getValue(sq, "cursor");
+    assertEquals(new SequenceCursor(sq, 10, 5, ++token), cursor);
+
+    /*
+     * Edit to insert gaps should invalidate the cached cursor
+     * insert 2 gaps at column[3] to make -AD---EF---
+     */
+    SequenceI[] seqs = new SequenceI[] { sq };
+    AlignmentI al = new Alignment(seqs);
+    new EditCommand().appendEdit(Action.INSERT_GAP, seqs, 3, 2, al, true);
+    assertEquals("-AD---EF---", sq.getSequenceAsString());
+    assertEquals(10, sq.findPosition(4)); // E10
+    // cursor should now be at [D 3]
+    cursor = (SequenceCursor) PA.getValue(sq, "cursor");
+    assertEquals(new SequenceCursor(sq, 9, 3, ++token), cursor);
+
+    /*
+     * insertCharAt should invalidate the cached cursor
+     * insert CC at column[4] to make -AD-CC--EF---
+     */
+    sq.insertCharAt(4, 2, 'C');
+    assertEquals("-AD-CC--EF---", sq.getSequenceAsString());
+    assertEquals(13, sq.findPosition(9)); // F13
+    // cursor should now be at [F 10]
+    cursor = (SequenceCursor) PA.getValue(sq, "cursor");
+    assertEquals(new SequenceCursor(sq, 13, 10, ++token), cursor);
+  }
+
+  @Test(groups = { "Functional" })
+  public void testGetSequence()
+  {
+    String seqstring = "-A--BCD-EF--";
+    Sequence sq = new Sequence("test/8-13", seqstring);
+    sq.createDatasetSequence();
+    assertTrue(Arrays.equals(sq.getSequence(), seqstring.toCharArray()));
+    assertTrue(Arrays.equals(sq.getDatasetSequence().getSequence(),
+            "ABCDEF".toCharArray()));
+
+    // verify a copy of the sequence array is returned
+    char[] theSeq = (char[]) PA.getValue(sq, "sequence");
+    assertNotSame(theSeq, sq.getSequence());
+    theSeq = (char[]) PA.getValue(sq.getDatasetSequence(), "sequence");
+    assertNotSame(theSeq, sq.getDatasetSequence().getSequence());
+  }
+
+  @Test(groups = { "Functional" })
+  public void testReplace()
+  {
+    String seqstring = "-A--BCD-EF--";
+    SequenceI sq = new Sequence("test/8-13", seqstring);
+    assertEquals(0, PA.getValue(sq, "changeCount"));
+
+    assertEquals(0, sq.replace('A', 'A')); // same char
+    assertEquals(seqstring, sq.getSequenceAsString());
+    assertEquals(0, PA.getValue(sq, "changeCount"));
+
+    assertEquals(0, sq.replace('X', 'Y')); // not there
+    assertEquals(seqstring, sq.getSequenceAsString());
+    assertEquals(0, PA.getValue(sq, "changeCount"));
+
+    assertEquals(1, sq.replace('A', 'K'));
+    assertEquals("-K--BCD-EF--", sq.getSequenceAsString());
+    assertEquals(1, PA.getValue(sq, "changeCount"));
+
+    assertEquals(6, sq.replace('-', '.'));
+    assertEquals(".K..BCD.EF..", sq.getSequenceAsString());
+    assertEquals(2, PA.getValue(sq, "changeCount"));
+  }
+
+  @Test(groups = { "Functional" })
+  public void testFindPositions()
+  {
+    SequenceI sq = new Sequence("test/8-13", "-ABC---DE-F--");
+
+    /*
+     * invalid inputs
+     */
+    assertNull(sq.findPositions(6, 5));
+    assertNull(sq.findPositions(0, 5));
+    assertNull(sq.findPositions(-1, 5));
+
+    /*
+     * all gapped ranges
+     */
+    assertNull(sq.findPositions(1, 1)); // 1-based columns
+    assertNull(sq.findPositions(5, 5));
+    assertNull(sq.findPositions(5, 6));
+    assertNull(sq.findPositions(5, 7));
+
+    /*
+     * all ungapped ranges
+     */
+    assertEquals(new Range(8, 8), sq.findPositions(2, 2)); // A
+    assertEquals(new Range(8, 9), sq.findPositions(2, 3)); // AB
+    assertEquals(new Range(8, 10), sq.findPositions(2, 4)); // ABC
+    assertEquals(new Range(9, 10), sq.findPositions(3, 4)); // BC
+
+    /*
+     * gap to ungapped range
+     */
+    assertEquals(new Range(8, 10), sq.findPositions(1, 4)); // ABC
+    assertEquals(new Range(11, 12), sq.findPositions(6, 9)); // DE
+
+    /*
+     * ungapped to gapped range
+     */
+    assertEquals(new Range(10, 10), sq.findPositions(4, 5)); // C
+    assertEquals(new Range(9, 13), sq.findPositions(3, 11)); // BCDEF
+
+    /*
+     * ungapped to ungapped enclosing gaps
+     */
+    assertEquals(new Range(10, 11), sq.findPositions(4, 8)); // CD
+    assertEquals(new Range(8, 13), sq.findPositions(2, 11)); // ABCDEF
+
+    /*
+     * gapped to gapped enclosing ungapped
+     */
+    assertEquals(new Range(8, 10), sq.findPositions(1, 5)); // ABC
+    assertEquals(new Range(11, 12), sq.findPositions(5, 10)); // DE
+    assertEquals(new Range(8, 13), sq.findPositions(1, 13)); // the lot
+    assertEquals(new Range(8, 13), sq.findPositions(1, 99));
+  }
+
+  @Test(groups = { "Functional" })
+  public void testFindFeatures_largeEndPos()
+  {
+    /*
+     * imitate a PDB sequence where end is larger than end position
+     */
+    SequenceI sq = new Sequence("test", "-ABC--DEF--", 1, 20);
+    sq.createDatasetSequence();
+  
+    assertTrue(sq.findFeatures(1, 9).isEmpty());
+    // should be no array bounds exception - JAL-2772
+    assertTrue(sq.findFeatures(1, 15).isEmpty());
+  
+    // add feature on BCD
+    SequenceFeature sfBCD = new SequenceFeature("Cath", "desc", 2, 4, 2f,
+            null);
+    sq.addSequenceFeature(sfBCD);
+  
+    // no features in columns 1-2 (-A)
+    List<SequenceFeature> found = sq.findFeatures(1, 2);
+    assertTrue(found.isEmpty());
+  
+    // columns 1-6 (-ABC--) includes BCD
+    found = sq.findFeatures(1, 6);
+    assertEquals(1, found.size());
+    assertTrue(found.contains(sfBCD));
+
+    // columns 10-11 (--) should find nothing
+    found = sq.findFeatures(10, 11);
+    assertEquals(0, found.size());
+  }
+
+  @Test(groups = { "Functional" })
+  public void testSetName()
+  {
+    SequenceI sq = new Sequence("test", "-ABC---DE-F--");
+    assertEquals("test", sq.getName());
+    assertEquals(1, sq.getStart());
+    assertEquals(6, sq.getEnd());
+
+    sq.setName("testing");
+    assertEquals("testing", sq.getName());
+
+    sq.setName("test/8-10");
+    assertEquals("test", sq.getName());
+    assertEquals(8, sq.getStart());
+    assertEquals(13, sq.getEnd()); // note end is recomputed
+
+    sq.setName("testing/7-99");
+    assertEquals("testing", sq.getName());
+    assertEquals(7, sq.getStart());
+    assertEquals(99, sq.getEnd()); // end may be beyond physical end
+
+    sq.setName("/2-3");
+    assertEquals("", sq.getName());
+    assertEquals(2, sq.getStart());
+    assertEquals(7, sq.getEnd());
+
+    sq.setName("test/"); // invalid
+    assertEquals("test/", sq.getName());
+    assertEquals(2, sq.getStart());
+    assertEquals(7, sq.getEnd());
+
+    sq.setName("test/6-13/7-99");
+    assertEquals("test/6-13", sq.getName());
+    assertEquals(7, sq.getStart());
+    assertEquals(99, sq.getEnd());
+
+    sq.setName("test/0-5"); // 0 is invalid - ignored
+    assertEquals("test/0-5", sq.getName());
+    assertEquals(7, sq.getStart());
+    assertEquals(99, sq.getEnd());
+
+    sq.setName("test/a-5"); // a is invalid - ignored
+    assertEquals("test/a-5", sq.getName());
+    assertEquals(7, sq.getStart());
+    assertEquals(99, sq.getEnd());
+
+    sq.setName("test/6-5"); // start > end is invalid - ignored
+    assertEquals("test/6-5", sq.getName());
+    assertEquals(7, sq.getStart());
+    assertEquals(99, sq.getEnd());
+
+    sq.setName("test/5"); // invalid - ignored
+    assertEquals("test/5", sq.getName());
+    assertEquals(7, sq.getStart());
+    assertEquals(99, sq.getEnd());
+
+    sq.setName("test/-5"); // invalid - ignored
+    assertEquals("test/-5", sq.getName());
+    assertEquals(7, sq.getStart());
+    assertEquals(99, sq.getEnd());
+
+    sq.setName("test/5-"); // invalid - ignored
+    assertEquals("test/5-", sq.getName());
+    assertEquals(7, sq.getStart());
+    assertEquals(99, sq.getEnd());
+
+    sq.setName("test/5-6-7"); // invalid - ignored
+    assertEquals("test/5-6-7", sq.getName());
+    assertEquals(7, sq.getStart());
+    assertEquals(99, sq.getEnd());
+
+    sq.setName(null); // invalid, gets converted to space
+    assertEquals("", sq.getName());
+    assertEquals(7, sq.getStart());
+    assertEquals(99, sq.getEnd());
+  }
+
+  @Test(groups = { "Functional" })
+  public void testCheckValidRange()
+  {
+    Sequence sq = new Sequence("test/7-12", "-ABC---DE-F--");
+    assertEquals(7, sq.getStart());
+    assertEquals(12, sq.getEnd());
+
+    /*
+     * checkValidRange ensures end is at least the last residue position
+     */
+    PA.setValue(sq, "end", 2);
+    sq.checkValidRange();
+    assertEquals(12, sq.getEnd());
+
+    /*
+     * end may be beyond the last residue position
+     */
+    PA.setValue(sq, "end", 22);
+    sq.checkValidRange();
+    assertEquals(22, sq.getEnd());
+  }
+
+  @Test(groups = { "Functional" })
+  public void testDeleteChars_withGaps()
+  {
+    /*
+     * delete gaps only
+     */
+    SequenceI sq = new Sequence("test/8-10", "A-B-C");
+    sq.createDatasetSequence();
+    assertEquals("ABC", sq.getDatasetSequence().getSequenceAsString());
+    sq.deleteChars(1, 2); // delete first gap
+    assertEquals("AB-C", sq.getSequenceAsString());
+    assertEquals(8, sq.getStart());
+    assertEquals(10, sq.getEnd());
+    assertEquals("ABC", sq.getDatasetSequence().getSequenceAsString());
+
+    /*
+     * delete gaps and residues at start (no new dataset sequence)
+     */
+    sq = new Sequence("test/8-10", "A-B-C");
+    sq.createDatasetSequence();
+    sq.deleteChars(0, 3); // delete A-B
+    assertEquals("-C", sq.getSequenceAsString());
+    assertEquals(10, sq.getStart());
+    assertEquals(10, sq.getEnd());
+    assertEquals("ABC", sq.getDatasetSequence().getSequenceAsString());
+
+    /*
+     * delete gaps and residues at end (no new dataset sequence)
+     */
+    sq = new Sequence("test/8-10", "A-B-C");
+    sq.createDatasetSequence();
+    sq.deleteChars(2, 5); // delete B-C
+    assertEquals("A-", sq.getSequenceAsString());
+    assertEquals(8, sq.getStart());
+    assertEquals(8, sq.getEnd());
+    assertEquals("ABC", sq.getDatasetSequence().getSequenceAsString());
+
+    /*
+     * delete gaps and residues internally (new dataset sequence)
+     * first delete from gap to residue
+     */
+    sq = new Sequence("test/8-10", "A-B-C");
+    sq.createDatasetSequence();
+    sq.deleteChars(1, 3); // delete -B
+    assertEquals("A-C", sq.getSequenceAsString());
+    assertEquals(8, sq.getStart());
+    assertEquals(9, sq.getEnd());
+    assertEquals("AC", sq.getDatasetSequence().getSequenceAsString());
+    assertEquals(8, sq.getDatasetSequence().getStart());
+    assertEquals(9, sq.getDatasetSequence().getEnd());
+
+    /*
+     * internal delete from gap to gap
+     */
+    sq = new Sequence("test/8-10", "A-B-C");
+    sq.createDatasetSequence();
+    sq.deleteChars(1, 4); // delete -B-
+    assertEquals("AC", sq.getSequenceAsString());
+    assertEquals(8, sq.getStart());
+    assertEquals(9, sq.getEnd());
+    assertEquals("AC", sq.getDatasetSequence().getSequenceAsString());
+    assertEquals(8, sq.getDatasetSequence().getStart());
+    assertEquals(9, sq.getDatasetSequence().getEnd());
+
+    /*
+     * internal delete from residue to residue
+     */
+    sq = new Sequence("test/8-10", "A-B-C");
+    sq.createDatasetSequence();
+    sq.deleteChars(2, 3); // delete B
+    assertEquals("A--C", sq.getSequenceAsString());
+    assertEquals(8, sq.getStart());
+    assertEquals(9, sq.getEnd());
+    assertEquals("AC", sq.getDatasetSequence().getSequenceAsString());
+    assertEquals(8, sq.getDatasetSequence().getStart());
+    assertEquals(9, sq.getDatasetSequence().getEnd());
+  }
 }
diff --git a/test/jalview/datamodel/features/FeatureStoreTest.java b/test/jalview/datamodel/features/FeatureStoreTest.java
new file mode 100644 (file)
index 0000000..db21c2f
--- /dev/null
@@ -0,0 +1,911 @@
+package jalview.datamodel.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import jalview.datamodel.SequenceFeature;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.testng.annotations.Test;
+
+public class FeatureStoreTest
+{
+
+  @Test(groups = "Functional")
+  public void testFindFeatures_nonNested()
+  {
+    FeatureStore fs = new FeatureStore();
+    fs.addFeature(new SequenceFeature("", "", 10, 20, Float.NaN,
+            null));
+    // same range different description
+    fs.addFeature(new SequenceFeature("", "desc", 10, 20, Float.NaN, null));
+    fs.addFeature(new SequenceFeature("", "", 15, 25, Float.NaN, null));
+    fs.addFeature(new SequenceFeature("", "", 20, 35, Float.NaN, null));
+
+    List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
+    assertTrue(overlaps.isEmpty());
+
+    overlaps = fs.findOverlappingFeatures(8, 10);
+    assertEquals(overlaps.size(), 2);
+    assertEquals(overlaps.get(0).getEnd(), 20);
+    assertEquals(overlaps.get(1).getEnd(), 20);
+
+    overlaps = fs.findOverlappingFeatures(12, 16);
+    assertEquals(overlaps.size(), 3);
+    assertEquals(overlaps.get(0).getEnd(), 20);
+    assertEquals(overlaps.get(1).getEnd(), 20);
+    assertEquals(overlaps.get(2).getEnd(), 25);
+
+    overlaps = fs.findOverlappingFeatures(33, 33);
+    assertEquals(overlaps.size(), 1);
+    assertEquals(overlaps.get(0).getEnd(), 35);
+  }
+
+  @Test(groups = "Functional")
+  public void testFindFeatures_nested()
+  {
+    FeatureStore fs = new FeatureStore();
+    SequenceFeature sf1 = addFeature(fs, 10, 50);
+    SequenceFeature sf2 = addFeature(fs, 10, 40);
+    SequenceFeature sf3 = addFeature(fs, 20, 30);
+    // fudge feature at same location but different group (so is added)
+    SequenceFeature sf4 = new SequenceFeature("", "", 20, 30, Float.NaN,
+            "different group");
+    fs.addFeature(sf4);
+    SequenceFeature sf5 = addFeature(fs, 35, 36);
+
+    List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
+    assertTrue(overlaps.isEmpty());
+
+    overlaps = fs.findOverlappingFeatures(10, 15);
+    assertEquals(overlaps.size(), 2);
+    assertTrue(overlaps.contains(sf1));
+    assertTrue(overlaps.contains(sf2));
+
+    overlaps = fs.findOverlappingFeatures(45, 60);
+    assertEquals(overlaps.size(), 1);
+    assertTrue(overlaps.contains(sf1));
+
+    overlaps = fs.findOverlappingFeatures(32, 38);
+    assertEquals(overlaps.size(), 3);
+    assertTrue(overlaps.contains(sf1));
+    assertTrue(overlaps.contains(sf2));
+    assertTrue(overlaps.contains(sf5));
+
+    overlaps = fs.findOverlappingFeatures(15, 25);
+    assertEquals(overlaps.size(), 4);
+    assertTrue(overlaps.contains(sf1));
+    assertTrue(overlaps.contains(sf2));
+    assertTrue(overlaps.contains(sf3));
+    assertTrue(overlaps.contains(sf4));
+  }
+
+  @Test(groups = "Functional")
+  public void testFindFeatures_mixed()
+  {
+    FeatureStore fs = new FeatureStore();
+    SequenceFeature sf1 = addFeature(fs, 10, 50);
+    SequenceFeature sf2 = addFeature(fs, 1, 15);
+    SequenceFeature sf3 = addFeature(fs, 20, 30);
+    SequenceFeature sf4 = addFeature(fs, 40, 100);
+    SequenceFeature sf5 = addFeature(fs, 60, 100);
+    SequenceFeature sf6 = addFeature(fs, 70, 70);
+
+    List<SequenceFeature> overlaps = fs.findOverlappingFeatures(200, 200);
+    assertTrue(overlaps.isEmpty());
+
+    overlaps = fs.findOverlappingFeatures(1, 9);
+    assertEquals(overlaps.size(), 1);
+    assertTrue(overlaps.contains(sf2));
+
+    overlaps = fs.findOverlappingFeatures(5, 18);
+    assertEquals(overlaps.size(), 2);
+    assertTrue(overlaps.contains(sf1));
+    assertTrue(overlaps.contains(sf2));
+
+    overlaps = fs.findOverlappingFeatures(30, 40);
+    assertEquals(overlaps.size(), 3);
+    assertTrue(overlaps.contains(sf1));
+    assertTrue(overlaps.contains(sf3));
+    assertTrue(overlaps.contains(sf4));
+
+    overlaps = fs.findOverlappingFeatures(80, 90);
+    assertEquals(overlaps.size(), 2);
+    assertTrue(overlaps.contains(sf4));
+    assertTrue(overlaps.contains(sf5));
+
+    overlaps = fs.findOverlappingFeatures(68, 70);
+    assertEquals(overlaps.size(), 3);
+    assertTrue(overlaps.contains(sf4));
+    assertTrue(overlaps.contains(sf5));
+    assertTrue(overlaps.contains(sf6));
+  }
+
+  /**
+   * Helper method to add a feature of no particular type
+   * 
+   * @param fs
+   * @param from
+   * @param to
+   * @return
+   */
+  SequenceFeature addFeature(FeatureStore fs, int from, int to)
+  {
+    SequenceFeature sf1 = new SequenceFeature("", "", from, to, Float.NaN,
+            null);
+    fs.addFeature(sf1);
+    return sf1;
+  }
+
+  @Test(groups = "Functional")
+  public void testFindFeatures_contactFeatures()
+  {
+    FeatureStore fs = new FeatureStore();
+
+    SequenceFeature sf = new SequenceFeature("disulphide bond", "bond", 10,
+            20, Float.NaN, null);
+    fs.addFeature(sf);
+
+    /*
+     * neither contact point in range
+     */
+    List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
+    assertTrue(overlaps.isEmpty());
+
+    /*
+     * neither contact point in range
+     */
+    overlaps = fs.findOverlappingFeatures(11, 19);
+    assertTrue(overlaps.isEmpty());
+
+    /*
+     * first contact point in range
+     */
+    overlaps = fs.findOverlappingFeatures(5, 15);
+    assertEquals(overlaps.size(), 1);
+    assertTrue(overlaps.contains(sf));
+
+    /*
+     * second contact point in range
+     */
+    overlaps = fs.findOverlappingFeatures(15, 25);
+    assertEquals(overlaps.size(), 1);
+    assertTrue(overlaps.contains(sf));
+
+    /*
+     * both contact points in range
+     */
+    overlaps = fs.findOverlappingFeatures(5, 25);
+    assertEquals(overlaps.size(), 1);
+    assertTrue(overlaps.contains(sf));
+  }
+
+  /**
+   * Tests for the method that returns false for an attempt to add a feature
+   * that would enclose, or be enclosed by, another feature
+   */
+  @Test(groups = "Functional")
+  public void testAddNonNestedFeature()
+  {
+    FeatureStore fs = new FeatureStore();
+
+    String type = "Domain";
+    SequenceFeature sf1 = new SequenceFeature(type, type, 10, 20,
+            Float.NaN, null);
+    assertTrue(fs.addNonNestedFeature(sf1));
+
+    // co-located feature is ok
+    SequenceFeature sf2 = new SequenceFeature(type, type, 10, 20,
+            Float.NaN, null);
+    assertTrue(fs.addNonNestedFeature(sf2));
+
+    // overlap left is ok
+    SequenceFeature sf3 = new SequenceFeature(type, type, 5, 15, Float.NaN,
+            null);
+    assertTrue(fs.addNonNestedFeature(sf3));
+
+    // overlap right is ok
+    SequenceFeature sf4 = new SequenceFeature(type, type, 15, 25,
+            Float.NaN, null);
+    assertTrue(fs.addNonNestedFeature(sf4));
+
+    // add enclosing feature is not ok
+    SequenceFeature sf5 = new SequenceFeature(type, type, 10, 21,
+            Float.NaN, null);
+    assertFalse(fs.addNonNestedFeature(sf5));
+    SequenceFeature sf6 = new SequenceFeature(type, type, 4, 15, Float.NaN,
+            null);
+    assertFalse(fs.addNonNestedFeature(sf6));
+    SequenceFeature sf7 = new SequenceFeature(type, type, 1, 50, Float.NaN,
+            null);
+    assertFalse(fs.addNonNestedFeature(sf7));
+
+    // add enclosed feature is not ok
+    SequenceFeature sf8 = new SequenceFeature(type, type, 10, 19,
+            Float.NaN, null);
+    assertFalse(fs.addNonNestedFeature(sf8));
+    SequenceFeature sf9 = new SequenceFeature(type, type, 16, 25,
+            Float.NaN, null);
+    assertFalse(fs.addNonNestedFeature(sf9));
+    SequenceFeature sf10 = new SequenceFeature(type, type, 7, 7, Float.NaN,
+            null);
+    assertFalse(fs.addNonNestedFeature(sf10));
+  }
+
+  @Test(groups = "Functional")
+  public void testGetPositionalFeatures()
+  {
+    FeatureStore store = new FeatureStore();
+    SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
+            Float.NaN, null);
+    store.addFeature(sf1);
+    // same range, different description
+    SequenceFeature sf2 = new SequenceFeature("Metal", "desc2", 10, 20,
+            Float.NaN, null);
+    store.addFeature(sf2);
+    // discontiguous range
+    SequenceFeature sf3 = new SequenceFeature("Metal", "desc", 30, 40,
+            Float.NaN, null);
+    store.addFeature(sf3);
+    // overlapping range
+    SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 15, 35,
+            Float.NaN, null);
+    store.addFeature(sf4);
+    // enclosing range
+    SequenceFeature sf5 = new SequenceFeature("Metal", "desc", 5, 50,
+            Float.NaN, null);
+    store.addFeature(sf5);
+    // non-positional feature
+    SequenceFeature sf6 = new SequenceFeature("Metal", "desc", 0, 0,
+            Float.NaN, null);
+    store.addFeature(sf6);
+    // contact feature
+    SequenceFeature sf7 = new SequenceFeature("Disulphide bond", "desc",
+            18, 45, Float.NaN, null);
+    store.addFeature(sf7);
+
+    List<SequenceFeature> features = store.getPositionalFeatures();
+    assertEquals(features.size(), 6);
+    assertTrue(features.contains(sf1));
+    assertTrue(features.contains(sf2));
+    assertTrue(features.contains(sf3));
+    assertTrue(features.contains(sf4));
+    assertTrue(features.contains(sf5));
+    assertFalse(features.contains(sf6));
+    assertTrue(features.contains(sf7));
+
+    features = store.getNonPositionalFeatures();
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf6));
+  }
+
+  @Test(groups = "Functional")
+  public void testDelete()
+  {
+    FeatureStore store = new FeatureStore();
+    SequenceFeature sf1 = addFeature(store, 10, 20);
+    assertTrue(store.getPositionalFeatures().contains(sf1));
+
+    /*
+     * simple deletion
+     */
+    assertTrue(store.delete(sf1));
+    assertTrue(store.getPositionalFeatures().isEmpty());
+
+    /*
+     * non-positional feature deletion
+     */
+    SequenceFeature sf2 = addFeature(store, 0, 0);
+    assertFalse(store.getPositionalFeatures().contains(sf2));
+    assertTrue(store.getNonPositionalFeatures().contains(sf2));
+    assertTrue(store.delete(sf2));
+    assertTrue(store.getNonPositionalFeatures().isEmpty());
+
+    /*
+     * contact feature deletion
+     */
+    SequenceFeature sf3 = new SequenceFeature("", "Disulphide Bond", 11,
+            23, Float.NaN, null);
+    store.addFeature(sf3);
+    assertEquals(store.getPositionalFeatures().size(), 1);
+    assertTrue(store.getPositionalFeatures().contains(sf3));
+    assertTrue(store.delete(sf3));
+    assertTrue(store.getPositionalFeatures().isEmpty());
+
+    /*
+     * nested feature deletion
+     */
+    SequenceFeature sf4 = addFeature(store, 20, 30);
+    SequenceFeature sf5 = addFeature(store, 22, 26); // to NCList
+    SequenceFeature sf6 = addFeature(store, 23, 24); // child of sf5
+    SequenceFeature sf7 = addFeature(store, 25, 25); // sibling of sf6
+    SequenceFeature sf8 = addFeature(store, 24, 24); // child of sf6
+    SequenceFeature sf9 = addFeature(store, 23, 23); // child of sf6
+    assertEquals(store.getPositionalFeatures().size(), 6);
+
+    // delete a node with children - they take its place
+    assertTrue(store.delete(sf6)); // sf8, sf9 should become children of sf5
+    assertEquals(store.getPositionalFeatures().size(), 5);
+    assertFalse(store.getPositionalFeatures().contains(sf6));
+
+    // delete a node with no children
+    assertTrue(store.delete(sf7));
+    assertEquals(store.getPositionalFeatures().size(), 4);
+    assertFalse(store.getPositionalFeatures().contains(sf7));
+
+    // delete root of NCList
+    assertTrue(store.delete(sf5));
+    assertEquals(store.getPositionalFeatures().size(), 3);
+    assertFalse(store.getPositionalFeatures().contains(sf5));
+
+    // continue the killing fields
+    assertTrue(store.delete(sf4));
+    assertEquals(store.getPositionalFeatures().size(), 2);
+    assertFalse(store.getPositionalFeatures().contains(sf4));
+
+    assertTrue(store.delete(sf9));
+    assertEquals(store.getPositionalFeatures().size(), 1);
+    assertFalse(store.getPositionalFeatures().contains(sf9));
+
+    assertTrue(store.delete(sf8));
+    assertTrue(store.getPositionalFeatures().isEmpty());
+  }
+
+  @Test(groups = "Functional")
+  public void testAddFeature()
+  {
+    FeatureStore fs = new FeatureStore();
+
+    SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
+            Float.NaN, null);
+    SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20,
+            Float.NaN, null);
+
+    assertTrue(fs.addFeature(sf1));
+    assertEquals(fs.getFeatureCount(true), 1); // positional
+    assertEquals(fs.getFeatureCount(false), 0); // non-positional
+
+    /*
+     * re-adding the same or an identical feature should fail
+     */
+    assertFalse(fs.addFeature(sf1));
+    assertEquals(fs.getFeatureCount(true), 1);
+    assertFalse(fs.addFeature(sf2));
+    assertEquals(fs.getFeatureCount(true), 1);
+
+    /*
+     * add non-positional
+     */
+    SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
+            null);
+    assertTrue(fs.addFeature(sf3));
+    assertEquals(fs.getFeatureCount(true), 1); // positional
+    assertEquals(fs.getFeatureCount(false), 1); // non-positional
+    SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
+            null);
+    assertFalse(fs.addFeature(sf4)); // already stored
+    assertEquals(fs.getFeatureCount(true), 1); // positional
+    assertEquals(fs.getFeatureCount(false), 1); // non-positional
+
+    /*
+     * add contact
+     */
+    SequenceFeature sf5 = new SequenceFeature("Disulfide bond", "", 10, 20,
+            Float.NaN, null);
+    assertTrue(fs.addFeature(sf5));
+    assertEquals(fs.getFeatureCount(true), 2); // positional - add 1 for contact
+    assertEquals(fs.getFeatureCount(false), 1); // non-positional
+    SequenceFeature sf6 = new SequenceFeature("Disulfide bond", "", 10, 20,
+            Float.NaN, null);
+    assertFalse(fs.addFeature(sf6)); // already stored
+    assertEquals(fs.getFeatureCount(true), 2); // no change
+    assertEquals(fs.getFeatureCount(false), 1); // no change
+  }
+
+  @Test(groups = "Functional")
+  public void testIsEmpty()
+  {
+    FeatureStore fs = new FeatureStore();
+    assertTrue(fs.isEmpty());
+    assertEquals(fs.getFeatureCount(true), 0);
+
+    /*
+     * non-nested feature
+     */
+    SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
+            Float.NaN, null);
+    fs.addFeature(sf1);
+    assertFalse(fs.isEmpty());
+    assertEquals(fs.getFeatureCount(true), 1);
+    fs.delete(sf1);
+    assertTrue(fs.isEmpty());
+    assertEquals(fs.getFeatureCount(true), 0);
+
+    /*
+     * non-positional feature
+     */
+    sf1 = new SequenceFeature("Cath", "", 0, 0, Float.NaN, null);
+    fs.addFeature(sf1);
+    assertFalse(fs.isEmpty());
+    assertEquals(fs.getFeatureCount(false), 1); // non-positional
+    assertEquals(fs.getFeatureCount(true), 0); // positional
+    fs.delete(sf1);
+    assertTrue(fs.isEmpty());
+    assertEquals(fs.getFeatureCount(false), 0);
+
+    /*
+     * contact feature
+     */
+    sf1 = new SequenceFeature("Disulfide bond", "", 19, 49, Float.NaN, null);
+    fs.addFeature(sf1);
+    assertFalse(fs.isEmpty());
+    assertEquals(fs.getFeatureCount(true), 1);
+    fs.delete(sf1);
+    assertTrue(fs.isEmpty());
+    assertEquals(fs.getFeatureCount(true), 0);
+
+    /*
+     * sf2, sf3 added as nested features
+     */
+    sf1 = new SequenceFeature("Cath", "", 19, 49, Float.NaN, null);
+    SequenceFeature sf2 = new SequenceFeature("Cath", "", 20, 40,
+            Float.NaN, null);
+    SequenceFeature sf3 = new SequenceFeature("Cath", "", 25, 35,
+            Float.NaN, null);
+    fs.addFeature(sf1);
+    fs.addFeature(sf2);
+    fs.addFeature(sf3);
+    assertEquals(fs.getFeatureCount(true), 3);
+    assertTrue(fs.delete(sf1));
+    assertEquals(fs.getFeatureCount(true), 2);
+    // FeatureStore should now only contain features in the NCList
+    assertTrue(fs.nonNestedFeatures.isEmpty());
+    assertEquals(fs.nestedFeatures.size(), 2);
+    assertFalse(fs.isEmpty());
+    assertTrue(fs.delete(sf2));
+    assertEquals(fs.getFeatureCount(true), 1);
+    assertFalse(fs.isEmpty());
+    assertTrue(fs.delete(sf3));
+    assertEquals(fs.getFeatureCount(true), 0);
+    assertTrue(fs.isEmpty()); // all gone
+  }
+
+  @Test(groups = "Functional")
+  public void testGetFeatureGroups()
+  {
+    FeatureStore fs = new FeatureStore();
+    assertTrue(fs.getFeatureGroups(true).isEmpty());
+    assertTrue(fs.getFeatureGroups(false).isEmpty());
+
+    SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 10, 20, 1f, "group1");
+    fs.addFeature(sf1);
+    Set<String> groups = fs.getFeatureGroups(true);
+    assertEquals(groups.size(), 1);
+    assertTrue(groups.contains("group1"));
+
+    /*
+     * add another feature of the same group, delete one, delete both
+     */
+    SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "group1");
+    fs.addFeature(sf2);
+    groups = fs.getFeatureGroups(true);
+    assertEquals(groups.size(), 1);
+    assertTrue(groups.contains("group1"));
+    fs.delete(sf2);
+    groups = fs.getFeatureGroups(true);
+    assertEquals(groups.size(), 1);
+    assertTrue(groups.contains("group1"));
+    fs.delete(sf1);
+    groups = fs.getFeatureGroups(true);
+    assertTrue(fs.getFeatureGroups(true).isEmpty());
+
+    SequenceFeature sf3 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "group2");
+    fs.addFeature(sf3);
+    SequenceFeature sf4 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "Group2");
+    fs.addFeature(sf4);
+    SequenceFeature sf5 = new SequenceFeature("Cath", "desc", 20, 30, 1f, null);
+    fs.addFeature(sf5);
+    groups = fs.getFeatureGroups(true);
+    assertEquals(groups.size(), 3);
+    assertTrue(groups.contains("group2"));
+    assertTrue(groups.contains("Group2")); // case sensitive
+    assertTrue(groups.contains(null)); // null allowed
+    assertTrue(fs.getFeatureGroups(false).isEmpty()); // non-positional
+
+    fs.delete(sf3);
+    groups = fs.getFeatureGroups(true);
+    assertEquals(groups.size(), 2);
+    assertFalse(groups.contains("group2"));
+    fs.delete(sf4);
+    groups = fs.getFeatureGroups(true);
+    assertEquals(groups.size(), 1);
+    assertFalse(groups.contains("Group2"));
+    fs.delete(sf5);
+    groups = fs.getFeatureGroups(true);
+    assertTrue(groups.isEmpty());
+
+    /*
+     * add non-positional feature
+     */
+    SequenceFeature sf6 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
+            "CathGroup");
+    fs.addFeature(sf6);
+    groups = fs.getFeatureGroups(false);
+    assertEquals(groups.size(), 1);
+    assertTrue(groups.contains("CathGroup"));
+    assertTrue(fs.delete(sf6));
+    assertTrue(fs.getFeatureGroups(false).isEmpty());
+  }
+
+  @Test(groups = "Functional")
+  public void testGetTotalFeatureLength()
+  {
+    FeatureStore fs = new FeatureStore();
+    assertEquals(fs.getTotalFeatureLength(), 0);
+
+    addFeature(fs, 10, 20); // 11
+    assertEquals(fs.getTotalFeatureLength(), 11);
+    addFeature(fs, 17, 37); // 21
+    SequenceFeature sf1 = addFeature(fs, 14, 74); // 61
+    assertEquals(fs.getTotalFeatureLength(), 93);
+
+    // non-positional features don't count
+    SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
+            "group1");
+    fs.addFeature(sf2);
+    assertEquals(fs.getTotalFeatureLength(), 93);
+
+    // contact features count 1
+    SequenceFeature sf3 = new SequenceFeature("disulphide bond", "desc",
+            15, 35, 1f, "group1");
+    fs.addFeature(sf3);
+    assertEquals(fs.getTotalFeatureLength(), 94);
+
+    assertTrue(fs.delete(sf1));
+    assertEquals(fs.getTotalFeatureLength(), 33);
+    assertFalse(fs.delete(sf1));
+    assertEquals(fs.getTotalFeatureLength(), 33);
+    assertTrue(fs.delete(sf2));
+    assertEquals(fs.getTotalFeatureLength(), 33);
+    assertTrue(fs.delete(sf3));
+    assertEquals(fs.getTotalFeatureLength(), 32);
+  }
+
+  @Test(groups = "Functional")
+  public void testGetFeatureLength()
+  {
+    /*
+     * positional feature
+     */
+    SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 10, 20, 1f, "group1");
+    assertEquals(FeatureStore.getFeatureLength(sf1), 11);
+  
+    /*
+     * non-positional feature
+     */
+    SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
+            "CathGroup");
+    assertEquals(FeatureStore.getFeatureLength(sf2), 0);
+
+    /*
+     * contact feature counts 1
+     */
+    SequenceFeature sf3 = new SequenceFeature("Disulphide Bond", "desc",
+            14, 28, 1f, "AGroup");
+    assertEquals(FeatureStore.getFeatureLength(sf3), 1);
+  }
+
+  @Test(groups = "Functional")
+  public void testMin()
+  {
+    assertEquals(FeatureStore.min(Float.NaN, Float.NaN), Float.NaN);
+    assertEquals(FeatureStore.min(Float.NaN, 2f), 2f);
+    assertEquals(FeatureStore.min(-2f, Float.NaN), -2f);
+    assertEquals(FeatureStore.min(2f, -3f), -3f);
+  }
+
+  @Test(groups = "Functional")
+  public void testMax()
+  {
+    assertEquals(FeatureStore.max(Float.NaN, Float.NaN), Float.NaN);
+    assertEquals(FeatureStore.max(Float.NaN, 2f), 2f);
+    assertEquals(FeatureStore.max(-2f, Float.NaN), -2f);
+    assertEquals(FeatureStore.max(2f, -3f), 2f);
+  }
+
+  @Test(groups = "Functional")
+  public void testGetMinimumScore_getMaximumScore()
+  {
+    FeatureStore fs = new FeatureStore();
+    assertEquals(fs.getMinimumScore(true), Float.NaN); // positional
+    assertEquals(fs.getMaximumScore(true), Float.NaN);
+    assertEquals(fs.getMinimumScore(false), Float.NaN); // non-positional
+    assertEquals(fs.getMaximumScore(false), Float.NaN);
+
+    // add features with no score
+    SequenceFeature sf1 = new SequenceFeature("type", "desc", 0, 0,
+            Float.NaN, "group");
+    fs.addFeature(sf1);
+    SequenceFeature sf2 = new SequenceFeature("type", "desc", 10, 20,
+            Float.NaN, "group");
+    fs.addFeature(sf2);
+    assertEquals(fs.getMinimumScore(true), Float.NaN);
+    assertEquals(fs.getMaximumScore(true), Float.NaN);
+    assertEquals(fs.getMinimumScore(false), Float.NaN);
+    assertEquals(fs.getMaximumScore(false), Float.NaN);
+
+    // add positional features with score
+    SequenceFeature sf3 = new SequenceFeature("type", "desc", 10, 20, 1f,
+            "group");
+    fs.addFeature(sf3);
+    SequenceFeature sf4 = new SequenceFeature("type", "desc", 12, 16, 4f,
+            "group");
+    fs.addFeature(sf4);
+    assertEquals(fs.getMinimumScore(true), 1f);
+    assertEquals(fs.getMaximumScore(true), 4f);
+    assertEquals(fs.getMinimumScore(false), Float.NaN);
+    assertEquals(fs.getMaximumScore(false), Float.NaN);
+
+    // add non-positional features with score
+    SequenceFeature sf5 = new SequenceFeature("type", "desc", 0, 0, 11f,
+            "group");
+    fs.addFeature(sf5);
+    SequenceFeature sf6 = new SequenceFeature("type", "desc", 0, 0, -7f,
+            "group");
+    fs.addFeature(sf6);
+    assertEquals(fs.getMinimumScore(true), 1f);
+    assertEquals(fs.getMaximumScore(true), 4f);
+    assertEquals(fs.getMinimumScore(false), -7f);
+    assertEquals(fs.getMaximumScore(false), 11f);
+
+    // delete one positional and one non-positional
+    // min-max should be recomputed
+    assertTrue(fs.delete(sf6));
+    assertTrue(fs.delete(sf3));
+    assertEquals(fs.getMinimumScore(true), 4f);
+    assertEquals(fs.getMaximumScore(true), 4f);
+    assertEquals(fs.getMinimumScore(false), 11f);
+    assertEquals(fs.getMaximumScore(false), 11f);
+
+    // delete remaining features with score
+    assertTrue(fs.delete(sf4));
+    assertTrue(fs.delete(sf5));
+    assertEquals(fs.getMinimumScore(true), Float.NaN);
+    assertEquals(fs.getMaximumScore(true), Float.NaN);
+    assertEquals(fs.getMinimumScore(false), Float.NaN);
+    assertEquals(fs.getMaximumScore(false), Float.NaN);
+
+    // delete all features
+    assertTrue(fs.delete(sf1));
+    assertTrue(fs.delete(sf2));
+    assertTrue(fs.isEmpty());
+    assertEquals(fs.getMinimumScore(true), Float.NaN);
+    assertEquals(fs.getMaximumScore(true), Float.NaN);
+    assertEquals(fs.getMinimumScore(false), Float.NaN);
+    assertEquals(fs.getMaximumScore(false), Float.NaN);
+  }
+
+  @Test(groups = "Functional")
+  public void testListContains()
+  {
+    assertFalse(FeatureStore.listContains(null, null));
+    List<SequenceFeature> features = new ArrayList<SequenceFeature>();
+    assertFalse(FeatureStore.listContains(features, null));
+
+    SequenceFeature sf1 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
+            "group1");
+    assertFalse(FeatureStore.listContains(null, sf1));
+    assertFalse(FeatureStore.listContains(features, sf1));
+
+    features.add(sf1);
+    SequenceFeature sf2 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
+            "group1");
+    SequenceFeature sf3 = new SequenceFeature("type1", "desc1", 20, 40, 3f,
+            "group1");
+
+    // sf2.equals(sf1) so contains should return true
+    assertTrue(FeatureStore.listContains(features, sf2));
+    assertFalse(FeatureStore.listContains(features, sf3));
+  }
+
+  @Test(groups = "Functional")
+  public void testGetFeaturesForGroup()
+  {
+    FeatureStore fs = new FeatureStore();
+
+    /*
+     * with no features
+     */
+    assertTrue(fs.getFeaturesForGroup(true, null).isEmpty());
+    assertTrue(fs.getFeaturesForGroup(false, null).isEmpty());
+    assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty());
+    assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty());
+
+    /*
+     * sf1: positional feature in the null group
+     */
+    SequenceFeature sf1 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
+            null);
+    fs.addFeature(sf1);
+    assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty());
+    assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty());
+    assertTrue(fs.getFeaturesForGroup(false, null).isEmpty());
+    List<SequenceFeature> features = fs.getFeaturesForGroup(true, null);
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf1));
+
+    /*
+     * sf2: non-positional feature in the null group
+     * sf3: positional feature in a non-null group
+     * sf4: non-positional feature in a non-null group
+     */
+    SequenceFeature sf2 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
+            null);
+    SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
+            "Uniprot");
+    SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
+            "Rfam");
+    fs.addFeature(sf2);
+    fs.addFeature(sf3);
+    fs.addFeature(sf4);
+
+    features = fs.getFeaturesForGroup(true, null);
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf1));
+
+    features = fs.getFeaturesForGroup(false, null);
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf2));
+
+    features = fs.getFeaturesForGroup(true, "Uniprot");
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf3));
+
+    features = fs.getFeaturesForGroup(false, "Rfam");
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf4));
+  }
+
+  @Test(groups = "Functional")
+  public void testShiftFeatures()
+  {
+    FeatureStore fs = new FeatureStore();
+    assertFalse(fs.shiftFeatures(1));
+
+    SequenceFeature sf1 = new SequenceFeature("Cath", "", 2, 5, 0f, null);
+    fs.addFeature(sf1);
+    // nested feature:
+    SequenceFeature sf2 = new SequenceFeature("Cath", "", 8, 14, 0f, null);
+    fs.addFeature(sf2);
+    // contact feature:
+    SequenceFeature sf3 = new SequenceFeature("Disulfide bond", "", 23, 32,
+            0f, null);
+    fs.addFeature(sf3);
+    // non-positional feature:
+    SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f, null);
+    fs.addFeature(sf4);
+
+    /*
+     * shift features right by 5
+     */
+    assertTrue(fs.shiftFeatures(5));
+
+    // non-positional features untouched:
+    List<SequenceFeature> nonPos = fs.getNonPositionalFeatures();
+    assertEquals(nonPos.size(), 1);
+    assertTrue(nonPos.contains(sf4));
+
+    // positional features are replaced
+    List<SequenceFeature> pos = fs.getPositionalFeatures();
+    assertEquals(pos.size(), 3);
+    assertFalse(pos.contains(sf1));
+    assertFalse(pos.contains(sf2));
+    assertFalse(pos.contains(sf3));
+    SequenceFeatures.sortFeatures(pos, true); // ascending start pos
+    assertEquals(pos.get(0).getBegin(), 7);
+    assertEquals(pos.get(0).getEnd(), 10);
+    assertEquals(pos.get(1).getBegin(), 13);
+    assertEquals(pos.get(1).getEnd(), 19);
+    assertEquals(pos.get(2).getBegin(), 28);
+    assertEquals(pos.get(2).getEnd(), 37);
+
+    /*
+     * now shift left by 15
+     * feature at [7-10] should be removed
+     * feature at [13-19] should become [1-4] 
+     */
+    assertTrue(fs.shiftFeatures(-15));
+    pos = fs.getPositionalFeatures();
+    assertEquals(pos.size(), 2);
+    SequenceFeatures.sortFeatures(pos, true);
+    assertEquals(pos.get(0).getBegin(), 1);
+    assertEquals(pos.get(0).getEnd(), 4);
+    assertEquals(pos.get(1).getBegin(), 13);
+    assertEquals(pos.get(1).getEnd(), 22);
+  }
+
+  @Test(groups = "Functional")
+  public void testDelete_readd()
+  {
+    /*
+     * add a feature and a nested feature
+     */
+    FeatureStore store = new FeatureStore();
+    SequenceFeature sf1 = addFeature(store, 10, 20);
+    // sf2 is nested in sf1 so will be stored in nestedFeatures
+    SequenceFeature sf2 = addFeature(store, 12, 14);
+    List<SequenceFeature> features = store.getPositionalFeatures();
+    assertEquals(features.size(), 2);
+    assertTrue(features.contains(sf1));
+    assertTrue(features.contains(sf2));
+    assertTrue(store.nonNestedFeatures.contains(sf1));
+    assertTrue(store.nestedFeatures.contains(sf2));
+  
+    /*
+     * delete the first feature
+     */
+    assertTrue(store.delete(sf1));
+    features = store.getPositionalFeatures();
+    assertFalse(features.contains(sf1));
+    assertTrue(features.contains(sf2));
+
+    /*
+     * re-add the 'nested' feature; is it now duplicated?
+     */
+    store.addFeature(sf2);
+    features = store.getPositionalFeatures();
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf2));
+  }
+
+  @Test(groups = "Functional")
+  public void testContains()
+  {
+    FeatureStore fs = new FeatureStore();
+    SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
+            Float.NaN, "group1");
+    SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20,
+            Float.NaN, "group2");
+    SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
+            "group1");
+    SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f,
+            "group1");
+    SequenceFeature sf5 = new SequenceFeature("Disulphide Bond", "", 5, 15,
+            Float.NaN, "group1");
+    SequenceFeature sf6 = new SequenceFeature("Disulphide Bond", "", 5, 15,
+            Float.NaN, "group2");
+
+    fs.addFeature(sf1);
+    fs.addFeature(sf3);
+    fs.addFeature(sf5);
+    assertTrue(fs.contains(sf1)); // positional feature
+    assertTrue(fs.contains(new SequenceFeature(sf1))); // identical feature
+    assertFalse(fs.contains(sf2)); // different group
+    assertTrue(fs.contains(sf3)); // non-positional
+    assertTrue(fs.contains(new SequenceFeature(sf3)));
+    assertFalse(fs.contains(sf4)); // different score
+    assertTrue(fs.contains(sf5)); // contact feature
+    assertTrue(fs.contains(new SequenceFeature(sf5)));
+    assertFalse(fs.contains(sf6)); // different group
+
+    /*
+     * add a nested feature
+     */
+    SequenceFeature sf7 = new SequenceFeature("Cath", "", 12, 16,
+            Float.NaN, "group1");
+    fs.addFeature(sf7);
+    assertTrue(fs.contains(sf7));
+    assertTrue(fs.contains(new SequenceFeature(sf7)));
+
+    /*
+     * delete the outer (enclosing, non-nested) feature
+     */
+    fs.delete(sf1);
+    assertFalse(fs.contains(sf1));
+    assertTrue(fs.contains(sf7));
+  }
+}
diff --git a/test/jalview/datamodel/features/NCListTest.java b/test/jalview/datamodel/features/NCListTest.java
new file mode 100644 (file)
index 0000000..2c7f752
--- /dev/null
@@ -0,0 +1,682 @@
+package jalview.datamodel.features;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+
+import jalview.datamodel.ContiguousI;
+import jalview.datamodel.Range;
+import jalview.datamodel.SequenceFeature;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Random;
+
+import junit.extensions.PA;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+public class NCListTest
+{
+
+  private Random random = new Random(107);
+
+  private Comparator<ContiguousI> sorter = new RangeComparator(true);
+
+  /**
+   * A basic sanity test of the constructor
+   */
+  @Test(groups = "Functional")
+  public void testConstructor()
+  {
+    List<Range> ranges = new ArrayList<Range>();
+    ranges.add(new Range(20, 20));
+    ranges.add(new Range(10, 20));
+    ranges.add(new Range(15, 30));
+    ranges.add(new Range(10, 30));
+    ranges.add(new Range(11, 19));
+    ranges.add(new Range(10, 20));
+    ranges.add(new Range(1, 100));
+
+    NCList<Range> ncl = new NCList<Range>(ranges);
+    String expected = "[1-100 [10-30 [10-20 [10-20 [11-19]]]], 15-30 [20-20]]";
+    assertEquals(ncl.toString(), expected);
+    assertTrue(ncl.isValid());
+
+    Collections.reverse(ranges);
+    ncl = new NCList<Range>(ranges);
+    assertEquals(ncl.toString(), expected);
+    assertTrue(ncl.isValid());
+  }
+
+  @Test(groups = "Functional")
+  public void testFindOverlaps()
+  {
+    List<Range> ranges = new ArrayList<Range>();
+    ranges.add(new Range(20, 50));
+    ranges.add(new Range(30, 70));
+    ranges.add(new Range(1, 100));
+    ranges.add(new Range(70, 120));
+  
+    NCList<Range> ncl = new NCList<Range>(ranges);
+
+    List<Range> overlaps = ncl.findOverlaps(121, 122);
+    assertEquals(overlaps.size(), 0);
+
+    overlaps = ncl.findOverlaps(21, 22);
+    assertEquals(overlaps.size(), 2);
+    assertEquals(((ContiguousI) overlaps.get(0)).getBegin(), 1);
+    assertEquals(((ContiguousI) overlaps.get(0)).getEnd(), 100);
+    assertEquals(((ContiguousI) overlaps.get(1)).getBegin(), 20);
+    assertEquals(((ContiguousI) overlaps.get(1)).getEnd(), 50);
+
+    overlaps = ncl.findOverlaps(110, 110);
+    assertEquals(overlaps.size(), 1);
+    assertEquals(((ContiguousI) overlaps.get(0)).getBegin(), 70);
+    assertEquals(((ContiguousI) overlaps.get(0)).getEnd(), 120);
+  }
+
+  @Test(groups = "Functional")
+  public void testAdd_onTheEnd()
+  {
+    List<Range> ranges = new ArrayList<Range>();
+    ranges.add(new Range(20, 50));
+    NCList<Range> ncl = new NCList<Range>(ranges);
+    assertEquals(ncl.toString(), "[20-50]");
+    assertTrue(ncl.isValid());
+
+    ncl.add(new Range(60, 70));
+    assertEquals(ncl.toString(), "[20-50, 60-70]");
+    assertTrue(ncl.isValid());
+  }
+
+  @Test(groups = "Functional")
+  public void testAdd_inside()
+  {
+    List<Range> ranges = new ArrayList<Range>();
+    ranges.add(new Range(20, 50));
+    NCList<Range> ncl = new NCList<Range>(ranges);
+    assertEquals(ncl.toString(), "[20-50]");
+    assertTrue(ncl.isValid());
+
+    ncl.add(new Range(30, 40));
+    assertEquals(ncl.toString(), "[20-50 [30-40]]");
+  }
+
+  @Test(groups = "Functional")
+  public void testAdd_onTheFront()
+  {
+    List<Range> ranges = new ArrayList<Range>();
+    ranges.add(new Range(20, 50));
+    NCList<Range> ncl = new NCList<Range>(ranges);
+    assertEquals(ncl.toString(), "[20-50]");
+    assertTrue(ncl.isValid());
+
+    ncl.add(new Range(5, 15));
+    assertEquals(ncl.toString(), "[5-15, 20-50]");
+    assertTrue(ncl.isValid());
+  }
+
+  @Test(groups = "Functional")
+  public void testAdd_enclosing()
+  {
+    List<Range> ranges = new ArrayList<Range>();
+    ranges.add(new Range(20, 50));
+    ranges.add(new Range(30, 60));
+    NCList<Range> ncl = new NCList<Range>(ranges);
+    assertEquals(ncl.toString(), "[20-50, 30-60]");
+    assertTrue(ncl.isValid());
+    assertEquals(ncl.getStart(), 20);
+
+    ncl.add(new Range(10, 70));
+    assertEquals(ncl.toString(), "[10-70 [20-50, 30-60]]");
+    assertTrue(ncl.isValid());
+  }
+
+  @Test(groups = "Functional")
+  public void testAdd_spanning()
+  {
+    List<Range> ranges = new ArrayList<Range>();
+    ranges.add(new Range(20, 40));
+    ranges.add(new Range(60, 70));
+    NCList<Range> ncl = new NCList<Range>(ranges);
+    assertEquals(ncl.toString(), "[20-40, 60-70]");
+    assertTrue(ncl.isValid());
+
+    ncl.add(new Range(30, 50));
+    assertEquals(ncl.toString(), "[20-40, 30-50, 60-70]");
+    assertTrue(ncl.isValid());
+
+    ncl.add(new Range(40, 65));
+    assertEquals(ncl.toString(), "[20-40, 30-50, 40-65, 60-70]");
+    assertTrue(ncl.isValid());
+  }
+
+  /**
+   * Provides the scales for pseudo-random NCLists i.e. the range of the maximal
+   * [0-scale] interval to be stored
+   * 
+   * @return
+   */
+  @DataProvider(name = "scalesOfLife")
+  public Object[][] getScales()
+  {
+    return new Object[][] { new Integer[] { 10 }, new Integer[] { 100 } };
+  }
+
+  /**
+   * Do a number of pseudo-random (reproducible) builds of an NCList, to
+   * exercise as many methods of the class as possible while generating the
+   * range of possible structure topologies
+   * <ul>
+   * <li>verify that add adds an entry and increments size</li>
+   * <li>...except where the entry is already contained (by equals test)</li>
+   * <li>verify that the structure is valid at all stages of construction</li>
+   * <li>generate, run and verify a range of overlap queries</li>
+   * <li>tear down the structure by deleting entries, verifying correctness at
+   * each stage</li>
+   * </ul>
+   */
+  @Test(groups = "Functional", dataProvider = "scalesOfLife")
+  public void test_pseudoRandom(Integer scale)
+  {
+    NCList<SequenceFeature> ncl = new NCList<SequenceFeature>();
+    List<SequenceFeature> features = new ArrayList<SequenceFeature>(scale);
+    
+    testAdd_pseudoRandom(scale, ncl, features);
+
+    /*
+     * sort the list of added ranges - this doesn't affect the test,
+     * just makes it easier to inspect the data in the debugger
+     */
+    Collections.sort(features, sorter);
+
+    testFindOverlaps_pseudoRandom(ncl, scale, features);
+
+    testDelete_pseudoRandom(ncl, features);
+  }
+
+  /**
+   * Pick randomly selected entries to delete in turn, checking the NCList size
+   * and validity at each stage, until it is empty
+   * 
+   * @param ncl
+   * @param features
+   */
+  protected void testDelete_pseudoRandom(NCList<SequenceFeature> ncl,
+          List<SequenceFeature> features)
+  {
+    int deleted = 0;
+
+    while (!features.isEmpty())
+    {
+      assertEquals(ncl.size(), features.size());
+      int toDelete = random.nextInt(features.size());
+      SequenceFeature entry = features.get(toDelete);
+      assertTrue(ncl.contains(entry), String.format(
+              "NCList doesn't contain entry [%d] '%s'!", deleted,
+              entry.toString()));
+
+      ncl.delete(entry);
+      assertFalse(ncl.contains(entry), String.format(
+              "NCList still contains deleted entry [%d] '%s'!", deleted,
+              entry.toString()));
+      features.remove(toDelete);
+      deleted++;
+
+      assertTrue(ncl.isValid(), String.format(
+              "NCList invalid after %d deletions, last deleted was '%s'",
+              deleted, entry.toString()));
+
+      /*
+       * brute force check that deleting one entry didn't delete any others
+       */
+      for (int i = 0; i < features.size(); i++)
+      {
+        SequenceFeature sf = features.get(i);
+        assertTrue(ncl.contains(sf), String.format(
+                        "NCList doesn't contain entry [%d] %s after deleting '%s'!",
+                        i, sf.toString(), entry.toString()));
+      }
+    }
+    assertEquals(ncl.size(), 0); // all gone
+  }
+
+  /**
+   * Randomly generate entries and add them to the NCList, checking its validity
+   * and size at each stage. A few entries should be duplicates (by equals test)
+   * so not get added.
+   * 
+   * @param scale
+   * @param ncl
+   * @param features
+   */
+  protected void testAdd_pseudoRandom(Integer scale,
+          NCList<SequenceFeature> ncl,
+          List<SequenceFeature> features)
+  {
+    int count = 0;
+    final int size = 50;
+
+    for (int i = 0; i < size; i++)
+    {
+      int r1 = random.nextInt(scale + 1);
+      int r2 = random.nextInt(scale + 1);
+      int from = Math.min(r1, r2);
+      int to = Math.max(r1, r2);
+
+      /*
+       * choice of two feature values means that occasionally an identical
+       * feature may be generated, in which case it should not be added 
+       */
+      float value = (float) i % 2;
+      SequenceFeature feature = new SequenceFeature("Pfam", "", from, to,
+              value, "group");
+
+      /*
+       * add to NCList - with duplicate entries (by equals) disallowed
+       */
+      ncl.add(feature, false);
+      if (features.contains(feature))
+      {
+        System.out.println("Duplicate feature generated "
+                + feature.toString());
+      }
+      else
+      {
+        features.add(feature);
+        count++;
+      }
+    
+      /*
+       * check list format is valid at each stage of its construction
+       */
+      assertTrue(ncl.isValid(),
+              String.format("Failed for scale = %d, i=%d", scale, i));
+      assertEquals(ncl.size(), count);
+    }
+    // System.out.println(ncl.prettyPrint());
+  }
+
+  /**
+   * A helper method that generates pseudo-random range queries and veries that
+   * findOverlaps returns the correct matches
+   * 
+   * @param ncl
+   *          the NCList to query
+   * @param scale
+   *          ncl maximal range is [0, scale]
+   * @param features
+   *          a list of the ranges stored in ncl
+   */
+  protected void testFindOverlaps_pseudoRandom(NCList<SequenceFeature> ncl,
+          int scale,
+          List<SequenceFeature> features)
+  {
+    int halfScale = scale / 2;
+    int minIterations = 20;
+
+    /*
+     * generates ranges in [-halfScale, scale+halfScale]
+     * - some should be internal to [0, scale] P = 1/4
+     * - some should lie before 0 P = 1/16
+     * - some should lie after scale P = 1/16
+     * - some should overlap left P = 1/4
+     * - some should overlap right P = 1/4
+     * - some should enclose P = 1/8
+     * 
+     * 50 iterations give a 96% probability of including the
+     * unlikeliest case; keep going until we have done all!
+     */
+    boolean inside = false;
+    boolean enclosing = false;
+    boolean before = false;
+    boolean after = false;
+    boolean overlapLeft = false;
+    boolean overlapRight = false;
+    boolean allCasesCovered = false;
+
+    int i = 0;
+    while (i < minIterations || !allCasesCovered)
+    {
+      i++;
+      int r1 = random.nextInt((scale + 1) * 2);
+      int r2 = random.nextInt((scale + 1) * 2);
+      int from = Math.min(r1, r2) - halfScale;
+      int to = Math.max(r1, r2) - halfScale;
+
+      /*
+       * ensure all cases of interest get covered
+       */
+      inside |= from >= 0 && to <= scale;
+      enclosing |= from <= 0 && to >= scale;
+      before |= to < 0;
+      after |= from > scale;
+      overlapLeft |= from < 0 && to >= 0 && to <= scale;
+      overlapRight |= from >= 0 && from <= scale && to > scale;
+      if (!allCasesCovered)
+      {
+        allCasesCovered |= inside && enclosing && before && after
+              && overlapLeft && overlapRight;
+        if (allCasesCovered)
+        {
+          System.out
+                  .println(String
+                          .format("Covered all findOverlaps cases after %d iterations for scale %d",
+                                  i, scale));
+        }
+      }
+
+      verifyFindOverlaps(ncl, from, to, features);
+    }
+  }
+
+  /**
+   * A helper method that verifies that overlaps found by interrogating an
+   * NCList correctly match those found by brute force search
+   * 
+   * @param ncl
+   * @param from
+   * @param to
+   * @param features
+   */
+  protected void verifyFindOverlaps(NCList<SequenceFeature> ncl, int from,
+          int to, List<SequenceFeature> features)
+  {
+    List<SequenceFeature> overlaps = ncl.findOverlaps(from, to);
+
+    /*
+     * check returned entries do indeed overlap from-to range
+     */
+    for (ContiguousI sf : overlaps)
+    {
+      int begin = sf.getBegin();
+      int end = sf.getEnd();
+      assertTrue(begin <= to && end >= from, String.format(
+              "[%d, %d] does not overlap query range [%d, %d]", begin, end,
+              from, to));
+    }
+
+    /*
+     * check overlapping ranges are included in the results
+     * (the test above already shows non-overlapping ranges are not)
+     */
+    for (ContiguousI sf : features)
+    {
+      int begin = sf.getBegin();
+      int end = sf.getEnd();
+      if (begin <= to && end >= from)
+      {
+        boolean found = overlaps.contains(sf);
+        assertTrue(found, String.format(
+                "[%d, %d] missing in query range [%d, %d]", begin, end,
+                from, to));
+      }
+    }
+  }
+
+  @Test(groups = "Functional")
+  public void testGetEntries()
+  {
+    List<Range> ranges = new ArrayList<Range>();
+    Range r1 = new Range(20, 20);
+    Range r2 = new Range(10, 20);
+    Range r3 = new Range(15, 30);
+    Range r4 = new Range(10, 30);
+    Range r5 = new Range(11, 19);
+    Range r6 = new Range(10, 20);
+    ranges.add(r1);
+    ranges.add(r2);
+    ranges.add(r3);
+    ranges.add(r4);
+    ranges.add(r5);
+    ranges.add(r6);
+  
+    NCList<Range> ncl = new NCList<Range>(ranges);
+    Range r7 = new Range(1, 100);
+    ncl.add(r7);
+
+    List<Range> contents = ncl.getEntries();
+    assertEquals(contents.size(), 7);
+    assertTrue(contents.contains(r1));
+    assertTrue(contents.contains(r2));
+    assertTrue(contents.contains(r3));
+    assertTrue(contents.contains(r4));
+    assertTrue(contents.contains(r5));
+    assertTrue(contents.contains(r6));
+    assertTrue(contents.contains(r7));
+
+    ncl = new NCList<Range>();
+    assertTrue(ncl.getEntries().isEmpty());
+  }
+
+  @Test(groups = "Functional")
+  public void testDelete()
+  {
+    List<Range> ranges = new ArrayList<Range>();
+    Range r1 = new Range(20, 30);
+    ranges.add(r1);
+    NCList<Range> ncl = new NCList<Range>(ranges);
+    assertTrue(ncl.getEntries().contains(r1));
+
+    Range r2 = new Range(20, 30);
+    assertFalse(ncl.delete(null)); // null argument
+    assertFalse(ncl.delete(r2)); // never added
+    assertTrue(ncl.delete(r1)); // success
+    assertTrue(ncl.getEntries().isEmpty());
+
+    /*
+     * tests where object.equals() == true
+     */
+    NCList<SequenceFeature> features = new NCList<SequenceFeature>();
+    SequenceFeature sf1 = new SequenceFeature("type", "desc", 1, 10, 2f,
+            "group");
+    SequenceFeature sf2 = new SequenceFeature("type", "desc", 1, 10, 2f,
+            "group");
+    features.add(sf1);
+    assertEquals(sf1, sf2); // sf1.equals(sf2)
+    assertFalse(features.delete(sf2)); // equality is not enough for deletion
+    assertTrue(features.getEntries().contains(sf1)); // still there!
+    assertTrue(features.delete(sf1));
+    assertTrue(features.getEntries().isEmpty()); // gone now
+
+    /*
+     * test with duplicate objects in NCList
+     */
+    features.add(sf1);
+    features.add(sf1);
+    assertEquals(features.getEntries().size(), 2);
+    assertSame(features.getEntries().get(0), sf1);
+    assertSame(features.getEntries().get(1), sf1);
+    assertTrue(features.delete(sf1)); // first match only is deleted
+    assertTrue(features.contains(sf1));
+    assertEquals(features.size(), 1);
+    assertTrue(features.delete(sf1));
+    assertTrue(features.getEntries().isEmpty());
+  }
+
+  @Test(groups = "Functional")
+  public void testAdd_overlapping()
+  {
+    List<Range> ranges = new ArrayList<Range>();
+    ranges.add(new Range(40, 50));
+    ranges.add(new Range(20, 30));
+    NCList<Range> ncl = new NCList<Range>(ranges);
+    assertEquals(ncl.toString(), "[20-30, 40-50]");
+    assertTrue(ncl.isValid());
+  
+    /*
+     * add range overlapping internally
+     */
+    ncl.add(new Range(25, 35));
+    assertEquals(ncl.toString(), "[20-30, 25-35, 40-50]");
+    assertTrue(ncl.isValid());
+
+    /*
+     * add range overlapping last range
+     */
+    ncl.add(new Range(45, 55));
+    assertEquals(ncl.toString(), "[20-30, 25-35, 40-50, 45-55]");
+    assertTrue(ncl.isValid());
+
+    /*
+     * add range overlapping first range
+     */
+    ncl.add(new Range(15, 25));
+    assertEquals(ncl.toString(), "[15-25, 20-30, 25-35, 40-50, 45-55]");
+    assertTrue(ncl.isValid());
+  }
+
+  /**
+   * Test the contains method (which uses object equals test)
+   */
+  @Test(groups = "Functional")
+  public void testContains()
+  {
+    NCList<SequenceFeature> ncl = new NCList<SequenceFeature>();
+    SequenceFeature sf1 = new SequenceFeature("type", "desc", 1, 10, 2f,
+            "group");
+    SequenceFeature sf2 = new SequenceFeature("type", "desc", 1, 10, 2f,
+            "group");
+    SequenceFeature sf3 = new SequenceFeature("type", "desc", 1, 10, 2f,
+            "anothergroup");
+    ncl.add(sf1);
+
+    assertTrue(ncl.contains(sf1));
+    assertTrue(ncl.contains(sf2)); // sf1.equals(sf2)
+    assertFalse(ncl.contains(sf3)); // !sf1.equals(sf3)
+
+    /*
+     * make some deeper structure in the NCList
+     */
+    SequenceFeature sf4 = new SequenceFeature("type", "desc", 2, 9, 2f,
+            "group");
+    ncl.add(sf4);
+    assertTrue(ncl.contains(sf4));
+    SequenceFeature sf5 = new SequenceFeature("type", "desc", 4, 5, 2f,
+            "group");
+    SequenceFeature sf6 = new SequenceFeature("type", "desc", 6, 8, 2f,
+            "group");
+    ncl.add(sf5);
+    ncl.add(sf6);
+    assertTrue(ncl.contains(sf5));
+    assertTrue(ncl.contains(sf6));
+  }
+
+  @Test(groups = "Functional")
+  public void testIsValid()
+  {
+    List<Range> ranges = new ArrayList<Range>();
+    Range r1 = new Range(40, 50);
+    ranges.add(r1);
+    NCList<Range> ncl = new NCList<Range>(ranges);
+    assertTrue(ncl.isValid());
+
+    Range r2 = new Range(42, 44);
+    ncl.add(r2);
+    assertTrue(ncl.isValid());
+    Range r3 = new Range(46, 48);
+    ncl.add(r3);
+    assertTrue(ncl.isValid());
+    Range r4 = new Range(43, 43);
+    ncl.add(r4);
+    assertTrue(ncl.isValid());
+
+    assertEquals(ncl.toString(), "[40-50 [42-44 [43-43], 46-48]]");
+    assertTrue(ncl.isValid());
+
+    PA.setValue(r1, "start", 43);
+    assertFalse(ncl.isValid()); // r2 not inside r1
+    PA.setValue(r1, "start", 40);
+    assertTrue(ncl.isValid());
+
+    PA.setValue(r3, "start", 41);
+    assertFalse(ncl.isValid()); // r3 should precede r2
+    PA.setValue(r3, "start", 46);
+    assertTrue(ncl.isValid());
+
+    PA.setValue(r4, "start", 41);
+    assertFalse(ncl.isValid()); // r4 not inside r2
+    PA.setValue(r4, "start", 43);
+    assertTrue(ncl.isValid());
+
+    PA.setValue(r4, "start", 44);
+    assertFalse(ncl.isValid()); // r4 has reverse range
+  }
+
+  @Test(groups = "Functional")
+  public void testPrettyPrint()
+  {
+    /*
+     * construct NCList from a list of ranges
+     * they are sorted then assembled into NCList subregions
+     * notice that 42-42 end up inside 41-46
+     */
+    List<Range> ranges = new ArrayList<Range>();
+    ranges.add(new Range(40, 50));
+    ranges.add(new Range(45, 55));
+    ranges.add(new Range(40, 45));
+    ranges.add(new Range(41, 46));
+    ranges.add(new Range(42, 42));
+    ranges.add(new Range(42, 42));
+    NCList<Range> ncl = new NCList<Range>(ranges);
+    assertTrue(ncl.isValid());
+    assertEquals(ncl.toString(),
+            "[40-50 [40-45], 41-46 [42-42 [42-42]], 45-55]");
+    String expected = "40-50\n  40-45\n41-46\n  42-42\n    42-42\n45-55\n";
+    assertEquals(ncl.prettyPrint(), expected);
+
+    /*
+     * repeat but now add ranges one at a time
+     * notice that 42-42 end up inside 40-50 so we get
+     * a different but equal valid NCList structure
+     */
+    ranges.clear();
+    ncl = new NCList<Range>(ranges);
+    ncl.add(new Range(40, 50));
+    ncl.add(new Range(45, 55));
+    ncl.add(new Range(40, 45));
+    ncl.add(new Range(41, 46));
+    ncl.add(new Range(42, 42));
+    ncl.add(new Range(42, 42));
+    assertTrue(ncl.isValid());
+    assertEquals(ncl.toString(),
+            "[40-50 [40-45 [42-42 [42-42]], 41-46], 45-55]");
+    expected = "40-50\n  40-45\n    42-42\n      42-42\n  41-46\n45-55\n";
+    assertEquals(ncl.prettyPrint(), expected);
+  }
+
+  /**
+   * A test that shows different valid trees can be constructed from the same
+   * set of ranges, depending on the order of construction
+   */
+  @Test(groups = "Functional")
+  public void testConstructor_alternativeTrees()
+  {
+    List<Range> ranges = new ArrayList<Range>();
+    ranges.add(new Range(10, 60));
+    ranges.add(new Range(20, 30));
+    ranges.add(new Range(40, 50));
+  
+    /*
+     * constructor with greedy traversal of sorted ranges to build nested
+     * containment lists results in 20-30 inside 10-60, 40-50 a sibling
+     */
+    NCList<Range> ncl = new NCList<Range>(ranges);
+    assertEquals(ncl.toString(), "[10-60 [20-30], 40-50]");
+    assertTrue(ncl.isValid());
+
+    /*
+     * adding ranges one at a time results in 40-50 
+     * a sibling of 20-30 inside 10-60
+     */
+    ncl = new NCList<Range>(new Range(10, 60));
+    ncl.add(new Range(20, 30));
+    ncl.add(new Range(40, 50));
+    assertEquals(ncl.toString(), "[10-60 [20-30, 40-50]]");
+    assertTrue(ncl.isValid());
+  }
+}
diff --git a/test/jalview/datamodel/features/NCNodeTest.java b/test/jalview/datamodel/features/NCNodeTest.java
new file mode 100644 (file)
index 0000000..4713084
--- /dev/null
@@ -0,0 +1,136 @@
+package jalview.datamodel.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import jalview.datamodel.Range;
+import jalview.datamodel.SequenceFeature;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.extensions.PA;
+
+import org.testng.annotations.Test;
+
+public class NCNodeTest
+{
+  @Test(groups = "Functional")
+  public void testAdd()
+  {
+    Range r1 = new Range(10, 20);
+    NCNode<Range> node = new NCNode<Range>(r1);
+    assertEquals(node.getBegin(), 10);
+    Range r2 = new Range(10, 15);
+    node.add(r2);
+
+    List<Range> contents = new ArrayList<Range>();
+    node.getEntries(contents);
+    assertEquals(contents.size(), 2);
+    assertTrue(contents.contains(r1));
+    assertTrue(contents.contains(r2));
+  }
+
+  @Test(
+    groups = "Functional",
+    expectedExceptions = { IllegalArgumentException.class })
+  public void testAdd_invalidRangeStart()
+  {
+    Range r1 = new Range(10, 20);
+    NCNode<Range> node = new NCNode<Range>(r1);
+    assertEquals(node.getBegin(), 10);
+    Range r2 = new Range(9, 15);
+    node.add(r2);
+  }
+
+  @Test(
+    groups = "Functional",
+    expectedExceptions = { IllegalArgumentException.class })
+  public void testAdd_invalidRangeEnd()
+  {
+    Range r1 = new Range(10, 20);
+    NCNode<Range> node = new NCNode<Range>(r1);
+    assertEquals(node.getBegin(), 10);
+    Range r2 = new Range(12, 21);
+    node.add(r2);
+  }
+
+  @Test(groups = "Functional")
+  public void testGetEntries()
+  {
+    Range r1 = new Range(10, 20);
+    NCNode<Range> node = new NCNode<Range>(r1);
+    List<Range> entries = new ArrayList<Range>();
+
+    node.getEntries(entries);
+    assertEquals(entries.size(), 1);
+    assertTrue(entries.contains(r1));
+
+    // clearing the returned list does not affect the NCNode
+    entries.clear();
+    node.getEntries(entries);
+    assertEquals(entries.size(), 1);
+    assertTrue(entries.contains(r1));
+
+    Range r2 = new Range(15, 18);
+    node.add(r2);
+    entries.clear();
+    node.getEntries(entries);
+    assertEquals(entries.size(), 2);
+    assertTrue(entries.contains(r1));
+    assertTrue(entries.contains(r2));
+  }
+
+  /**
+   * Tests for the contains method (uses entry.equals() test)
+   */
+  @Test(groups = "Functional")
+  public void testContains()
+  {
+    SequenceFeature sf1 = new SequenceFeature("type", "desc", 1, 10, 2f,
+            "group");
+    SequenceFeature sf2 = new SequenceFeature("type", "desc", 1, 10, 2f,
+            "group");
+    SequenceFeature sf3 = new SequenceFeature("type", "desc", 1, 10, 2f,
+            "anothergroup");
+    NCNode<SequenceFeature> node = new NCNode<SequenceFeature>(sf1);
+
+    assertFalse(node.contains(null));
+    assertTrue(node.contains(sf1));
+    assertTrue(node.contains(sf2)); // sf1.equals(sf2)
+    assertFalse(node.contains(sf3)); // !sf1.equals(sf3)
+  }
+
+  /**
+   * Test method that checks for valid structure. Valid means that all
+   * subregions (if any) lie within the root range, and that all subregions have
+   * valid structure.
+   */
+  @Test(groups = "Functional")
+  public void testIsValid()
+  {
+    Range r1 = new Range(10, 20);
+    Range r2 = new Range(14, 15);
+    Range r3 = new Range(16, 17);
+    NCNode<Range> node = new NCNode<Range>(r1);
+    node.add(r2);
+    node.add(r3);
+
+    /*
+     * node has root range [10-20] and contains an
+     * NCList of [14-15, 16-17]
+     */
+    assertTrue(node.isValid());
+    PA.setValue(r1, "start", 15);
+    assertFalse(node.isValid()); // r2 not within r1
+    PA.setValue(r1, "start", 10);
+    assertTrue(node.isValid());
+    PA.setValue(r1, "end", 16);
+    assertFalse(node.isValid()); // r3 not within r1
+    PA.setValue(r1, "end", 20);
+    assertTrue(node.isValid());
+    PA.setValue(r3, "start", 12);
+    assertFalse(node.isValid()); // r3 should precede r2
+  }
+}
diff --git a/test/jalview/datamodel/features/RangeComparatorTest.java b/test/jalview/datamodel/features/RangeComparatorTest.java
new file mode 100644 (file)
index 0000000..4849b38
--- /dev/null
@@ -0,0 +1,65 @@
+package jalview.datamodel.features;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.datamodel.ContiguousI;
+import jalview.datamodel.Range;
+
+import java.util.Comparator;
+
+import org.testng.annotations.Test;
+
+public class RangeComparatorTest
+{
+
+  @Test(groups = "Functional")
+  public void testCompare()
+  {
+    RangeComparator comp = new RangeComparator(true);
+
+    // same position, same length
+    assertEquals(comp.compare(10, 10, 20, 20), 0);
+    // same position, len1 > len2
+    assertEquals(comp.compare(10, 10, 20, 19), -1);
+    // same position, len1 < len2
+    assertEquals(comp.compare(10, 10, 20, 21), 1);
+    // pos1 > pos2
+    assertEquals(comp.compare(11, 10, 20, 20), 1);
+    // pos1 < pos2
+    assertEquals(comp.compare(10, 11, 20, 10), -1);
+  }
+
+  @Test(groups = "Functional")
+  public void testCompare_byStart()
+  {
+    Comparator<ContiguousI> comp = RangeComparator.BY_START_POSITION;
+
+    // same start position, same length
+    assertEquals(comp.compare(new Range(10, 20), new Range(10, 20)), 0);
+    // same start position, len1 > len2
+    assertEquals(comp.compare(new Range(10, 20), new Range(10, 19)), -1);
+    // same start position, len1 < len2
+    assertEquals(comp.compare(new Range(10, 18), new Range(10, 20)), 1);
+    // pos1 > pos2
+    assertEquals(comp.compare(new Range(11, 20), new Range(10, 20)), 1);
+    // pos1 < pos2
+    assertEquals(comp.compare(new Range(10, 20), new Range(11, 20)), -1);
+  }
+
+  @Test(groups = "Functional")
+  public void testCompare_byEnd()
+  {
+    Comparator<ContiguousI> comp = RangeComparator.BY_END_POSITION;
+
+    // same end position, same length
+    assertEquals(comp.compare(new Range(10, 20), new Range(10, 20)), 0);
+    // same end position, len1 > len2
+    assertEquals(comp.compare(new Range(10, 20), new Range(11, 20)), -1);
+    // same end position, len1 < len2
+    assertEquals(comp.compare(new Range(11, 20), new Range(10, 20)), 1);
+    // end1 > end2
+    assertEquals(comp.compare(new Range(10, 21), new Range(10, 20)), 1);
+    // end1 < end2
+    assertEquals(comp.compare(new Range(10, 20), new Range(10, 21)), -1);
+  }
+}
diff --git a/test/jalview/datamodel/features/SequenceFeaturesTest.java b/test/jalview/datamodel/features/SequenceFeaturesTest.java
new file mode 100644 (file)
index 0000000..39d6dce
--- /dev/null
@@ -0,0 +1,1224 @@
+package jalview.datamodel.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+
+import jalview.datamodel.SequenceFeature;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import junit.extensions.PA;
+
+import org.testng.annotations.Test;
+
+public class SequenceFeaturesTest
+{
+  @Test(groups = "Functional")
+  public void testConstructor()
+  {
+    SequenceFeaturesI store = new SequenceFeatures();
+    assertFalse(store.hasFeatures());
+
+    store = new SequenceFeatures((List<SequenceFeature>) null);
+    assertFalse(store.hasFeatures());
+
+    List<SequenceFeature> features = new ArrayList<>();
+    store = new SequenceFeatures(features);
+    assertFalse(store.hasFeatures());
+
+    SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
+            Float.NaN, null);
+    features.add(sf1);
+    SequenceFeature sf2 = new SequenceFeature("Metal", "desc", 15, 18,
+            Float.NaN, null);
+    features.add(sf2); // nested
+    SequenceFeature sf3 = new SequenceFeature("Pfam", "desc2", 0, 0,
+            Float.NaN, null); // non-positional
+    features.add(sf3);
+    store = new SequenceFeatures(features);
+    assertTrue(store.hasFeatures());
+    assertEquals(2, store.getFeatureCount(true)); // positional
+    assertEquals(1, store.getFeatureCount(false)); // non-positional
+    assertFalse(store.add(sf1)); // already contained
+    assertFalse(store.add(sf2)); // already contained
+    assertFalse(store.add(sf3)); // already contained
+  }
+
+  @Test(groups = "Functional")
+  public void testGetPositionalFeatures()
+  {
+    SequenceFeaturesI store = new SequenceFeatures();
+    SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf1);
+    // same range, different description
+    SequenceFeature sf2 = new SequenceFeature("Metal", "desc2", 10, 20,
+            Float.NaN, null);
+    store.add(sf2);
+    // discontiguous range
+    SequenceFeature sf3 = new SequenceFeature("Metal", "desc", 30, 40,
+            Float.NaN, null);
+    store.add(sf3);
+    // overlapping range
+    SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 15, 35,
+            Float.NaN, null);
+    store.add(sf4);
+    // enclosing range
+    SequenceFeature sf5 = new SequenceFeature("Metal", "desc", 5, 50,
+            Float.NaN, null);
+    store.add(sf5);
+    // non-positional feature
+    SequenceFeature sf6 = new SequenceFeature("Metal", "desc", 0, 0,
+            Float.NaN, null);
+    store.add(sf6);
+    // contact feature
+    SequenceFeature sf7 = new SequenceFeature("Disulphide bond", "desc",
+            18, 45, Float.NaN, null);
+    store.add(sf7);
+    // different feature type
+    SequenceFeature sf8 = new SequenceFeature("Pfam", "desc", 30, 40,
+            Float.NaN, null);
+    store.add(sf8);
+    SequenceFeature sf9 = new SequenceFeature("Pfam", "desc", 15, 35,
+            Float.NaN, null);
+    store.add(sf9);
+
+    /*
+     * get all positional features
+     */
+    List<SequenceFeature> features = store.getPositionalFeatures();
+    assertEquals(features.size(), 8);
+    assertTrue(features.contains(sf1));
+    assertTrue(features.contains(sf2));
+    assertTrue(features.contains(sf3));
+    assertTrue(features.contains(sf4));
+    assertTrue(features.contains(sf5));
+    assertFalse(features.contains(sf6)); // non-positional
+    assertTrue(features.contains(sf7));
+    assertTrue(features.contains(sf8));
+    assertTrue(features.contains(sf9));
+
+    /*
+     * get features by type
+     */
+    assertTrue(store.getPositionalFeatures((String) null).isEmpty());
+    assertTrue(store.getPositionalFeatures("Cath").isEmpty());
+    assertTrue(store.getPositionalFeatures("METAL").isEmpty());
+
+    features = store.getPositionalFeatures("Metal");
+    assertEquals(features.size(), 5);
+    assertTrue(features.contains(sf1));
+    assertTrue(features.contains(sf2));
+    assertTrue(features.contains(sf3));
+    assertTrue(features.contains(sf4));
+    assertTrue(features.contains(sf5));
+    assertFalse(features.contains(sf6));
+
+    features = store.getPositionalFeatures("Disulphide bond");
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf7));
+
+    features = store.getPositionalFeatures("Pfam");
+    assertEquals(features.size(), 2);
+    assertTrue(features.contains(sf8));
+    assertTrue(features.contains(sf9));
+  }
+
+  @Test(groups = "Functional")
+  public void testGetContactFeatures()
+  {
+    SequenceFeaturesI store = new SequenceFeatures();
+    // non-contact
+    SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf1);
+    // non-positional
+    SequenceFeature sf2 = new SequenceFeature("Metal", "desc", 0, 0,
+            Float.NaN, null);
+    store.add(sf2);
+    // contact feature
+    SequenceFeature sf3 = new SequenceFeature("Disulphide bond", "desc",
+            18, 45, Float.NaN, null);
+    store.add(sf3);
+    // repeat for different feature type
+    SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf4);
+    SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 0, 0,
+            Float.NaN, null);
+    store.add(sf5);
+    SequenceFeature sf6 = new SequenceFeature("Disulfide bond", "desc", 18,
+            45, Float.NaN, null);
+    store.add(sf6);
+  
+    /*
+     * get all contact features
+     */
+    List<SequenceFeature> features = store.getContactFeatures();
+    assertEquals(features.size(), 2);
+    assertTrue(features.contains(sf3));
+    assertTrue(features.contains(sf6));
+  
+    /*
+     * get contact features by type
+     */
+    assertTrue(store.getContactFeatures((String) null).isEmpty());
+    assertTrue(store.getContactFeatures("Cath").isEmpty());
+    assertTrue(store.getContactFeatures("Pfam").isEmpty());
+    assertTrue(store.getContactFeatures("DISULPHIDE BOND").isEmpty());
+  
+    features = store.getContactFeatures("Disulphide bond");
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf3));
+  
+    features = store.getContactFeatures("Disulfide bond");
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf6));
+  }
+
+  @Test(groups = "Functional")
+  public void testGetNonPositionalFeatures()
+  {
+    SequenceFeaturesI store = new SequenceFeatures();
+    // positional
+    SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf1);
+    // non-positional
+    SequenceFeature sf2 = new SequenceFeature("Metal", "desc", 0, 0,
+            Float.NaN, null);
+    store.add(sf2);
+    // contact feature
+    SequenceFeature sf3 = new SequenceFeature("Disulphide bond", "desc",
+            18, 45, Float.NaN, null);
+    store.add(sf3);
+    // repeat for different feature type
+    SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf4);
+    SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 0, 0,
+            Float.NaN, null);
+    store.add(sf5);
+    SequenceFeature sf6 = new SequenceFeature("Disulfide bond", "desc", 18,
+            45, Float.NaN, null);
+    store.add(sf6);
+    // one more non-positional, different description
+    SequenceFeature sf7 = new SequenceFeature("Pfam", "desc2", 0, 0,
+            Float.NaN, null);
+    store.add(sf7);
+  
+    /*
+     * get all non-positional features
+     */
+    List<SequenceFeature> features = store.getNonPositionalFeatures();
+    assertEquals(features.size(), 3);
+    assertTrue(features.contains(sf2));
+    assertTrue(features.contains(sf5));
+    assertTrue(features.contains(sf7));
+  
+    /*
+     * get non-positional features by type
+     */
+    assertTrue(store.getNonPositionalFeatures((String) null).isEmpty());
+    assertTrue(store.getNonPositionalFeatures("Cath").isEmpty());
+    assertTrue(store.getNonPositionalFeatures("PFAM").isEmpty());
+  
+    features = store.getNonPositionalFeatures("Metal");
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf2));
+  
+    features = store.getNonPositionalFeatures("Pfam");
+    assertEquals(features.size(), 2);
+    assertTrue(features.contains(sf5));
+    assertTrue(features.contains(sf7));
+  }
+
+  /**
+   * Helper method to add a feature of no particular type
+   * 
+   * @param sf
+   * @param type
+   * @param from
+   * @param to
+   * @return
+   */
+  SequenceFeature addFeature(SequenceFeaturesI sf, String type, int from,
+          int to)
+  {
+    SequenceFeature sf1 = new SequenceFeature(type, "", from, to,
+            Float.NaN,
+            null);
+    sf.add(sf1);
+    return sf1;
+  }
+
+  @Test(groups = "Functional")
+  public void testFindFeatures()
+  {
+    SequenceFeaturesI sf = new SequenceFeatures();
+    SequenceFeature sf1 = addFeature(sf, "Pfam", 10, 50);
+    SequenceFeature sf2 = addFeature(sf, "Pfam", 1, 15);
+    SequenceFeature sf3 = addFeature(sf, "Pfam", 20, 30);
+    SequenceFeature sf4 = addFeature(sf, "Pfam", 40, 100);
+    SequenceFeature sf5 = addFeature(sf, "Pfam", 60, 100);
+    SequenceFeature sf6 = addFeature(sf, "Pfam", 70, 70);
+    SequenceFeature sf7 = addFeature(sf, "Cath", 10, 50);
+    SequenceFeature sf8 = addFeature(sf, "Cath", 1, 15);
+    SequenceFeature sf9 = addFeature(sf, "Cath", 20, 30);
+    SequenceFeature sf10 = addFeature(sf, "Cath", 40, 100);
+    SequenceFeature sf11 = addFeature(sf, "Cath", 60, 100);
+    SequenceFeature sf12 = addFeature(sf, "Cath", 70, 70);
+  
+    List<SequenceFeature> overlaps = sf.findFeatures(200, 200, "Pfam");
+    assertTrue(overlaps.isEmpty());
+  
+    overlaps = sf.findFeatures( 1, 9, "Pfam");
+    assertEquals(overlaps.size(), 1);
+    assertTrue(overlaps.contains(sf2));
+  
+    overlaps = sf.findFeatures( 5, 18, "Pfam");
+    assertEquals(overlaps.size(), 2);
+    assertTrue(overlaps.contains(sf1));
+    assertTrue(overlaps.contains(sf2));
+  
+    overlaps = sf.findFeatures(30, 40, "Pfam");
+    assertEquals(overlaps.size(), 3);
+    assertTrue(overlaps.contains(sf1));
+    assertTrue(overlaps.contains(sf3));
+    assertTrue(overlaps.contains(sf4));
+  
+    overlaps = sf.findFeatures( 80, 90, "Pfam");
+    assertEquals(overlaps.size(), 2);
+    assertTrue(overlaps.contains(sf4));
+    assertTrue(overlaps.contains(sf5));
+  
+    overlaps = sf.findFeatures( 68, 70, "Pfam");
+    assertEquals(overlaps.size(), 3);
+    assertTrue(overlaps.contains(sf4));
+    assertTrue(overlaps.contains(sf5));
+    assertTrue(overlaps.contains(sf6));
+
+    overlaps = sf.findFeatures(16, 69, "Cath");
+    assertEquals(overlaps.size(), 4);
+    assertTrue(overlaps.contains(sf7));
+    assertFalse(overlaps.contains(sf8));
+    assertTrue(overlaps.contains(sf9));
+    assertTrue(overlaps.contains(sf10));
+    assertTrue(overlaps.contains(sf11));
+    assertFalse(overlaps.contains(sf12));
+
+    assertTrue(sf.findFeatures(0, 1000, "Metal").isEmpty());
+
+    overlaps = sf.findFeatures(7, 7, (String) null);
+    assertTrue(overlaps.isEmpty());
+  }
+
+  @Test(groups = "Functional")
+  public void testDelete()
+  {
+    SequenceFeaturesI sf = new SequenceFeatures();
+    SequenceFeature sf1 = addFeature(sf, "Pfam", 10, 50);
+    assertTrue(sf.getPositionalFeatures().contains(sf1));
+
+    assertFalse(sf.delete(null));
+    SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 15, 0f, null);
+    assertFalse(sf.delete(sf2)); // not added, can't delete it
+    assertTrue(sf.delete(sf1));
+    assertTrue(sf.getPositionalFeatures().isEmpty());
+  }
+
+  @Test(groups = "Functional")
+  public void testHasFeatures()
+  {
+    SequenceFeaturesI sf = new SequenceFeatures();
+    assertFalse(sf.hasFeatures());
+
+    SequenceFeature sf1 = addFeature(sf, "Pfam", 10, 50);
+    assertTrue(sf.hasFeatures());
+
+    sf.delete(sf1);
+    assertFalse(sf.hasFeatures());
+  }
+
+  /**
+   * Tests for the method that gets feature groups for positional or
+   * non-positional features
+   */
+  @Test(groups = "Functional")
+  public void testGetFeatureGroups()
+  {
+    SequenceFeaturesI sf = new SequenceFeatures();
+    assertTrue(sf.getFeatureGroups(true).isEmpty());
+    assertTrue(sf.getFeatureGroups(false).isEmpty());
+
+    /*
+     * add a non-positional feature (begin/end = 0/0)
+     */
+    SequenceFeature sfx = new SequenceFeature("AType", "Desc", 0, 0, 0f,
+            "AGroup");
+    sf.add(sfx);
+    Set<String> groups = sf.getFeatureGroups(true); // for positional
+    assertTrue(groups.isEmpty());
+    groups = sf.getFeatureGroups(false); // for non-positional
+    assertEquals(groups.size(), 1);
+    assertTrue(groups.contains("AGroup"));
+    groups = sf.getFeatureGroups(false, "AType");
+    assertEquals(groups.size(), 1);
+    assertTrue(groups.contains("AGroup"));
+    groups = sf.getFeatureGroups(true, "AnotherType");
+    assertTrue(groups.isEmpty());
+
+    /*
+     * add, then delete, more non-positional features of different types
+     */
+    SequenceFeature sfy = new SequenceFeature("AnotherType", "Desc", 0, 0,
+            0f,
+            "AnotherGroup");
+    sf.add(sfy);
+    SequenceFeature sfz = new SequenceFeature("AThirdType", "Desc", 0, 0,
+            0f,
+            null);
+    sf.add(sfz);
+    groups = sf.getFeatureGroups(false);
+    assertEquals(groups.size(), 3);
+    assertTrue(groups.contains("AGroup"));
+    assertTrue(groups.contains("AnotherGroup"));
+    assertTrue(groups.contains(null)); // null is a possible group
+    sf.delete(sfz);
+    sf.delete(sfy);
+    groups = sf.getFeatureGroups(false);
+    assertEquals(groups.size(), 1);
+    assertTrue(groups.contains("AGroup"));
+
+    /*
+     * add positional features
+     */
+    SequenceFeature sf1 = new SequenceFeature("Pfam", "Desc", 10, 50, 0f,
+            "PfamGroup");
+    sf.add(sf1);
+    groups = sf.getFeatureGroups(true);
+    assertEquals(groups.size(), 1);
+    assertTrue(groups.contains("PfamGroup"));
+    groups = sf.getFeatureGroups(false); // non-positional unchanged
+    assertEquals(groups.size(), 1);
+    assertTrue(groups.contains("AGroup"));
+
+    SequenceFeature sf2 = new SequenceFeature("Cath", "Desc", 10, 50, 0f,
+            null);
+    sf.add(sf2);
+    groups = sf.getFeatureGroups(true);
+    assertEquals(groups.size(), 2);
+    assertTrue(groups.contains("PfamGroup"));
+    assertTrue(groups.contains(null));
+
+    sf.delete(sf1);
+    sf.delete(sf2);
+    assertTrue(sf.getFeatureGroups(true).isEmpty());
+
+    SequenceFeature sf3 = new SequenceFeature("CDS", "", 10, 50, 0f,
+            "Ensembl");
+    sf.add(sf3);
+    SequenceFeature sf4 = new SequenceFeature("exon", "", 10, 50, 0f,
+            "Ensembl");
+    sf.add(sf4);
+    groups = sf.getFeatureGroups(true);
+    assertEquals(groups.size(), 1);
+    assertTrue(groups.contains("Ensembl"));
+
+    /*
+     * delete last Ensembl group feature from CDS features
+     * but still have one in exon features
+     */
+    sf.delete(sf3);
+    groups = sf.getFeatureGroups(true);
+    assertEquals(groups.size(), 1);
+    assertTrue(groups.contains("Ensembl"));
+
+    /*
+     * delete the last non-positional feature
+     */
+    sf.delete(sfx);
+    groups = sf.getFeatureGroups(false);
+    assertTrue(groups.isEmpty());
+  }
+
+  @Test(groups = "Functional")
+  public void testGetFeatureTypesForGroups()
+  {
+    SequenceFeaturesI sf = new SequenceFeatures();
+    assertTrue(sf.getFeatureTypesForGroups(true, (String) null).isEmpty());
+  
+    /*
+     * add feature with group = "Uniprot", type = "helix"
+     */
+    String groupUniprot = "Uniprot";
+    SequenceFeature sf1 = new SequenceFeature("helix", "Desc", 10, 50, 0f,
+            groupUniprot);
+    sf.add(sf1);
+    Set<String> groups = sf.getFeatureTypesForGroups(true, groupUniprot);
+    assertEquals(groups.size(), 1);
+    assertTrue(groups.contains("helix"));
+    assertTrue(sf.getFeatureTypesForGroups(true, (String) null).isEmpty());
+  
+    /*
+     * add feature with group = "Uniprot", type = "strand"
+     */
+    SequenceFeature sf2 = new SequenceFeature("strand", "Desc", 10, 50, 0f,
+            groupUniprot);
+    sf.add(sf2);
+    groups = sf.getFeatureTypesForGroups(true, groupUniprot);
+    assertEquals(groups.size(), 2);
+    assertTrue(groups.contains("helix"));
+    assertTrue(groups.contains("strand"));
+
+    /*
+     * delete the "strand" Uniprot feature - still have "helix"
+     */
+    sf.delete(sf2);
+    groups = sf.getFeatureTypesForGroups(true, groupUniprot);
+    assertEquals(groups.size(), 1);
+    assertTrue(groups.contains("helix"));
+
+    /*
+     * delete the "helix" Uniprot feature - none left
+     */
+    sf.delete(sf1);
+    assertTrue(sf.getFeatureTypesForGroups(true, groupUniprot).isEmpty());
+
+    /*
+     * add some null group features
+     */
+    SequenceFeature sf3 = new SequenceFeature("strand", "Desc", 10, 50, 0f,
+            null);
+    sf.add(sf3);
+    SequenceFeature sf4 = new SequenceFeature("turn", "Desc", 10, 50, 0f,
+            null);
+    sf.add(sf4);
+    groups = sf.getFeatureTypesForGroups(true, (String) null);
+    assertEquals(groups.size(), 2);
+    assertTrue(groups.contains("strand"));
+    assertTrue(groups.contains("turn"));
+
+    /*
+     * add strand/Cath  and turn/Scop and query for one or both groups
+     * (find feature types for groups selected in Feature Settings)
+     */
+    SequenceFeature sf5 = new SequenceFeature("strand", "Desc", 10, 50, 0f,
+            "Cath");
+    sf.add(sf5);
+    SequenceFeature sf6 = new SequenceFeature("turn", "Desc", 10, 50, 0f,
+            "Scop");
+    sf.add(sf6);
+    groups = sf.getFeatureTypesForGroups(true, "Cath");
+    assertEquals(groups.size(), 1);
+    assertTrue(groups.contains("strand"));
+    groups = sf.getFeatureTypesForGroups(true, "Scop");
+    assertEquals(groups.size(), 1);
+    assertTrue(groups.contains("turn"));
+    groups = sf.getFeatureTypesForGroups(true, "Cath", "Scop");
+    assertEquals(groups.size(), 2);
+    assertTrue(groups.contains("turn"));
+    assertTrue(groups.contains("strand"));
+    // alternative vararg syntax
+    groups = sf.getFeatureTypesForGroups(true, new String[] { "Cath",
+        "Scop" });
+    assertEquals(groups.size(), 2);
+    assertTrue(groups.contains("turn"));
+    assertTrue(groups.contains("strand"));
+  }
+
+  @Test(groups = "Functional")
+  public void testGetFeatureTypes()
+  {
+    SequenceFeaturesI store = new SequenceFeatures();
+    Set<String> types = store.getFeatureTypes();
+    assertTrue(types.isEmpty());
+
+    SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf1);
+    types = store.getFeatureTypes();
+    assertEquals(types.size(), 1);
+    assertTrue(types.contains("Metal"));
+
+    // null type is rejected...
+    SequenceFeature sf2 = new SequenceFeature(null, "desc", 10, 20,
+            Float.NaN, null);
+    assertFalse(store.add(sf2));
+    types = store.getFeatureTypes();
+    assertEquals(types.size(), 1);
+    assertFalse(types.contains(null));
+    assertTrue(types.contains("Metal"));
+
+    /*
+     * add non-positional feature
+     */
+    SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 0, 0,
+            Float.NaN, null);
+    store.add(sf3);
+    types = store.getFeatureTypes();
+    assertEquals(types.size(), 2);
+    assertTrue(types.contains("Pfam"));
+
+    /*
+     * add contact feature
+     */
+    SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc",
+            10, 20, Float.NaN, null);
+    store.add(sf4);
+    types = store.getFeatureTypes();
+    assertEquals(types.size(), 3);
+    assertTrue(types.contains("Disulphide Bond"));
+
+    /*
+     * add another Pfam
+     */
+    SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf5);
+    types = store.getFeatureTypes();
+    assertEquals(types.size(), 3); // unchanged
+
+    /*
+     * delete first Pfam - still have one
+     */
+    assertTrue(store.delete(sf3));
+    types = store.getFeatureTypes();
+    assertEquals(types.size(), 3);
+    assertTrue(types.contains("Pfam"));
+
+    /*
+     * delete second Pfam - no longer have one
+     */
+    assertTrue(store.delete(sf5));
+    types = store.getFeatureTypes();
+    assertEquals(types.size(), 2);
+    assertFalse(types.contains("Pfam"));
+  }
+
+  @Test(groups = "Functional")
+  public void testGetFeatureCount()
+  {
+    SequenceFeaturesI store = new SequenceFeatures();
+    assertEquals(store.getFeatureCount(true), 0);
+    assertEquals(store.getFeatureCount(false), 0);
+  
+    /*
+     * add positional
+     */
+    SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf1);
+    assertEquals(store.getFeatureCount(true), 1);
+    assertEquals(store.getFeatureCount(false), 0);
+
+    /*
+     * null feature type is rejected
+     */
+    SequenceFeature sf2 = new SequenceFeature(null, "desc", 10, 20,
+            Float.NaN, null);
+    assertFalse(store.add(sf2));
+    assertEquals(store.getFeatureCount(true), 1);
+    assertEquals(store.getFeatureCount(false), 0);
+  
+    /*
+     * add non-positional feature
+     */
+    SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 0, 0,
+            Float.NaN, null);
+    store.add(sf3);
+    assertEquals(store.getFeatureCount(true), 1);
+    assertEquals(store.getFeatureCount(false), 1);
+  
+    /*
+     * add contact feature (counts as 1)
+     */
+    SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc",
+            10, 20, Float.NaN, null);
+    store.add(sf4);
+    assertEquals(store.getFeatureCount(true), 2);
+    assertEquals(store.getFeatureCount(false), 1);
+  
+    /*
+     * add another Pfam but this time as a positional feature
+     */
+    SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf5);
+    assertEquals(store.getFeatureCount(true), 3); // sf1, sf4, sf5
+    assertEquals(store.getFeatureCount(false), 1); // sf3
+    assertEquals(store.getFeatureCount(true, "Pfam"), 1); // positional
+    assertEquals(store.getFeatureCount(false, "Pfam"), 1); // non-positional
+    // search for type==null
+    assertEquals(store.getFeatureCount(true, (String) null), 0);
+    // search with no type specified
+    assertEquals(store.getFeatureCount(true, (String[]) null), 3);
+    assertEquals(store.getFeatureCount(true, "Metal", "Cath"), 1);
+    assertEquals(store.getFeatureCount(true, "Disulphide Bond"), 1);
+    assertEquals(store.getFeatureCount(true, "Metal", "Pfam", null), 2);
+
+    /*
+     * delete first Pfam (non-positional)
+     */
+    assertTrue(store.delete(sf3));
+    assertEquals(store.getFeatureCount(true), 3);
+    assertEquals(store.getFeatureCount(false), 0);
+  
+    /*
+     * delete second Pfam (positional)
+     */
+    assertTrue(store.delete(sf5));
+    assertEquals(store.getFeatureCount(true), 2);
+    assertEquals(store.getFeatureCount(false), 0);
+  }
+
+  @Test(groups = "Functional")
+  public void testGetAllFeatures()
+  {
+    SequenceFeaturesI store = new SequenceFeatures();
+    List<SequenceFeature> features = store.getAllFeatures();
+    assertTrue(features.isEmpty());
+  
+    SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf1);
+    features = store.getAllFeatures();
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf1));
+  
+    SequenceFeature sf2 = new SequenceFeature("Metallic", "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf2);
+    features = store.getAllFeatures();
+    assertEquals(features.size(), 2);
+    assertTrue(features.contains(sf2));
+  
+    /*
+     * add non-positional feature
+     */
+    SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 0, 0,
+            Float.NaN, null);
+    store.add(sf3);
+    features = store.getAllFeatures();
+    assertEquals(features.size(), 3);
+    assertTrue(features.contains(sf3));
+  
+    /*
+     * add contact feature
+     */
+    SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc",
+            10, 20, Float.NaN, null);
+    store.add(sf4);
+    features = store.getAllFeatures();
+    assertEquals(features.size(), 4);
+    assertTrue(features.contains(sf4));
+  
+    /*
+     * add another Pfam
+     */
+    SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf5);
+    features = store.getAllFeatures();
+    assertEquals(features.size(), 5);
+    assertTrue(features.contains(sf5));
+
+    /*
+     * select by type does not apply to non-positional features
+     */
+    features = store.getAllFeatures("Cath");
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf3));
+
+    features = store.getAllFeatures("Pfam", "Cath", "Metal");
+    assertEquals(features.size(), 3);
+    assertTrue(features.contains(sf1));
+    assertTrue(features.contains(sf3));
+    assertTrue(features.contains(sf5));
+  
+    /*
+     * delete first Pfam
+     */
+    assertTrue(store.delete(sf3));
+    features = store.getAllFeatures();
+    assertEquals(features.size(), 4);
+    assertFalse(features.contains(sf3));
+  
+    /*
+     * delete second Pfam
+     */
+    assertTrue(store.delete(sf5));
+    features = store.getAllFeatures();
+    assertEquals(features.size(), 3);
+    assertFalse(features.contains(sf3));
+  }
+
+  @Test(groups = "Functional")
+  public void testGetTotalFeatureLength()
+  {
+    SequenceFeaturesI store = new SequenceFeatures();
+    assertEquals(store.getTotalFeatureLength(), 0);
+
+    SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
+            Float.NaN, null);
+    assertTrue(store.add(sf1));
+    assertEquals(store.getTotalFeatureLength(), 11);
+    assertEquals(store.getTotalFeatureLength("Metal"), 11);
+    assertEquals(store.getTotalFeatureLength("Plastic"), 0);
+
+    // re-add does nothing!
+    assertFalse(store.add(sf1));
+    assertEquals(store.getTotalFeatureLength(), 11);
+
+    /*
+     * add non-positional feature
+     */
+    SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 0, 0,
+            Float.NaN, null);
+    store.add(sf3);
+    assertEquals(store.getTotalFeatureLength(), 11);
+
+    /*
+     * add contact feature - counts 1 to feature length
+     */
+    SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc",
+            10, 20, Float.NaN, null);
+    store.add(sf4);
+    assertEquals(store.getTotalFeatureLength(), 12);
+
+    /*
+     * add another Pfam
+     */
+    SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf5);
+    assertEquals(store.getTotalFeatureLength(), 23);
+
+    /*
+     * delete features
+     */
+    assertTrue(store.delete(sf3)); // non-positional
+    assertEquals(store.getTotalFeatureLength(), 23); // no change
+
+    assertTrue(store.delete(sf5));
+    assertEquals(store.getTotalFeatureLength(), 12);
+
+    assertTrue(store.delete(sf4)); // contact
+    assertEquals(store.getTotalFeatureLength(), 11);
+
+    assertTrue(store.delete(sf1));
+    assertEquals(store.getTotalFeatureLength(), 0);
+  }
+
+  @Test(groups = "Functional")
+  public void testGetMinimumScore_getMaximumScore()
+  {
+    SequenceFeatures sf = new SequenceFeatures();
+    SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 0, 0,
+            Float.NaN, "group"); // non-positional, no score
+    sf.add(sf1);
+    SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 10, 20,
+            Float.NaN, "group"); // positional, no score
+    sf.add(sf2);
+    SequenceFeature sf3 = new SequenceFeature("Metal", "desc", 10, 20, 1f,
+            "group");
+    sf.add(sf3);
+    SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 12, 16, 4f,
+            "group");
+    sf.add(sf4);
+    SequenceFeature sf5 = new SequenceFeature("Cath", "desc", 0, 0, 11f,
+            "group");
+    sf.add(sf5);
+    SequenceFeature sf6 = new SequenceFeature("Cath", "desc", 0, 0, -7f,
+            "group");
+    sf.add(sf6);
+
+    assertEquals(sf.getMinimumScore("nosuchtype", true), Float.NaN);
+    assertEquals(sf.getMinimumScore("nosuchtype", false), Float.NaN);
+    assertEquals(sf.getMaximumScore("nosuchtype", true), Float.NaN);
+    assertEquals(sf.getMaximumScore("nosuchtype", false), Float.NaN);
+
+    // positional features min-max:
+    assertEquals(sf.getMinimumScore("Metal", true), 1f);
+    assertEquals(sf.getMaximumScore("Metal", true), 4f);
+    assertEquals(sf.getMinimumScore("Cath", true), Float.NaN);
+    assertEquals(sf.getMaximumScore("Cath", true), Float.NaN);
+
+    // non-positional features min-max:
+    assertEquals(sf.getMinimumScore("Cath", false), -7f);
+    assertEquals(sf.getMaximumScore("Cath", false), 11f);
+    assertEquals(sf.getMinimumScore("Metal", false), Float.NaN);
+    assertEquals(sf.getMaximumScore("Metal", false), Float.NaN);
+
+    // delete features; min-max should get recomputed
+    sf.delete(sf6);
+    assertEquals(sf.getMinimumScore("Cath", false), 11f);
+    assertEquals(sf.getMaximumScore("Cath", false), 11f);
+    sf.delete(sf4);
+    assertEquals(sf.getMinimumScore("Metal", true), 1f);
+    assertEquals(sf.getMaximumScore("Metal", true), 1f);
+    sf.delete(sf5);
+    assertEquals(sf.getMinimumScore("Cath", false), Float.NaN);
+    assertEquals(sf.getMaximumScore("Cath", false), Float.NaN);
+    sf.delete(sf3);
+    assertEquals(sf.getMinimumScore("Metal", true), Float.NaN);
+    assertEquals(sf.getMaximumScore("Metal", true), Float.NaN);
+    sf.delete(sf1);
+    sf.delete(sf2);
+    assertFalse(sf.hasFeatures());
+    assertEquals(sf.getMinimumScore("Cath", false), Float.NaN);
+    assertEquals(sf.getMaximumScore("Cath", false), Float.NaN);
+    assertEquals(sf.getMinimumScore("Metal", true), Float.NaN);
+    assertEquals(sf.getMaximumScore("Metal", true), Float.NaN);
+  }
+
+  @Test(groups = "Functional")
+  public void testVarargsToTypes()
+  {
+    SequenceFeatures sf = new SequenceFeatures();
+    sf.add(new SequenceFeature("Metal", "desc", 0, 0, Float.NaN, "group"));
+    sf.add(new SequenceFeature("Cath", "desc", 10, 20, Float.NaN, "group"));
+
+    /*
+     * no type specified - get all types stored
+     * they are returned in keyset (alphabetical) order
+     */
+    Map<String, FeatureStore> featureStores = (Map<String, FeatureStore>) PA
+            .getValue(sf, "featureStore");
+
+    Iterable<FeatureStore> types = sf.varargToTypes();
+    Iterator<FeatureStore> iterator = types.iterator();
+    assertTrue(iterator.hasNext());
+    assertSame(iterator.next(), featureStores.get("Cath"));
+    assertTrue(iterator.hasNext());
+    assertSame(iterator.next(), featureStores.get("Metal"));
+    assertFalse(iterator.hasNext());
+
+    /*
+     * empty array is the same as no vararg parameter supplied
+     * so treated as all stored types
+     */
+    types = sf.varargToTypes(new String[] {});
+    iterator = types.iterator();
+    assertTrue(iterator.hasNext());
+    assertSame(iterator.next(), featureStores.get("Cath"));
+    assertTrue(iterator.hasNext());
+    assertSame(iterator.next(), featureStores.get("Metal"));
+    assertFalse(iterator.hasNext());
+
+    /*
+     * null type specified; this is passed as vararg
+     * String[1] {null}
+     */
+    types = sf.varargToTypes((String) null);
+    assertFalse(types.iterator().hasNext());
+
+    /*
+     * null types array specified; this is passed as vararg null
+     */
+    types = sf.varargToTypes((String[]) null);
+    iterator = types.iterator();
+    assertTrue(iterator.hasNext());
+    assertSame(iterator.next(), featureStores.get("Cath"));
+    assertTrue(iterator.hasNext());
+    assertSame(iterator.next(), featureStores.get("Metal"));
+    assertFalse(iterator.hasNext());
+
+    /*
+     * one type specified
+     */
+    types = sf.varargToTypes("Metal");
+    iterator = types.iterator();
+    assertTrue(iterator.hasNext());
+    assertSame(iterator.next(), featureStores.get("Metal"));
+    assertFalse(iterator.hasNext());
+
+    /*
+     * two types specified - get sorted alphabetically
+     */
+    types = sf.varargToTypes("Metal", "Cath");
+    iterator = types.iterator();
+    assertTrue(iterator.hasNext());
+    assertSame(iterator.next(), featureStores.get("Cath"));
+    assertTrue(iterator.hasNext());
+    assertSame(iterator.next(), featureStores.get("Metal"));
+    assertFalse(iterator.hasNext());
+
+    /*
+     * null type included - should be ignored
+     */
+    types = sf.varargToTypes("Metal", null, "Helix");
+    iterator = types.iterator();
+    assertTrue(iterator.hasNext());
+    assertSame(iterator.next(), featureStores.get("Metal"));
+    assertFalse(iterator.hasNext());
+  }
+
+  @Test(groups = "Functional")
+  public void testGetFeatureTypes_byOntology()
+  {
+    SequenceFeaturesI store = new SequenceFeatures();
+  
+    SequenceFeature sf1 = new SequenceFeature("transcript", "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf1);
+    // mRNA isA mature_transcript isA transcript
+    SequenceFeature sf2 = new SequenceFeature("mRNA", "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf2);
+    // just to prove non-positional feature types are included
+    SequenceFeature sf3 = new SequenceFeature("mRNA", "desc", 0, 0,
+            Float.NaN, null);
+    store.add(sf3);
+    SequenceFeature sf4 = new SequenceFeature("CDS", "desc", 0, 0,
+            Float.NaN, null);
+    store.add(sf4);
+
+    Set<String> types = store.getFeatureTypes("transcript");
+    assertEquals(types.size(), 2);
+    assertTrue(types.contains("transcript"));
+    assertTrue(types.contains("mRNA"));
+
+    // matches include arguments whether SO terms or not
+    types = store.getFeatureTypes("transcript", "CDS");
+    assertEquals(types.size(), 3);
+    assertTrue(types.contains("transcript"));
+    assertTrue(types.contains("mRNA"));
+    assertTrue(types.contains("CDS"));
+
+    types = store.getFeatureTypes("exon");
+    assertTrue(types.isEmpty());
+  }
+
+  @Test(groups = "Functional")
+  public void testGetFeaturesByOntology()
+  {
+    SequenceFeaturesI store = new SequenceFeatures();
+    List<SequenceFeature> features = store.getFeaturesByOntology();
+    assertTrue(features.isEmpty());
+    assertTrue(store.getFeaturesByOntology(new String[] {}).isEmpty());
+    assertTrue(store.getFeaturesByOntology((String[]) null).isEmpty());
+  
+    SequenceFeature sf1 = new SequenceFeature("transcript", "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf1);
+
+    // mRNA isA transcript; added here 'as if' non-positional
+    // just to show that non-positional features are included in results
+    SequenceFeature sf2 = new SequenceFeature("mRNA", "desc", 0, 0,
+            Float.NaN, null);
+    store.add(sf2);
+
+    SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 30, 40,
+            Float.NaN, null);
+    store.add(sf3);
+
+    features = store.getFeaturesByOntology("transcript");
+    assertEquals(features.size(), 2);
+    assertTrue(features.contains(sf1));
+    assertTrue(features.contains(sf2));
+
+    features = store.getFeaturesByOntology("mRNA");
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf2));
+
+    features = store.getFeaturesByOntology("mRNA", "Pfam");
+    assertEquals(features.size(), 2);
+    assertTrue(features.contains(sf2));
+    assertTrue(features.contains(sf3));
+
+    features = store.getFeaturesByOntology("sequence_variant");
+    assertTrue(features.isEmpty());
+  }
+
+  @Test(groups = "Functional")
+  public void testSortFeatures()
+  {
+    List<SequenceFeature> sfs = new ArrayList<SequenceFeature>();
+    SequenceFeature sf1 = new SequenceFeature("Pfam", "desc", 30, 80,
+            Float.NaN, null);
+    sfs.add(sf1);
+    SequenceFeature sf2 = new SequenceFeature("Rfam", "desc", 40, 50,
+            Float.NaN, null);
+    sfs.add(sf2);
+    SequenceFeature sf3 = new SequenceFeature("Rfam", "desc", 50, 60,
+            Float.NaN, null);
+    sfs.add(sf3);
+
+    // sort by end position descending
+    SequenceFeatures.sortFeatures(sfs, false);
+    assertSame(sfs.get(0), sf1);
+    assertSame(sfs.get(1), sf3);
+    assertSame(sfs.get(2), sf2);
+
+    // sort by start position ascending
+    SequenceFeatures.sortFeatures(sfs, true);
+    assertSame(sfs.get(0), sf1);
+    assertSame(sfs.get(1), sf2);
+    assertSame(sfs.get(2), sf3);
+  }
+
+  @Test(groups = "Functional")
+  public void testGetFeaturesForGroup()
+  {
+    SequenceFeaturesI store = new SequenceFeatures();
+
+    List<SequenceFeature> features = store.getFeaturesForGroup(true, null);
+    assertTrue(features.isEmpty());
+    assertTrue(store.getFeaturesForGroup(false, null).isEmpty());
+    assertTrue(store.getFeaturesForGroup(true, "Uniprot").isEmpty());
+    assertTrue(store.getFeaturesForGroup(false, "Uniprot").isEmpty());
+
+    SequenceFeature sf1 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
+            null);
+    SequenceFeature sf2 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
+            null);
+    SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
+            "Uniprot");
+    SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 0, 0, 0f,
+            "Rfam");
+    SequenceFeature sf5 = new SequenceFeature("Cath", "desc", 5, 15, 0f,
+            null);
+    store.add(sf1);
+    store.add(sf2);
+    store.add(sf3);
+    store.add(sf4);
+    store.add(sf5);
+
+    // positional features for null group, any type
+    features = store.getFeaturesForGroup(true, null);
+    assertEquals(features.size(), 2);
+    assertTrue(features.contains(sf1));
+    assertTrue(features.contains(sf5));
+
+    // positional features for null group, specified type
+    features = store.getFeaturesForGroup(true, null, new String[] { "Pfam",
+        "Xfam" });
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf1));
+    features = store.getFeaturesForGroup(true, null, new String[] { "Pfam",
+        "Xfam", "Cath" });
+    assertEquals(features.size(), 2);
+    assertTrue(features.contains(sf1));
+    assertTrue(features.contains(sf5));
+
+    // positional features for non-null group, any type
+    features = store.getFeaturesForGroup(true, "Uniprot");
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf3));
+    assertTrue(store.getFeaturesForGroup(true, "Rfam").isEmpty());
+
+    // positional features for non-null group, specified type
+    features = store.getFeaturesForGroup(true, "Uniprot", "Pfam", "Xfam",
+            "Rfam");
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf3));
+    assertTrue(store.getFeaturesForGroup(true, "Uniprot", "Cath").isEmpty());
+
+    // non-positional features for null group, any type
+    features = store.getFeaturesForGroup(false, null);
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf2));
+
+    // non-positional features for null group, specified type
+    features = store.getFeaturesForGroup(false, null, "Pfam", "Xfam");
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf2));
+    assertTrue(store.getFeaturesForGroup(false, null, "Cath").isEmpty());
+
+    // non-positional features for non-null group, any type
+    features = store.getFeaturesForGroup(false, "Rfam");
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf4));
+    assertTrue(store.getFeaturesForGroup(false, "Uniprot").isEmpty());
+
+    // non-positional features for non-null group, specified type
+    features = store.getFeaturesForGroup(false, "Rfam", "Pfam", "Metal");
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf4));
+    assertTrue(store.getFeaturesForGroup(false, "Rfam", "Cath", "Pfam")
+            .isEmpty());
+  }
+
+  @Test(groups = "Functional")
+  public void testShiftFeatures()
+  {
+    SequenceFeatures store = new SequenceFeatures();
+    assertFalse(store.shiftFeatures(1));
+
+    SequenceFeature sf1 = new SequenceFeature("Cath", "", 2, 5, 0f, null);
+    store.add(sf1);
+    // nested feature:
+    SequenceFeature sf2 = new SequenceFeature("Metal", "", 8, 14, 0f, null);
+    store.add(sf2);
+    // contact feature:
+    SequenceFeature sf3 = new SequenceFeature("Disulfide bond", "", 23, 32,
+            0f, null);
+    store.add(sf3);
+    // non-positional feature:
+    SequenceFeature sf4 = new SequenceFeature("Pfam", "", 0, 0, 0f, null);
+    store.add(sf4);
+  
+    /*
+     * shift features right by 5
+     */
+    assertTrue(store.shiftFeatures(5));
+  
+    // non-positional features untouched:
+    List<SequenceFeature> nonPos = store.getNonPositionalFeatures();
+    assertEquals(nonPos.size(), 1);
+    assertTrue(nonPos.contains(sf4));
+  
+    // positional features are replaced
+    List<SequenceFeature> pos = store.getPositionalFeatures();
+    assertEquals(pos.size(), 3);
+    assertFalse(pos.contains(sf1));
+    assertFalse(pos.contains(sf2));
+    assertFalse(pos.contains(sf3));
+    SequenceFeatures.sortFeatures(pos, true); // ascending start pos
+    assertEquals(pos.get(0).getBegin(), 7);
+    assertEquals(pos.get(0).getEnd(), 10);
+    assertEquals(pos.get(0).getType(), "Cath");
+    assertEquals(pos.get(1).getBegin(), 13);
+    assertEquals(pos.get(1).getEnd(), 19);
+    assertEquals(pos.get(1).getType(), "Metal");
+    assertEquals(pos.get(2).getBegin(), 28);
+    assertEquals(pos.get(2).getEnd(), 37);
+    assertEquals(pos.get(2).getType(), "Disulfide bond");
+  
+    /*
+     * now shift left by 15
+     * feature at [7-10] should be removed
+     * feature at [13-19] should become [1-4] 
+     */
+    assertTrue(store.shiftFeatures(-15));
+    pos = store.getPositionalFeatures();
+    assertEquals(pos.size(), 2);
+    SequenceFeatures.sortFeatures(pos, true);
+    assertEquals(pos.get(0).getBegin(), 1);
+    assertEquals(pos.get(0).getEnd(), 4);
+    assertEquals(pos.get(0).getType(), "Metal");
+    assertEquals(pos.get(1).getBegin(), 13);
+    assertEquals(pos.get(1).getEnd(), 22);
+    assertEquals(pos.get(1).getType(), "Disulfide bond");
+  }
+
+  @Test(groups = "Functional")
+  public void testIsOntologyTerm()
+  {
+    SequenceFeatures store = new SequenceFeatures();
+    assertTrue(store.isOntologyTerm("gobbledygook"));
+    assertTrue(store.isOntologyTerm("transcript", "transcript"));
+    assertTrue(store.isOntologyTerm("mRNA", "transcript"));
+    assertFalse(store.isOntologyTerm("transcript", "mRNA"));
+    assertTrue(store.isOntologyTerm("junk", "transcript", "junk"));
+    assertTrue(store.isOntologyTerm("junk", new String[] {}));
+    assertTrue(store.isOntologyTerm("junk", (String[]) null));
+  }
+}
index fb0204b..6611e05 100644 (file)
@@ -212,14 +212,16 @@ public class EnsemblCdnaTest
             20500, 0f, null);
     assertFalse(testee.retainFeature(sf, accId));
 
-    sf.setType("aberrant_processed_transcript");
+    sf = new SequenceFeature("aberrant_processed_transcript", "", 20000,
+            20500, 0f, null);
     assertFalse(testee.retainFeature(sf, accId));
 
-    sf.setType("NMD_transcript_variant");
+    sf = new SequenceFeature("NMD_transcript_variant", "", 20000, 20500,
+            0f, null);
     assertFalse(testee.retainFeature(sf, accId));
 
     // other feature with no parent is retained
-    sf.setType("sequence_variant");
+    sf = new SequenceFeature("sequence_variant", "", 20000, 20500, 0f, null);
     assertTrue(testee.retainFeature(sf, accId));
 
     // other feature with desired parent is retained
@@ -254,15 +256,18 @@ public class EnsemblCdnaTest
     assertTrue(testee.identifiesSequence(sf, accId));
 
     // exon sub-type with right parent is valid
-    sf.setType("coding_exon");
+    sf = new SequenceFeature("coding_exon", "", 1, 2, 0f, null);
+    sf.setValue("Parent", "transcript:" + accId);
     assertTrue(testee.identifiesSequence(sf, accId));
 
     // transcript not valid:
-    sf.setType("transcript");
+    sf = new SequenceFeature("transcript", "", 1, 2, 0f, null);
+    sf.setValue("Parent", "transcript:" + accId);
     assertFalse(testee.identifiesSequence(sf, accId));
 
     // CDS not valid:
-    sf.setType("CDS");
+    sf = new SequenceFeature("CDS", "", 1, 2, 0f, null);
+    sf.setValue("Parent", "transcript:" + accId);
     assertFalse(testee.identifiesSequence(sf, accId));
   }
 
index b7f9f8d..8482c90 100644 (file)
@@ -130,11 +130,12 @@ public class EnsemblCdsTest
             null);
     assertFalse(testee.retainFeature(sf, accId));
 
-    sf.setType("CDS_predicted");
+    sf = new SequenceFeature("CDS_predicted", "", 20000, 20500, 0f, null);
     assertFalse(testee.retainFeature(sf, accId));
 
     // other feature with no parent is retained
-    sf.setType("sequence_variant");
+    sf = new SequenceFeature("CDS_psequence_variantredicted", "", 20000,
+            20500, 0f, null);
     assertTrue(testee.retainFeature(sf, accId));
 
     // other feature with desired parent is retained
@@ -169,15 +170,18 @@ public class EnsemblCdsTest
     assertTrue(testee.identifiesSequence(sf, accId));
 
     // cds sub-type with right parent is valid
-    sf.setType("CDS_predicted");
+    sf = new SequenceFeature("CDS_predicted", "", 1, 2, 0f, null);
+    sf.setValue("Parent", "transcript:" + accId);
     assertTrue(testee.identifiesSequence(sf, accId));
 
     // transcript not valid:
-    sf.setType("transcript");
+    sf = new SequenceFeature("transcript", "", 1, 2, 0f, null);
+    sf.setValue("Parent", "transcript:" + accId);
     assertFalse(testee.identifiesSequence(sf, accId));
 
     // exon not valid:
-    sf.setType("exon");
+    sf = new SequenceFeature("exon", "", 1, 2, 0f, null);
+    sf.setValue("Parent", "transcript:" + accId);
     assertFalse(testee.identifiesSequence(sf, accId));
   }
 
index 6cfd85b..5920b89 100644 (file)
@@ -22,7 +22,6 @@ package jalview.ext.ensembl;
 
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertFalse;
-import static org.testng.AssertJUnit.assertSame;
 import static org.testng.AssertJUnit.assertTrue;
 
 import jalview.api.FeatureSettingsModelI;
@@ -76,7 +75,9 @@ public class EnsemblGeneTest
     genomic.setEnd(50000);
     String geneId = "ABC123";
 
-    // gene at (start+10000) length 501
+    // gene at (start+20000) length 501
+    // should be ignored - the first 'gene' found defines the whole range
+    // (note features are found in position order, not addition order)
     SequenceFeature sf = new SequenceFeature("gene", "", 20000, 20500, 0f,
             null);
     sf.setValue("ID", "gene:" + geneId);
@@ -84,7 +85,6 @@ public class EnsemblGeneTest
     genomic.addSequenceFeature(sf);
 
     // gene at (start + 10500) length 101
-    // should be ignored - the first 'gene' found defines the whole range
     sf = new SequenceFeature("gene", "", 10500, 10600, 0f, null);
     sf.setValue("ID", "gene:" + geneId);
     sf.setStrand("+");
@@ -94,13 +94,13 @@ public class EnsemblGeneTest
             23);
     List<int[]> fromRanges = ranges.getFromRanges();
     assertEquals(1, fromRanges.size());
-    assertEquals(20000, fromRanges.get(0)[0]);
-    assertEquals(20500, fromRanges.get(0)[1]);
+    assertEquals(10500, fromRanges.get(0)[0]);
+    assertEquals(10600, fromRanges.get(0)[1]);
     // to range should start from given start numbering
     List<int[]> toRanges = ranges.getToRanges();
     assertEquals(1, toRanges.size());
     assertEquals(23, toRanges.get(0)[0]);
-    assertEquals(523, toRanges.get(0)[1]);
+    assertEquals(123, toRanges.get(0)[1]);
   }
 
   /**
@@ -115,7 +115,9 @@ public class EnsemblGeneTest
     genomic.setEnd(50000);
     String geneId = "ABC123";
 
-    // gene at (start+10000) length 501
+    // gene at (start+20000) length 501
+    // should be ignored - the first 'gene' found defines the whole range
+    // (real data would only have one such feature)
     SequenceFeature sf = new SequenceFeature("ncRNA_gene", "", 20000,
             20500, 0f, null);
     sf.setValue("ID", "gene:" + geneId);
@@ -123,8 +125,6 @@ public class EnsemblGeneTest
     genomic.addSequenceFeature(sf);
 
     // gene at (start + 10500) length 101
-    // should be ignored - the first 'gene' found defines the whole range
-    // (real data would only have one such feature)
     sf = new SequenceFeature("gene", "", 10500, 10600, 0f, null);
     sf.setValue("ID", "gene:" + geneId);
     sf.setStrand("+");
@@ -135,13 +135,13 @@ public class EnsemblGeneTest
     List<int[]> fromRanges = ranges.getFromRanges();
     assertEquals(1, fromRanges.size());
     // from range on reverse strand:
-    assertEquals(20500, fromRanges.get(0)[0]);
-    assertEquals(20000, fromRanges.get(0)[1]);
+    assertEquals(10500, fromRanges.get(0)[0]);
+    assertEquals(10600, fromRanges.get(0)[1]);
     // to range should start from given start numbering
     List<int[]> toRanges = ranges.getToRanges();
     assertEquals(1, toRanges.size());
     assertEquals(23, toRanges.get(0)[0]);
-    assertEquals(523, toRanges.get(0)[1]);
+    assertEquals(123, toRanges.get(0)[1]);
   }
 
   /**
@@ -164,7 +164,7 @@ public class EnsemblGeneTest
     genomic.addSequenceFeature(sf1);
 
     // transcript sub-type feature
-    SequenceFeature sf2 = new SequenceFeature("snRNA", "", 20000, 20500,
+    SequenceFeature sf2 = new SequenceFeature("snRNA", "", 21000, 21500,
             0f, null);
     sf2.setValue("Parent", "gene:" + geneId);
     sf2.setValue("transcript_id", "transcript2");
@@ -172,13 +172,13 @@ public class EnsemblGeneTest
 
     // NMD_transcript_variant treated like transcript in Ensembl
     SequenceFeature sf3 = new SequenceFeature("NMD_transcript_variant", "",
-            20000, 20500, 0f, null);
+            22000, 22500, 0f, null);
     sf3.setValue("Parent", "gene:" + geneId);
     sf3.setValue("transcript_id", "transcript3");
     genomic.addSequenceFeature(sf3);
 
     // transcript for a different gene - ignored
-    SequenceFeature sf4 = new SequenceFeature("snRNA", "", 20000, 20500,
+    SequenceFeature sf4 = new SequenceFeature("snRNA", "", 23000, 23500,
             0f, null);
     sf4.setValue("Parent", "gene:XYZ");
     sf4.setValue("transcript_id", "transcript4");
@@ -192,9 +192,9 @@ public class EnsemblGeneTest
     List<SequenceFeature> features = testee.getTranscriptFeatures(geneId,
             genomic);
     assertEquals(3, features.size());
-    assertSame(sf1, features.get(0));
-    assertSame(sf2, features.get(1));
-    assertSame(sf3, features.get(2));
+    assertTrue(features.contains(sf1));
+    assertTrue(features.contains(sf2));
+    assertTrue(features.contains(sf3));
   }
 
   /**
@@ -211,22 +211,24 @@ public class EnsemblGeneTest
     sf.setValue("ID", "gene:" + geneId);
     assertFalse(testee.retainFeature(sf, geneId));
 
-    sf.setType("transcript");
+    sf = new SequenceFeature("transcript", "", 20000, 20500, 0f, null);
     sf.setValue("Parent", "gene:" + geneId);
     assertTrue(testee.retainFeature(sf, geneId));
 
-    sf.setType("mature_transcript");
+    sf = new SequenceFeature("mature_transcript", "", 20000, 20500, 0f,
+            null);
     sf.setValue("Parent", "gene:" + geneId);
     assertTrue(testee.retainFeature(sf, geneId));
 
-    sf.setType("NMD_transcript_variant");
+    sf = new SequenceFeature("NMD_transcript_variant", "", 20000, 20500,
+            0f, null);
     sf.setValue("Parent", "gene:" + geneId);
     assertTrue(testee.retainFeature(sf, geneId));
 
     sf.setValue("Parent", "gene:XYZ");
     assertFalse(testee.retainFeature(sf, geneId));
 
-    sf.setType("anything");
+    sf = new SequenceFeature("anything", "", 20000, 20500, 0f, null);
     assertTrue(testee.retainFeature(sf, geneId));
   }
 
@@ -253,15 +255,18 @@ public class EnsemblGeneTest
     assertTrue(testee.identifiesSequence(sf, accId));
 
     // gene sub-type with right ID is valid
-    sf.setType("snRNA_gene");
+    sf = new SequenceFeature("snRNA_gene", "", 1, 2, 0f, null);
+    sf.setValue("ID", "gene:" + accId);
     assertTrue(testee.identifiesSequence(sf, accId));
 
     // transcript not valid:
-    sf.setType("transcript");
+    sf = new SequenceFeature("transcript", "", 1, 2, 0f, null);
+    sf.setValue("ID", "gene:" + accId);
     assertFalse(testee.identifiesSequence(sf, accId));
 
     // exon not valid:
-    sf.setType("exon");
+    sf = new SequenceFeature("exon", "", 1, 2, 0f, null);
+    sf.setValue("ID", "gene:" + accId);
     assertFalse(testee.identifiesSequence(sf, accId));
   }
 
@@ -291,4 +296,28 @@ public class EnsemblGeneTest
     assertEquals(-1, fc.compare("coding_exon", "feature_variant"));
     assertEquals(1f, fc.getTransparency());
   }
+
+  @Test(groups = "Network")
+  public void testGetGeneIds()
+  {
+    /*
+     * ENSG00000158828 gene id PINK1 human
+     * ENST00000321556 transcript for the same gene - should not be duplicated
+     * P30419 Uniprot identifier for ENSG00000136448
+     * ENST00000592782 transcript for Uniprot gene - should not be duplicated
+     * BRAF - gene name resolvabe (at time of writing) for 6 model species
+     */
+    String ids = "ENSG00000158828 ENST00000321556 P30419 ENST00000592782 BRAF";
+    EnsemblGene testee = new EnsemblGene();
+    List<String> geneIds = testee.getGeneIds(ids);
+    assertEquals(8, geneIds.size());
+    assertTrue(geneIds.contains("ENSG00000158828"));
+    assertTrue(geneIds.contains("ENSG00000136448"));
+    assertTrue(geneIds.contains("ENSG00000157764")); // BRAF human
+    assertTrue(geneIds.contains("ENSMUSG00000002413")); // mouse
+    assertTrue(geneIds.contains("ENSRNOG00000010957")); // rat
+    assertTrue(geneIds.contains("ENSXETG00000004845")); // xenopus
+    assertTrue(geneIds.contains("ENSDARG00000017661")); // zebrafish
+    assertTrue(geneIds.contains("ENSGALG00000012865")); // chicken
+  }
 }
index 654797c..8687da9 100644 (file)
@@ -136,14 +136,16 @@ public class EnsemblGenomeTest
             20500, 0f, null);
     assertFalse(testee.retainFeature(sf, accId));
 
-    sf.setType("mature_transcript");
+    sf = new SequenceFeature("mature_transcript", "", 20000, 20500, 0f,
+            null);
     assertFalse(testee.retainFeature(sf, accId));
 
-    sf.setType("NMD_transcript_variant");
+    sf = new SequenceFeature("NMD_transcript_variant", "", 20000, 20500,
+            0f, null);
     assertFalse(testee.retainFeature(sf, accId));
 
     // other feature with no parent is kept
-    sf.setType("anything");
+    sf = new SequenceFeature("anything", "", 20000, 20500, 0f, null);
     assertTrue(testee.retainFeature(sf, accId));
 
     // other feature with correct parent is kept
@@ -179,19 +181,23 @@ public class EnsemblGenomeTest
     assertTrue(testee.identifiesSequence(sf, accId));
 
     // transcript sub-type with right ID is valid
-    sf.setType("ncRNA");
+    sf = new SequenceFeature("ncRNA", "", 1, 2, 0f, null);
+    sf.setValue("ID", "transcript:" + accId);
     assertTrue(testee.identifiesSequence(sf, accId));
 
     // Ensembl treats NMD_transcript_variant as if a transcript
-    sf.setType("NMD_transcript_variant");
+    sf = new SequenceFeature("NMD_transcript_variant", "", 1, 2, 0f, null);
+    sf.setValue("ID", "transcript:" + accId);
     assertTrue(testee.identifiesSequence(sf, accId));
 
     // gene not valid:
-    sf.setType("gene");
+    sf = new SequenceFeature("gene", "", 1, 2, 0f, null);
+    sf.setValue("ID", "transcript:" + accId);
     assertFalse(testee.identifiesSequence(sf, accId));
 
     // exon not valid:
-    sf.setType("exon");
+    sf = new SequenceFeature("exon", "", 1, 2, 0f, null);
+    sf.setValue("ID", "transcript:" + accId);
     assertFalse(testee.identifiesSequence(sf, accId));
   }
 
index 31001da..cc3a3db 100644 (file)
  */
 package jalview.ext.ensembl;
 
+import static org.testng.Assert.assertTrue;
+
 import jalview.datamodel.AlignmentI;
 
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.List;
 
+import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 public class EnsemblRestClientTest
 {
+  private EnsemblRestClient sf;
 
   @Test(suiteName = "live")
   public void testIsEnsemblAvailable()
   {
-    EnsemblRestClient sf = new EnsemblRestClient()
+    boolean isAvailable = sf.isEnsemblAvailable();
+    if (isAvailable)
+    {
+      System.out.println("Ensembl is UP!");
+    }
+    else
+    {
+      System.err
+              .println("Ensembl is DOWN or unreachable ******************* BAD!");
+    }
+  }
+
+  @BeforeMethod(alwaysRun = true)
+  protected void setUp()
+  {
+    sf = new EnsemblRestClient()
     {
 
       @Override
@@ -74,16 +93,14 @@ public class EnsemblRestClientTest
       }
 
     };
-    boolean isAvailable = sf.isEnsemblAvailable();
-    if (isAvailable)
-    {
-      System.out.println("Ensembl is UP!");
-    }
-    else
+  }
+
+  @Test(groups = "Network")
+  public void testCheckEnsembl_overload()
+  {
+    for (int i = 0; i < 20; i++)
     {
-      System.err
-              .println("Ensembl is DOWN or unreachable ******************* BAD!");
+      assertTrue(sf.checkEnsembl(), "Error on " + (i + 1) + "th ping");
     }
   }
-
 }
index e977233..e2af26b 100644 (file)
@@ -22,12 +22,13 @@ package jalview.ext.ensembl;
 
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertSame;
 import static org.testng.AssertJUnit.assertTrue;
-import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
 
 import jalview.datamodel.Alignment;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
+import jalview.datamodel.features.SequenceFeatures;
 import jalview.gui.JvOptionPane;
 import jalview.io.DataSourceType;
 import jalview.io.FastaFile;
@@ -37,6 +38,7 @@ import jalview.io.gff.SequenceOntologyLite;
 
 import java.lang.reflect.Method;
 import java.util.Arrays;
+import java.util.List;
 
 import org.testng.Assert;
 import org.testng.annotations.AfterClass;
@@ -189,34 +191,6 @@ public class EnsemblSeqProxyTest
 
   }
 
-  @Test(groups = "Functional")
-  public void testIsTranscriptIdentifier()
-  {
-    EnsemblSeqProxy testee = new EnsemblGene();
-    assertFalse(testee.isTranscriptIdentifier(null));
-    assertFalse(testee.isTranscriptIdentifier(""));
-    assertFalse(testee.isTranscriptIdentifier("ENSG00000012345"));
-    assertTrue(testee.isTranscriptIdentifier("ENST00000012345"));
-    assertTrue(testee.isTranscriptIdentifier("ENSMUST00000012345"));
-    assertFalse(testee.isTranscriptIdentifier("enst00000012345"));
-    assertFalse(testee.isTranscriptIdentifier("ENST000000123456"));
-    assertFalse(testee.isTranscriptIdentifier("ENST0000001234"));
-  }
-
-  @Test(groups = "Functional")
-  public void testIsGeneIdentifier()
-  {
-    EnsemblSeqProxy testee = new EnsemblGene();
-    assertFalse(testee.isGeneIdentifier(null));
-    assertFalse(testee.isGeneIdentifier(""));
-    assertFalse(testee.isGeneIdentifier("ENST00000012345"));
-    assertTrue(testee.isGeneIdentifier("ENSG00000012345"));
-    assertTrue(testee.isGeneIdentifier("ENSMUSG00000012345"));
-    assertFalse(testee.isGeneIdentifier("ensg00000012345"));
-    assertFalse(testee.isGeneIdentifier("ENSG000000123456"));
-    assertFalse(testee.isGeneIdentifier("ENSG0000001234"));
-  }
-
   /**
    * Test the method that appends a single allele's reverse complement to a
    * string buffer
@@ -269,15 +243,22 @@ public class EnsemblSeqProxyTest
     SequenceFeature sf2 = new SequenceFeature("", "", 8, 12, 0f, null);
     SequenceFeature sf3 = new SequenceFeature("", "", 8, 13, 0f, null);
     SequenceFeature sf4 = new SequenceFeature("", "", 11, 11, 0f, null);
-    SequenceFeature[] sfs = new SequenceFeature[] { sf1, sf2, sf3, sf4 };
+    List<SequenceFeature> sfs = Arrays.asList(new SequenceFeature[] { sf1,
+        sf2, sf3, sf4 });
 
     // sort by start position ascending (forward strand)
     // sf2 and sf3 tie and should not be reordered by sorting
-    EnsemblSeqProxy.sortFeatures(sfs, true);
-    assertArrayEquals(new SequenceFeature[] { sf2, sf3, sf1, sf4 }, sfs);
+    SequenceFeatures.sortFeatures(sfs, true);
+    assertSame(sfs.get(0), sf2);
+    assertSame(sfs.get(1), sf3);
+    assertSame(sfs.get(2), sf1);
+    assertSame(sfs.get(3), sf4);
 
     // sort by end position descending (reverse strand)
-    EnsemblSeqProxy.sortFeatures(sfs, false);
-    assertArrayEquals(new SequenceFeature[] { sf1, sf3, sf2, sf4 }, sfs);
+    SequenceFeatures.sortFeatures(sfs, false);
+    assertSame(sfs.get(0), sf1);
+    assertSame(sfs.get(1), sf3);
+    assertSame(sfs.get(2), sf2);
+    assertSame(sfs.get(3), sf4);
   }
 }
diff --git a/test/jalview/ext/ensembl/SpeciesTest.java b/test/jalview/ext/ensembl/SpeciesTest.java
new file mode 100644 (file)
index 0000000..44658e7
--- /dev/null
@@ -0,0 +1,30 @@
+package jalview.ext.ensembl;
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Set;
+
+import org.testng.annotations.Test;
+
+public class SpeciesTest
+{
+  @Test
+  public void testGetModelOrganisms()
+  {
+    Set<Species> models = Species.getModelOrganisms();
+    assertTrue(models.contains(Species.human));
+    assertFalse(models.contains(Species.horse));
+    for (Species s : Species.values())
+    {
+      if (s.isModelOrganism())
+      {
+        assertTrue(models.contains(s));
+      }
+      else
+      {
+        assertFalse(models.contains(s));
+      }
+    }
+  }
+}
index 36e9b20..f5e637c 100644 (file)
@@ -277,10 +277,9 @@ public class JmolParserTest
     /*
      * the ID is also the group for features derived from structure data 
      */
-    assertNotNull(structureData.getSeqs().get(0).getSequenceFeatures()[0].featureGroup);
-    assertEquals(
-            structureData.getSeqs().get(0).getSequenceFeatures()[0].featureGroup,
-            "localstruct");
-
+    String featureGroup = structureData.getSeqs().get(0)
+            .getSequenceFeatures().get(0).featureGroup;
+    assertNotNull(featureGroup);
+    assertEquals(featureGroup, "localstruct");
   }
 }
index 85fc039..c6c1a29 100644 (file)
@@ -152,10 +152,10 @@ public class TestAnnotate3D
         {
           {
             SequenceI struseq = null;
-            String sq_ = new String(sq.getSequence()).toLowerCase();
+            String sq_ = sq.getSequenceAsString().toLowerCase();
             for (SequenceI _struseq : pdbf.getSeqsAsArray())
             {
-              final String lowerCase = new String(_struseq.getSequence())
+              final String lowerCase = _struseq.getSequenceAsString()
                       .toLowerCase();
               if (lowerCase.equals(sq_))
               {
index c9e1cad..63d5e4e 100644 (file)
@@ -29,6 +29,11 @@ public class AtomSpecModelTest
     assertEquals(model.getAtomSpec(), "#0:1-4.B,5-9.C|#1:2-5.A,8.A,5-10.B");
     model.addRange(0, 3, 10, "C"); // subsumes 5-9
     assertEquals(model.getAtomSpec(), "#0:1-4.B,3-10.C|#1:2-5.A,8.A,5-10.B");
+    model.addRange(5, 25, 35, " "); // empty chain code - e.g. from homology
+                                    // modelling
+    assertEquals(model.getAtomSpec(),
+            "#0:1-4.B,3-10.C|#1:2-5.A,8.A,5-10.B|#5:25-35.");
+
   }
 
 }
index 29fd092..734f7eb 100644 (file)
@@ -39,6 +39,7 @@ import jalview.gui.JvOptionPane;
 import jalview.gui.Preferences;
 import jalview.gui.StructureViewer;
 import jalview.gui.StructureViewer.ViewerType;
+import jalview.io.DataSourceType;
 import jalview.io.FileLoader;
 import jalview.structure.StructureMapping;
 import jalview.structure.StructureSelectionManager;
@@ -50,7 +51,6 @@ import java.io.File;
 import java.io.IOException;
 import java.util.List;
 import java.util.Vector;
-import jalview.io.DataSourceType;
 
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.AfterMethod;
@@ -440,15 +440,18 @@ public class JalviewChimeraView
     binding.copyStructureAttributesToFeatures("phi", af.getViewport()
             .getAlignPanel());
     fr.setVisible("phi");
-    List<SequenceFeature> fs = fr.findFeaturesAtRes(fer2Arath, 54);
+    List<SequenceFeature> fs = fer2Arath.getFeatures().findFeatures(54, 54);
     assertEquals(fs.size(), 3);
-    assertEquals(fs.get(0).getType(), "RESNUM");
-    assertEquals(fs.get(1).getType(), "phi");
-    assertEquals(fs.get(2).getType(), "phi");
-    assertEquals(fs.get(1).getDescription(), "A"); // chain
-    assertEquals(fs.get(2).getDescription(), "B");
-    assertEquals(fs.get(1).getScore(), -131.0713f, 0.001f);
-    assertEquals(fs.get(2).getScore(), -127.39512, 0.001f);
+    /*
+     * order of returned features is not guaranteed
+     */
+    assertTrue("RESNUM".equals(fs.get(0).getType())
+            || "RESNUM".equals(fs.get(1).getType())
+            || "RESNUM".equals(fs.get(2).getType()));
+    assertTrue(fs.contains(new SequenceFeature("phi", "A", 54, 54,
+            -131.0713f, "Chimera")));
+    assertTrue(fs.contains(new SequenceFeature("phi", "B", 54, 54,
+            -127.39512f, "Chimera")));
 
     /*
      * tear down - also in AfterMethod
@@ -470,7 +473,8 @@ public class JalviewChimeraView
           int res, String featureType)
   {
     String where = "at position " + res;
-    List<SequenceFeature> fs = fr.findFeaturesAtRes(seq, res);
+    List<SequenceFeature> fs = seq.getFeatures().findFeatures(res, res);
+
     assertEquals(fs.size(), 2, where);
     assertEquals(fs.get(0).getType(), "RESNUM", where);
     SequenceFeature sf = fs.get(1);
index b2286e0..5ed0cac 100644 (file)
@@ -75,6 +75,13 @@ public class AlignViewportTest
   {
     Jalview.main(new String[] { "-nonews", "-props",
         "test/jalview/testProps.jvprops" });
+
+    /*
+     * remove any sequence mappings left lying around by other tests
+     */
+    StructureSelectionManager ssm = StructureSelectionManager
+            .getStructureSelectionManager(Desktop.instance);
+    ssm.resetAll();
   }
 
   @BeforeMethod(alwaysRun = true)
@@ -89,57 +96,6 @@ public class AlignViewportTest
     testee = new AlignViewport(al);
   }
 
-  @Test(groups = { "Functional" })
-  public void testCollateForPdb()
-  {
-    // JBP: What behaviour is this supposed to test ?
-    /*
-     * Set up sequence pdb ids
-     */
-    PDBEntry pdb1 = new PDBEntry("1ABC", "B", Type.PDB, "1ABC.pdb");
-    PDBEntry pdb2 = new PDBEntry("2ABC", "C", Type.PDB, "2ABC.pdb");
-    PDBEntry pdb3 = new PDBEntry("3ABC", "D", Type.PDB, "3ABC.pdb");
-
-    /*
-     * seq1 and seq3 refer to 1abcB, seq2 to 2abcC, none to 3abcD
-     */
-    al.getSequenceAt(0).getDatasetSequence()
-            .addPDBId(new PDBEntry("1ABC", "B", Type.PDB, "1ABC.pdb"));
-    al.getSequenceAt(2).getDatasetSequence()
-            .addPDBId(new PDBEntry("1ABC", "B", Type.PDB, "1ABC.pdb"));
-    al.getSequenceAt(1).getDatasetSequence()
-            .addPDBId(new PDBEntry("2ABC", "C", Type.PDB, "2ABC.pdb"));
-    /*
-     * Add a second chain PDB xref to Seq2 - should not result in a duplicate in
-     * the results
-     */
-    al.getSequenceAt(1).getDatasetSequence()
-            .addPDBId(new PDBEntry("2ABC", "D", Type.PDB, "2ABC.pdb"));
-    /*
-     * Seq3 refers to 3abc - this does not match 3ABC (as the code stands)
-     */
-    al.getSequenceAt(2).getDatasetSequence()
-            .addPDBId(new PDBEntry("3abc", "D", Type.PDB, "3ABC.pdb"));
-
-    /*
-     * run method under test
-     */
-    SequenceI[][] seqs = testee.collateForPDB(new PDBEntry[] { pdb1, pdb2,
-        pdb3 });
-
-    // seq1 and seq3 refer to PDBEntry[0]
-    assertEquals(2, seqs[0].length);
-    assertSame(al.getSequenceAt(0), seqs[0][0]);
-    assertSame(al.getSequenceAt(2), seqs[0][1]);
-
-    // seq2 refers to PDBEntry[1]
-    assertEquals(1, seqs[1].length);
-    assertSame(al.getSequenceAt(1), seqs[1][0]);
-
-    // no sequence refers to PDBEntry[2]
-    assertEquals(0, seqs[2].length);
-  }
-
   /**
    * Test that a mapping is not deregistered when a second view is closed but
    * the first still holds a reference to the mapping
@@ -173,18 +129,19 @@ public class AlignViewportTest
      */
     StructureSelectionManager ssm = StructureSelectionManager
             .getStructureSelectionManager(Desktop.instance);
-    assertEquals(2, ssm.getSequenceMappings().size());
-    assertTrue(ssm.getSequenceMappings().contains(acf1));
-    assertTrue(ssm.getSequenceMappings().contains(acf2));
+    List<AlignedCodonFrame> sequenceMappings = ssm.getSequenceMappings();
+    assertEquals(2, sequenceMappings.size());
+    assertTrue(sequenceMappings.contains(acf1));
+    assertTrue(sequenceMappings.contains(acf2));
 
     /*
      * Close the second view. Verify that mappings are not removed as the first
      * view still holds a reference to them.
      */
     af1.closeMenuItem_actionPerformed(false);
-    assertEquals(2, ssm.getSequenceMappings().size());
-    assertTrue(ssm.getSequenceMappings().contains(acf1));
-    assertTrue(ssm.getSequenceMappings().contains(acf2));
+    assertEquals(2, sequenceMappings.size());
+    assertTrue(sequenceMappings.contains(acf1));
+    assertTrue(sequenceMappings.contains(acf2));
   }
 
   /**
index b228ba1..2819dbf 100644 (file)
@@ -21,6 +21,7 @@
 package jalview.gui;
 
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotEquals;
 
 import jalview.bin.Cache;
 import jalview.bin.Jalview;
@@ -218,4 +219,31 @@ public class AlignmentPanelTest
             .getAlignment().getWidth() - 1 - 21); // 21 is the number of hidden
                                                   // columns
   }
+
+  /**
+   * Test that update layout reverts to original (unwrapped) values for endRes
+   * and endSeq when switching from wrapped to unwrapped mode (JAL-2739)
+   */
+  @Test(groups = "Functional")
+  public void TestUpdateLayout_endRes()
+  {
+    // get details of original alignment dimensions
+    ViewportRanges ranges = af.getViewport().getRanges();
+    int endres = ranges.getEndRes();
+
+    // wrap
+    af.alignPanel.getAlignViewport().setWrapAlignment(true);
+    af.alignPanel.updateLayout();
+
+    // endRes changes
+    assertNotEquals(ranges.getEndRes(), endres);
+
+    // unwrap
+    af.alignPanel.getAlignViewport().setWrapAlignment(false);
+    af.alignPanel.updateLayout();
+
+    // endRes and endSeq back to original values
+    assertEquals(ranges.getEndRes(), endres);
+
+  }
 }
diff --git a/test/jalview/gui/AnnotationColumnChooserTest.java b/test/jalview/gui/AnnotationColumnChooserTest.java
new file mode 100644 (file)
index 0000000..06478d5
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.gui;
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.AssertJUnit.assertEquals;
+
+import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
+import jalview.bin.Cache;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.SequenceI;
+import jalview.io.DataSourceType;
+import jalview.io.FileFormat;
+import jalview.io.FormatAdapter;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Unit tests for AnnotationChooser
+ * 
+ * @author kmourao
+ *
+ */
+public class AnnotationColumnChooserTest
+{
+  @BeforeClass(alwaysRun = true)
+  public void setUpJvOptionPane()
+  {
+    JvOptionPane.setInteractiveMode(false);
+    JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
+  }
+
+  // 4 sequences x 13 positions
+  final static String TEST_DATA = ">FER_CAPAA Ferredoxin\n"
+          + "TIETHKEAELVG-\n"
+          + ">FER_CAPAN Ferredoxin, chloroplast precursor\n"
+          + "TIETHKEAELVG-\n"
+          + ">FER1_SOLLC Ferredoxin-1, chloroplast precursor\n"
+          + "TIETHKEEELTA-\n" + ">Q93XJ9_SOLTU Ferredoxin I precursor\n"
+          + "TIETHKEEELTA-\n";
+
+  AnnotationChooser testee;
+
+  AlignmentPanel parentPanel;
+
+  AlignFrame af;
+
+  @BeforeMethod(alwaysRun = true)
+  public void setUp() throws IOException
+  {
+    Cache.loadProperties("test/jalview/io/testProps.jvprops");
+    // pin down annotation sort order for test
+    Cache.applicationProperties.setProperty(Preferences.SORT_ANNOTATIONS,
+            SequenceAnnotationOrder.NONE.name());
+    final String TRUE = Boolean.TRUE.toString();
+    Cache.applicationProperties.setProperty(Preferences.SHOW_AUTOCALC_ABOVE,
+            TRUE);
+    Cache.applicationProperties.setProperty("SHOW_QUALITY", TRUE);
+    Cache.applicationProperties.setProperty("SHOW_CONSERVATION", TRUE);
+    Cache.applicationProperties.setProperty("SHOW_IDENTITY", TRUE);
+
+    AlignmentI al = new FormatAdapter().readFile(TEST_DATA,
+            DataSourceType.PASTE, FileFormat.Fasta);
+    af = new AlignFrame(al, 700, 500);
+    parentPanel = new AlignmentPanel(af, af.getViewport());
+    addAnnotations();
+  }
+
+  /**
+   * Add 4 annotations, 3 of them sequence-specific.
+   * 
+   * <PRE>
+   * ann1 - for sequence 0 - label 'IUPRED' ann2 - not sequence related - label
+   * 'Beauty' ann3 - for sequence 3 - label 'JMol' ann4 - for sequence 2 - label
+   * 'IUPRED' ann5 - for sequence 1 - label 'JMol'
+   */
+  private void addAnnotations()
+  {
+    Annotation an = new Annotation(2f);
+    Annotation[] anns = new Annotation[] { an, an, an };
+    AlignmentAnnotation ann0 = new AlignmentAnnotation("IUPRED", "", anns);
+    AlignmentAnnotation ann1 = new AlignmentAnnotation("Beauty", "", anns);
+    AlignmentAnnotation ann2 = new AlignmentAnnotation("JMol", "", anns);
+    AlignmentAnnotation ann3 = new AlignmentAnnotation("IUPRED", "", anns);
+    AlignmentAnnotation ann4 = new AlignmentAnnotation("JMol", "", anns);
+    SequenceI[] seqs = parentPanel.getAlignment().getSequencesArray();
+    ann0.setSequenceRef(seqs[0]);
+    ann2.setSequenceRef(seqs[3]);
+    ann3.setSequenceRef(seqs[2]);
+    ann4.setSequenceRef(seqs[1]);
+    parentPanel.getAlignment().addAnnotation(ann0);
+    parentPanel.getAlignment().addAnnotation(ann1);
+    parentPanel.getAlignment().addAnnotation(ann2);
+    parentPanel.getAlignment().addAnnotation(ann3);
+    parentPanel.getAlignment().addAnnotation(ann4);
+  }
+
+  /**
+   * Test reset
+   */
+  @Test(groups = { "Functional" })
+  public void testReset()
+  {
+    AnnotationColumnChooser acc = new AnnotationColumnChooser(
+            af.getViewport(), af.alignPanel);
+
+    HiddenColumns oldhidden = new HiddenColumns();
+    oldhidden.hideColumns(10, 20);
+    acc.setOldHiddenColumns(oldhidden);
+
+    HiddenColumns newHidden = new HiddenColumns();
+    newHidden.hideColumns(0, 3);
+    newHidden.hideColumns(22, 25);
+    af.getViewport().setHiddenColumns(newHidden);
+
+    HiddenColumns currentHidden = af.getViewport().getAlignment()
+            .getHiddenColumns();
+    List<int[]> regions = currentHidden.getHiddenColumnsCopy();
+    assertEquals(regions.get(0)[0], 0);
+    assertEquals(regions.get(0)[1], 3);
+    assertEquals(regions.get(1)[0], 22);
+    assertEquals(regions.get(1)[1], 25);
+
+    // now reset hidden columns
+    acc.reset();
+    currentHidden = af.getViewport().getAlignment().getHiddenColumns();
+    regions = currentHidden.getHiddenColumnsCopy();
+    assertEquals(regions.get(0)[0], 10);
+    assertEquals(regions.get(0)[1], 20);
+
+    // check works with empty hidden columns as old columns
+    oldhidden = new HiddenColumns();
+    acc.setOldHiddenColumns(oldhidden);
+    acc.reset();
+    currentHidden = af.getViewport().getAlignment().getHiddenColumns();
+    assertFalse(currentHidden.hasHiddenColumns());
+
+    // check works with empty hidden columns as new columns
+    oldhidden.hideColumns(10, 20);
+    acc.setOldHiddenColumns(oldhidden);
+    currentHidden = af.getViewport().getAlignment().getHiddenColumns();
+    assertFalse(currentHidden.hasHiddenColumns());
+
+    acc.reset();
+    currentHidden = af.getViewport().getAlignment().getHiddenColumns();
+    regions = currentHidden.getHiddenColumnsCopy();
+    assertEquals(regions.get(0)[0], 10);
+    assertEquals(regions.get(0)[1], 20);
+  }
+}
diff --git a/test/jalview/gui/FreeUpMemoryTest.java b/test/jalview/gui/FreeUpMemoryTest.java
new file mode 100644 (file)
index 0000000..e93bfac
--- /dev/null
@@ -0,0 +1,216 @@
+package jalview.gui;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import jalview.analysis.AlignmentGenerator;
+import jalview.bin.Cache;
+import jalview.bin.Jalview;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceGroup;
+import jalview.io.DataSourceType;
+import jalview.io.FileLoader;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class FreeUpMemoryTest
+{
+  private static final int ONE_MB = 1000 * 1000;
+
+  /**
+   * Configure (read-only) Jalview property settings for test
+   */
+  @BeforeClass(alwaysRun = true)
+  public void setUp()
+  {
+    Jalview.main(new String[] { "-nonews", "-props",
+        "test/jalview/testProps.jvprops" });
+    Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS",
+            Boolean.TRUE.toString());
+    Cache.applicationProperties.setProperty("SHOW_QUALITY",
+            Boolean.TRUE.toString());
+    Cache.applicationProperties.setProperty("SHOW_CONSERVATION",
+            Boolean.TRUE.toString());
+    Cache.applicationProperties.setProperty("SHOW_OCCUPANCY",
+            Boolean.TRUE.toString());
+    Cache.applicationProperties.setProperty("SHOW_IDENTITY",
+            Boolean.TRUE.toString());
+  }
+
+  /**
+   * A simple test that memory is released when all windows are closed.
+   * <ul>
+   * <li>generates a reasonably large alignment and loads it</li>
+   * <li>performs various operations on the alignment</li>
+   * <li>closes all windows</li>
+   * <li>requests garbage collection</li>
+   * <li>asserts that the remaining memory footprint (heap usage) is 'not large'
+   * </li>
+   * </ul>
+   * If the test fails, this suggests that a reference to some large object
+   * (perhaps the alignment data, or some annotation / Tree / PCA data) has
+   * failed to be garbage collected. If this is the case, the heap will need to
+   * be inspected manually (suggest using jvisualvm) in order to track down
+   * where large objects are still referenced. The code (for example
+   * AlignmentViewport.dispose()) should then be updated to ensure references to
+   * large objects are set to null when they are no longer required.
+   * 
+   * @throws IOException
+   */
+  @Test(groups = "Memory")
+  public void testFreeMemoryOnClose() throws IOException
+  {
+    File f = generateAlignment();
+    f.deleteOnExit();
+
+    doStuffInJalview(f);
+
+    Desktop.instance.closeAll_actionPerformed(null);
+
+    checkUsedMemory(35L);
+  }
+
+  /**
+   * Requests garbage collection and then checks whether remaining memory in use
+   * is less than the expected value (in Megabytes)
+   * 
+   * @param expectedMax
+   */
+  protected void checkUsedMemory(long expectedMax)
+  {
+    /*
+     * request garbage collection and wait briefly for it to run;
+     * NB there is no guarantee when, or whether, it will do so
+     */
+    System.gc();
+    waitFor(100);
+
+    /*
+     * a second gc() call should not be necessary - but it is!
+     * the test passes with it, and fails without it
+     */
+    System.gc();
+    waitFor(100);
+
+    /*
+     * check used memory is 'reasonably low'
+     */
+    long availableMemory = Runtime.getRuntime().totalMemory() / ONE_MB;
+    long freeMemory = Runtime.getRuntime().freeMemory() / ONE_MB;
+    long usedMemory = availableMemory - freeMemory;
+
+    /*
+     * sanity check - fails if any frame was added after
+     * closeAll_actionPerformed
+     */
+    assertEquals(Desktop.instance.getAllFrames().length, 0);
+
+    /*
+     * if this assertion fails
+     * - set a breakpoint here
+     * - run jvisualvm to inspect a heap dump of Jalview
+     * - identify large objects in the heap and their referers
+     * - fix code as necessary to null the references on close
+     */
+    System.out.println("Used memory after gc = " + usedMemory + "MB");
+    assertTrue(usedMemory < expectedMax, String.format(
+            "Used memory %d should be less than %d (Recommend running test manually to verify)",
+            usedMemory,
+            expectedMax));
+  }
+
+  /**
+   * Loads an alignment from file and exercises various operations in Jalview
+   * 
+   * @param f
+   */
+  protected void doStuffInJalview(File f)
+  {
+    /*
+     * load alignment, wait for consensus and other threads to complete
+     */
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(f.getPath(),
+            DataSourceType.FILE);
+    while (af.getViewport().isCalcInProgress())
+    {
+      waitFor(200);
+    }
+
+    /*
+     * set a selection group - potential memory leak if it retains
+     * a reference to the alignment
+     */
+    SequenceGroup sg = new SequenceGroup();
+    sg.setStartRes(0);
+    sg.setEndRes(100);
+    AlignmentI al = af.viewport.getAlignment();
+    for (int i = 0; i < al.getHeight(); i++)
+    {
+      sg.addSequence(al.getSequenceAt(i), false);
+    }
+    af.viewport.setSelectionGroup(sg);
+
+    /*
+     * compute Tree and PCA (on all sequences, 100 columns)
+     */
+    af.openTreePcaDialog();
+    CalculationChooser dialog = af.alignPanel.getCalculationDialog();
+    dialog.openPcaPanel("BLOSUM62", dialog.getSimilarityParameters(true));
+    dialog.openTreePanel("BLOSUM62", dialog.getSimilarityParameters(false));
+
+    /*
+     * wait until Tree and PCA have been computed
+     */
+    while (af.viewport.getCurrentTree() == null
+            && dialog.getPcaPanel().isWorking())
+    {
+      waitFor(10);
+    }
+
+    /*
+     * give Swing time to add the PCA panel (?!?)
+     */
+    waitFor(100);
+  }
+
+  /**
+   * Wait for waitMs miliseconds
+   * 
+   * @param waitMs
+   */
+  protected void waitFor(int waitMs)
+  {
+    try
+    {
+      Thread.sleep(waitMs);
+    } catch (InterruptedException e)
+    {
+    }
+  }
+
+  /**
+   * Generates an alignment and saves it in a temporary file, to be loaded by
+   * Jalview. We use a peptide alignment (so Conservation and Quality are
+   * calculated), which is wide enough to ensure Consensus, Conservation and
+   * Occupancy have a significant memory footprint (if not removed from the
+   * heap).
+   * 
+   * @return
+   * @throws IOException
+   */
+  private File generateAlignment() throws IOException
+  {
+    File f = File.createTempFile("MemoryTest", "fa");
+    PrintStream ps = new PrintStream(f);
+    AlignmentGenerator ag = new AlignmentGenerator(false, ps);
+    int width = 100000;
+    int height = 100;
+    ag.generate(width, height, 0, 10, 15);
+    return f;
+  }
+}
diff --git a/test/jalview/gui/PairwiseAlignmentPanelTest.java b/test/jalview/gui/PairwiseAlignmentPanelTest.java
new file mode 100644 (file)
index 0000000..3322ee8
--- /dev/null
@@ -0,0 +1,73 @@
+package jalview.gui;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceGroup;
+import jalview.io.DataSourceType;
+import jalview.io.FileLoader;
+
+import javax.swing.JTextArea;
+
+import junit.extensions.PA;
+
+import org.testng.annotations.Test;
+
+public class PairwiseAlignmentPanelTest
+{
+  @Test(groups = "Functional")
+  public void testConstructor_withSelectionGroup()
+  {
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+            "examples/uniref50.fa", DataSourceType.FILE);
+    AlignViewport viewport = af.getViewport();
+    AlignmentI al = viewport.getAlignment();
+
+    /*
+     * select columns 29-36 of sequences 4 and 5 for alignment
+     * Q93XJ9_SOLTU/23-29 L-KAISNV
+     * FER1_PEA/26-32     V-TTTKAF
+     */
+    SequenceGroup sg = new SequenceGroup();
+    sg.addSequence(al.getSequenceAt(3), false);
+    sg.addSequence(al.getSequenceAt(4), false);
+    sg.setStartRes(28);
+    sg.setEndRes(35);
+    viewport.setSelectionGroup(sg);
+
+    PairwiseAlignPanel testee = new PairwiseAlignPanel(viewport);
+
+    String text = ((JTextArea) PA.getValue(testee, "textarea")).getText();
+    String expected = "Score = 80.0\n" + "Length of alignment = 4\n"
+            + "Sequence     FER1_PEA/29-32 (Sequence length = 7)\n"
+            + "Sequence Q93XJ9_SOLTU/23-26 (Sequence length = 7)\n\n"
+            + "    FER1_PEA/29-32 TKAF\n" + "                    ||.\n"
+            + "Q93XJ9_SOLTU/23-26 LKAI\n\n" + "Percentage ID = 50.00\n\n";
+    assertEquals(text, expected);
+  }
+
+  /**
+   * This test aligns the same sequences as testConstructor_withSelectionGroup
+   * but as a complete alignment (no selection). Note that in fact the user is
+   * currently required to make a selection in order to calculate pairwise
+   * alignments, so this case does not arise.
+   */
+  @Test(groups = "Functional")
+  public void testConstructor_noSelectionGroup()
+  {
+    String seqs = ">Q93XJ9_SOLTU/23-29\nL-KAISNV\n>FER1_PEA/26-32\nV-TTTKAF\n";
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(seqs,
+            DataSourceType.PASTE);
+    AlignViewport viewport = af.getViewport();
+
+    PairwiseAlignPanel testee = new PairwiseAlignPanel(viewport);
+
+    String text = ((JTextArea) PA.getValue(testee, "textarea")).getText();
+    String expected = "Score = 80.0\n" + "Length of alignment = 4\n"
+            + "Sequence     FER1_PEA/29-32 (Sequence length = 7)\n"
+            + "Sequence Q93XJ9_SOLTU/23-26 (Sequence length = 7)\n\n"
+            + "    FER1_PEA/29-32 TKAF\n" + "                    ||.\n"
+            + "Q93XJ9_SOLTU/23-26 LKAI\n\n" + "Percentage ID = 50.00\n\n";
+    assertEquals(text, expected);
+  }
+}
index a1715e9..72a288b 100644 (file)
@@ -29,6 +29,7 @@ import java.awt.GridLayout;
 
 import javax.swing.JLabel;
 import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
 
 import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
@@ -119,8 +120,15 @@ public class ProgressBarTest
    * @param layout
    * @param msgs
    */
-  private void verifyProgress(GridLayout layout, String[] msgs)
+  private void verifyProgress(final GridLayout layout, final String[] msgs)
   {
+    try
+    {
+    SwingUtilities.invokeAndWait(new Runnable()
+    {
+      @Override
+      public void run()
+      {
     int msgCount = msgs.length;
     assertEquals(1 + msgCount, layout.getRows());
     assertEquals(msgCount, statusPanel.getComponentCount());
@@ -132,5 +140,13 @@ public class ProgressBarTest
       assertEquals(msgs[i++],
               ((JLabel) ((JPanel) c).getComponent(0)).getText());
     }
+      }
+    });
+    } catch (Exception e)
+    {
+      throw new AssertionError(
+              "Unexpected exception waiting for progress bar validation",
+              e);
+    }
   }
 }
diff --git a/test/jalview/gui/SeqCanvasTest.java b/test/jalview/gui/SeqCanvasTest.java
new file mode 100644 (file)
index 0000000..a27bc3f
--- /dev/null
@@ -0,0 +1,283 @@
+package jalview.gui;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.datamodel.AlignmentI;
+import jalview.io.DataSourceType;
+import jalview.io.FileLoader;
+
+import java.awt.Font;
+import java.awt.FontMetrics;
+
+import junit.extensions.PA;
+
+import org.testng.annotations.Test;
+
+import sun.swing.SwingUtilities2;
+
+public class SeqCanvasTest
+{
+  /**
+   * Test the method that computes wrapped width in residues, height of wrapped
+   * widths in pixels, and the number of widths visible
+   */
+  @Test(groups = "Functional")
+  public void testCalculateWrappedGeometry_noAnnotations()
+  {
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+            "examples/uniref50.fa", DataSourceType.FILE);
+    AlignViewport av = af.getViewport();
+    AlignmentI al = av.getAlignment();
+    assertEquals(al.getWidth(), 157);
+    assertEquals(al.getHeight(), 15);
+
+    av.setWrapAlignment(true);
+    av.getRanges().setStartEndSeq(0, 14);
+    av.setFont(new Font("SansSerif", Font.PLAIN, 14), true);
+    int charHeight = av.getCharHeight();
+    int charWidth = av.getCharWidth();
+    assertEquals(charHeight, 17);
+    assertEquals(charWidth, 12);
+
+    SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
+
+    /*
+     * first with scales above, left, right
+     */
+    av.setShowAnnotation(false);
+    av.setScaleAboveWrapped(true);
+    av.setScaleLeftWrapped(true);
+    av.setScaleRightWrapped(true);
+    FontMetrics fm = SwingUtilities2.getFontMetrics(testee, av.getFont());
+    int labelWidth = fm.stringWidth("000") + charWidth;
+    assertEquals(labelWidth, 39); // 3 x 9 + charWidth
+
+    /*
+     * width 400 pixels leaves (400 - 2*labelWidth) for residue columns
+     * take the whole multiple of character widths
+     */
+    int canvasWidth = 400;
+    int canvasHeight = 300;
+    int residueColumns = (canvasWidth - 2 * labelWidth) / charWidth;
+    int wrappedWidth = testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+    assertEquals(wrappedWidth, residueColumns);
+    assertEquals(PA.getValue(testee, "labelWidthWest"), labelWidth);
+    assertEquals(PA.getValue(testee, "labelWidthEast"), labelWidth);
+    assertEquals(PA.getValue(testee, "wrappedSpaceAboveAlignment"),
+            2 * charHeight);
+    int repeatingHeight = (int) PA.getValue(testee, "wrappedRepeatHeightPx");
+    assertEquals(repeatingHeight, charHeight * (2 + al.getHeight()));
+    assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 1);
+
+    /*
+     * repeat height is 17 * (2 + 15) = 289
+     * make canvas height 2 * 289 + 3 * charHeight so just enough to
+     * draw 2 widths and the first sequence of a third
+     */
+    canvasHeight = charHeight * (17 * 2 + 3);
+    testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+    assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
+
+    /*
+     * reduce canvas height by 1 pixel - should not be enough height
+     * to draw 3 widths
+     */
+    canvasHeight -= 1;
+    testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+    assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
+
+    /*
+     * turn off scale above - can now fit in 2 and a bit widths
+     */
+    av.setScaleAboveWrapped(false);
+    testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+    assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
+
+    /*
+     * reduce height to enough for 2 widths and not quite a third
+     * i.e. two repeating heights + spacer + sequence - 1 pixel
+     */
+    canvasHeight = charHeight * (16 * 2 + 2) - 1;
+    testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+    assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
+
+    /*
+     * make canvas width enough for scales and 20 residues
+     */
+    canvasWidth = 2 * labelWidth + 20 * charWidth;
+    wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
+            canvasHeight);
+    assertEquals(wrappedWidth, 20);
+
+    /*
+     * reduce width by 1 pixel - rounds down to 19 residues
+     */
+    canvasWidth -= 1;
+    wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
+            canvasHeight);
+    assertEquals(wrappedWidth, 19);
+
+    /*
+     * turn off West scale - adds labelWidth (39) to available for residues
+     * which with the 11 remainder makes 50 which is 4 more charWidths rem 2
+     */
+    av.setScaleLeftWrapped(false);
+    wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
+            canvasHeight);
+    assertEquals(wrappedWidth, 23);
+
+    /*
+     * add 10 pixels to width to fit in another whole residue column
+     */
+    canvasWidth += 9;
+    wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
+            canvasHeight);
+    assertEquals(wrappedWidth, 23);
+    canvasWidth += 1;
+    wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
+            canvasHeight);
+    assertEquals(wrappedWidth, 24);
+
+    /*
+     * turn off East scale to gain 39 more pixels (3 columns remainder 3)
+     */
+    av.setScaleRightWrapped(false);
+    wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
+            canvasHeight);
+    assertEquals(wrappedWidth, 27);
+
+    /*
+     * add 9 pixels to width to gain a residue column
+     */
+    canvasWidth += 8;
+    wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
+            canvasHeight);
+    assertEquals(wrappedWidth, 27);
+    canvasWidth += 1;
+    wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
+            canvasHeight);
+    assertEquals(wrappedWidth, 28);
+
+    /*
+     * now West but not East scale - lose 39 pixels or 4 columns
+     */
+    av.setScaleLeftWrapped(true);
+    wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
+            canvasHeight);
+    assertEquals(wrappedWidth, 24);
+
+    /*
+     * adding 3 pixels to width regains one column
+     */
+    canvasWidth += 2;
+    wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
+            canvasHeight);
+    assertEquals(wrappedWidth, 24);
+    canvasWidth += 1;
+    wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
+            canvasHeight);
+    assertEquals(wrappedWidth, 25);
+
+    /*
+     * turn off scales left and right, make width exactly 157 columns
+     */
+    av.setScaleLeftWrapped(false);
+    canvasWidth = al.getWidth() * charWidth;
+    testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+    assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 1);
+  }
+
+  /**
+   * Test the method that computes wrapped width in residues, height of wrapped
+   * widths in pixels, and the number of widths visible
+   */
+  @Test(groups = "Functional")
+  public void testCalculateWrappedGeometry_withAnnotations()
+  {
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+            "examples/uniref50.fa", DataSourceType.FILE);
+    AlignViewport av = af.getViewport();
+    AlignmentI al = av.getAlignment();
+    assertEquals(al.getWidth(), 157);
+    assertEquals(al.getHeight(), 15);
+  
+    av.setWrapAlignment(true);
+    av.getRanges().setStartEndSeq(0, 14);
+    av.setFont(new Font("SansSerif", Font.PLAIN, 14), true);
+    int charHeight = av.getCharHeight();
+    int charWidth = av.getCharWidth();
+    assertEquals(charHeight, 17);
+    assertEquals(charWidth, 12);
+  
+    SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
+  
+    /*
+     * first with scales above, left, right
+     */
+    av.setShowAnnotation(true);
+    av.setScaleAboveWrapped(true);
+    av.setScaleLeftWrapped(true);
+    av.setScaleRightWrapped(true);
+    FontMetrics fm = SwingUtilities2.getFontMetrics(testee, av.getFont());
+    int labelWidth = fm.stringWidth("000") + charWidth;
+    assertEquals(labelWidth, 39); // 3 x 9 + charWidth
+    int annotationHeight = testee.getAnnotationHeight();
+
+    /*
+     * width 400 pixels leaves (400 - 2*labelWidth) for residue columns
+     * take the whole multiple of character widths
+     */
+    int canvasWidth = 400;
+    int canvasHeight = 300;
+    int residueColumns = (canvasWidth - 2 * labelWidth) / charWidth;
+    int wrappedWidth = testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+    assertEquals(wrappedWidth, residueColumns);
+    assertEquals(PA.getValue(testee, "labelWidthWest"), labelWidth);
+    assertEquals(PA.getValue(testee, "labelWidthEast"), labelWidth);
+    assertEquals(PA.getValue(testee, "wrappedSpaceAboveAlignment"),
+            2 * charHeight);
+    int repeatingHeight = (int) PA.getValue(testee, "wrappedRepeatHeightPx");
+    assertEquals(repeatingHeight, charHeight * (2 + al.getHeight())
+            + annotationHeight);
+    assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 1);
+  
+    /*
+     * repeat height is 17 * (2 + 15) = 289 + annotationHeight = 507
+     * make canvas height 2 * 289 + 3 * charHeight so just enough to
+     * draw 2 widths and the first sequence of a third
+     */
+    canvasHeight = charHeight * (17 * 2 + 3) + 2 * annotationHeight;
+    testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+    assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
+  
+    /*
+     * reduce canvas height by 1 pixel - should not be enough height
+     * to draw 3 widths
+     */
+    canvasHeight -= 1;
+    testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+    assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
+  
+    /*
+     * turn off scale above - can now fit in 2 and a bit widths
+     */
+    av.setScaleAboveWrapped(false);
+    testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+    assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
+  
+    /*
+     * reduce height to enough for 2 widths and not quite a third
+     * i.e. two repeating heights + spacer + sequence - 1 pixel
+     */
+    canvasHeight = charHeight * (16 * 2 + 2) + 2 * annotationHeight - 1;
+    testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+    assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
+
+    /*
+     * add 1 pixel to height - should now get 3 widths drawn
+     */
+    canvasHeight += 1;
+    testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+    assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
+  }
+}
index c80b830..359377a 100644 (file)
  */
 package jalview.gui;
 
-import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.Assert.assertEquals;
 
+import jalview.bin.Jalview;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
+import jalview.renderer.ResidueShader;
+import jalview.renderer.ResidueShaderI;
 import jalview.schemes.ZappoColourScheme;
 
 import java.awt.Color;
 
 import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 public class SequenceRendererTest
 {
+  AlignmentI al;
+  AlignViewport av;
+
+  SequenceI seq1;
 
   @BeforeClass(alwaysRun = true)
-  public void setUpJvOptionPane()
+  public static void setUpBeforeClass() throws Exception
   {
-    JvOptionPane.setInteractiveMode(false);
-    JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
+    Jalview.main(
+            new String[]
+    { "-nonews", "-props", "test/jalview/testProps.jvprops" });
   }
 
-  @Test(groups = { "Functional" })
-  public void testGetResidueBoxColour_zappo()
+  @BeforeMethod(alwaysRun = true)
+  public void setUp()
   {
-    SequenceI seq = new Sequence("name", "MATVLGSPRAPAFF"); // FER1_MAIZE...
-    AlignmentI al = new Alignment(new SequenceI[] { seq });
-    final AlignViewport av = new AlignViewport(al);
-    SequenceRenderer sr = new SequenceRenderer(av);
-    av.setGlobalColourScheme(new ZappoColourScheme());
-
-    // @see ResidueProperties.zappo
-    assertEquals(Color.pink, sr.getResidueBoxColour(seq, 0)); // M
-    assertEquals(Color.green, sr.getResidueBoxColour(seq, 2)); // T
-    assertEquals(Color.magenta, sr.getResidueBoxColour(seq, 5)); // G
-    assertEquals(Color.orange, sr.getResidueBoxColour(seq, 12)); // F
+    seq1 = new Sequence("Seq1", "ABCEEEABCABC");
+    SequenceI seq2 = new Sequence("Seq2", "ABCABCABCABC");
+    SequenceI seq3 = new Sequence("Seq3", "ABCABCABCABC");
+    SequenceI[] seqs = new SequenceI[] { seq1, seq2, seq3 };
+    al = new Alignment(seqs);
+    al.setDataset(null);
+    av = new AlignViewport(al);
   }
 
-  @Test(groups = { "Functional" })
-  public void testGetResidueBoxColour_none()
+  @Test(groups = "Functional")
+  public void testGetResidueColour_WithGroup()
   {
-    SequenceI seq = new Sequence("name", "MA--TVLGSPRAPAFF");
-    AlignmentI al = new Alignment(new SequenceI[] { seq });
-    final AlignViewport av = new AlignViewport(al);
     SequenceRenderer sr = new SequenceRenderer(av);
+    SequenceGroup sg = new SequenceGroup();
+    sg.addSequence(seq1, false);
+    sg.setStartRes(3);
+    sg.setEndRes(5);
 
-    assertEquals(Color.white, sr.getResidueBoxColour(seq, 0));
-    assertEquals(Color.white, sr.getResidueBoxColour(seq, 2));
+    ResidueShaderI rs = new ResidueShader();
+    rs.setColourScheme(new ZappoColourScheme());
+    sg.setGroupColourScheme(rs);
 
-    // set for overview
-    sr.forOverview = true;
-    assertEquals(Color.lightGray, sr.getResidueBoxColour(seq, 0));
-    assertEquals(Color.white, sr.getResidueBoxColour(seq, 2));
-  }
+    av.getAlignment().addGroup(sg);
 
-  // TODO more tests for getResidueBoxColour covering groups, feature rendering,
-  // gaps, overview...
+    // outside group residues are white
+    assertEquals(Color.white, sr.getResidueColour(seq1, 1, null));
 
+    // within group use Zappo scheme - E = red
+    assertEquals(Color.red, sr.getResidueColour(seq1, 3, null));
+  }
 }
index c1c1d5c..86342d2 100644 (file)
@@ -1,10 +1,17 @@
 package jalview.gui;
 
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
 
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.PDBEntry.Type;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+
+import java.util.Map;
 
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
@@ -20,9 +27,11 @@ public class StructureViewerTest
   }
 
   @Test(groups = "Functional")
-  public void testGetUniquePdbFiles()
+  public void testGetSequencesForPdbs()
   {
-    assertNull(StructureViewer.getUniquePdbFiles(null));
+    StructureViewer sv = new StructureViewer(null);
+
+    assertNull(sv.getSequencesForPdbs(null, null));
 
     PDBEntry pdbe1 = new PDBEntry("1A70", "A", Type.PDB, "path1");
     PDBEntry pdbe2 = new PDBEntry("3A6S", "A", Type.PDB, "path2");
@@ -30,13 +39,53 @@ public class StructureViewerTest
     PDBEntry pdbe4 = new PDBEntry("1GAQ", "A", Type.PDB, null);
     PDBEntry pdbe5 = new PDBEntry("3A6S", "B", Type.PDB, "path2");
     PDBEntry pdbe6 = new PDBEntry("1GAQ", "B", Type.PDB, null);
+    PDBEntry pdbe7 = new PDBEntry("1FOO", "Q", Type.PDB, null);
+
+    PDBEntry[] pdbs = new PDBEntry[] { pdbe1, pdbe2, pdbe3, pdbe4, pdbe5,
+        pdbe6, pdbe7 };
+
+    /*
+     * seq1 ... seq6 associated with pdbe1 ... pdbe6
+     */
+    SequenceI[] seqs = new SequenceI[pdbs.length];
+    for (int i = 0; i < seqs.length; i++)
+    {
+      seqs[i] = new Sequence("Seq" + i, "abc");
+    }
 
     /*
-     * pdbe2 and pdbe5 get removed as having a duplicate file path
+     * pdbe3/5/6 should get removed as having a duplicate file path
      */
-    PDBEntry[] uniques = StructureViewer.getUniquePdbFiles(new PDBEntry[] {
-        pdbe1, pdbe2, pdbe3, pdbe4, pdbe5, pdbe6 });
-    assertEquals(uniques,
- new PDBEntry[] { pdbe1, pdbe2, pdbe4, pdbe6 });
+    Map<PDBEntry, SequenceI[]> uniques = sv.getSequencesForPdbs(pdbs, seqs);
+    assertTrue(uniques.containsKey(pdbe1));
+    assertTrue(uniques.containsKey(pdbe2));
+    assertFalse(uniques.containsKey(pdbe3));
+    assertTrue(uniques.containsKey(pdbe4));
+    assertFalse(uniques.containsKey(pdbe5));
+    assertFalse(uniques.containsKey(pdbe6));
+    assertTrue(uniques.containsKey(pdbe7));
+
+    // 1A70 associates with seq1 and seq3
+    SequenceI[] ss = uniques.get(pdbe1);
+    assertEquals(ss.length, 2);
+    assertSame(seqs[0], ss[0]);
+    assertSame(seqs[2], ss[1]);
+
+    // 3A6S has seq2 and seq5
+    ss = uniques.get(pdbe2);
+    assertEquals(ss.length, 2);
+    assertSame(seqs[1], ss[0]);
+    assertSame(seqs[4], ss[1]);
+
+    // 1GAQ has seq4 and seq6
+    ss = uniques.get(pdbe4);
+    assertEquals(ss.length, 2);
+    assertSame(seqs[3], ss[0]);
+    assertSame(seqs[5], ss[1]);
+
+    // 1FOO has seq7
+    ss = uniques.get(pdbe7);
+    assertEquals(ss.length, 1);
+    assertSame(seqs[6], ss[0]);
   }
 }
index d8ae999..e14a478 100644 (file)
@@ -30,12 +30,14 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
+import jalview.datamodel.features.SequenceFeatures;
 import jalview.gui.AlignFrame;
 import jalview.gui.JvOptionPane;
 import jalview.structure.StructureImportSettings;
 import jalview.structure.StructureImportSettings.StructureParser;
 
 import java.io.File;
+import java.util.List;
 
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
@@ -127,32 +129,35 @@ public class AnnotatedPDBFileInputTest
     /*
      * 1GAQ/A
      */
-    SequenceFeature[] sf = al.getSequenceAt(0).getSequenceFeatures();
-    assertEquals(296, sf.length);
-    assertEquals("RESNUM", sf[0].getType());
-    assertEquals("GLU:  19  1gaqA", sf[0].getDescription());
-    assertEquals("RESNUM", sf[295].getType());
-    assertEquals("TYR: 314  1gaqA", sf[295].getDescription());
+    List<SequenceFeature> sf = al.getSequenceAt(0).getSequenceFeatures();
+    SequenceFeatures.sortFeatures(sf, true);
+    assertEquals(296, sf.size());
+    assertEquals("RESNUM", sf.get(0).getType());
+    assertEquals("GLU:  19  1gaqA", sf.get(0).getDescription());
+    assertEquals("RESNUM", sf.get(295).getType());
+    assertEquals("TYR: 314  1gaqA", sf.get(295).getDescription());
 
     /*
      * 1GAQ/B
      */
     sf = al.getSequenceAt(1).getSequenceFeatures();
-    assertEquals(98, sf.length);
-    assertEquals("RESNUM", sf[0].getType());
-    assertEquals("ALA:   1  1gaqB", sf[0].getDescription());
-    assertEquals("RESNUM", sf[97].getType());
-    assertEquals("ALA:  98  1gaqB", sf[97].getDescription());
+    SequenceFeatures.sortFeatures(sf, true);
+    assertEquals(98, sf.size());
+    assertEquals("RESNUM", sf.get(0).getType());
+    assertEquals("ALA:   1  1gaqB", sf.get(0).getDescription());
+    assertEquals("RESNUM", sf.get(97).getType());
+    assertEquals("ALA:  98  1gaqB", sf.get(97).getDescription());
 
     /*
      * 1GAQ/C
      */
     sf = al.getSequenceAt(2).getSequenceFeatures();
-    assertEquals(296, sf.length);
-    assertEquals("RESNUM", sf[0].getType());
-    assertEquals("GLU:  19  1gaqC", sf[0].getDescription());
-    assertEquals("RESNUM", sf[295].getType());
-    assertEquals("TYR: 314  1gaqC", sf[295].getDescription());
+    SequenceFeatures.sortFeatures(sf, true);
+    assertEquals(296, sf.size());
+    assertEquals("RESNUM", sf.get(0).getType());
+    assertEquals("GLU:  19  1gaqC", sf.get(0).getDescription());
+    assertEquals("RESNUM", sf.get(295).getType());
+    assertEquals("TYR: 314  1gaqC", sf.get(295).getDescription());
   }
 
   @Test(groups = { "Functional" })
index ec5855f..0715857 100644 (file)
@@ -31,10 +31,12 @@ import jalview.gui.CrossRefAction;
 import jalview.gui.Desktop;
 import jalview.gui.Jalview2XML;
 import jalview.gui.JvOptionPane;
+import jalview.util.DBRefUtils;
 
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 
@@ -65,10 +67,13 @@ public class CrossRef2xmlTests extends Jalview2xmlBase
   public void testRetrieveAndShowCrossref() throws Exception
   {
 
-    List<String> failedDBRetr = new ArrayList<String>();
-    List<String> failedXrefMenuItems = new ArrayList<String>();
-    List<String> failedProjectRecoveries = new ArrayList<String>();
-
+    List<String> failedDBRetr = new ArrayList<>();
+    List<String> failedXrefMenuItems = new ArrayList<>();
+    List<String> failedProjectRecoveries = new ArrayList<>();
+    // only search for ensembl or Uniprot crossrefs
+    List<String> limit=Arrays.asList(new String[] {
+        DBRefUtils.getCanonicalName("ENSEMBL"), 
+        DBRefUtils.getCanonicalName("Uniprot")});
     // for every set of db queries
     // retrieve db query
     // verify presence of expected xrefs
@@ -85,12 +90,11 @@ public class CrossRef2xmlTests extends Jalview2xmlBase
     // . codonframes
     //
     //
-    HashMap<String, String> dbtoviewBit = new HashMap<String, String>();
-    List<String> keyseq = new ArrayList<String>();
-    HashMap<String, File> savedProjects = new HashMap<String, File>();
+    HashMap<String, String> dbtoviewBit = new HashMap<>();
+    List<String> keyseq = new ArrayList<>();
+    HashMap<String, File> savedProjects = new HashMap<>();
 
-    for (String[] did : new String[][] { { "ENSEMBL", "ENSG00000157764" },
-    { "UNIPROT", "P01731" } })
+    for (String[] did : new String[][] { { "UNIPROT", "P00338" } })
     {
       // pass counters - 0 - first pass, 1 means retrieve project rather than
       // perform action
@@ -163,7 +167,8 @@ public class CrossRef2xmlTests extends Jalview2xmlBase
 
         ptypes = (seqs == null || seqs.length == 0) ? null : new CrossRef(
                 seqs, dataset).findXrefSourcesForSequences(dna);
-
+        filterDbRefs(ptypes, limit);
+        
         // start of pass2: retrieve each cross-ref for fetched or restored
         // project.
         do // first cross ref and recover crossref loop
@@ -176,7 +181,7 @@ public class CrossRef2xmlTests extends Jalview2xmlBase
             // build next key so we an retrieve all views
             String nextxref = first + " -> " + db + "{" + firstcr_ap + "}";
             // perform crossref action, or retrieve stored project
-            List<AlignmentViewPanel> cra_views = new ArrayList<AlignmentViewPanel>();
+            List<AlignmentViewPanel> cra_views = new ArrayList<>();
             CrossRefAction cra = null;
 
             if (pass2 == 0)
@@ -237,7 +242,7 @@ public class CrossRef2xmlTests extends Jalview2xmlBase
 
               }
             }
-            HashMap<String, List<String>> xrptypes = new HashMap<String, List<String>>();
+            HashMap<String, List<String>> xrptypes = new HashMap<>();
             // first save/verify views.
             for (AlignmentViewPanel avp : cra_views)
             {
@@ -274,7 +279,7 @@ public class CrossRef2xmlTests extends Jalview2xmlBase
                 nextxref = first + " -> " + db + "{" + firstcr_ap++ + "}";
                 for (String xrefdb : xrptypes.get(nextxref))
                 {
-                  List<AlignmentViewPanel> cra_views2 = new ArrayList<AlignmentViewPanel>();
+                  List<AlignmentViewPanel> cra_views2 = new ArrayList<>();
                   int q = 0;
                   String nextnextxref = nextxref + " -> " + xrefdb + "{"
                           + q + "}";
@@ -437,6 +442,25 @@ public class CrossRef2xmlTests extends Jalview2xmlBase
     }
   }
 
+  private void filterDbRefs(List<String> ptypes, List<String> limit)
+  {
+    if (limit != null)
+    {
+      int p = 0;
+      while (ptypes.size() > p)
+      {
+        if (!limit.contains(ptypes.get(p)))
+        {
+          ptypes.remove(p);
+        }
+        else
+        {
+          p++;
+        }
+      }
+    }
+  }
+
   /**
    * wrapper to trap known defect for AH002001 testcase
    * 
@@ -480,7 +504,7 @@ public class CrossRef2xmlTests extends Jalview2xmlBase
   private void assertType(boolean expectProtein,
           AlignmentViewPanel alignmentViewPanel, String message)
   {
-    List<SequenceI> nonType = new ArrayList<SequenceI>();
+    List<SequenceI> nonType = new ArrayList<>();
     for (SequenceI sq : alignmentViewPanel.getAlignViewport()
             .getAlignment().getSequences())
     {
index cc7dca0..152ab84 100644 (file)
@@ -23,7 +23,6 @@ package jalview.io;
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertFalse;
 import static org.testng.AssertJUnit.assertNotNull;
-import static org.testng.AssertJUnit.assertNull;
 import static org.testng.AssertJUnit.assertTrue;
 
 import jalview.api.FeatureColourI;
@@ -33,19 +32,39 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.SequenceDummy;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
+import jalview.datamodel.features.SequenceFeatures;
 import jalview.gui.AlignFrame;
+import jalview.gui.Desktop;
 import jalview.gui.JvOptionPane;
+import jalview.structure.StructureSelectionManager;
 
 import java.awt.Color;
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
+import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
 public class FeaturesFileTest
 {
+  private static String simpleGffFile = "examples/testdata/simpleGff3.gff";
+
+  @AfterClass(alwaysRun = true)
+  public void tearDownAfterClass()
+  {
+    /*
+     * remove any sequence mappings created so they don't pollute other tests
+     */
+    StructureSelectionManager ssm = StructureSelectionManager
+            .getStructureSelectionManager(Desktop.instance);
+    ssm.resetAll();
+  }
 
   @BeforeClass(alwaysRun = true)
   public void setUpJvOptionPane()
@@ -54,8 +73,6 @@ public class FeaturesFileTest
     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
   }
 
-  private static String simpleGffFile = "examples/testdata/simpleGff3.gff";
-
   @Test(groups = { "Functional" })
   public void testParse() throws Exception
   {
@@ -86,10 +103,15 @@ public class FeaturesFileTest
     /*
      * verify (some) features on sequences
      */
-    SequenceFeature[] sfs = al.getSequenceAt(0).getDatasetSequence()
+    List<SequenceFeature> sfs = al.getSequenceAt(0).getDatasetSequence()
             .getSequenceFeatures(); // FER_CAPAA
-    assertEquals(8, sfs.length);
-    SequenceFeature sf = sfs[0];
+    SequenceFeatures.sortFeatures(sfs, true);
+    assertEquals(8, sfs.size());
+
+    /*
+     * verify (in ascending start position order)
+     */
+    SequenceFeature sf = sfs.get(0);
     assertEquals("Pfam family%LINK%", sf.description);
     assertEquals(0, sf.begin);
     assertEquals(0, sf.end);
@@ -99,46 +121,52 @@ public class FeaturesFileTest
     assertEquals("Pfam family|http://pfam.xfam.org/family/PF00111",
             sf.links.get(0));
 
-    sf = sfs[1];
+    sf = sfs.get(1);
+    assertEquals("Ferredoxin_fold Status: True Positive ", sf.description);
+    assertEquals(3, sf.begin);
+    assertEquals(93, sf.end);
+    assertEquals("uniprot", sf.featureGroup);
+    assertEquals("Cath", sf.type);
+
+    sf = sfs.get(2);
+    assertEquals("Fer2 Status: True Positive Pfam 8_8%LINK%",
+            sf.description);
+    assertEquals("Pfam 8_8|http://pfam.xfam.org/family/PF00111",
+            sf.links.get(0));
+    assertEquals(8, sf.begin);
+    assertEquals(83, sf.end);
+    assertEquals("uniprot", sf.featureGroup);
+    assertEquals("Pfam", sf.type);
+
+    sf = sfs.get(3);
     assertEquals("Iron-sulfur (2Fe-2S)", sf.description);
     assertEquals(39, sf.begin);
     assertEquals(39, sf.end);
     assertEquals("uniprot", sf.featureGroup);
     assertEquals("METAL", sf.type);
-    sf = sfs[2];
+
+    sf = sfs.get(4);
     assertEquals("Iron-sulfur (2Fe-2S)", sf.description);
     assertEquals(44, sf.begin);
     assertEquals(44, sf.end);
     assertEquals("uniprot", sf.featureGroup);
     assertEquals("METAL", sf.type);
-    sf = sfs[3];
+
+    sf = sfs.get(5);
     assertEquals("Iron-sulfur (2Fe-2S)", sf.description);
     assertEquals(47, sf.begin);
     assertEquals(47, sf.end);
     assertEquals("uniprot", sf.featureGroup);
     assertEquals("METAL", sf.type);
-    sf = sfs[4];
+
+    sf = sfs.get(6);
     assertEquals("Iron-sulfur (2Fe-2S)", sf.description);
     assertEquals(77, sf.begin);
     assertEquals(77, sf.end);
     assertEquals("uniprot", sf.featureGroup);
     assertEquals("METAL", sf.type);
-    sf = sfs[5];
-    assertEquals("Fer2 Status: True Positive Pfam 8_8%LINK%",
-            sf.description);
-    assertEquals("Pfam 8_8|http://pfam.xfam.org/family/PF00111",
-            sf.links.get(0));
-    assertEquals(8, sf.begin);
-    assertEquals(83, sf.end);
-    assertEquals("uniprot", sf.featureGroup);
-    assertEquals("Pfam", sf.type);
-    sf = sfs[6];
-    assertEquals("Ferredoxin_fold Status: True Positive ", sf.description);
-    assertEquals(3, sf.begin);
-    assertEquals(93, sf.end);
-    assertEquals("uniprot", sf.featureGroup);
-    assertEquals("Cath", sf.type);
-    sf = sfs[7];
+
+    sf = sfs.get(7);
     assertEquals(
             "High confidence server. Only hits with scores over 0.8 are reported. PHOSPHORYLATION (T) 89_8%LINK%",
             sf.description);
@@ -181,10 +209,10 @@ public class FeaturesFileTest
     assertEquals(colours.get("METAL").getColour(), new Color(0xcc9900));
 
     // verify feature on FER_CAPAA
-    SequenceFeature[] sfs = al.getSequenceAt(0).getDatasetSequence()
+    List<SequenceFeature> sfs = al.getSequenceAt(0).getDatasetSequence()
             .getSequenceFeatures();
-    assertEquals(1, sfs.length);
-    SequenceFeature sf = sfs[0];
+    assertEquals(1, sfs.size());
+    SequenceFeature sf = sfs.get(0);
     assertEquals("Iron-sulfur,2Fe-2S", sf.description);
     assertEquals(44, sf.begin);
     assertEquals(45, sf.end);
@@ -194,8 +222,8 @@ public class FeaturesFileTest
 
     // verify feature on FER1_SOLLC
     sfs = al.getSequenceAt(2).getDatasetSequence().getSequenceFeatures();
-    assertEquals(1, sfs.length);
-    sf = sfs[0];
+    assertEquals(1, sfs.size());
+    sf = sfs.get(0);
     assertEquals("uniprot", sf.description);
     assertEquals(55, sf.begin);
     assertEquals(130, sf.end);
@@ -242,10 +270,10 @@ public class FeaturesFileTest
             featuresFile.parse(al.getDataset(), colours, true));
 
     // verify feature on FER_CAPAA
-    SequenceFeature[] sfs = al.getSequenceAt(0).getDatasetSequence()
+    List<SequenceFeature> sfs = al.getSequenceAt(0).getDatasetSequence()
             .getSequenceFeatures();
-    assertEquals(1, sfs.length);
-    SequenceFeature sf = sfs[0];
+    assertEquals(1, sfs.size());
+    SequenceFeature sf = sfs.get(0);
     // description parsed from Note attribute
     assertEquals("Iron-sulfur (2Fe-2S),another note", sf.description);
     assertEquals(39, sf.begin);
@@ -258,8 +286,8 @@ public class FeaturesFileTest
 
     // verify feature on FER1_SOLLC1
     sfs = al.getSequenceAt(2).getDatasetSequence().getSequenceFeatures();
-    assertEquals(1, sfs.length);
-    sf = sfs[0];
+    assertEquals(1, sfs.size());
+    sf = sfs.get(0);
     // ID used for description if available
     assertEquals("$23", sf.description);
     assertEquals(55, sf.begin);
@@ -295,10 +323,10 @@ public class FeaturesFileTest
             featuresFile.parse(al.getDataset(), colours, true));
 
     // verify FER_CAPAA feature
-    SequenceFeature[] sfs = al.getSequenceAt(0).getDatasetSequence()
+    List<SequenceFeature> sfs = al.getSequenceAt(0).getDatasetSequence()
             .getSequenceFeatures();
-    assertEquals(1, sfs.length);
-    SequenceFeature sf = sfs[0];
+    assertEquals(1, sfs.size());
+    SequenceFeature sf = sfs.get(0);
     assertEquals("Iron-sulfur (2Fe-2S)", sf.description);
     assertEquals(39, sf.begin);
     assertEquals(39, sf.end);
@@ -306,8 +334,8 @@ public class FeaturesFileTest
 
     // verify FER1_SOLLC feature
     sfs = al.getSequenceAt(2).getDatasetSequence().getSequenceFeatures();
-    assertEquals(1, sfs.length);
-    sf = sfs[0];
+    assertEquals(1, sfs.size());
+    sf = sfs.get(0);
     assertEquals("Iron-phosphorus (2Fe-P)", sf.description);
     assertEquals(86, sf.begin);
     assertEquals(87, sf.end);
@@ -337,14 +365,14 @@ public class FeaturesFileTest
     assertFalse("dummy replacement buggy for seq2",
             placeholderseq.equals(seq2.getSequenceAsString()));
     assertNotNull("No features added to seq1", seq1.getSequenceFeatures());
-    assertEquals("Wrong number of features", 3,
-            seq1.getSequenceFeatures().length);
-    assertNull(seq2.getSequenceFeatures());
+    assertEquals("Wrong number of features", 3, seq1.getSequenceFeatures()
+            .size());
+    assertTrue(seq2.getSequenceFeatures().isEmpty());
     assertEquals(
             "Wrong number of features",
             0,
             seq2.getSequenceFeatures() == null ? 0 : seq2
-                    .getSequenceFeatures().length);
+                    .getSequenceFeatures().size());
     assertTrue(
             "Expected at least one CDNA/Protein mapping for seq1",
             dataset.getCodonFrame(seq1) != null
@@ -410,6 +438,7 @@ public class FeaturesFileTest
             + "GAMMA-TURN\tred|0,255,255|20.0|95.0|below|66.0\n"
             + "Pfam\tred\n"
             + "STARTGROUP\tuniprot\n"
+            + "Cath\tFER_CAPAA\t-1\t0\t0\tDomain\n" // non-positional feature
             + "Iron\tFER_CAPAA\t-1\t39\t39\tMETAL\n"
             + "Turn\tFER_CAPAA\t-1\t36\t38\tGAMMA-TURN\n"
             + "<html>Pfam domain<a href=\"http://pfam.xfam.org/family/PF00111\">Pfam_3_4</a></html>\tFER_CAPAA\t-1\t20\t20\tPfam\n"
@@ -419,28 +448,57 @@ public class FeaturesFileTest
     featuresFile.parse(al.getDataset(), colours, false);
 
     /*
-     * first with no features displayed
+     * add positional and non-positional features with null and
+     * empty feature group to check handled correctly
+     */
+    SequenceI seq = al.getSequenceAt(1); // FER_CAPAN
+    seq.addSequenceFeature(new SequenceFeature("Pfam", "desc1", 0, 0, 1.3f,
+            null));
+    seq.addSequenceFeature(new SequenceFeature("Pfam", "desc2", 4, 9,
+            Float.NaN, null));
+    seq = al.getSequenceAt(2); // FER1_SOLLC
+    seq.addSequenceFeature(new SequenceFeature("Pfam", "desc3", 0, 0,
+            Float.NaN, ""));
+    seq.addSequenceFeature(new SequenceFeature("Pfam", "desc4", 5, 8,
+            -2.6f, ""));
+
+    /*
+     * first with no features displayed, exclude non-positional features
      */
     FeatureRenderer fr = af.alignPanel.getFeatureRenderer();
     Map<String, FeatureColourI> visible = fr.getDisplayedFeatureCols();
+    List<String> visibleGroups = new ArrayList<String>(
+            Arrays.asList(new String[] {}));
     String exported = featuresFile.printJalviewFormat(
-            al.getSequencesArray(), visible);
+            al.getSequencesArray(), visible, visibleGroups, false);
     String expected = "No Features Visible";
     assertEquals(expected, exported);
 
     /*
+     * include non-positional features
+     */
+    visibleGroups.add("uniprot");
+    exported = featuresFile.printJalviewFormat(al.getSequencesArray(),
+            visible, visibleGroups, true);
+    expected = "Cath\tFER_CAPAA\t-1\t0\t0\tDomain\t0.0\n"
+            + "desc1\tFER_CAPAN\t-1\t0\t0\tPfam\t1.3\n"
+            + "desc3\tFER1_SOLLC\t-1\t0\t0\tPfam\n" // NaN is not output
+            + "\nSTARTGROUP\tuniprot\nENDGROUP\tuniprot\n";
+    assertEquals(expected, exported);
+
+    /*
      * set METAL (in uniprot group) and GAMMA-TURN visible, but not Pfam
      */
     fr.setVisible("METAL");
     fr.setVisible("GAMMA-TURN");
     visible = fr.getDisplayedFeatureCols();
     exported = featuresFile.printJalviewFormat(al.getSequencesArray(),
-            visible);
+            visible, visibleGroups, false);
     expected = "METAL\tcc9900\n"
             + "GAMMA-TURN\tff0000|00ffff|20.0|95.0|below|66.0\n"
             + "\nSTARTGROUP\tuniprot\n"
-            + "Iron\tFER_CAPAA\t-1\t39\t39\tMETAL\t0.0\n"
             + "Turn\tFER_CAPAA\t-1\t36\t38\tGAMMA-TURN\t0.0\n"
+            + "Iron\tFER_CAPAA\t-1\t39\t39\tMETAL\t0.0\n"
             + "ENDGROUP\tuniprot\n";
     assertEquals(expected, exported);
 
@@ -450,19 +508,119 @@ public class FeaturesFileTest
     fr.setVisible("Pfam");
     visible = fr.getDisplayedFeatureCols();
     exported = featuresFile.printJalviewFormat(al.getSequencesArray(),
-            visible);
+            visible, visibleGroups, false);
     /*
-     * note the order of feature types is uncontrolled - derives from
-     * FeaturesDisplayed.featuresDisplayed which is a HashSet
+     * features are output within group, ordered by sequence and by type
      */
     expected = "METAL\tcc9900\n"
             + "Pfam\tff0000\n"
             + "GAMMA-TURN\tff0000|00ffff|20.0|95.0|below|66.0\n"
             + "\nSTARTGROUP\tuniprot\n"
-            + "Iron\tFER_CAPAA\t-1\t39\t39\tMETAL\t0.0\n"
             + "Turn\tFER_CAPAA\t-1\t36\t38\tGAMMA-TURN\t0.0\n"
+            + "Iron\tFER_CAPAA\t-1\t39\t39\tMETAL\t0.0\n"
             + "<html>Pfam domain<a href=\"http://pfam.xfam.org/family/PF00111\">Pfam_3_4</a></html>\tFER_CAPAA\t-1\t20\t20\tPfam\t0.0\n"
-            + "ENDGROUP\tuniprot\n";
+            + "ENDGROUP\tuniprot\n"
+            // null / empty group features output after features in named
+            // groups:
+            + "desc2\tFER_CAPAN\t-1\t4\t9\tPfam\n"
+            + "desc4\tFER1_SOLLC\t-1\t5\t8\tPfam\t-2.6\n";
+    assertEquals(expected, exported);
+  }
+
+  @Test(groups = { "Functional" })
+  public void testPrintGffFormat() throws Exception
+  {
+    File f = new File("examples/uniref50.fa");
+    AlignmentI al = readAlignmentFile(f);
+    AlignFrame af = new AlignFrame(al, 500, 500);
+
+    /*
+     * no features
+     */
+    FeaturesFile featuresFile = new FeaturesFile();
+    FeatureRenderer fr = af.alignPanel.getFeatureRenderer();
+    Map<String, FeatureColourI> visible = new HashMap<String, FeatureColourI>();
+    List<String> visibleGroups = new ArrayList<String>(
+            Arrays.asList(new String[] {}));
+    String exported = featuresFile.printGffFormat(al.getSequencesArray(),
+            visible, visibleGroups, false);
+    String gffHeader = "##gff-version 2\n";
+    assertEquals(gffHeader, exported);
+    exported = featuresFile.printGffFormat(al.getSequencesArray(), visible,
+            visibleGroups, true);
+    assertEquals(gffHeader, exported);
+
+    /*
+     * add some features
+     */
+    al.getSequenceAt(0).addSequenceFeature(
+            new SequenceFeature("Domain", "Cath", 0, 0, 0f, "Uniprot"));
+    al.getSequenceAt(0).addSequenceFeature(
+            new SequenceFeature("METAL", "Cath", 39, 39, 1.2f, null));
+    al.getSequenceAt(1)
+            .addSequenceFeature(
+                    new SequenceFeature("GAMMA-TURN", "Turn", 36, 38, 2.1f,
+                            "s3dm"));
+    SequenceFeature sf = new SequenceFeature("Pfam", "", 20, 20, 0f,
+            "Uniprot");
+    sf.setAttributes("x=y;black=white");
+    sf.setStrand("+");
+    sf.setPhase("2");
+    al.getSequenceAt(1).addSequenceFeature(sf);
+
+    /*
+     * with no features displayed, exclude non-positional features
+     */
+    exported = featuresFile.printGffFormat(al.getSequencesArray(), visible,
+            visibleGroups, false);
+    assertEquals(gffHeader, exported);
+
+    /*
+     * include non-positional features
+     */
+    visibleGroups.add("Uniprot");
+    exported = featuresFile.printGffFormat(al.getSequencesArray(), visible,
+            visibleGroups, true);
+    String expected = gffHeader
+            + "FER_CAPAA\tUniprot\tDomain\t0\t0\t0.0\t.\t.\n";
+    assertEquals(expected, exported);
+
+    /*
+     * set METAL (in uniprot group) and GAMMA-TURN visible, but not Pfam
+     * only Uniprot group visible here...
+     */
+    fr.setVisible("METAL");
+    fr.setVisible("GAMMA-TURN");
+    visible = fr.getDisplayedFeatureCols();
+    exported = featuresFile.printGffFormat(al.getSequencesArray(), visible,
+            visibleGroups, false);
+    // METAL feature has null group: description used for column 2
+    expected = gffHeader + "FER_CAPAA\tCath\tMETAL\t39\t39\t1.2\t.\t.\n";
+    assertEquals(expected, exported);
+
+    /*
+     * set s3dm group visible
+     */
+    visibleGroups.add("s3dm");
+    exported = featuresFile.printGffFormat(al.getSequencesArray(), visible,
+            visibleGroups, false);
+    // METAL feature has null group: description used for column 2
+    expected = gffHeader + "FER_CAPAA\tCath\tMETAL\t39\t39\t1.2\t.\t.\n"
+            + "FER_CAPAN\ts3dm\tGAMMA-TURN\t36\t38\t2.1\t.\t.\n";
+    assertEquals(expected, exported);
+
+    /*
+     * now set Pfam visible
+     */
+    fr.setVisible("Pfam");
+    visible = fr.getDisplayedFeatureCols();
+    exported = featuresFile.printGffFormat(al.getSequencesArray(), visible,
+            visibleGroups, false);
+    // Pfam feature columns include strand(+), phase(2), attributes
+    expected = gffHeader
+            + "FER_CAPAA\tCath\tMETAL\t39\t39\t1.2\t.\t.\n"
+            + "FER_CAPAN\ts3dm\tGAMMA-TURN\t36\t38\t2.1\t.\t.\n"
+            + "FER_CAPAN\tUniprot\tPfam\t20\t20\t0.0\t+\t2\tx=y;black=white\n";
     assertEquals(expected, exported);
   }
 }
index e046d94..158c901 100644 (file)
@@ -32,6 +32,7 @@ import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
+import jalview.datamodel.features.SequenceFeatures;
 import jalview.gui.AlignFrame;
 import jalview.gui.JvOptionPane;
 import jalview.json.binding.biojson.v1.ColourSchemeMapper;
@@ -42,6 +43,7 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.testng.Assert;
 import org.testng.AssertJUnit;
@@ -96,6 +98,10 @@ public class JSONFileTest
   @BeforeTest(alwaysRun = true)
   public void setup() throws Exception
   {
+    /*
+     * construct expected values
+     * nb this have to match the data in examples/example.json
+     */
     // create and add sequences
     Sequence[] seqs = new Sequence[5];
     seqs[0] = new Sequence("FER_CAPAN",
@@ -115,14 +121,18 @@ public class JSONFileTest
 
     // create and add sequence features
     SequenceFeature seqFeature2 = new SequenceFeature("feature_x",
-            "desciption", "status", 6, 15, "Jalview");
+            "theDesc", 6, 15, "Jalview");
     SequenceFeature seqFeature3 = new SequenceFeature("feature_x",
-            "desciption", "status", 9, 18, "Jalview");
+            "theDesc", 9, 18, "Jalview");
     SequenceFeature seqFeature4 = new SequenceFeature("feature_x",
-            "desciption", "status", 9, 18, "Jalview");
+            "theDesc", 9, 18, "Jalview");
+    // non-positional feature:
+    SequenceFeature seqFeature5 = new SequenceFeature("Domain",
+            "My description", 0, 0, "Pfam");
     seqs[2].addSequenceFeature(seqFeature2);
     seqs[3].addSequenceFeature(seqFeature3);
     seqs[4].addSequenceFeature(seqFeature4);
+    seqs[2].addSequenceFeature(seqFeature5);
 
     for (Sequence seq : seqs)
     {
@@ -456,7 +466,7 @@ public class JSONFileTest
     return true;
   }
 
-  public boolean isSeqMatched(SequenceI expectedSeq, SequenceI actualSeq)
+  boolean isSeqMatched(SequenceI expectedSeq, SequenceI actualSeq)
   {
     System.out.println("Testing >>> " + actualSeq.getName());
 
@@ -490,14 +500,19 @@ public class JSONFileTest
             + actualGrp.getStartRes());
     System.out.println(expectedGrp.getEndRes() + " | "
             + actualGrp.getEndRes());
-    System.out.println(expectedGrp.cs + " | " + actualGrp.cs);
+    System.out.println(expectedGrp.cs.getColourScheme() + " | "
+            + actualGrp.cs.getColourScheme());
 
+    boolean colourSchemeMatches = (expectedGrp.cs.getColourScheme() == null && actualGrp.cs
+            .getColourScheme() == null)
+            || expectedGrp.cs.getColourScheme().getClass()
+                    .equals(actualGrp.cs.getColourScheme().getClass());
     if (expectedGrp.getName().equals(actualGrp.getName())
             && expectedGrp.getColourText() == actualGrp.getColourText()
             && expectedGrp.getDisplayBoxes() == actualGrp.getDisplayBoxes()
             && expectedGrp.getIgnoreGapsConsensus() == actualGrp
                     .getIgnoreGapsConsensus()
-            && (expectedGrp.cs.getClass().equals(actualGrp.cs.getClass()))
+            && colourSchemeMatches
             && expectedGrp.getSequences().size() == actualGrp
                     .getSequences().size()
             && expectedGrp.getStartRes() == actualGrp.getStartRes()
@@ -510,7 +525,6 @@ public class JSONFileTest
 
   private boolean featuresMatched(SequenceI seq1, SequenceI seq2)
   {
-    boolean matched = false;
     try
     {
       if (seq1 == null && seq2 == null)
@@ -518,52 +532,95 @@ public class JSONFileTest
         return true;
       }
 
-      SequenceFeature[] inFeature = seq1.getSequenceFeatures();
-      SequenceFeature[] outFeature = seq2.getSequenceFeatures();
+      List<SequenceFeature> inFeature = seq1.getFeatures().getAllFeatures();
+      List<SequenceFeature> outFeature = seq2.getFeatures()
+              .getAllFeatures();
 
-      if (inFeature == null && outFeature == null)
-      {
-        return true;
-      }
-      else if ((inFeature == null && outFeature != null)
-              || (inFeature != null && outFeature == null))
+      if (inFeature.size() != outFeature.size())
       {
+        System.err.println("Feature count in: " + inFeature.size()
+                + ", out: " + outFeature.size());
         return false;
       }
 
-      int testSize = inFeature.length;
-      int matchedCount = 0;
+      SequenceFeatures.sortFeatures(inFeature, true);
+      SequenceFeatures.sortFeatures(outFeature, true);
+      int i = 0;
       for (SequenceFeature in : inFeature)
       {
-        for (SequenceFeature out : outFeature)
+        SequenceFeature out = outFeature.get(i);
+        /*
+        System.out.println(out.getType() + " | " + in.getType());
+        System.out.println(out.getBegin() + " | " + in.getBegin());
+        System.out.println(out.getEnd() + " | " + in.getEnd());
+        */
+        if (!in.equals(out))
         {
-          System.out.println(out.getType() + " | " + in.getType());
-          System.out.println(out.getBegin() + " | " + in.getBegin());
-          System.out.println(out.getEnd() + " | " + in.getEnd());
-
-          if (inFeature.length == outFeature.length
-                  && in.getBegin() == out.getBegin()
-                  && in.getEnd() == out.getEnd()
-                  && in.getScore() == out.getScore()
-                  && in.getFeatureGroup().equals(out.getFeatureGroup())
-                  && in.getType().equals(out.getType()))
-          {
-
-            ++matchedCount;
-          }
+          System.err.println("Mismatch of " + in.toString() + " "
+                  + out.toString());
+          return false;
         }
-      }
-      System.out.println("matched count >>>>>> " + matchedCount);
-      if (testSize == matchedCount)
-      {
-        matched = true;
+        /*
+                if (in.getBegin() == out.getBegin() && in.getEnd() == out.getEnd()
+                        && in.getScore() == out.getScore()
+                        && in.getFeatureGroup().equals(out.getFeatureGroup())
+                        && in.getType().equals(out.getType())
+                        && mapsMatch(in.otherDetails, out.otherDetails))
+                {
+                }
+                else
+                {
+                  System.err.println("Feature[" + i + "] mismatch, in: "
+                          + in.toString() + ", out: "
+                          + outFeature.get(i).toString());
+                  return false;
+                }
+                */
+        i++;
       }
     } catch (Exception e)
     {
       e.printStackTrace();
     }
     // System.out.println(">>>>>>>>>>>>>> features matched : " + matched);
-    return matched;
+    return true;
+  }
+
+  boolean mapsMatch(Map<String, Object> m1, Map<String, Object> m2)
+  {
+    if (m1 == null || m2 == null)
+    {
+      if (m1 != null || m2 != null)
+      {
+        System.err
+                .println("only one SequenceFeature.otherDetails is not null");
+        return false;
+      }
+      else
+      {
+        return true;
+      }
+    }
+    if (m1.size() != m2.size())
+    {
+      System.err.println("otherDetails map different sizes");
+      return false;
+    }
+    for (String key : m1.keySet())
+    {
+      if (!m2.containsKey(key))
+      {
+        System.err.println(key + " in only one otherDetails");
+        return false;
+      }
+      if (m1.get(key) == null && m2.get(key) != null || m1.get(key) != null
+              && m2.get(key) == null || !m1.get(key).equals(m2.get(key)))
+      {
+        System.err.println(key + " values in otherDetails don't match");
+        return false;
+      }
+    }
+    return true;
   }
 
   /**
@@ -599,7 +656,7 @@ public class JSONFileTest
     Assert.assertNotNull(newAlignment.getGroups());
     for (SequenceGroup seqGrp : newAlignment.getGroups())
     {
-      SequenceGroup expectedGrp = expectedGrps.get(seqGrp.getName());
+      SequenceGroup expectedGrp = copySg;
       AssertJUnit.assertTrue(
               "Failed SequenceGroup Test for >>> " + seqGrp.getName(),
               isGroupMatched(expectedGrp, seqGrp));
index 2895874..9e61bec 100644 (file)
 package jalview.io;
 
 import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertTrue;
 
+import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceI;
 import jalview.gui.JvOptionPane;
+import jalview.io.gff.GffConstants;
 
+import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.Map;
 
+import junit.extensions.PA;
+
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
@@ -192,4 +200,134 @@ public class SequenceAnnotationReportTest
     // if no <html> tag, html-encodes > and < (only):
     assertEquals("METAL 1 3; &lt;br&gt;&kHD&gt;6", sb.toString());
   }
+
+  @Test(groups = "Functional")
+  public void testCreateSequenceAnnotationReport()
+  {
+    SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
+    StringBuilder sb = new StringBuilder();
+
+    SequenceI seq = new Sequence("s1", "MAKLKRFQSSTLL");
+    seq.setDescription("SeqDesc");
+
+    sar.createSequenceAnnotationReport(sb, seq, true, true, null);
+
+    /*
+     * positional features are ignored
+     */
+    seq.addSequenceFeature(new SequenceFeature("Domain", "Ferredoxin", 5,
+            10, 1f, null));
+    assertEquals("<i><br>SeqDesc</i>", sb.toString());
+
+    /*
+     * non-positional feature
+     */
+    seq.addSequenceFeature(new SequenceFeature("Type1", "Nonpos", 0, 0, 1f,
+            null));
+    sb.setLength(0);
+    sar.createSequenceAnnotationReport(sb, seq, true, true, null);
+    String expected = "<i><br>SeqDesc<br>Type1 ; Nonpos</i>";
+    assertEquals(expected, sb.toString());
+
+    /*
+     * non-positional features not wanted
+     */
+    sb.setLength(0);
+    sar.createSequenceAnnotationReport(sb, seq, true, false, null);
+    assertEquals("<i><br>SeqDesc</i>", sb.toString());
+
+    /*
+     * add non-pos feature with score inside min-max range for feature type
+     * minmax holds { [positionalMin, positionalMax], [nonPosMin, nonPosMax] }
+     * score is only appended for positional features so ignored here!
+     * minMax are not recorded for non-positional features
+     */
+    seq.addSequenceFeature(new SequenceFeature("Metal", "Desc", 0, 0, 5f,
+            null));
+    Map<String, float[][]> minmax = new HashMap<String, float[][]>();
+    minmax.put("Metal", new float[][] { null, new float[] { 2f, 5f } });
+    sb.setLength(0);
+    sar.createSequenceAnnotationReport(sb, seq, true, true, minmax);
+    expected = "<i><br>SeqDesc<br>Metal ; Desc<br>Type1 ; Nonpos</i>";
+    assertEquals(expected, sb.toString());
+    
+    /*
+     * 'linkonly' features are ignored; this is obsolete, as linkonly
+     * is only set by DasSequenceFetcher, and DAS is history
+     */
+    SequenceFeature sf = new SequenceFeature("Metal", "Desc", 0, 0, 5f,
+            null);
+    sf.setValue("linkonly", Boolean.TRUE);
+    seq.addSequenceFeature(sf);
+    sb.setLength(0);
+    sar.createSequenceAnnotationReport(sb, seq, true, true, minmax);
+    assertEquals(expected, sb.toString()); // unchanged!
+
+    /*
+     * 'clinical_significance' currently being specially included
+     */
+    SequenceFeature sf2 = new SequenceFeature("Variant", "Havana", 0, 0,
+            5f, null);
+    sf2.setValue(GffConstants.CLINICAL_SIGNIFICANCE, "benign");
+    seq.addSequenceFeature(sf2);
+    sb.setLength(0);
+    sar.createSequenceAnnotationReport(sb, seq, true, true, minmax);
+    expected = "<i><br>SeqDesc<br>Metal ; Desc<br>Type1 ; Nonpos<br>Variant ; Havana; benign</i>";
+    assertEquals(expected, sb.toString());
+
+    /*
+     * add dbrefs
+     */
+    seq.addDBRef(new DBRefEntry("PDB", "0", "3iu1"));
+    seq.addDBRef(new DBRefEntry("Uniprot", "1", "P30419"));
+    // with showDbRefs = false
+    sb.setLength(0);
+    sar.createSequenceAnnotationReport(sb, seq, false, true, minmax);
+    assertEquals(expected, sb.toString()); // unchanged
+    // with showDbRefs = true
+    sb.setLength(0);
+    sar.createSequenceAnnotationReport(sb, seq, true, true, minmax);
+    expected = "<i><br>SeqDesc<br>UNIPROT P30419<br>PDB 3iu1<br>Metal ; Desc<br>Type1 ; Nonpos<br>Variant ; Havana; benign</i>";
+    assertEquals(expected, sb.toString());
+    // with showNonPositionalFeatures = false
+    sb.setLength(0);
+    sar.createSequenceAnnotationReport(sb, seq, true, false, minmax);
+    expected = "<i><br>SeqDesc<br>UNIPROT P30419<br>PDB 3iu1</i>";
+    assertEquals(expected, sb.toString());
+
+    // see other tests for treatment of status and html
+  }
+
+  /**
+   * Test that exercises an abbreviated sequence details report, with ellipsis
+   * where there are more than 40 different sources, or more than 4 dbrefs for a
+   * single source
+   */
+  @Test(groups = "Functional")
+  public void testCreateSequenceAnnotationReport_withEllipsis()
+  {
+    SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
+    StringBuilder sb = new StringBuilder();
+  
+    SequenceI seq = new Sequence("s1", "ABC");
+
+    int maxSources = (int) PA.getValue(sar, "MAX_SOURCES");
+    for (int i = 0; i <= maxSources; i++)
+    {
+      seq.addDBRef(new DBRefEntry("PDB" + i, "0", "3iu1"));
+    }
+    
+    int maxRefs = (int) PA.getValue(sar, "MAX_REFS_PER_SOURCE");
+    for (int i = 0; i <= maxRefs; i++)
+    {
+      seq.addDBRef(new DBRefEntry("Uniprot", "0", "P3041" + i));
+    }
+  
+    sar.createSequenceAnnotationReport(sb, seq, true, true, null, true);
+    String report = sb.toString();
+    assertTrue(report
+            .startsWith("<i><br>UNIPROT P30410, P30411, P30412, P30413,...<br>PDB0 3iu1"));
+    assertTrue(report
+            .endsWith("<br>PDB7 3iu1<br>PDB8,...<br>(Output Sequence Details to list all database references)</i>"));
+  }
 }
index 228c935..4273e6c 100644 (file)
@@ -287,7 +287,8 @@ public class StockholmFileTest
     seq_original = al.getSequencesArray();
     SequenceI[] seq_new = new SequenceI[al_input.getSequencesArray().length];
     seq_new = al_input.getSequencesArray();
-    SequenceFeature[] sequenceFeatures_original, sequenceFeatures_new;
+    List<SequenceFeature> sequenceFeatures_original;
+    List<SequenceFeature> sequenceFeatures_new;
     AlignmentAnnotation annot_original, annot_new;
     //
     for (int i = 0; i < al.getSequencesArray().length; i++)
@@ -323,23 +324,20 @@ public class StockholmFileTest
                   && seq_new[in].getSequenceFeatures() != null)
           {
             System.out.println("There are feature!!!");
-            sequenceFeatures_original = new SequenceFeature[seq_original[i]
-                    .getSequenceFeatures().length];
             sequenceFeatures_original = seq_original[i]
                     .getSequenceFeatures();
-            sequenceFeatures_new = new SequenceFeature[seq_new[in]
-                    .getSequenceFeatures().length];
             sequenceFeatures_new = seq_new[in].getSequenceFeatures();
 
-            assertEquals("different number of features",
-                    seq_original[i].getSequenceFeatures().length,
-                    seq_new[in].getSequenceFeatures().length);
+            assertEquals("different number of features", seq_original[i]
+                    .getSequenceFeatures().size(), seq_new[in]
+                    .getSequenceFeatures().size());
 
-            for (int feat = 0; feat < seq_original[i].getSequenceFeatures().length; feat++)
+            for (int feat = 0; feat < seq_original[i].getSequenceFeatures()
+                    .size(); feat++)
             {
               assertEquals("Different features",
-                      sequenceFeatures_original[feat],
-                      sequenceFeatures_new[feat]);
+                      sequenceFeatures_original.get(feat),
+                      sequenceFeatures_new.get(feat));
             }
           }
           // compare alignment annotation
index bf038ac..cd5a0d8 100644 (file)
@@ -37,7 +37,9 @@ import jalview.gui.JvOptionPane;
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
@@ -231,4 +233,48 @@ public class Gff3HelperTest
             .getToRanges().get(0));
   }
 
+  @Test(groups = "Functional")
+  public void testGetDescription()
+  {
+    Gff3Helper testee = new Gff3Helper();
+    SequenceFeature sf = new SequenceFeature("type", "desc", 10, 20, 3f,
+            "group");
+    Map<String, List<String>> attributes = new HashMap<String, List<String>>();
+    assertNull(testee.getDescription(sf, attributes));
+
+    // ID if any is a fall-back for description
+    sf.setValue("ID", "Patrick");
+    assertEquals("Patrick", testee.getDescription(sf, attributes));
+
+    // Target is set by Exonerate
+    sf.setValue("Target", "Destination Moon");
+    assertEquals("Destination", testee.getDescription(sf, attributes));
+
+    // Ensembl variant feature - extract "alleles" value
+    // may be sequence_variant or a sub-type in the sequence ontology
+    sf = new SequenceFeature("feature_variant", "desc", 10, 20, 3f, "group");
+    List<String> atts = new ArrayList<String>();
+    atts.add("A");
+    atts.add("C");
+    atts.add("T");
+    attributes.put("alleles", atts);
+    assertEquals("A,C,T", testee.getDescription(sf, attributes));
+
+    // Ensembl transcript or exon feature - extract Name
+    List<String> atts2 = new ArrayList<String>();
+    atts2.add("ENSE00001871077");
+    attributes.put("Name", atts2);
+    sf = new SequenceFeature("transcript", "desc", 10, 20, 3f, "group");
+    assertEquals("ENSE00001871077", testee.getDescription(sf, attributes));
+    // transcript sub-type in SO
+    sf = new SequenceFeature("mRNA", "desc", 10, 20, 3f, "group");
+    assertEquals("ENSE00001871077", testee.getDescription(sf, attributes));
+    // special usage of feature by Ensembl
+    sf = new SequenceFeature("NMD_transcript_variant", "desc", 10, 20, 3f,
+            "group");
+    assertEquals("ENSE00001871077", testee.getDescription(sf, attributes));
+    // exon feature
+    sf = new SequenceFeature("exon", "desc", 10, 20, 3f, "group");
+    assertEquals("ENSE00001871077", testee.getDescription(sf, attributes));
+  }
 }
index bcccf35..dde83a3 100644 (file)
@@ -21,6 +21,7 @@
 package jalview.io.gff;
 
 import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNotNull;
 import static org.testng.AssertJUnit.assertSame;
 import static org.testng.AssertJUnit.assertTrue;
 import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
@@ -30,6 +31,7 @@ import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceDummy;
+import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.gui.JvOptionPane;
 
@@ -76,6 +78,16 @@ public class InterProScanHelperTest
     assertEquals(1, newseqs.size());
     assertTrue(newseqs.get(0) instanceof SequenceDummy);
     assertEquals("match$17_5_30", newseqs.get(0).getName());
+
+    assertNotNull(newseqs.get(0).getSequenceFeatures());
+    assertEquals(1, newseqs.get(0).getSequenceFeatures().size());
+    SequenceFeature sf = newseqs.get(0).getSequenceFeatures().get(0);
+    assertEquals(1, sf.getBegin());
+    assertEquals(26, sf.getEnd());
+    assertEquals("Pfam", sf.getType());
+    assertEquals("4Fe-4S dicluster domain", sf.getDescription());
+    assertEquals("InterProScan", sf.getFeatureGroup());
+
     assertEquals(1, align.getCodonFrames().size());
     AlignedCodonFrame mapping = align.getCodonFrames().iterator().next();
 
diff --git a/test/jalview/renderer/OverviewResColourFinderTest.java b/test/jalview/renderer/OverviewResColourFinderTest.java
new file mode 100644 (file)
index 0000000..1687516
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.renderer;
+
+import static org.testng.AssertJUnit.assertEquals;
+
+import jalview.bin.Cache;
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignViewport;
+import jalview.gui.JvOptionPane;
+import jalview.schemes.ColourSchemeI;
+import jalview.schemes.UserColourScheme;
+import jalview.schemes.ZappoColourScheme;
+
+import java.awt.Color;
+import java.util.ArrayList;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class OverviewResColourFinderTest
+{
+
+  @BeforeClass(alwaysRun = true)
+  public void setUpJvOptionPane()
+  {
+    JvOptionPane.setInteractiveMode(false);
+    JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
+    Cache.loadProperties("test/jalview/io/testProps.jvprops");
+  }
+
+  @Test(groups = { "Functional" })
+  public void testGetResidueBoxColour_none()
+  {
+    SequenceI seq = new Sequence("name", "MA--TVLGSPRAPAFF");
+    AlignmentI al = new Alignment(new SequenceI[] { seq });
+    final AlignViewport av = new AlignViewport(al);
+    ResidueColourFinder rcf = new OverviewResColourFinder();
+
+    // gaps are grey, residues white
+    assertEquals(Color.white, rcf.getResidueColour(true,
+            av.getResidueShading(),
+            null, seq, 0, null));
+    assertEquals(Color.lightGray, rcf
+            .getResidueColour(true, av.getResidueShading(), null, seq, 2,
+                    null));
+
+    // unaffected by showBoxes setting
+    assertEquals(Color.white, rcf.getResidueColour(false,
+            av.getResidueShading(), null, seq, 0, null));
+    assertEquals(Color.lightGray, rcf.getResidueColour(false,
+            av.getResidueShading(), null, seq, 2, null));
+  }
+
+  @Test(groups = { "Functional" })
+  public void testGetResidueBoxColour_zappo()
+  {
+    SequenceI seq = new Sequence("name", "MAT--GSPRAPAFF"); // FER1_MAIZE... + a
+                                                            // gap
+    AlignmentI al = new Alignment(new SequenceI[] { seq });
+    final AlignViewport av = new AlignViewport(al);
+    ResidueColourFinder rcf = new OverviewResColourFinder();
+    av.setGlobalColourScheme(new ZappoColourScheme());
+
+    // @see ResidueProperties.zappo
+    assertEquals(Color.pink,
+            rcf.getResidueColour(true, av.getResidueShading(),
+            null, seq, 0, null)); // M
+    assertEquals(Color.green,
+            rcf.getResidueColour(true, av.getResidueShading(),
+            null, seq, 2, null)); // T
+    assertEquals(Color.magenta,
+            rcf.getResidueColour(true, av.getResidueShading(),
+            null, seq, 5, null)); // G
+    assertEquals(Color.orange,
+            rcf.getResidueColour(true, av.getResidueShading(),
+            null, seq, 12, null)); // F
+
+    // gap colour not specified so gaps are lightGray
+    assertEquals(Color.lightGray, rcf
+            .getResidueColour(true, av.getResidueShading(), null, seq, 3,
+                    null));
+
+    // unaffected by showBoxes setting
+    assertEquals(Color.pink, rcf.getResidueColour(false,
+            av.getResidueShading(), null, seq, 0, null)); // M
+    assertEquals(Color.green, rcf.getResidueColour(false,
+            av.getResidueShading(), null, seq, 2, null)); // T
+    assertEquals(Color.magenta, rcf.getResidueColour(false,
+            av.getResidueShading(), null, seq, 5, null)); // G
+    assertEquals(Color.orange, rcf.getResidueColour(false,
+            av.getResidueShading(), null, seq, 12, null)); // F
+
+    // gap colour not specified so gaps are lightGray
+    assertEquals(Color.lightGray, rcf
+            .getResidueColour(false, av.getResidueShading(), null, seq, 3,
+                    null));
+
+  }
+
+  @Test(groups = { "Functional" })
+  public void testGetResidueBoxColour_userdef()
+  {
+    SequenceI seq = new Sequence("name", "MAT--GSPRAPAFF"); // FER1_MAIZE... + a
+                                                            // gap
+    AlignmentI al = new Alignment(new SequenceI[] { seq });
+    final AlignViewport av = new AlignViewport(al);
+    ResidueColourFinder rcf = new OverviewResColourFinder();
+
+    Color[] newColours = new Color[24];
+    for (int i = 0; i < 24; i++)
+    {
+      newColours[i] = null;
+    }
+
+    av.setGlobalColourScheme(new UserColourScheme(newColours));
+
+    // gap colour not specified so gaps are lightGray
+    assertEquals(Color.lightGray, rcf
+            .getResidueColour(true, av.getResidueShading(), null, seq, 3,
+                    null));
+
+    newColours[23] = Color.pink;
+    av.setGlobalColourScheme(new UserColourScheme(newColours));
+
+    // gap colour specified as pink
+    assertEquals(Color.pink, rcf.getResidueColour(true,
+            av.getResidueShading(),
+            null, seq, 3, null));
+
+    // unaffected by showBoxes setting
+    // gap colour not specified so gaps are lightGray
+    newColours[23] = null;
+    assertEquals(Color.lightGray, rcf.getResidueColour(false,
+            av.getResidueShading(), null, seq, 3, null));
+
+    newColours[23] = Color.pink;
+    av.setGlobalColourScheme(new UserColourScheme(newColours));
+
+    // gap colour specified as pink
+    assertEquals(Color.pink, rcf.getResidueColour(false,
+            av.getResidueShading(), null, seq, 3, null));
+  }
+
+  @Test
+  public void testGetResidueBoxColour_group()
+  {
+    SequenceI seq = new Sequence("name", "MA--TVLGSPRAPAFF");
+    AlignmentI al = new Alignment(new SequenceI[] { seq });
+    
+    ColourSchemeI cs = new ZappoColourScheme();
+    ArrayList<SequenceI> seqlist = new ArrayList<>();
+    seqlist.add(seq);
+    SequenceGroup sg = new SequenceGroup(seqlist, "testgroup", cs, true,
+            true, true, 5, 9);
+    al.addGroup(sg);
+    SequenceGroup[] groups = new SequenceGroup[1];
+    groups[0] = sg;
+    
+    final AlignViewport av = new AlignViewport(al);
+    ResidueColourFinder rcf = new OverviewResColourFinder();
+    
+    // G in group specified as magenta in Zappo
+    assertEquals(Color.magenta, rcf.getResidueColour(false,
+            av.getResidueShading(), groups, seq, 7, null));
+
+    // Residue outside group coloured white
+    assertEquals(Color.white, rcf.getResidueColour(false,
+            av.getResidueShading(), groups, seq, 0, null));
+
+    // Gap outside group coloured lightgray
+    assertEquals(Color.lightGray, rcf.getResidueColour(false,
+            av.getResidueShading(), groups, seq, 2, null));
+
+    // use legacy colouring
+    rcf = new OverviewResColourFinder(true, Color.blue, Color.red);
+  
+    // G in group specified as magenta in Zappo
+    assertEquals(Color.magenta, rcf.getResidueColour(false,
+            av.getResidueShading(), groups, seq, 7, null));
+
+    // Residue outside group coloured lightgray
+    assertEquals(Color.lightGray, rcf.getResidueColour(false,
+            av.getResidueShading(), groups, seq, 0, null));
+
+    // Gap outside group coloured white
+    assertEquals(Color.white, rcf.getResidueColour(false,
+            av.getResidueShading(), groups, seq, 2, null));
+
+    // use new colouring
+    rcf = new OverviewResColourFinder(false, Color.blue, Color.red);
+
+    // G in group specified as magenta in Zappo
+    assertEquals(Color.magenta, rcf.getResidueColour(false,
+            av.getResidueShading(), groups, seq, 7, null));
+
+    // Residue outside group coloured white
+    assertEquals(Color.white, rcf.getResidueColour(false,
+            av.getResidueShading(), groups, seq, 0, null));
+
+    // Gap outside group coloured blue
+    assertEquals(Color.blue, rcf.getResidueColour(false,
+            av.getResidueShading(), groups, seq, 2, null));
+  }
+
+  @Test
+  public void testGetBoxColour()
+  {
+    SequenceI seq = new Sequence("name", "MAT--GSPRAPAFF"); // FER1_MAIZE... + a
+                                                            // gap
+    AlignmentI al = new Alignment(new SequenceI[] { seq });
+    final AlignViewport av = new AlignViewport(al);
+
+    // non-legacy colouring
+    ResidueColourFinder rcf = new OverviewResColourFinder();
+    ResidueShaderI shader = new ResidueShader();
+
+    // residues white
+    Color c = rcf.getBoxColour(shader, seq, 0);
+    assertEquals(Color.white, c);
+
+    // gaps gap colour
+    c = rcf.getBoxColour(shader, seq, 3);
+    assertEquals(
+            jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_GAP,
+            c);
+
+    // legacy colouring set explicitly via constructor
+    rcf = new OverviewResColourFinder(true, Color.blue, Color.red);
+    shader = new ResidueShader();
+
+    // residues light gray
+    c = rcf.getBoxColour(shader, seq, 0);
+    assertEquals(Color.lightGray, c);
+
+    // gaps white
+    c = rcf.getBoxColour(shader, seq, 3);
+    assertEquals(Color.white, c);
+
+    // legacy colouring off
+    rcf = new OverviewResColourFinder();
+    shader = new ResidueShader();
+
+    // residues white
+    c = rcf.getBoxColour(shader, seq, 0);
+    assertEquals(Color.white, c);
+
+    // gaps gap colour
+    c = rcf.getBoxColour(shader, seq, 3);
+    assertEquals(
+            jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_GAP,
+            c);
+
+    // non legacy colouring with colour scheme
+    rcf = new OverviewResColourFinder(false, Color.blue, Color.red);
+    shader = new ResidueShader(new ZappoColourScheme());
+
+    // M residue pink
+    c = rcf.getBoxColour(shader, seq, 0);
+    assertEquals(Color.pink, c);
+
+    // gaps blue
+    c = rcf.getBoxColour(shader, seq, 3);
+    assertEquals(Color.blue, c);
+
+    // legacy colouring with colour scheme
+    rcf = new OverviewResColourFinder(true, Color.blue, Color.red);
+
+    // M residue pink
+    c = rcf.getBoxColour(shader, seq, 0);
+    assertEquals(Color.pink, c);
+
+    // gaps white
+    c = rcf.getBoxColour(shader, seq, 3);
+    assertEquals(Color.white, c);
+  }
+}
diff --git a/test/jalview/renderer/ResidueColourFinderTest.java b/test/jalview/renderer/ResidueColourFinderTest.java
new file mode 100644 (file)
index 0000000..81fb2c0
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.renderer;
+
+import static org.testng.AssertJUnit.assertEquals;
+
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignViewport;
+import jalview.gui.JvOptionPane;
+import jalview.schemes.UserColourScheme;
+import jalview.schemes.ZappoColourScheme;
+
+import java.awt.Color;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class ResidueColourFinderTest
+{
+
+  @BeforeClass(alwaysRun = true)
+  public void setUpJvOptionPane()
+  {
+    JvOptionPane.setInteractiveMode(false);
+    JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
+  }
+
+  @Test(groups = { "Functional" })
+  public void testGetResidueColour_zappo()
+  {
+    SequenceI seq = new Sequence("name", "MATVLGSPRAPAFF"); // FER1_MAIZE...
+    AlignmentI al = new Alignment(new SequenceI[] { seq });
+    final AlignViewport av = new AlignViewport(al);
+    ResidueColourFinder rcf = new ResidueColourFinder();
+    av.setGlobalColourScheme(new ZappoColourScheme());
+
+    // @see ResidueProperties.zappo
+    assertEquals(Color.pink,
+            rcf.getResidueColour(true, av.getResidueShading(), null, seq, 0,
+                    null)); // M
+    assertEquals(Color.green,
+            rcf.getResidueColour(true, av.getResidueShading(), null, seq, 2,
+                    null)); // T
+    assertEquals(Color.magenta,
+            rcf.getResidueColour(true, av.getResidueShading(), null, seq, 5,
+                    null)); // G
+    assertEquals(Color.orange,
+            rcf.getResidueColour(true, av.getResidueShading(), null, seq,
+                    12,
+                    null)); // F
+
+    // everything is white if showBoxes is false
+    assertEquals(Color.white, rcf.getResidueColour(false,
+            av.getResidueShading(), null, seq, 0, null)); // M
+    assertEquals(Color.white, rcf.getResidueColour(false,
+            av.getResidueShading(), null, seq, 2, null)); // T
+    assertEquals(Color.white, rcf.getResidueColour(false,
+            av.getResidueShading(), null, seq, 5, null)); // G
+    assertEquals(Color.white, rcf.getResidueColour(false,
+            av.getResidueShading(), null, seq, 12, null)); // F
+  }
+
+  @Test(groups = { "Functional" })
+  public void testGetResidueColour_none()
+  {
+    SequenceI seq = new Sequence("name", "MA--TVLGSPRAPAFF");
+    AlignmentI al = new Alignment(new SequenceI[] { seq });
+    final AlignViewport av = new AlignViewport(al);
+    ResidueColourFinder rcf = new ResidueColourFinder();
+
+    assertEquals(Color.white,
+            rcf.getResidueColour(true, av.getResidueShading(),
+            null, seq, 0, null));
+    assertEquals(Color.white,
+            rcf.getResidueColour(true, av.getResidueShading(),
+            null, seq, 2, null));
+
+    // no change if showBoxes is false
+    assertEquals(Color.white, rcf.getResidueColour(false,
+            av.getResidueShading(), null, seq, 0, null));
+    assertEquals(Color.white, rcf.getResidueColour(false,
+            av.getResidueShading(), null, seq, 2, null));
+  }
+
+  @Test(groups = { "Functional" })
+  public void testGetResidueColour_userdef()
+  {
+    SequenceI seq = new Sequence("name", "MAT--GSPRAPAFF"); // FER1_MAIZE... + a
+                                                            // gap
+    AlignmentI al = new Alignment(new SequenceI[] { seq });
+    final AlignViewport av = new AlignViewport(al);
+    ResidueColourFinder rcf = new ResidueColourFinder();
+
+    Color[] newColours = new Color[24];
+    for (int i = 0; i < 24; i++)
+    {
+      newColours[i] = null;
+    }
+
+    av.setGlobalColourScheme(new UserColourScheme(newColours));
+
+    // gap colour not specified so gap colour is null
+    // this is consistent with previous behaviour, but may not be correct?
+    assertEquals(null, rcf.getResidueColour(true, av.getResidueShading(),
+            null, seq, 3, null));
+
+    newColours[23] = Color.pink;
+    av.setGlobalColourScheme(new UserColourScheme(newColours));
+
+    // gap colour specified as pink
+    assertEquals(Color.pink, rcf.getResidueColour(true,
+            av.getResidueShading(),
+            null, seq, 3, null));
+
+    // everything is white if showBoxes is false
+    newColours[23] = null;
+    assertEquals(Color.white, rcf.getResidueColour(false,
+            av.getResidueShading(),
+            null, seq, 3, null));
+
+    newColours[23] = Color.pink;
+    av.setGlobalColourScheme(new UserColourScheme(newColours));
+
+    // gap colour specified as pink
+    assertEquals(Color.white, rcf.getResidueColour(false,
+            av.getResidueShading(), null, seq, 3, null));
+  }
+
+  // TODO more tests for getResidueColour covering groups, feature rendering...
+}
index 76fd9b4..eba5f59 100644 (file)
@@ -8,9 +8,15 @@ import jalview.analysis.Conservation;
 import jalview.datamodel.Profile;
 import jalview.datamodel.ProfileI;
 import jalview.datamodel.Profiles;
+import jalview.datamodel.ProfilesI;
+import jalview.datamodel.ResidueCount;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceI;
+import jalview.schemes.ColourSchemeI;
 import jalview.schemes.PIDColourScheme;
+import jalview.schemes.ResidueProperties;
+import jalview.schemes.UserColourScheme;
+import jalview.schemes.ZappoColourScheme;
 
 import java.awt.Color;
 import java.util.Collections;
@@ -163,4 +169,165 @@ public class ResidueShaderTest
     assertEquals(Color.WHITE, ccs.applyConservation(colour, 12));
   }
 
+  @Test(groups = "Functional")
+  public void testFindColour_gapColour()
+  {
+    /*
+     * normally, a gap is coloured white
+     */
+    ResidueShader rs = new ResidueShader(new ZappoColourScheme());
+    assertEquals(Color.white, rs.findColour(' ', 7, null));
+
+    /*
+     * a User Colour Scheme may specify a bespoke gap colour
+     */
+    Color[] colours = new Color[ResidueProperties.maxProteinIndex + 1];
+    colours[5] = Color.blue; // Q colour
+    colours[23] = Color.red; // gap colour
+    ColourSchemeI cs = new UserColourScheme(colours);
+    rs = new ResidueShader(cs);
+  
+    assertEquals(Color.red, rs.findColour(' ', 7, null));
+    assertEquals(Color.blue, rs.findColour('Q', 7, null));
+  
+    /*
+     * stub Conservation to return a given consensus string
+     */
+    final String consSequence = "0123456789+*-";
+    Conservation cons = new Conservation(null,
+            Collections.<SequenceI> emptyList(), 0, 0)
+    {
+      @Override
+      public SequenceI getConsSequence()
+      {
+        return new Sequence("seq", consSequence);
+      }
+    };
+    rs.setConservation(cons);
+  
+    /*
+     * with 0% threshold, there should be no fading
+     */
+    rs.setConservationInc(0);
+    assertEquals(Color.red, rs.findColour(' ', 7, null));
+    assertEquals(Color.blue, rs.findColour('Q', 7, null));
+  
+    /*
+     * with 40% threshold, 'fade factor' is 
+     * (11-score)/10 * 40/20 = (11-score)/5
+     * so position 7, score 7 fades 80% of the way to white (255, 255, 255)
+     */
+    rs.setConservationInc(40);
+
+    /*
+     * gap colour is unchanged for Conservation
+     */
+    assertEquals(Color.red, rs.findColour(' ', 7, null));
+    assertEquals(Color.red, rs.findColour('-', 7, null));
+    assertEquals(Color.red, rs.findColour('.', 7, null));
+
+    /*
+     * residue colour is faded 80% of the way from
+     * blue(0, 0, 255) to white(255, 255, 255)
+     * making (204, 204, 255)
+     */
+    assertEquals(new Color(204, 204, 255), rs.findColour('Q', 7, null));
+
+    /*
+     * turn off By Conservation, apply Above Identity Threshold
+     * providing a stub Consensus that has modal residue "Q" with pid 60%
+     */
+    rs.setConservationApplied(false);
+    ProfilesI consensus = getStubConsensus("Q", 60f);
+    rs.setConsensus(consensus);
+
+    // with consensus pid (60) above threshold (50), colours are unchanged
+    rs.setThreshold(50, false);
+    assertEquals(Color.blue, rs.findColour('Q', 7, null));
+    assertEquals(Color.red, rs.findColour('-', 7, null));
+
+    // with consensus pid (60) below threshold (70),
+    // residue colour becomes white, gap colour is unchanged
+    rs.setThreshold(70, false);
+    assertEquals(Color.white, rs.findColour('Q', 7, null));
+    assertEquals(Color.red, rs.findColour('-', 7, null));
+  }
+
+  /**
+   * @param modalResidue
+   * @param pid
+   * @return
+   */
+  protected ProfilesI getStubConsensus(final String modalResidue,
+          final float pid)
+  {
+    ProfilesI consensus = new ProfilesI() {
+
+      @Override
+      public ProfileI get(int i)
+      {
+        return new ProfileI() {
+          @Override
+          public void setCounts(ResidueCount residueCounts)
+          {
+          }
+
+          @Override
+          public float getPercentageIdentity(boolean ignoreGaps)
+          {
+            return pid;
+          }
+
+          @Override
+          public ResidueCount getCounts()
+          {
+            return null;
+          }
+
+          @Override
+          public int getHeight()
+          {
+            return 0;
+          }
+
+          @Override
+          public int getGapped()
+          {
+            return 0;
+          }
+
+          @Override
+          public int getMaxCount()
+          {
+            return 0;
+          }
+
+          @Override
+          public String getModalResidue()
+          {
+            return modalResidue;
+          }
+
+          @Override
+          public int getNonGapped()
+          {
+            return 0;
+         }};
+      }
+
+      @Override
+      public int getStartColumn()
+      {
+        return 0;
+      }
+
+      @Override
+      public int getEndColumn()
+      {
+        return 0;
+      }
+      
+    };
+    return consensus;
+  }
 }
index cf1039f..0af67cd 100644 (file)
@@ -26,11 +26,11 @@ public class ScaleRendererTest
     AlignViewport av = af.getViewport();
 
     /*
-     * scale has minor ticks at 5 and 15, major at 10 and 20
+     * scale has minor ticks at 5, 15, 25, major at 10 and 20
      * (these are base 1, ScaleMark holds base 0 values)
      */
     List<ScaleMark> marks = new ScaleRenderer().calculateMarks(av, 0, 25);
-    assertEquals(marks.size(), 4);
+    assertEquals(marks.size(), 5);
 
     assertFalse(marks.get(0).major);
     assertEquals(marks.get(0).column, 4);
@@ -48,6 +48,10 @@ public class ScaleRendererTest
     assertEquals(marks.get(3).column, 19);
     assertEquals(marks.get(3).text, "20");
 
+    assertFalse(marks.get(4).major);
+    assertEquals(marks.get(4).column, 24);
+    assertNull(marks.get(4).text);
+
     /*
      * now hide columns 9-11 and 18-20 (base 1)
      * scale marks are now in the same columns as before, but
@@ -56,7 +60,7 @@ public class ScaleRendererTest
     av.hideColumns(8, 10);
     av.hideColumns(17, 19);
     marks = new ScaleRenderer().calculateMarks(av, 0, 25);
-    assertEquals(marks.size(), 4);
+    assertEquals(marks.size(), 5);
     assertFalse(marks.get(0).major);
     assertEquals(marks.get(0).column, 4);
     assertNull(marks.get(0).text);
@@ -69,5 +73,8 @@ public class ScaleRendererTest
     assertTrue(marks.get(3).major);
     assertEquals(marks.get(3).column, 19);
     assertEquals(marks.get(3).text, "26"); // +6 hidden columns
+    assertFalse(marks.get(4).major);
+    assertEquals(marks.get(4).column, 24);
+    assertNull(marks.get(4).text);
   }
 }
index 4fc079e..f6dfed6 100644 (file)
@@ -2,6 +2,7 @@ package jalview.renderer.seqfeatures;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotEquals;
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 
@@ -16,6 +17,7 @@ import jalview.io.FileLoader;
 import jalview.schemes.FeatureColour;
 
 import java.awt.Color;
+import java.util.List;
 
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.BeforeTest;
@@ -70,13 +72,10 @@ public class FeatureColourFinderTest
   @BeforeMethod(alwaysRun = true)
   public void setUpBeforeTest()
   {
-    SequenceFeature[] sfs = seq.getSequenceFeatures();
-    if (sfs != null)
+    List<SequenceFeature> sfs = seq.getSequenceFeatures();
+    for (SequenceFeature sf : sfs)
     {
-      for (SequenceFeature sf : sfs)
-      {
-        seq.deleteFeature(sf);
-      }
+      seq.deleteFeature(sf);
     }
     fr.findAllFeatures(true);
 
@@ -287,6 +286,28 @@ public class FeatureColourFinderTest
   }
 
   @Test(groups = "Functional")
+  public void testFindFeatureAtEnd()
+  {
+    /*
+     * terminal residue feature
+     */
+    seq.addSequenceFeature(new SequenceFeature("PDBRESNUM", "pdb res 1",
+            seq.getEnd(), seq.getEnd(), Float.NaN, "1seq.pdb"));
+    fr.setColour("PDBRESNUM", new FeatureColour(Color.red));
+    fr.featuresAdded();
+    av.setShowSequenceFeatures(true);
+
+    /*
+     * final column should have PDBRESNUM feature, the others not
+     */
+    Color c = finder.findFeatureColour(Color.blue, seq,
+            seq.getLength() - 2);
+    assertNotEquals(c, Color.red);
+    c = finder.findFeatureColour(Color.blue, seq, seq.getLength() - 1);
+    assertEquals(c, Color.red);
+  }
+
+  @Test(groups = "Functional")
   public void testFindFeatureColour_graduatedFeatureColour()
   {
     seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 2,
@@ -454,15 +475,19 @@ public class FeatureColourFinderTest
   @Test(groups = "Functional")
   public void testFindFeatureColour_graduatedWithThreshold()
   {
-    seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 2,
+    String kdFeature = "kd";
+    String metalFeature = "Metal";
+    seq.addSequenceFeature(new SequenceFeature(kdFeature, "hydrophobicity", 2,
             2, 0f, "KdGroup"));
-    seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 4,
+    seq.addSequenceFeature(new SequenceFeature(kdFeature, "hydrophobicity", 4,
             4, 5f, "KdGroup"));
-    seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 7,
+    seq.addSequenceFeature(new SequenceFeature(metalFeature, "Fe", 4, 4,
+            5f, "MetalGroup"));
+    seq.addSequenceFeature(new SequenceFeature(kdFeature, "hydrophobicity", 7,
             7, 10f, "KdGroup"));
   
     /*
-     * graduated colour from 0 to 10
+     * kd feature has graduated colour from 0 to 10
      * above threshold value of 5
      */
     Color min = new Color(100, 50, 150);
@@ -470,8 +495,19 @@ public class FeatureColourFinderTest
     FeatureColourI fc = new FeatureColour(min, max, 0, 10);
     fc.setAboveThreshold(true);
     fc.setThreshold(5f);
-    fr.setColour("kd", fc);
+    fr.setColour(kdFeature, fc);
+    FeatureColour green = new FeatureColour(Color.green);
+    fr.setColour(metalFeature, green);
     fr.featuresAdded();
+
+    /*
+     * render order is kd above Metal
+     */
+    Object[][] data = new Object[2][];
+    data[0] = new Object[] { kdFeature, fc, true };
+    data[1] = new Object[] { metalFeature, green, true };
+    fr.setFeaturePriority(data);
+
     av.setShowSequenceFeatures(true);
   
     /*
@@ -481,10 +517,11 @@ public class FeatureColourFinderTest
     assertEquals(c, Color.blue);
 
     /*
-     * position 4, column 3, score 5 - at threshold - default colour
+     * position 4, column 3, score 5 - at threshold
+     * should return Green (colour of Metal feature)
      */
     c = finder.findFeatureColour(Color.blue, seq, 3);
-    assertEquals(c, Color.blue);
+    assertEquals(c, Color.green);
   
     /*
      * position 7, column 9, score 10 - maximum colour in range
@@ -504,10 +541,11 @@ public class FeatureColourFinderTest
     assertEquals(c, min);
 
     /*
-     * position 4, column 3, score 5 - at threshold - default colour
+     * position 4, column 3, score 5 - at threshold
+     * should return Green (colour of Metal feature)
      */
     c = finder.findFeatureColour(Color.blue, seq, 3);
-    assertEquals(c, Color.blue);
+    assertEquals(c, Color.green);
 
     /*
      * position 7, column 9, score 10 - above threshold - default colour
diff --git a/test/jalview/renderer/seqfeatures/FeatureRendererTest.java b/test/jalview/renderer/seqfeatures/FeatureRendererTest.java
new file mode 100644 (file)
index 0000000..d3cddf9
--- /dev/null
@@ -0,0 +1,363 @@
+package jalview.renderer.seqfeatures;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import jalview.api.AlignViewportI;
+import jalview.api.FeatureColourI;
+import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignFrame;
+import jalview.io.DataSourceType;
+import jalview.io.FileLoader;
+import jalview.schemes.FeatureColour;
+
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.testng.annotations.Test;
+
+public class FeatureRendererTest
+{
+
+  @Test(groups = "Functional")
+  public void testFindAllFeatures()
+  {
+    String seqData = ">s1\nabcdef\n>s2\nabcdef\n>s3\nabcdef\n>s4\nabcdef\n";
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(seqData,
+            DataSourceType.PASTE);
+    AlignViewportI av = af.getViewport();
+    FeatureRenderer fr = new FeatureRenderer(av);
+
+    /*
+     * with no features
+     */
+    fr.findAllFeatures(true);
+    assertTrue(fr.getRenderOrder().isEmpty());
+    assertTrue(fr.getFeatureGroups().isEmpty());
+
+    List<SequenceI> seqs = av.getAlignment().getSequences();
+
+    // add a non-positional feature - should be ignored by FeatureRenderer
+    SequenceFeature sf1 = new SequenceFeature("Type", "Desc", 0, 0, 1f,
+            "Group");
+    seqs.get(0).addSequenceFeature(sf1);
+    fr.findAllFeatures(true);
+    // ? bug - types and groups added for non-positional features
+    List<String> types = fr.getRenderOrder();
+    List<String> groups = fr.getFeatureGroups();
+    assertEquals(types.size(), 0);
+    assertFalse(types.contains("Type"));
+    assertEquals(groups.size(), 0);
+    assertFalse(groups.contains("Group"));
+
+    // add some positional features
+    seqs.get(1).addSequenceFeature(
+            new SequenceFeature("Pfam", "Desc", 5, 9, 1f, "PfamGroup"));
+    seqs.get(2).addSequenceFeature(
+            new SequenceFeature("Pfam", "Desc", 14, 22, 2f, "RfamGroup"));
+    // bug in findAllFeatures - group not checked for a known feature type
+    seqs.get(2).addSequenceFeature(
+            new SequenceFeature("Rfam", "Desc", 5, 9, Float.NaN,
+                    "RfamGroup"));
+    // existing feature type with null group
+    seqs.get(3).addSequenceFeature(
+            new SequenceFeature("Rfam", "Desc", 5, 9, Float.NaN, null));
+    // new feature type with null group
+    seqs.get(3).addSequenceFeature(
+            new SequenceFeature("Scop", "Desc", 5, 9, Float.NaN, null));
+    // null value for type produces NullPointerException
+    fr.findAllFeatures(true);
+    types = fr.getRenderOrder();
+    groups = fr.getFeatureGroups();
+    assertEquals(types.size(), 3);
+    assertFalse(types.contains("Type"));
+    assertTrue(types.contains("Pfam"));
+    assertTrue(types.contains("Rfam"));
+    assertTrue(types.contains("Scop"));
+    assertEquals(groups.size(), 2);
+    assertFalse(groups.contains("Group"));
+    assertTrue(groups.contains("PfamGroup"));
+    assertTrue(groups.contains("RfamGroup"));
+    assertFalse(groups.contains(null)); // null group is ignored
+
+    /*
+     * check min-max values
+     */
+    Map<String, float[][]> minMax = fr.getMinMax();
+    assertEquals(minMax.size(), 1); // non-positional and NaN not stored
+    assertEquals(minMax.get("Pfam")[0][0], 1f); // positional min
+    assertEquals(minMax.get("Pfam")[0][1], 2f); // positional max
+
+    // increase max for Pfam, add scores for Rfam
+    seqs.get(0).addSequenceFeature(
+            new SequenceFeature("Pfam", "Desc", 14, 22, 8f, "RfamGroup"));
+    seqs.get(1).addSequenceFeature(
+            new SequenceFeature("Rfam", "Desc", 5, 9, 6f, "RfamGroup"));
+    fr.findAllFeatures(true);
+    // note minMax is not a defensive copy, shouldn't expose this
+    assertEquals(minMax.size(), 2);
+    assertEquals(minMax.get("Pfam")[0][0], 1f);
+    assertEquals(minMax.get("Pfam")[0][1], 8f);
+    assertEquals(minMax.get("Rfam")[0][0], 6f);
+    assertEquals(minMax.get("Rfam")[0][1], 6f);
+
+    /*
+     * check render order (last is on top)
+     */
+    List<String> renderOrder = fr.getRenderOrder();
+    assertEquals(renderOrder, Arrays.asList("Scop", "Rfam", "Pfam"));
+
+    /*
+     * change render order (todo: an easier way)
+     * nb here last comes first in the data array
+     */
+    Object[][] data = new Object[3][];
+    FeatureColourI colour = new FeatureColour(Color.RED);
+    data[0] = new Object[] { "Rfam", colour, true };
+    data[1] = new Object[] { "Pfam", colour, false };
+    data[2] = new Object[] { "Scop", colour, false };
+    fr.setFeaturePriority(data);
+    assertEquals(fr.getRenderOrder(), Arrays.asList("Scop", "Pfam", "Rfam"));
+    assertEquals(fr.getDisplayedFeatureTypes(), Arrays.asList("Rfam"));
+
+    /*
+     * add a new feature type: should go on top of render order as visible,
+     * other feature ordering and visibility should be unchanged
+     */
+    seqs.get(2).addSequenceFeature(
+            new SequenceFeature("Metal", "Desc", 14, 22, 8f, "MetalGroup"));
+    fr.findAllFeatures(true);
+    assertEquals(fr.getRenderOrder(),
+            Arrays.asList("Scop", "Pfam", "Rfam", "Metal"));
+    assertEquals(fr.getDisplayedFeatureTypes(),
+            Arrays.asList("Rfam", "Metal"));
+  }
+
+  @Test(groups = "Functional")
+  public void testFindFeaturesAtColumn()
+  {
+    String seqData = ">s1/4-29\n-ab--cdefghijklmnopqrstuvwxyz\n";
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(seqData,
+            DataSourceType.PASTE);
+    AlignViewportI av = af.getViewport();
+    FeatureRenderer fr = new FeatureRenderer(av);
+    SequenceI seq = av.getAlignment().getSequenceAt(0);
+
+    /*
+     * with no features
+     */
+    List<SequenceFeature> features = fr.findFeaturesAtColumn(seq, 3);
+    assertTrue(features.isEmpty());
+
+    /*
+     * add features
+     */
+    SequenceFeature sf1 = new SequenceFeature("Type1", "Desc", 0, 0, 1f,
+            "Group"); // non-positional
+    seq.addSequenceFeature(sf1);
+    SequenceFeature sf2 = new SequenceFeature("Type2", "Desc", 8, 18, 1f,
+            "Group1");
+    seq.addSequenceFeature(sf2);
+    SequenceFeature sf3 = new SequenceFeature("Type3", "Desc", 8, 18, 1f,
+            "Group2");
+    seq.addSequenceFeature(sf3);
+    SequenceFeature sf4 = new SequenceFeature("Type3", "Desc", 8, 18, 1f,
+            null); // null group is always treated as visible
+    seq.addSequenceFeature(sf4);
+
+    /*
+     * add contact features
+     */
+    SequenceFeature sf5 = new SequenceFeature("Disulphide Bond", "Desc", 7,
+            15, 1f, "Group1");
+    seq.addSequenceFeature(sf5);
+    SequenceFeature sf6 = new SequenceFeature("Disulphide Bond", "Desc", 7,
+            15, 1f, "Group2");
+    seq.addSequenceFeature(sf6);
+    SequenceFeature sf7 = new SequenceFeature("Disulphide Bond", "Desc", 7,
+            15, 1f, null);
+    seq.addSequenceFeature(sf7);
+
+    // feature spanning B--C
+    SequenceFeature sf8 = new SequenceFeature("Type1", "Desc", 5, 6, 1f,
+            "Group");
+    seq.addSequenceFeature(sf8);
+    // contact feature B/C
+    SequenceFeature sf9 = new SequenceFeature("Disulphide Bond", "Desc", 5,
+            6, 1f, "Group");
+    seq.addSequenceFeature(sf9);
+
+    /*
+     * let feature renderer discover features (and make visible)
+     */
+    fr.findAllFeatures(true);
+    features = fr.findFeaturesAtColumn(seq, 15); // all positional
+    assertEquals(features.size(), 6);
+    assertTrue(features.contains(sf2));
+    assertTrue(features.contains(sf3));
+    assertTrue(features.contains(sf4));
+    assertTrue(features.contains(sf5));
+    assertTrue(features.contains(sf6));
+    assertTrue(features.contains(sf7));
+
+    /*
+     * at a non-contact position
+     */
+    features = fr.findFeaturesAtColumn(seq, 14);
+    assertEquals(features.size(), 3);
+    assertTrue(features.contains(sf2));
+    assertTrue(features.contains(sf3));
+    assertTrue(features.contains(sf4));
+
+    /*
+     * make "Type2" not displayed
+     */
+    Object[][] data = new Object[4][];
+    FeatureColourI colour = new FeatureColour(Color.RED);
+    data[0] = new Object[] { "Type1", colour, true };
+    data[1] = new Object[] { "Type2", colour, false };
+    data[2] = new Object[] { "Type3", colour, true };
+    data[3] = new Object[] { "Disulphide Bond", colour, true };
+    fr.setFeaturePriority(data);
+
+    features = fr.findFeaturesAtColumn(seq, 15);
+    assertEquals(features.size(), 5); // no sf2
+    assertTrue(features.contains(sf3));
+    assertTrue(features.contains(sf4));
+    assertTrue(features.contains(sf5));
+    assertTrue(features.contains(sf6));
+    assertTrue(features.contains(sf7));
+
+    /*
+     * make "Group2" not displayed
+     */
+    fr.setGroupVisibility("Group2", false);
+
+    features = fr.findFeaturesAtColumn(seq, 15);
+    assertEquals(features.size(), 3); // no sf2, sf3, sf6
+    assertTrue(features.contains(sf4));
+    assertTrue(features.contains(sf5));
+    assertTrue(features.contains(sf7));
+
+    // features 'at' a gap between b and c
+    // - returns enclosing feature BC but not contact feature B/C
+    features = fr.findFeaturesAtColumn(seq, 4);
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf8));
+    features = fr.findFeaturesAtColumn(seq, 5);
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf8));
+  }
+
+  @Test(groups = "Functional")
+  public void testFilterFeaturesForDisplay()
+  {
+    String seqData = ">s1\nabcdef\n";
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(seqData,
+            DataSourceType.PASTE);
+    AlignViewportI av = af.getViewport();
+    FeatureRenderer fr = new FeatureRenderer(av);
+
+    List<SequenceFeature> features = new ArrayList<>();
+    fr.filterFeaturesForDisplay(features, null); // empty list, does nothing
+
+    SequenceI seq = av.getAlignment().getSequenceAt(0);
+    SequenceFeature sf1 = new SequenceFeature("Cath", "", 6, 8, Float.NaN,
+            "group1");
+    seq.addSequenceFeature(sf1);
+    SequenceFeature sf2 = new SequenceFeature("Cath", "", 5, 11, 2f,
+            "group2");
+    seq.addSequenceFeature(sf2);
+    SequenceFeature sf3 = new SequenceFeature("Cath", "", 5, 11, 3f,
+            "group3");
+    seq.addSequenceFeature(sf3);
+    SequenceFeature sf4 = new SequenceFeature("Cath", "", 6, 8, 4f,
+            "group4");
+    seq.addSequenceFeature(sf4);
+    SequenceFeature sf5 = new SequenceFeature("Cath", "", 6, 9, 5f,
+            "group4");
+    seq.addSequenceFeature(sf5);
+
+    fr.findAllFeatures(true);
+
+    features = seq.getSequenceFeatures();
+    assertEquals(features.size(), 5);
+    assertTrue(features.contains(sf1));
+    assertTrue(features.contains(sf2));
+    assertTrue(features.contains(sf3));
+    assertTrue(features.contains(sf4));
+    assertTrue(features.contains(sf5));
+
+    /*
+     * filter out duplicate (co-located) features
+     * note: which gets removed is not guaranteed
+     */
+    fr.filterFeaturesForDisplay(features, new FeatureColour(Color.blue));
+    assertEquals(features.size(), 3);
+    assertTrue(features.contains(sf1) || features.contains(sf4));
+    assertFalse(features.contains(sf1) && features.contains(sf4));
+    assertTrue(features.contains(sf2) || features.contains(sf3));
+    assertFalse(features.contains(sf2) && features.contains(sf3));
+    assertTrue(features.contains(sf5));
+
+    /*
+     * hide group 3 - sf3 is removed, sf2 is retained
+     */
+    fr.setGroupVisibility("group3", false);
+    features = seq.getSequenceFeatures();
+    fr.filterFeaturesForDisplay(features, new FeatureColour(Color.blue));
+    assertEquals(features.size(), 3);
+    assertTrue(features.contains(sf1) || features.contains(sf4));
+    assertFalse(features.contains(sf1) && features.contains(sf4));
+    assertTrue(features.contains(sf2));
+    assertFalse(features.contains(sf3));
+    assertTrue(features.contains(sf5));
+
+    /*
+     * hide group 2, show group 3 - sf2 is removed, sf3 is retained
+     */
+    fr.setGroupVisibility("group2", false);
+    fr.setGroupVisibility("group3", true);
+    features = seq.getSequenceFeatures();
+    fr.filterFeaturesForDisplay(features, null);
+    assertEquals(features.size(), 3);
+    assertTrue(features.contains(sf1) || features.contains(sf4));
+    assertFalse(features.contains(sf1) && features.contains(sf4));
+    assertFalse(features.contains(sf2));
+    assertTrue(features.contains(sf3));
+    assertTrue(features.contains(sf5));
+
+    /*
+     * no filtering of co-located features with graduated colour scheme
+     * filterFeaturesForDisplay does _not_ check colour threshold
+     * sf2 is removed as its group is hidden
+     */
+    features = seq.getSequenceFeatures();
+    fr.filterFeaturesForDisplay(features, new FeatureColour(Color.black,
+            Color.white, 0f, 1f));
+    assertEquals(features.size(), 4);
+    assertTrue(features.contains(sf1));
+    assertTrue(features.contains(sf3));
+    assertTrue(features.contains(sf4));
+    assertTrue(features.contains(sf5));
+
+    /*
+     * co-located features with colour by label
+     * should not get filtered
+     */
+    features = seq.getSequenceFeatures();
+    FeatureColour fc = new FeatureColour(Color.black);
+    fc.setColourByLabel(true);
+    fr.filterFeaturesForDisplay(features, fc);
+    assertEquals(features.size(), 4);
+    assertTrue(features.contains(sf1));
+    assertTrue(features.contains(sf3));
+    assertTrue(features.contains(sf4));
+    assertTrue(features.contains(sf5));
+  }
+}
index 1c93856..b7a5164 100644 (file)
@@ -49,7 +49,7 @@ public class AnnotationColourGradientTest
       anns[col] = new Annotation("a", "a", 'a', col, colour);
     }
 
-    seq = new Sequence("", "");
+    seq = new Sequence("Seq", "");
     al = new Alignment(new SequenceI[]{ seq});
     
     /*
index c16d541..7a72c15 100644 (file)
@@ -22,6 +22,7 @@ package jalview.schemes;
 
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertNull;
 import static org.testng.AssertJUnit.assertTrue;
 import static org.testng.AssertJUnit.fail;
 
@@ -84,60 +85,11 @@ public class FeatureColourTest
   }
 
   @Test(groups = { "Functional" })
-  public void testIsColored_simpleColour()
-  {
-    FeatureColour fc = new FeatureColour(Color.RED);
-    assertTrue(fc.isColored(new SequenceFeature()));
-  }
-
-  @Test(groups = { "Functional" })
-  public void testIsColored_colourByLabel()
-  {
-    FeatureColour fc = new FeatureColour();
-    fc.setColourByLabel(true);
-    assertTrue(fc.isColored(new SequenceFeature()));
-  }
-
-  @Test(groups = { "Functional" })
-  public void testIsColored_aboveThreshold()
-  {
-    // graduated colour range from score 20 to 100
-    FeatureColour fc = new FeatureColour(Color.WHITE, Color.BLACK, 20f,
-            100f);
-
-    // score 0 is adjusted to bottom of range
-    SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 0f,
-            null);
-    assertTrue(fc.isColored(sf));
-    assertEquals(Color.WHITE, fc.getColor(sf));
-
-    // score 120 is adjusted to top of range
-    sf.setScore(120f);
-    assertEquals(Color.BLACK, fc.getColor(sf));
-
-    // value below threshold is still rendered
-    // setting threshold has no effect yet...
-    fc.setThreshold(60f);
-    sf.setScore(36f);
-    assertTrue(fc.isColored(sf));
-    assertEquals(new Color(204, 204, 204), fc.getColor(sf));
-
-    // now apply threshold:
-    fc.setAboveThreshold(true);
-    assertFalse(fc.isColored(sf));
-    // colour is still returned though ?!?
-    assertEquals(new Color(204, 204, 204), fc.getColor(sf));
-
-    sf.setScore(84); // above threshold now
-    assertTrue(fc.isColored(sf));
-    assertEquals(new Color(51, 51, 51), fc.getColor(sf));
-  }
-
-  @Test(groups = { "Functional" })
   public void testGetColor_simpleColour()
   {
     FeatureColour fc = new FeatureColour(Color.RED);
-    assertEquals(Color.RED, fc.getColor(new SequenceFeature()));
+    assertEquals(Color.RED,
+            fc.getColor(new SequenceFeature("Cath", "", 1, 2, 0f, null)));
   }
 
   @Test(groups = { "Functional" })
@@ -169,20 +121,35 @@ public class FeatureColourTest
   }
 
   @Test(groups = { "Functional" })
-  public void testGetColor_belowThreshold()
+  public void testGetColor_aboveBelowThreshold()
   {
     // gradient from [50, 150] from WHITE(255, 255, 255) to BLACK(0, 0, 0)
     FeatureColour fc = new FeatureColour(Color.WHITE, Color.BLACK, 50f,
             150f);
     SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 70f,
             null);
+
+    /*
+     * feature with score of Float.NaN is always assigned minimum colour
+     */
+    SequenceFeature sf2 = new SequenceFeature("type", "desc", 0, 20,
+            Float.NaN, null);
+
     fc.setThreshold(100f); // ignore for now
-    assertTrue(fc.isColored(sf));
     assertEquals(new Color(204, 204, 204), fc.getColor(sf));
+    assertEquals(Color.white, fc.getColor(sf2));
 
     fc.setAboveThreshold(true); // feature lies below threshold
-    assertFalse(fc.isColored(sf));
-    assertEquals(new Color(204, 204, 204), fc.getColor(sf));
+    assertNull(fc.getColor(sf));
+    assertEquals(Color.white, fc.getColor(sf2));
+
+    fc.setBelowThreshold(true);
+    fc.setThreshold(70f);
+    assertNull(fc.getColor(sf)); // feature score == threshold - hidden
+    assertEquals(Color.white, fc.getColor(sf2));
+    fc.setThreshold(69f);
+    assertNull(fc.getColor(sf)); // feature score > threshold - hidden
+    assertEquals(Color.white, fc.getColor(sf2));
   }
 
   /**
index a7e52ff..a59fbde 100644 (file)
@@ -145,7 +145,7 @@ public class StructureSelectionManagerTest
     /*
      * Verify a RESNUM sequence feature in the PDBfile sequence
      */
-    SequenceFeature sf = pmap.getSeqs().get(0).getSequenceFeatures()[0];
+    SequenceFeature sf = pmap.getSeqs().get(0).getSequenceFeatures().get(0);
     assertEquals("RESNUM", sf.getType());
     assertEquals("1gaq", sf.getFeatureGroup());
     assertEquals("GLU:  19  1gaqA", sf.getDescription());
@@ -155,7 +155,7 @@ public class StructureSelectionManagerTest
      * sequence
      */
     StructureMapping map = sm.getMapping("examples/1gaq.txt")[0];
-    sf = map.sequence.getSequenceFeatures()[0];
+    sf = map.sequence.getSequenceFeatures().get(0);
     assertEquals("RESNUM", sf.getType());
     assertEquals("1gaq", sf.getFeatureGroup());
     assertEquals("ALA:   1  1gaqB", sf.getDescription());
index c125ef6..af02d5e 100644 (file)
@@ -20,8 +20,8 @@
  */
 package jalview.structures.models;
 
+import static org.testng.Assert.assertFalse;
 import static org.testng.AssertJUnit.assertEquals;
-import static org.testng.AssertJUnit.assertFalse;
 import static org.testng.AssertJUnit.assertTrue;
 
 import jalview.api.AlignmentViewPanel;
@@ -36,6 +36,7 @@ import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceI;
 import jalview.gui.JvOptionPane;
 import jalview.io.DataSourceType;
+import jalview.io.FileFormats;
 import jalview.schemes.ColourSchemeI;
 import jalview.structure.AtomSpec;
 import jalview.structure.StructureMappingcommandSet;
@@ -43,6 +44,7 @@ import jalview.structure.StructureSelectionManager;
 import jalview.structures.models.AAStructureBindingModel.SuperposeData;
 
 import java.awt.Color;
+import java.io.IOException;
 import java.util.Arrays;
 import java.util.BitSet;
 import java.util.List;
@@ -98,6 +100,150 @@ public class AAStructureBindingModelTest
           + "ATOM     33  CA  ALA A  10      26.790   4.320   3.172  1.00 11.98           C  \n"
           + "ATOM     39  CA AVAL A  12      24.424   3.853   6.106  0.50 13.83           C  \n";
 
+  /**
+   * Multichain PDB with identical sequences imported - Binding should correctly
+   * recover chain mappings for each derived sequence
+   */
+  private static final String PDB_4_MC = "HEADER    HYDROLASE                               09-SEP-09   3A6S              \n"
+          + "ATOM      2  CA  MET A   1      15.366 -11.648  24.854  1.00 32.05           C  \n"
+          + "ATOM     10  CA  LYS A   2      16.846  -9.215  22.340  1.00 25.68           C  \n"
+          + "ATOM     19  CA  LYS A   3      15.412  -6.335  20.343  1.00 19.42           C  \n"
+          + "ATOM     28  CA  LEU A   4      15.629  -5.719  16.616  1.00 15.49           C  \n"
+          + "ATOM     36  CA  GLN A   5      14.412  -2.295  15.567  1.00 12.19           C  \n"
+          + "ATOM   1030  CA  MET B   1      18.869  -7.572   3.432  1.00 31.52           C  \n"
+          + "ATOM   1038  CA  LYS B   2      19.182 -10.025   6.313  1.00 26.41           C  \n"
+          + "ATOM   1047  CA  LYS B   3      17.107 -12.963   7.534  1.00 19.71           C  \n"
+          + "ATOM   1056  CA  LEU B   4      16.142 -13.579  11.164  1.00 14.81           C  \n"
+          + "ATOM   1064  CA  GLN B   5      14.648 -17.005  11.785  1.00 13.38           C  \n";
+
+  // TODO: JAL-2227 - import mmCIF PISA assembly & identify master/copy chains
+
+  @Test(groups= {"Functional"})
+  public void testImportPDBPreservesChainMappings() throws IOException
+  {
+    AlignmentI importedAl = new jalview.io.FormatAdapter().readFile(
+            PDB_4_MC, DataSourceType.PASTE, FileFormats.getInstance()
+                    .forName(jalview.io.FileFormat.PDB.toString()));
+    // ideally, we would match on the actual data for the 'File' handle for
+    // pasted files,
+    // see JAL-623 - pasting is still not correctly handled...
+    PDBEntry importedPDB = new PDBEntry("3A6S", "", Type.PDB,
+            "Paste");
+    AAStructureBindingModel binder = new AAStructureBindingModel(
+            new StructureSelectionManager(), new PDBEntry[]
+            { importedPDB },
+            new SequenceI[][]
+            { importedAl.getSequencesArray() }, null)
+    {
+      
+      @Override
+      public void updateColours(Object source)
+      {
+        // TODO Auto-generated method stub
+        
+      }
+      
+      @Override
+      public void releaseReferences(Object svl)
+      {
+        // TODO Auto-generated method stub
+        
+      }
+      
+      @Override
+      public String[] getStructureFiles()
+      {
+        // TODO Auto-generated method stub
+        return null;
+      }
+      
+      @Override
+      public String superposeStructures(AlignmentI[] alignments,
+              int[] structureIndices, HiddenColumns[] hiddenCols)
+      {
+        // TODO Auto-generated method stub
+        return null;
+      }
+      
+      @Override
+      public void setJalviewColourScheme(ColourSchemeI cs)
+      {
+        // TODO Auto-generated method stub
+        
+      }
+      
+      @Override
+      public void setBackgroundColour(Color col)
+      {
+        // TODO Auto-generated method stub
+        
+      }
+      
+      @Override
+      public void highlightAtoms(List<AtomSpec> atoms)
+      {
+        // TODO Auto-generated method stub
+        
+      }
+      
+      @Override
+      public SequenceRenderer getSequenceRenderer(AlignmentViewPanel alignment)
+      {
+        // TODO Auto-generated method stub
+        return null;
+      }
+      
+      @Override
+      public FeatureRenderer getFeatureRenderer(AlignmentViewPanel alignment)
+      {
+        // TODO Auto-generated method stub
+        return null;
+      }
+      
+      @Override
+      protected StructureMappingcommandSet[] getColourBySequenceCommands(
+              String[] files, SequenceRenderer sr, AlignmentViewPanel avp)
+      {
+        // TODO Auto-generated method stub
+        return null;
+      }
+      
+      @Override
+      public List<String> getChainNames()
+      {
+        // TODO Auto-generated method stub
+        return null;
+      }
+      
+      @Override
+      protected void colourBySequence(
+              StructureMappingcommandSet[] colourBySequenceCommands)
+      {
+        // TODO Auto-generated method stub
+        
+      }
+      
+      @Override
+      public void colourByCharge()
+      {
+        // TODO Auto-generated method stub
+        
+      }
+      
+      @Override
+      public void colourByChain()
+      {
+        // TODO Auto-generated method stub
+        
+      }
+    };
+    String[][] chains = binder.getChains();
+    assertFalse(chains == null || chains[0] == null,
+            "No chains discovered by binding");
+    assertEquals(2, chains[0].length);
+    assertEquals("A", chains[0][0]);
+    assertEquals("B", chains[0][1]);
+  }
   AAStructureBindingModel testee;
 
   AlignmentI al = null;
@@ -129,11 +275,11 @@ public class AAStructureBindingModelTest
     StructureSelectionManager ssm = new StructureSelectionManager();
 
     ssm.setMapping(new SequenceI[] { seq1a, seq1b }, null, PDB_1,
-            DataSourceType.PASTE);
+            DataSourceType.PASTE, null);
     ssm.setMapping(new SequenceI[] { seq2 }, null, PDB_2,
-            DataSourceType.PASTE);
+            DataSourceType.PASTE, null);
     ssm.setMapping(new SequenceI[] { seq3 }, null, PDB_3,
-            DataSourceType.PASTE);
+            DataSourceType.PASTE, null);
 
     testee = new AAStructureBindingModel(ssm, pdbFiles, seqs, null)
     {
index d0ec3e8..5226819 100644 (file)
@@ -1149,4 +1149,49 @@ public class MappingUtilsTest
     assertEquals("[12, 11, 8, 4]", Arrays.toString(ranges));
   }
 
+  @Test(groups = "Functional")
+  public void testRemoveEndPositions()
+  {
+    List<int[]> ranges = new ArrayList<>();
+
+    /*
+     * case 1: truncate last range
+     */
+    ranges.add(new int[] { 1, 10 });
+    ranges.add(new int[] { 20, 30 });
+    MappingUtils.removeEndPositions(5, ranges);
+    assertEquals(2, ranges.size());
+    assertEquals(25, ranges.get(1)[1]);
+
+    /*
+     * case 2: remove last range
+     */
+    ranges.clear();
+    ranges.add(new int[] { 1, 10 });
+    ranges.add(new int[] { 20, 22 });
+    MappingUtils.removeEndPositions(3, ranges);
+    assertEquals(1, ranges.size());
+    assertEquals(10, ranges.get(0)[1]);
+
+    /*
+     * case 3: truncate penultimate range
+     */
+    ranges.clear();
+    ranges.add(new int[] { 1, 10 });
+    ranges.add(new int[] { 20, 21 });
+    MappingUtils.removeEndPositions(3, ranges);
+    assertEquals(1, ranges.size());
+    assertEquals(9, ranges.get(0)[1]);
+
+    /*
+     * case 4: remove last two ranges
+     */
+    ranges.clear();
+    ranges.add(new int[] { 1, 10 });
+    ranges.add(new int[] { 20, 20 });
+    ranges.add(new int[] { 30, 30 });
+    MappingUtils.removeEndPositions(3, ranges);
+    assertEquals(1, ranges.size());
+    assertEquals(9, ranges.get(0)[1]);
+  }
 }
index 70a3687..41a313f 100644 (file)
@@ -1,6 +1,7 @@
 package jalview.viewmodel;
 
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertTrue;
 
 import jalview.analysis.AlignmentGenerator;
@@ -12,6 +13,7 @@ import jalview.datamodel.HiddenSequences;
 import java.beans.PropertyChangeEvent;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 
 import org.testng.annotations.BeforeClass;
@@ -83,7 +85,6 @@ public class ViewportRangesTest {
     vr.setEndSeq(al.getHeight());
     assertEquals(vr.getEndSeq(), al.getHeight() - 1);
 
-    // vr.setEndRes(al.getHeight() - 1);
     vr.setEndSeq(al.getHeight() - 1);
     assertEquals(vr.getEndSeq(), al.getHeight() - 1);
   }
@@ -167,6 +168,24 @@ public class ViewportRangesTest {
   }
 
   @Test(groups = { "Functional" })
+  public void testSetStartResAndSeq()
+  {
+    ViewportRanges vr = new ViewportRanges(al);
+    vr.setViewportHeight(10);
+    vr.setStartResAndSeq(3, 6);
+    assertEquals(vr.getStartRes(), 3);
+    assertEquals(vr.getStartSeq(), 6);
+    assertEquals(vr.getEndRes(), 3 + vr.getViewportWidth() - 1);
+    assertEquals(vr.getEndSeq(), 6 + vr.getViewportHeight() - 1);
+
+    vr.setStartResAndSeq(10, 25);
+    assertEquals(vr.getStartRes(), 10);
+    assertEquals(vr.getStartSeq(), 19);
+    assertEquals(vr.getEndRes(), 10 + vr.getViewportWidth() - 1);
+    assertEquals(vr.getEndSeq(), 19 + vr.getViewportHeight() - 1);
+  }
+
+  @Test(groups = { "Functional" })
   public void testSetViewportHeight()
   {
     ViewportRanges vr = new ViewportRanges(al);
@@ -346,27 +365,50 @@ public class ViewportRangesTest {
   @Test(groups = { "Functional" })
   public void testScrollToWrappedVisible()
   {
-    ViewportRanges vr = new ViewportRanges(al);
+    AlignmentI al2 = gen.generate(60, 30, 1, 5, 5);
+
+    ViewportRanges vr = new ViewportRanges(al2);
+
+    // start with viewport on 5-14
     vr.setViewportStartAndWidth(5, 10);
+    assertEquals(vr.getStartRes(), 5);
+    assertEquals(vr.getEndRes(), 14);
+
+    // scroll to 12 - no change
+    assertFalse(vr.scrollToWrappedVisible(12));
+    assertEquals(vr.getStartRes(), 5);
 
-    vr.scrollToWrappedVisible(0);
+    // scroll to 2 - back to 0-9
+    assertTrue(vr.scrollToWrappedVisible(2));
     assertEquals(vr.getStartRes(), 0);
+    assertEquals(vr.getEndRes(), 9);
 
-    vr.scrollToWrappedVisible(10);
-    assertEquals(vr.getStartRes(), 10);
+    // scroll to 9 - no change
+    assertFalse(vr.scrollToWrappedVisible(9));
+    assertEquals(vr.getStartRes(), 0);
 
-    vr.scrollToWrappedVisible(15);
+    // scroll to 12 - moves to 10-19
+    assertTrue(vr.scrollToWrappedVisible(12));
     assertEquals(vr.getStartRes(), 10);
+    assertEquals(vr.getEndRes(), 19);
+
+    vr.setStartRes(13);
+    assertEquals(vr.getStartRes(), 13);
+    assertEquals(vr.getEndRes(), 22);
+
+    // scroll to 45 - jumps to 43-52
+    assertTrue(vr.scrollToWrappedVisible(45));
+    assertEquals(vr.getStartRes(), 43);
+    assertEquals(vr.getEndRes(), 52);
   }
 
-  // leave until JAL-2388 is merged and we can do without viewport
-  /*@Test(groups = { "Functional" })
+  @Test(groups = { "Functional" })
   public void testScrollToVisible()
   {
     ViewportRanges vr = new ViewportRanges(al);
     vr.setViewportStartAndWidth(12,5);
     vr.setViewportStartAndHeight(10,6);
-    vr.scrollToVisible(13,14)
+    vr.scrollToVisible(13, 14);
     
     // no change
     assertEquals(vr.getStartRes(), 12);
@@ -377,7 +419,15 @@ public class ViewportRangesTest {
     assertEquals(vr.getStartSeq(), 6);
     
     // test for hidden columns too
-  }*/
+    al.getHiddenColumns().hideColumns(1, 3);
+    vr.scrollToVisible(13, 3);
+    assertEquals(vr.getStartRes(), 6);
+    assertEquals(vr.getStartSeq(), 3);
+
+    vr.scrollToVisible(2, 9);
+    assertEquals(vr.getStartRes(), 0);
+    assertEquals(vr.getStartSeq(), 4);
+  }
 
   @Test(groups = { "Functional" })
   public void testEventFiring()
@@ -392,7 +442,7 @@ public class ViewportRangesTest {
 
     // one event fired when startRes is called with new value
     vr.setStartRes(4);
-    assertTrue(l.verify(1, Arrays.asList("startres")));
+    assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
     l.reset();
 
     // no event fired for same value
@@ -401,7 +451,7 @@ public class ViewportRangesTest {
     l.reset();
 
     vr.setStartSeq(4);
-    assertTrue(l.verify(1, Arrays.asList("startseq")));
+    assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
     l.reset();
 
     vr.setStartSeq(4);
@@ -409,7 +459,7 @@ public class ViewportRangesTest {
     l.reset();
 
     vr.setEndSeq(10);
-    assertTrue(l.verify(1, Arrays.asList("startseq")));
+    assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
     l.reset();
 
     vr.setEndSeq(10);
@@ -417,7 +467,7 @@ public class ViewportRangesTest {
     l.reset();
 
     vr.setStartEndRes(2, 15);
-    assertTrue(l.verify(1, Arrays.asList("startres")));
+    assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
     l.reset();
 
     vr.setStartEndRes(2, 15);
@@ -426,16 +476,18 @@ public class ViewportRangesTest {
 
     // check new value fired by event is corrected startres
     vr.setStartEndRes(-1, 5);
-    assertTrue(l.verify(1, Arrays.asList("startres"), Arrays.asList(0)));
+    assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES),
+            Arrays.asList(0)));
     l.reset();
 
     // check new value fired by event is corrected endres
     vr.setStartEndRes(0, -1);
-    assertTrue(l.verify(1, Arrays.asList("endres"), Arrays.asList(0)));
+    assertTrue(l.verify(1, Arrays.asList(ViewportRanges.ENDRES),
+            Arrays.asList(0)));
     l.reset();
 
     vr.setStartEndSeq(2, 15);
-    assertTrue(l.verify(1, Arrays.asList("startseq")));
+    assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
     l.reset();
 
     vr.setStartEndSeq(2, 15);
@@ -448,12 +500,14 @@ public class ViewportRangesTest {
 
     // check new value fired by event is corrected startseq
     vr.setStartEndSeq(-1, 5);
-    assertTrue(l.verify(1, Arrays.asList("startseq"), Arrays.asList(0)));
+    assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ),
+            Arrays.asList(0)));
     l.reset();
 
     // check new value fired by event is corrected endseq
     vr.setStartEndSeq(0, -1);
-    assertTrue(l.verify(1, Arrays.asList("endseq"), Arrays.asList(0)));
+    assertTrue(l.verify(1, Arrays.asList(ViewportRanges.ENDSEQ),
+            Arrays.asList(0)));
     l.reset();
 
     // reset for later tests
@@ -462,55 +516,71 @@ public class ViewportRangesTest {
 
     // test viewport height and width setting triggers event
     vr.setViewportHeight(10);
-    assertTrue(l.verify(1, Arrays.asList("endseq")));
+    assertTrue(l.verify(1, Arrays.asList(ViewportRanges.ENDSEQ)));
     l.reset();
 
     vr.setViewportWidth(18);
-    assertTrue(l.verify(1, Arrays.asList("endres")));
+    assertTrue(l.verify(1, Arrays.asList(ViewportRanges.ENDRES)));
     l.reset();
 
     // already has seq start set to 2, so triggers endseq
     vr.setViewportStartAndHeight(2, 16);
-    assertTrue(l.verify(1, Arrays.asList("endseq")));
+    assertTrue(l.verify(1, Arrays.asList(ViewportRanges.ENDSEQ)));
     l.reset();
 
     vr.setViewportStartAndWidth(1, 14);
-    assertTrue(l.verify(1, Arrays.asList("startres")));
+    assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
     l.reset();
 
     // test page up/down triggers event
     vr.pageUp();
-    assertTrue(l.verify(1, Arrays.asList("startseq")));
+    assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
     l.reset();
 
     vr.pageDown();
-    assertTrue(l.verify(1, Arrays.asList("startseq")));
+    assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
     l.reset();
 
     // test scrolling triggers event
     vr.scrollUp(true);
-    assertTrue(l.verify(1, Arrays.asList("startseq")));
+    assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
     l.reset();
 
     vr.scrollUp(false);
-    assertTrue(l.verify(1, Arrays.asList("startseq")));
+    assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
     l.reset();
 
     vr.scrollRight(true);
-    assertTrue(l.verify(1, Arrays.asList("startres")));
+    assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
     l.reset();
 
     vr.scrollRight(false);
-    assertTrue(l.verify(1, Arrays.asList("startres")));
+    assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
     l.reset();
 
     vr.scrollToVisible(10, 10);
     assertTrue(l.verify(4,
-            Arrays.asList("startseq", "startseq", "startseq", "startseq")));
+            Arrays.asList(ViewportRanges.STARTSEQ, ViewportRanges.STARTSEQ,
+                    ViewportRanges.STARTSEQ, ViewportRanges.STARTSEQ)));
+    l.reset();
+
+    /*
+     * scrollToWrappedVisible does nothing if the target position is
+     * within the current startRes-endRes range
+     */
+    assertFalse(vr.scrollToWrappedVisible(5));
+    assertTrue(l.verify(0, Collections.<String> emptyList()));
     l.reset();
 
-    vr.scrollToWrappedVisible(5);
-    assertTrue(l.verify(1, Arrays.asList("startres")));
+    vr.scrollToWrappedVisible(25);
+    assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
+    l.reset();
+
+    // test setStartResAndSeq triggers one event
+    vr.setStartResAndSeq(5, 7);
+    assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRESANDSEQ),
+            Arrays.asList(5, 7)));
+
     l.reset();
   }
 
@@ -730,6 +800,136 @@ public class ViewportRangesTest {
       }
     }
   }
+
+  @Test(groups = { "Functional" })
+  public void testScrollUp_wrapped()
+  {
+    /*
+     * alignment 30 tall and 45 wide
+     */
+    AlignmentI al2 = gen.generate(45, 30, 1, 0, 5);
+
+    /*
+     * wrapped view, 5 sequences high, start at sequence offset 1
+     */
+    ViewportRanges vr = new ViewportRanges(al2);
+    vr.setWrappedMode(true);
+    vr.setViewportStartAndHeight(1, 5);
+
+    /*
+     * offset wrapped view to column 3
+     */
+    vr.setStartEndRes(3, 22);
+
+    int startRes = vr.getStartRes();
+    int width = vr.getViewportWidth();
+    assertEquals(startRes, 3);
+    assertEquals(width, 20);
+
+    // in wrapped mode, we change startRes but not startSeq
+    // scroll down:
+    vr.scrollUp(false);
+    assertEquals(vr.getStartSeq(), 1);
+    assertEquals(vr.getStartRes(), 23);
+
+    // scroll up returns to original position
+    vr.scrollUp(true);
+    assertEquals(vr.getStartSeq(), 1);
+    assertEquals(vr.getStartRes(), 3);
+
+    // scroll up again returns to 'origin'
+    vr.scrollUp(true);
+    assertEquals(vr.getStartSeq(), 1);
+    assertEquals(vr.getStartRes(), 0);
+
+    /*
+     * offset 3 columns once more and do some scroll downs
+     */
+    vr.setStartEndRes(3, 22);
+    vr.scrollUp(false);
+    assertEquals(vr.getStartSeq(), 1);
+    assertEquals(vr.getStartRes(), 23);
+    vr.scrollUp(false);
+    assertEquals(vr.getStartSeq(), 1);
+    assertEquals(vr.getStartRes(), 43);
+
+    /*
+     * scroll down beyond end of alignment does nothing
+     */
+    vr.scrollUp(false);
+    assertEquals(vr.getStartSeq(), 1);
+    assertEquals(vr.getStartRes(), 43);
+  }
+
+  @Test(groups = { "Functional" })
+  public void testSetViewportLocation()
+  {
+    AlignmentI al2 = gen.generate(60, 80, 1, 0, 0);
+
+    ViewportRanges vr = new ViewportRanges(al2);
+
+    // start with viewport on 5-14
+    vr.setViewportStartAndWidth(5, 10);
+    assertEquals(vr.getStartRes(), 5);
+    assertEquals(vr.getEndRes(), 14);
+
+    vr.setViewportStartAndHeight(3, 13);
+    assertEquals(vr.getStartSeq(), 3);
+    assertEquals(vr.getEndSeq(), 15);
+
+    // set location to (8,5) - no change
+    vr.setViewportLocation(8, 5);
+    assertEquals(vr.getStartRes(), 5);
+    assertEquals(vr.getEndRes(), 14);
+    assertEquals(vr.getStartSeq(), 3);
+    assertEquals(vr.getEndSeq(), 15);
+
+    // set location to (40,50) - change to top left (40,50)
+    vr.setViewportLocation(40, 50);
+    assertEquals(vr.getStartRes(), 40);
+    assertEquals(vr.getEndRes(), 49);
+    assertEquals(vr.getStartSeq(), 50);
+    assertEquals(vr.getEndSeq(), 62);
+
+    // set location past end of alignment - resets to leftmost pos
+    vr.setViewportLocation(63, 85);
+    assertEquals(vr.getStartRes(), 50);
+    assertEquals(vr.getEndRes(), 59);
+    assertEquals(vr.getStartSeq(), 67);
+    assertEquals(vr.getEndSeq(), 79);
+
+    // hide some columns
+    al2.getHiddenColumns().hideColumns(20, 50);
+    vr.setViewportLocation(55, 4);
+    assertEquals(vr.getStartRes(), 19);
+    assertEquals(vr.getEndRes(), 28);
+    assertEquals(vr.getStartSeq(), 4);
+    assertEquals(vr.getEndSeq(), 16);
+
+    // hide some sequences
+    al2.getHiddenSequences().hideSequence(al2.getSequenceAt(3));
+    al2.getHiddenSequences().hideSequence(al2.getSequenceAt(4));
+    vr.setViewportLocation(17, 5);
+    assertEquals(vr.getStartRes(), 17);
+    assertEquals(vr.getEndRes(), 26);
+    assertEquals(vr.getStartSeq(), 3);
+    assertEquals(vr.getEndSeq(), 15);
+
+    // set wrapped mode
+    vr.setWrappedMode(true);
+    vr.setViewportLocation(1, 8);
+    assertEquals(vr.getStartRes(), 0);
+    assertEquals(vr.getEndRes(), 9);
+    assertEquals(vr.getStartSeq(), 3);
+    assertEquals(vr.getEndSeq(), 15);
+
+    // try further down the alignment
+    vr.setViewportLocation(57, 5);
+    assertEquals(vr.getStartRes(), 20);
+    assertEquals(vr.getEndRes(), 29);
+    assertEquals(vr.getStartSeq(), 3);
+    assertEquals(vr.getEndSeq(), 15);
+  }
 }
 
 // mock listener for property change events
@@ -751,7 +951,15 @@ class MockPropChangeListener implements ViewportListenerI
   {
     firecount++;
     events.add(evt.getPropertyName());
-    newvalues.add((Integer) evt.getNewValue());
+    if (evt.getPropertyName().equals(ViewportRanges.STARTRESANDSEQ))
+    {
+      newvalues.add(((int[]) evt.getNewValue())[0]);
+      newvalues.add(((int[]) evt.getNewValue())[1]);
+    }
+    else
+    {
+      newvalues.add((Integer) evt.getNewValue());
+    }
   }
 
   public boolean verify(int count, List<String> eventslist,
index 2f548d0..f98ef85 100644 (file)
@@ -26,9 +26,9 @@ import static org.testng.AssertJUnit.assertNotNull;
 import static org.testng.AssertJUnit.assertNull;
 
 import jalview.datamodel.PDBEntry;
-import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
-import jalview.datamodel.UniprotEntry;
+import jalview.datamodel.xdb.uniprot.UniprotEntry;
+import jalview.datamodel.xdb.uniprot.UniprotFeature;
 import jalview.gui.JvOptionPane;
 
 import java.io.Reader;
@@ -97,13 +97,12 @@ public class UniprotTest
     /*
      * Check sequence features
      */
-    Vector<SequenceFeature> features = entry.getFeature();
+    Vector<UniprotFeature> features = entry.getFeature();
     assertEquals(3, features.size());
-    SequenceFeature sf = features.get(0);
+    UniprotFeature sf = features.get(0);
     assertEquals("signal peptide", sf.getType());
     assertNull(sf.getDescription());
     assertNull(sf.getStatus());
-    assertEquals(1, sf.getPosition());
     assertEquals(1, sf.getBegin());
     assertEquals(18, sf.getEnd());
     sf = features.get(1);
@@ -139,10 +138,8 @@ public class UniprotTest
     xref = xrefs.get(2);
     assertEquals("AE007869", xref.getId());
     assertEquals("EMBL", xref.getType());
-    assertEquals("AAK85932.1",
- xref.getProperty("protein sequence ID"));
-    assertEquals("Genomic_DNA",
- xref.getProperty("molecule type"));
+    assertEquals("AAK85932.1", xref.getProperty("protein sequence ID"));
+    assertEquals("Genomic_DNA", xref.getProperty("molecule type"));
   }
 
   @Test(groups = { "Functional" })
@@ -166,11 +163,11 @@ public class UniprotTest
             new StringReader(UNIPROT_XML)).get(0);
 
     /*
-     * name formatted as source | accession ids | names
-     * source database converted to Jalview canonical name
+     * name formatted with Uniprot Entry name
      */
-    String expectedName = "UNIPROT|A9CKP4|A9CKP5|A9CKP4_AGRT5|A9CKP4_AGRT6";
-    assertEquals(expectedName, Uniprot.getUniprotEntryId(entry));
+    String expectedName = "A9CKP4_AGRT5|A9CKP4_AGRT6";
+    assertEquals(expectedName,
+            Uniprot.getUniprotEntryId(entry));
   }
 
   /**
index 40737ca..c559966 100644 (file)
@@ -47,33 +47,26 @@ public class EBIFetchClientTest
     /*
      * EMBL
      */
-    assertEquals("http://www.ebi.ac.uk/ena/data/view/x53838&display=xml",
+    assertEquals("https://www.ebi.ac.uk/ena/data/view/x53838&display=xml",
             EBIFetchClient.buildUrl("X53838", "EMBL", "display=xml"));
 
     /*
      * EMBLCDS
      */
-    assertEquals("http://www.ebi.ac.uk/ena/data/view/caa37824&display=xml",
+    assertEquals("https://www.ebi.ac.uk/ena/data/view/caa37824&display=xml",
             EBIFetchClient.buildUrl("CAA37824", "EMBL", "display=xml"));
 
     /*
-     * Uniprot
-     */
-    assertEquals(
-            "http://www.ebi.ac.uk/Tools/dbfetch/dbfetch/uniprot/p00340/uniprotxml",
-            EBIFetchClient.buildUrl("P00340", "UNIPROT", "uniprotxml"));
-
-    /*
      * PDB / pdb
      */
-    assertEquals("http://www.ebi.ac.uk/Tools/dbfetch/dbfetch/pdb/3a6s/pdb",
+    assertEquals("https://www.ebi.ac.uk/Tools/dbfetch/dbfetch/pdb/3a6s/pdb",
             EBIFetchClient.buildUrl("3A6S", "PDB", "pdb"));
 
     /*
      * PDB / mmCIF
      */
     assertEquals(
-            "http://www.ebi.ac.uk/Tools/dbfetch/dbfetch/pdb/3a6s/mmCIF",
+            "https://www.ebi.ac.uk/Tools/dbfetch/dbfetch/pdb/3a6s/mmCIF",
             EBIFetchClient.buildUrl("3A6S", "PDB", "mmCIF"));
   }
 
index e35f83e..de91af3 100644 (file)
@@ -21,6 +21,7 @@
 package jalview.ws.seqfetcher;
 
 import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertFalse;
 import static org.testng.AssertJUnit.assertNotNull;
 import static org.testng.AssertJUnit.assertTrue;
 
@@ -173,13 +174,13 @@ public class DbRefFetcherTest
     SequenceI seq = alsq.getSequenceAt(0);
     assertEquals("Wrong sequence name", embl.getDbSource() + "|"
             + retrievalId, seq.getName());
-    SequenceFeature[] sfs = seq.getSequenceFeatures();
-    assertNotNull("Sequence features missing", sfs);
+    List<SequenceFeature> sfs = seq.getSequenceFeatures();
+    assertFalse("Sequence features missing", sfs.isEmpty());
     assertTrue(
             "Feature not CDS",
             FeatureProperties.isCodingFeature(embl.getDbSource(),
-                    sfs[0].getType()));
-    assertEquals(embl.getDbSource(), sfs[0].getFeatureGroup());
+ sfs.get(0).getType()));
+    assertEquals(embl.getDbSource(), sfs.get(0).getFeatureGroup());
     DBRefEntry[] dr = DBRefUtils.selectRefs(seq.getDBRefs(),
             new String[] { DBRefSource.UNIPROT });
     assertNotNull(dr);
index 557700a..a649cb4 100755 (executable)
@@ -1471,7 +1471,7 @@ and any path to a file to save to the file]]></string>
                                                                <boolean>true</boolean>
                                                        </property>
                                                        <property name="destinationName">
-                                                               <string><![CDATA[min-jabaws-client-2.1.0.jar]]></string>
+                                                               <string><![CDATA[min-jabaws-client-2.2.0.jar]]></string>
                                                        </property>
                                                        <property name="fileSize">
                                                                <long>601804</long>
@@ -2025,7 +2025,7 @@ and any path to a file to save to the file]]></string>
                                                                <string><![CDATA[664]]></string>
                                                        </property>
                                                        <property name="sourceName">
-                                                               <string><![CDATA[groovy-all-2.4.6-indy.jar]]></string>
+                                                               <string><![CDATA[groovy-all-2.4.12-indy.jar]]></string>
                                                        </property>
                                                        <property name="overrideUnixPermissions">
                                                                <boolean>false</boolean>
@@ -2043,7 +2043,7 @@ and any path to a file to save to the file]]></string>
                                                                <boolean>true</boolean>
                                                        </property>
                                                        <property name="destinationName">
-                                                               <string><![CDATA[groovy-all-2.4.6-indy.jar]]></string>
+                                                               <string><![CDATA[groovy-all-2.4.12-indy.jar]]></string>
                                                        </property>
                                                        <property name="fileSize">
                                                                <long>6149494</long>
@@ -5270,7 +5270,7 @@ Press "Done" to quit the installer.]]></string>
                                        </method>
                                        <method name="put">
                                                <string><![CDATA[com.zerog.ia.installer.options.valid.vm.list]]></string>
-                                               <string><![CDATA[1.8+]]></string>
+                                               <string><![CDATA[1.8*]]></string>
                                        </method>
                                        <method name="put">
                                                <string><![CDATA[com.zerog.ia.project.build.last.date]]></string>
@@ -5366,7 +5366,7 @@ Press "Done" to quit the installer.]]></string>
                                        </method>
                                        <method name="put">
                                                <string><![CDATA[com.zerog.ia.installer.options.platform.macosx.vm.version]]></string>
-                                               <string><![CDATA[1.8+]]></string>
+                                               <string><![CDATA[1.8*]]></string>
                                        </method>
                                        <method name="put">
                                                <string><![CDATA[com.zerog.ia.build.platform.java.novm]]></string>
index ac9e260..122b8d0 100644 (file)
     <!-- 
        Suppress check of externally sourced code 
     --> 
-    <suppress checks="[a-zA-Z0-9]*" files="com[\\/]*"/>
-    <suppress checks="[a-zA-Z0-9]*" files="ext[\\/]*"/>
-    <suppress checks="[a-zA-Z0-9]*" files="org[\\/]*"/>
-    <suppress checks="[a-zA-Z0-9]*" files="uk[\\/]*"/>
+    <suppress checks="[a-zA-Z0-9]*" files="[\\/]com[\\/]github*"/>
+    <suppress checks="[a-zA-Z0-9]*" files="[\\/]com[\\/]stevesoft*"/>
+    <suppress checks="[a-zA-Z0-9]*" files="[\\/]ext[\\/]edu*"/>
+    <suppress checks="[a-zA-Z0-9]*" files="[\\/]ext[\\/]vamsas*"/>
+    <suppress checks="[a-zA-Z0-9]*" files="[\\/]org[\\/]jibble*"/>
+    <suppress checks="[a-zA-Z0-9]*" files="[\\/]uk[\\/]ac*"/>
     
     <!-- 
        ImportControl can only handle one top level package
index b41aab3..c47aaec 100644 (file)
                <subpackage name="datamodel">
                <disallow pkg="jalview.gui"/>
                <allow pkg="fr.orsay.lri.varna"/>
-                       <subpackage name="xdb">
-                               <subpackage name="embl">
-                               <allow pkg="org.exolab.castor"/>
-                           </subpackage>
+                       <subpackage name="xdb.embl">
+                       <allow pkg="org.exolab.castor"/>
                    </subpackage>
            </subpackage>
                
+               <subpackage name="ext">
+                       <subpackage name="ensembl">
+                       <allow pkg="javax.ws"/>
+                       <allow pkg="org.json"/>
+                       </subpackage>
+                       <subpackage name="htsjdk">
+                       <allow pkg="htsjdk"/>
+                       </subpackage>
+                       <subpackage name="jmol">
+                       <allow pkg="MCview"/>
+                       <allow pkg="org.jmol"/>
+                       </subpackage>
+                       <subpackage name="paradise">
+                       <allow pkg="org.apache"/>
+                       <allow pkg="org.json"/>
+                       </subpackage>
+                       <subpackage name="rbvi">
+                       <allow pkg="ext.edu.ucsf"/>
+                       <allow pkg="javax.servlet"/>
+                       </subpackage>
+                       <subpackage name="so">
+                       <allow pkg="org.biojava"/>
+                       </subpackage>
+                       <subpackage name="varna">
+                       <allow pkg="fr.orsay"/>
+                       </subpackage>
+           </subpackage>
+               
                <subpackage name="fts">
                <allow pkg="javax.swing"/>
                <allow pkg="javax.ws"/>
                <allow pkg="javax.servlet"/>
                </subpackage>
 
+               <subpackage name="schemes">
+                       <allow pkg="org.exolab.castor" class="jalview.schemes.ColourSchemeLoader"/>
+               </subpackage>
+
                <subpackage name="structure">
                <allow pkg="MCview"/>
                </subpackage>
+               
+               <subpackage name="urls">
+                       <allow pkg="javax.swing" class="jalview.urls.UrlLinkTableModel"/>
+                       <allow pkg="org.json"/>
+               </subpackage>
 
                <subpackage name="util">
                <allow pkg="javax.swing"/>