Merge branch 'features/1769_headless-mode-test' into develop
authortcofoegbu <tcnofoegbu@dundee.ac.uk>
Mon, 6 Jul 2015 16:01:28 +0000 (17:01 +0100)
committertcofoegbu <tcnofoegbu@dundee.ac.uk>
Mon, 6 Jul 2015 16:01:28 +0000 (17:01 +0100)
33 files changed:
.classpath
THIRDPARTYLIBS
build.xml
lib/VARNAv3-93.jar [moved from lib/VARNAv3-91.jar with 65% similarity]
resources/lang/Messages.properties
schemas/jalview.xsd
src/jalview/appletgui/AlignFrame.java
src/jalview/appletgui/AlignmentPanel.java
src/jalview/datamodel/AlignmentAnnotation.java
src/jalview/datamodel/RnaViewerModel.java [new file with mode: 0644]
src/jalview/datamodel/xdb/embl/EmblEntry.java
src/jalview/ext/varna/RnaModel.java [new file with mode: 0644]
src/jalview/gui/AlignFrame.java
src/jalview/gui/AlignViewport.java
src/jalview/gui/AppVarna.java
src/jalview/gui/AppVarnaBinding.java
src/jalview/gui/ChimeraViewFrame.java
src/jalview/gui/Jalview2XML.java
src/jalview/gui/PopupMenu.java
src/jalview/schemabinding/version2/.castor.cdr
src/jalview/schemabinding/version2/JSeq.java
src/jalview/schemabinding/version2/RnaViewer.java [new file with mode: 0644]
src/jalview/schemabinding/version2/SecondaryStructure.java [new file with mode: 0644]
src/jalview/schemabinding/version2/descriptors/JSeqDescriptor.java
src/jalview/schemabinding/version2/descriptors/RnaViewerDescriptor.java [new file with mode: 0644]
src/jalview/schemabinding/version2/descriptors/SecondaryStructureDescriptor.java [new file with mode: 0644]
src/jalview/structure/SecondaryStructureListener.java
src/jalview/structure/StructureSelectionManager.java
test/MCview/PDBChainTest.java
test/jalview/analysis/AlignSeqTest.java [new file with mode: 0644]
test/jalview/analysis/AnnotationSorterTest.java
test/jalview/analysis/RnaTest.java [new file with mode: 0644]
utils/InstallAnywhere/Jalview.iap_xml

index 3fac886..5961ce9 100644 (file)
@@ -48,7 +48,7 @@
        <classpathentry kind="lib" path="lib/jsoup-1.8.1.jar"/>
        <classpathentry kind="lib" path="lib/log4j-to-slf4j-2.0-rc2.jar"/>
        <classpathentry kind="lib" path="lib/slf4j-log4j12-1.7.7.jar"/>
-       <classpathentry kind="lib" path="lib/VARNAv3-91.jar"/>
+       <classpathentry kind="lib" path="lib/VARNAv3-93.jar"/>
        <classpathentry kind="lib" path="lib/jfreesvg-2.1.jar"/>
        <classpathentry kind="lib" path="lib/quaqua-filechooser-only-8.0.jar"/>
        <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/plugin"/>
index bbef868..52214b2 100644 (file)
@@ -11,7 +11,7 @@ Licencing information for each library is given below:
 
 JGoogleAnalytics_0.3.jar       APL 2.0 License - http://code.google.com/p/jgoogleanalytics/
 Jmol-12.1.13.jar       GPL/LGPLv2 http://sourceforge.net/projects/jmol/files/
-VARNAv3-91.jar GPL licenced software by Kévin Darty, Alain Denise and Yann Ponty. http://varna.lri.fr
+VARNAv3-93.jar GPL licenced software by K�vin Darty, Alain Denise and Yann Ponty. http://varna.lri.fr
 activation.jar 
 apache-mime4j-0.6.jar
 axis.jar
index 02e8253..e32ae33 100755 (executable)
--- a/build.xml
+++ b/build.xml
     <property name="outputJar" value="jalview.jar" />
     <!-- Jalview Applet JMol Jar Dependency -->
     <property name="jmolJar" value="JmolApplet-12.2.4.jar" />
-    <property name="varnaJar" value="VARNAv3-91.jar" />
+    <property name="varnaJar" value="VARNAv3-93.jar" />
     <property name="jsoup" value="jsoup-1.8.1.jar" />
     <property name="jsonSimple" value="json_simple-1.1.jar" />
     <property name="javaJson" value="java-json.jar" />
similarity index 65%
rename from lib/VARNAv3-91.jar
rename to lib/VARNAv3-93.jar
index edfbca5..b73b58d 100644 (file)
Binary files a/lib/VARNAv3-91.jar and b/lib/VARNAv3-93.jar differ
index 1f5d4cb..b2bf58b 100644 (file)
@@ -662,7 +662,7 @@ label.cancel_job_close_dialog = Close this dialog and cancel job
 label.input_output = Input/Output
 label.cut_paste = Cut'n'Paste
 label.adjusting_parameters_for_calculation = Adjusting parameters for existing Calculation
-label.2d_rna_structure_line = 2D RNA {0}
+label.2d_rna_structure_line = 2D RNA {0} (alignment)
 label.2d_rna_sequence_name = 2D RNA - {0}
 label.edit_name_and_description_current_group = Edit name and description of current group.
 label.view_structure_for = View structure for {0}
index eab6500..f60bb6a 100755 (executable)
@@ -1,26 +1,26 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--
- * 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.
--->
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:vamsas="www.vamsas.ac.uk/jalview/version2" xmlns:jalview="www.jalview.org/colours" xmlns:jv="www.jalview.org" xmlns:jvws="www.jalview.org/xml/wsparamset" targetNamespace="www.jalview.org" elementFormDefault="qualified" attributeFormDefault="unqualified">
-               <xs:import namespace="www.vamsas.ac.uk/jalview/version2" schemaLocation="vamsas.xsd"/>
-       <xs:import namespace="www.jalview.org/colours" schemaLocation="JalviewUserColours.xsd"/>
-       <xs:import namespace="www.jalview.org/xml/wsparamset" schemaLocation="JalviewWsParamSet.xsd"/>
+<!-- * 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. -->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+       xmlns:vamsas="www.vamsas.ac.uk/jalview/version2" xmlns:jalview="www.jalview.org/colours"
+       xmlns:jv="www.jalview.org" xmlns:jvws="www.jalview.org/xml/wsparamset"
+       targetNamespace="www.jalview.org" elementFormDefault="qualified"
+       attributeFormDefault="unqualified">
+       <xs:import namespace="www.vamsas.ac.uk/jalview/version2"
+               schemaLocation="vamsas.xsd" />
+       <xs:import namespace="www.jalview.org/colours"
+               schemaLocation="JalviewUserColours.xsd" />
+       <xs:import namespace="www.jalview.org/xml/wsparamset"
+               schemaLocation="JalviewWsParamSet.xsd" />
        <xs:complexType name="JalviewModel">
                <xs:sequence>
                        <xs:element name="creationDate" type="xs:dateTime" />
                                <xs:element name="JSeq" maxOccurs="unbounded" minOccurs="0">
                                        <xs:complexType>
                                                <xs:sequence>
-                                                       <xs:element name="features"
-                                                               type="jv:feature" minOccurs="0" maxOccurs="unbounded" />
-                                                       <xs:element name="pdbids" minOccurs="0"
-                                                               maxOccurs="unbounded">
+                                                       <xs:element name="features" type="jv:feature"
+                                                               minOccurs="0" maxOccurs="unbounded" />
+                                                       <xs:element name="pdbids" minOccurs="0" maxOccurs="unbounded">
                                                                <xs:complexType>
                                                                        <xs:complexContent>
-                                                                               <xs:extension
-                                                                                       base="jv:pdbentry">
+                                                                               <xs:extension base="jv:pdbentry">
                                                                                        <xs:sequence>
-                                                                                               <xs:element
-                                                                                                       name="structureState" minOccurs="0"
+                                                                                               <xs:element name="structureState" minOccurs="0"
                                                                                                        maxOccurs="unbounded">
                                                                                                        <xs:complexType>
                                                                                                                <xs:simpleContent>
-                                                                                                                       <xs:extension
-                                                                                                                               base="xs:string">
-                                                                                                                               <xs:attributeGroup
-                                                                                                                                       ref="jv:swingwindow" />
-                                                                                                                               <xs:attribute
-                                                                                                                                       name="visible" type="xs:boolean" />
-                                                                                                                               <xs:attribute
-                                                                                                                                       name="viewId" type="xs:string" use="optional">
+                                                                                                                       <xs:extension base="xs:string">
+                                                                                                                               <xs:attributeGroup ref="jv:swingwindow" />
+                                                                                                                               <xs:attribute name="visible" type="xs:boolean" />
+                                                                                                                               <xs:attribute name="viewId" type="xs:string"
+                                                                                                                                       use="optional">
                                                                                                                                        <xs:annotation>
                                                                                                                                                <xs:documentation>
                                                                                                                                                        additional
                                                                                                                                                </xs:documentation>
                                                                                                                                        </xs:annotation>
                                                                                                                                </xs:attribute>
-                                                                                                                               <xs:attribute
-                                                                                                                                       name="alignwithAlignPanel" type="xs:boolean"
-                                                                                                                                       use="optional" default="true">
+                                                                                                                               <xs:attribute name="alignwithAlignPanel"
+                                                                                                                                       type="xs:boolean" use="optional" default="true">
                                                                                                                                        <xs:annotation>
                                                                                                                                                <xs:documentation>
                                                                                                                                                        Flag
                                                                                                                                                </xs:documentation>
                                                                                                                                        </xs:annotation>
                                                                                                                                </xs:attribute>
-                                                                                                                               <xs:attribute
-                                                                                                                                       name="colourwithAlignPanel" type="xs:boolean"
-                                                                                                                                       use="optional" default="false">
+                                                                                                                               <xs:attribute name="colourwithAlignPanel"
+                                                                                                                                       type="xs:boolean" use="optional" default="false">
                                                                                                                                        <xs:annotation>
                                                                                                                                                <xs:documentation>
                                                                                                                                                        Flag
                                                                                                                                                </xs:documentation>
                                                                                                                                        </xs:annotation>
                                                                                                                                </xs:attribute>
-                                                                                                                               <xs:attribute
-                                                                                                                                       name="colourByJmol" type="xs:boolean" use="optional"
-                                                                                                                                       default="true">
+                                                                                                                               <xs:attribute name="colourByJmol" type="xs:boolean"
+                                                                                                                                       use="optional" default="true">
                                                                                                                                        <xs:annotation>
                                                                                                                                                <xs:documentation>
                                                                                                                                                        Flag
                                                                                                                                        use="optional">
                                                                                                                                        <xs:annotation>
                                                                                                                                                <xs:documentation>
-                                                                                                                                                       An identifier for the viewer type, currently either
-                                                                                                                                                       JMOL or CHIMERA
+                                                                                                                                                       An
+                                                                                                                                                       identifier
+                                                                                                                                                       for
+                                                                                                                                                       the
+                                                                                                                                                       viewer
+                                                                                                                                                       type,
+                                                                                                                                                       currently
+                                                                                                                                                       either
+                                                                                                                                                       JMOL
+                                                                                                                                                       or
+                                                                                                                                                       CHIMERA
                                                                                                                                                </xs:documentation>
                                                                                                                                        </xs:annotation>
                                                                                                                                </xs:attribute>
                                                                        </xs:complexContent>
                                                                </xs:complexType>
                                                        </xs:element>
-                                                       <xs:element name="hiddenSequences"
-                                                               type="xs:int" minOccurs="0" maxOccurs="unbounded" />
+                                                       <xs:element name="hiddenSequences" type="xs:int"
+                                                               minOccurs="0" maxOccurs="unbounded" />
+                                                       <xs:element name="rnaViewer" minOccurs="0" maxOccurs="unbounded">
+                                                               <xs:annotation>
+                                                                       <xs:documentation>Reference to a viewer showing RNA structure
+                                                                               for this sequence. Schema supports one viewer showing multiple
+                                                                               annotations for multiple sequences, though currently only one
+                                                                               annotation for one sequence (gapped or trimmed) is used
+                                                                       </xs:documentation>
+                                                               </xs:annotation>
+                                                               <xs:complexType>
+                                                                       <xs:sequence>
+                                                                               <xs:element name="secondaryStructure" minOccurs="1"
+                                                                                       maxOccurs="unbounded">
+                                                                                       <xs:complexType>
+                                                                                               <xs:attribute name="title" type="xs:string" />
+                                                                                               <xs:attribute name="annotationId" type="xs:string"
+                                                                                                       use="required">
+                                                                                                       <xs:annotation>
+                                                                                                               <xs:documentation>id attribute of Annotation in
+                                                                                                                       vamsasModel for
+                                                                                                                       the secondary structure annotation shown
+                                                                                                                       in the viewer
+                                                                                                               </xs:documentation>
+                                                                                                       </xs:annotation>
+                                                                                               </xs:attribute>
+                                                                                               <xs:attribute name="gapped" type="xs:boolean">
+                                                                                                       <xs:annotation>
+                                                                                                               <xs:documentation>if true the RNA structure is shown with gaps, if false without
+                                                                                                               </xs:documentation>
+                                                                                                       </xs:annotation>
+                                                                                               </xs:attribute>
+                                                                                               <xs:attribute name="viewerState" type="xs:string">
+                                                                                                       <xs:annotation>
+                                                                                                               <xs:documentation>name of the project jar entry that holds
+                                                                                                                       the VARNA viewer state for the structure
+                                                                                                               </xs:documentation>
+                                                                                                       </xs:annotation>
+                                                                                               </xs:attribute>
+                                                                                       </xs:complexType>
+                                                                               </xs:element>
+                                                                       </xs:sequence>
+                                                                       <xs:attributeGroup ref="jv:swingwindow" />
+                                                                       <xs:attribute name="title" type="xs:string" />
+                                                                       <xs:attribute name="viewId" type="xs:string">
+                                                                               <xs:annotation>
+                                                                                       <xs:documentation>An id unique to the RNA viewer panel
+                                                                                       </xs:documentation>
+                                                                               </xs:annotation>
+                                                                       </xs:attribute>
+                                                                       <xs:attribute name="dividerLocation" type="xs:int">
+                                                                               <xs:annotation>
+                                                                                       <xs:documentation>horizontal position of split pane divider
+                                                                                       </xs:documentation>
+                                                                               </xs:annotation>
+                                                                       </xs:attribute>
+                                                                       <xs:attribute name="selectedRna" type="xs:int">
+                                                                               <xs:annotation>
+                                                                                       <xs:documentation>Index of the selected structure in the
+                                                                                               viewer panel
+                                                                                       </xs:documentation>
+                                                                               </xs:annotation>
+                                                                       </xs:attribute>
+                                                               </xs:complexType>
+                                                       </xs:element>
                                                </xs:sequence>
-                                               <xs:attribute name="colour" type="xs:int"
-                                                       use="optional" />
-                                               <xs:attribute name="start" type="xs:int"
-                                                       use="required" />
-                                               <xs:attribute name="end" type="xs:int"
-                                                       use="required" />
-                                               <xs:attribute name="id" type="xs:string"
-                                                       use="required" />
+                                               <xs:attribute name="colour" type="xs:int" use="optional" />
+                                               <xs:attribute name="start" type="xs:int" use="required" />
+                                               <xs:attribute name="end" type="xs:int" use="required" />
+                                               <xs:attribute name="id" type="xs:string" use="required" />
                                                <xs:attribute name="hidden" type="xs:boolean" />
                                        </xs:complexType>
                                </xs:element>
-                               <xs:element name="JGroup" minOccurs="0"
-                                       maxOccurs="unbounded">
+                               <xs:element name="JGroup" minOccurs="0" maxOccurs="unbounded">
                                        <xs:complexType>
-            <xs:sequence>
+                                               <xs:sequence>
                                                        <xs:element name="seq" type="xs:string" maxOccurs="unbounded" />
                                                        <xs:element name="annotationColours" type="jv:AnnotationColourScheme"
                                                                minOccurs="0" maxOccurs="1" />
                                                <xs:attribute name="end" type="xs:int" />
                                                <xs:attribute name="name" type="xs:string" />
                                                <xs:attribute name="colour" type="xs:string" />
-                                               <xs:attribute name="consThreshold"
-                                                       type="xs:int" />
+                                               <xs:attribute name="consThreshold" type="xs:int" />
                                                <xs:attribute name="pidThreshold" type="xs:int" />
-                                               <xs:attribute name="outlineColour"
-                                                       type="xs:int" />
-                                               <xs:attribute name="displayBoxes"
-                                                       type="xs:boolean" />
-                                               <xs:attribute name="displayText"
-                                                       type="xs:boolean" />
-                                               <xs:attribute name="colourText"
-                                                       type="xs:boolean" />
+                                               <xs:attribute name="outlineColour" type="xs:int" />
+                                               <xs:attribute name="displayBoxes" type="xs:boolean" />
+                                               <xs:attribute name="displayText" type="xs:boolean" />
+                                               <xs:attribute name="colourText" type="xs:boolean" />
                                                <xs:attribute name="textCol1" type="xs:int" />
                                                <xs:attribute name="textCol2" type="xs:int" />
-                                               <xs:attribute name="textColThreshold"
-                                                       type="xs:int" />
-                                               <xs:attribute name="showUnconserved"
-                                                       type="xs:boolean" use="optional" />
-                                               <xs:attribute name="ignoreGapsinConsensus"
-                                                       type="xs:boolean" use="optional" default="true" />
-                                               <xs:attribute name="showConsensusHistogram"
-                                                       type="xs:boolean" use="optional" default="true" />
-                                               <xs:attribute name="showSequenceLogo"
-                                                       type="xs:boolean" use="optional" default="false" />
-                                               <xs:attribute name="normaliseSequenceLogo"
-              type="xs:boolean" use="optional" default="false" />
-            <xs:attribute name="id" type="xs:string"
-                                                       use="optional">
+                                               <xs:attribute name="textColThreshold" type="xs:int" />
+                                               <xs:attribute name="showUnconserved" type="xs:boolean"
+                                                       use="optional" />
+                                               <xs:attribute name="ignoreGapsinConsensus" type="xs:boolean"
+                                                       use="optional" default="true" />
+                                               <xs:attribute name="showConsensusHistogram" type="xs:boolean"
+                                                       use="optional" default="true" />
+                                               <xs:attribute name="showSequenceLogo" type="xs:boolean"
+                                                       use="optional" default="false" />
+                                               <xs:attribute name="normaliseSequenceLogo" type="xs:boolean"
+                                                       use="optional" default="false" />
+                                               <xs:attribute name="id" type="xs:string" use="optional">
                                                        <xs:annotation>
                                                                <xs:documentation>
                                                                        Optional sequence group ID (only
-                                                                       needs to be unique for this
+                                                                       needs to be
+                                                                       unique for this
                                                                        alignment)
                                                                </xs:documentation>
                                                        </xs:annotation>
                                                </xs:attribute>
                                        </xs:complexType>
                                </xs:element>
-                               <xs:element name="Viewport" maxOccurs="unbounded" minOccurs="0">
+                               <xs:element name="Viewport" maxOccurs="unbounded"
+                                       minOccurs="0">
                                        <xs:complexType>
                                                <xs:sequence>
-                                                       <xs:element name="AnnotationColours" type="jv:AnnotationColourScheme" 
+                                                       <xs:element name="AnnotationColours" type="jv:AnnotationColourScheme"
                                                                minOccurs="0" maxOccurs="1">
                                                        </xs:element>
-                                                       <xs:element name="hiddenColumns"
-                                                               minOccurs="0" maxOccurs="unbounded">
+                                                       <xs:element name="hiddenColumns" minOccurs="0"
+                                                               maxOccurs="unbounded">
                                                                <xs:complexType>
-                                                                       <xs:attribute name="start"
-                                                                               type="xs:int" />
-                                                                       <xs:attribute name="end"
-                                                                               type="xs:int" />
+                                                                       <xs:attribute name="start" type="xs:int" />
+                                                                       <xs:attribute name="end" type="xs:int" />
                                                                </xs:complexType>
                                                        </xs:element>
-                                                       <xs:element name="calcIdParam" 
-                                                        
-                                                       minOccurs="0" maxOccurs="unbounded">
-                                                       <xs:complexType>
-                                                       <xs:complexContent>
-                                                       <xs:extension base="jvws:WebServiceParameterSet">
-                                                       <xs:attribute name="calcId" type="xs:string" use="required">
-                                                       <xs:annotation>
-                                                       <xs:documentation>handle for the calculation which uses this parameter set</xs:documentation></xs:annotation>
-                                                       </xs:attribute>
-                                                       <xs:attribute name="needsUpdate" type="xs:boolean" use="optional" default="false">
-                                                       <xs:annotation><xs:documentation>should the calculation be performed immediately after loading in order to refresh results</xs:documentation></xs:annotation>
-                                                       </xs:attribute>
-                                                       <xs:attribute name="autoUpdate" type="xs:boolean" use="required">
-                                                       <xs:annotation><xs:documentation>should the calculation be automatically performed on edits</xs:documentation></xs:annotation>
-                                                       </xs:attribute>
-                                                       </xs:extension>
-                                                       </xs:complexContent>
-                                                       </xs:complexType>
+                                                       <xs:element name="calcIdParam" minOccurs="0"
+                                                               maxOccurs="unbounded">
+                                                               <xs:complexType>
+                                                                       <xs:complexContent>
+                                                                               <xs:extension base="jvws:WebServiceParameterSet">
+                                                                                       <xs:attribute name="calcId" type="xs:string"
+                                                                                               use="required">
+                                                                                               <xs:annotation>
+                                                                                                       <xs:documentation>handle for the calculation which uses
+                                                                                                               this parameter set
+                                                                                                       </xs:documentation>
+                                                                                               </xs:annotation>
+                                                                                       </xs:attribute>
+                                                                                       <xs:attribute name="needsUpdate" type="xs:boolean"
+                                                                                               use="optional" default="false">
+                                                                                               <xs:annotation>
+                                                                                                       <xs:documentation>should the calculation be performed
+                                                                                                               immediately after loading in order to refresh results
+                                                                                                       </xs:documentation>
+                                                                                               </xs:annotation>
+                                                                                       </xs:attribute>
+                                                                                       <xs:attribute name="autoUpdate" type="xs:boolean"
+                                                                                               use="required">
+                                                                                               <xs:annotation>
+                                                                                                       <xs:documentation>should the calculation be automatically
+                                                                                                               performed on edits
+                                                                                                       </xs:documentation>
+                                                                                               </xs:annotation>
+                                                                                       </xs:attribute>
+                                                                               </xs:extension>
+                                                                       </xs:complexContent>
+                                                               </xs:complexType>
                                                        </xs:element>
                                                </xs:sequence>
                                                <xs:attributeGroup ref="jv:swingwindow" />
-                                               <xs:attribute name="conservationSelected"
-                                                       type="xs:boolean" />
-                                               <xs:attribute name="pidSelected"
-                                                       type="xs:boolean" />
+                                               <xs:attribute name="conservationSelected" type="xs:boolean" />
+                                               <xs:attribute name="pidSelected" type="xs:boolean" />
                                                <xs:attribute name="bgColour" type="xs:string" />
-                                               <xs:attribute name="consThreshold"
-                                                       type="xs:int" />
+                                               <xs:attribute name="consThreshold" type="xs:int" />
                                                <xs:attribute name="pidThreshold" type="xs:int" />
                                                <xs:attribute name="title" type="xs:string" />
-                                               <xs:attribute name="showFullId"
-                                                       type="xs:boolean" />
-                                               <xs:attribute name="rightAlignIds"
-                                                       type="xs:boolean" />
+                                               <xs:attribute name="showFullId" type="xs:boolean" />
+                                               <xs:attribute name="rightAlignIds" type="xs:boolean" />
                                                <xs:attribute name="showText" type="xs:boolean" />
-                                               <xs:attribute name="showColourText"
-                                                       type="xs:boolean" />
-                                               <xs:attribute name="showUnconserved"
-                                                       type="xs:boolean" use="optional" default="false" />
-                                               <xs:attribute name="showBoxes"
-                                                       type="xs:boolean" />
-                                               <xs:attribute name="wrapAlignment"
-                                                       type="xs:boolean" />
-                                               <xs:attribute name="renderGaps"
-                                                       type="xs:boolean" />
-                                               <xs:attribute name="showSequenceFeatures"
-                                                       type="xs:boolean" />
-                                               <xs:attribute name="showNPfeatureTooltip"
-                                                       type="xs:boolean" use="optional" />
-                                               <xs:attribute name="showDbRefTooltip"
-                                                       type="xs:boolean" use="optional" />
-                                               <xs:attribute name="followHighlight"
-                                                       type="xs:boolean" use="optional" default="true" />
-                                               <xs:attribute name="followSelection"
-                                                       type="xs:boolean" use="optional" default="true" />
-                                               <xs:attribute name="showAnnotation"
-                                                       type="xs:boolean" />
-                                               <xs:attribute name="centreColumnLabels"
-                                                       type="xs:boolean" use="optional" default="false" />
-                                               <xs:attribute name="showGroupConservation"
-                                                       type="xs:boolean" use="optional" default="false" />
-                                               <xs:attribute name="showGroupConsensus"
-                                                       type="xs:boolean" use="optional" default="false" />
-                                               <xs:attribute name="showConsensusHistogram"
-                                                       type="xs:boolean" use="optional" default="true" />
-                                               <xs:attribute name="showSequenceLogo"
-                                                       type="xs:boolean" use="optional" default="false" />
-                                   <xs:attribute name="normaliseSequenceLogo"
-                                     type="xs:boolean" use="optional" default="false" />
-                                               <xs:attribute name="ignoreGapsinConsensus"
-                                                       type="xs:boolean" use="optional" default="true" />
-                                                       <xs:attribute name="startRes" type="xs:int" />
+                                               <xs:attribute name="showColourText" type="xs:boolean" />
+                                               <xs:attribute name="showUnconserved" type="xs:boolean"
+                                                       use="optional" default="false" />
+                                               <xs:attribute name="showBoxes" type="xs:boolean" />
+                                               <xs:attribute name="wrapAlignment" type="xs:boolean" />
+                                               <xs:attribute name="renderGaps" type="xs:boolean" />
+                                               <xs:attribute name="showSequenceFeatures" type="xs:boolean" />
+                                               <xs:attribute name="showNPfeatureTooltip" type="xs:boolean"
+                                                       use="optional" />
+                                               <xs:attribute name="showDbRefTooltip" type="xs:boolean"
+                                                       use="optional" />
+                                               <xs:attribute name="followHighlight" type="xs:boolean"
+                                                       use="optional" default="true" />
+                                               <xs:attribute name="followSelection" type="xs:boolean"
+                                                       use="optional" default="true" />
+                                               <xs:attribute name="showAnnotation" type="xs:boolean" />
+                                               <xs:attribute name="centreColumnLabels" type="xs:boolean"
+                                                       use="optional" default="false" />
+                                               <xs:attribute name="showGroupConservation" type="xs:boolean"
+                                                       use="optional" default="false" />
+                                               <xs:attribute name="showGroupConsensus" type="xs:boolean"
+                                                       use="optional" default="false" />
+                                               <xs:attribute name="showConsensusHistogram" type="xs:boolean"
+                                                       use="optional" default="true" />
+                                               <xs:attribute name="showSequenceLogo" type="xs:boolean"
+                                                       use="optional" default="false" />
+                                               <xs:attribute name="normaliseSequenceLogo" type="xs:boolean"
+                                                       use="optional" default="false" />
+                                               <xs:attribute name="ignoreGapsinConsensus" type="xs:boolean"
+                                                       use="optional" default="true" />
+                                               <xs:attribute name="startRes" type="xs:int" />
                                                <xs:attribute name="startSeq" type="xs:int" />
                                                <xs:attribute name="fontName" type="xs:string" />
                                                <xs:attribute name="fontSize" type="xs:int" />
                                                <xs:attribute name="fontStyle" type="xs:int" />
                                                <xs:attribute name="viewName" type="xs:string" />
-                                               <xs:attribute name="sequenceSetId"
-                                                       type="xs:string" />
-                                               <xs:attribute name="gatheredViews"
-                                                       type="xs:boolean" />
+                                               <xs:attribute name="sequenceSetId" type="xs:string" />
+                                               <xs:attribute name="gatheredViews" type="xs:boolean" />
                                                <xs:attribute name="textCol1" type="xs:int" />
                                                <xs:attribute name="textCol2" type="xs:int" />
-                                               <xs:attribute name="textColThreshold"
-                                                       type="xs:int" />
-                                               <xs:attribute name="id" type="xs:ID"
-                                                       use="optional">
+                                               <xs:attribute name="textColThreshold" type="xs:int" />
+                                               <xs:attribute name="id" type="xs:ID" use="optional">
                                                        <xs:annotation>
                                                                <xs:documentation>
                                                                        unique id used by jalview to
-                                                                       synchronize between stored and
+                                                                       synchronize
+                                                                       between stored and
                                                                        instantiated views
                                                                </xs:documentation>
                                                        </xs:annotation>
                                                        use="optional">
                                                        <xs:annotation>
                                                                <xs:documentation>
-                                                                       The viewport id of this viewport's (cdna/protein) coding complement, if any
+                                                                       The viewport id of this viewport's
+                                                                       (cdna/protein) coding complement, if any
                                                                </xs:documentation>
                                                        </xs:annotation>
                                                </xs:attribute>
                                        </xs:complexType>
                                </xs:element>
-                               <xs:element name="UserColours" minOccurs="0"
-                                       maxOccurs="unbounded">
+                               <xs:element name="UserColours" minOccurs="0" maxOccurs="unbounded">
                                        <xs:complexType>
                                                <xs:sequence>
-                                                       <xs:element name="UserColourScheme"
-                                                               type="jalview:JalviewUserColours" />
+                                                       <xs:element name="UserColourScheme" type="jalview:JalviewUserColours" />
                                                </xs:sequence>
                                                <xs:attribute name="id" type="xs:string" />
                                        </xs:complexType>
                                </xs:element>
-                               <xs:element name="tree" minOccurs="0"
-                                       maxOccurs="unbounded">
+                               <xs:element name="tree" minOccurs="0" maxOccurs="unbounded">
                                        <xs:complexType>
                                                <xs:sequence minOccurs="0">
                                                        <xs:element name="title" type="xs:string" />
                                                <xs:attribute name="fontSize" type="xs:int" />
                                                <xs:attribute name="fontStyle" type="xs:int" />
                                                <xs:attribute name="threshold" type="xs:float" />
-                                               <xs:attribute name="showBootstrap"
-                                                       type="xs:boolean" />
-                                               <xs:attribute name="showDistances"
-                                                       type="xs:boolean" />
-                                               <xs:attribute name="markUnlinked"
-                                                       type="xs:boolean" />
-                                               <xs:attribute name="fitToWindow"
-                                                       type="xs:boolean" />
-                                               <xs:attribute name="currentTree"
-                                                       type="xs:boolean" />
-                                               <xs:attribute name="id" type="xs:ID"
-                                                       use="optional">
+                                               <xs:attribute name="showBootstrap" type="xs:boolean" />
+                                               <xs:attribute name="showDistances" type="xs:boolean" />
+                                               <xs:attribute name="markUnlinked" type="xs:boolean" />
+                                               <xs:attribute name="fitToWindow" type="xs:boolean" />
+                                               <xs:attribute name="currentTree" type="xs:boolean" />
+                                               <xs:attribute name="id" type="xs:ID" use="optional">
                                                        <xs:annotation>
                                                                <xs:documentation>
                                                                        Tree ID added for binding tree
-                                                                       visualization settings to vamsas
+                                                                       visualization
+                                                                       settings to vamsas
                                                                        document trees in jalview 2.4.1
                                                                </xs:documentation>
                                                        </xs:annotation>
                                <xs:element name="FeatureSettings" minOccurs="0">
                                        <xs:complexType>
                                                <xs:sequence>
-                                                       <xs:element name="setting" minOccurs="0"
-                                                               maxOccurs="unbounded">
+                                                       <xs:element name="setting" minOccurs="0" maxOccurs="unbounded">
                                                                <xs:complexType>
-                                                                       <xs:attribute name="type"
-                                                                               type="xs:string" use="required" />
-                                                                       <xs:attribute name="colour"
-                                                                               type="xs:int" use="required" />
-                                                                       <xs:attribute name="display"
-                                                                               type="xs:boolean" use="required" />
-                                                                       <xs:attribute name="order"
-                                                                               type="xs:float" use="optional" />
-                                                                       <xs:attribute name="mincolour"
-                                                                               type="xs:int" use="optional">
+                                                                       <xs:attribute name="type" type="xs:string" use="required" />
+                                                                       <xs:attribute name="colour" type="xs:int" use="required" />
+                                                                       <xs:attribute name="display" type="xs:boolean"
+                                                                               use="required" />
+                                                                       <xs:attribute name="order" type="xs:float" use="optional" />
+                                                                       <xs:attribute name="mincolour" type="xs:int" use="optional">
                                                                                <xs:annotation>
                                                                                        <xs:documentation>
                                                                                                Optional minimum colour
-                                                                                               for graduated feature
+                                                                                               for graduated
+                                                                                               feature
                                                                                                colour
                                                                                        </xs:documentation>
                                                                                </xs:annotation>
                                                                        </xs:attribute>
-                                                                       <xs:attribute name="threshold"
-                                                                               type="xs:float" use="optional">
+                                                                       <xs:attribute name="threshold" type="xs:float"
+                                                                               use="optional">
                                                                                <xs:annotation>
                                                                                        <xs:documentation>
                                                                                                threshold value for
                                                                                        </xs:documentation>
                                                                                </xs:annotation>
                                                                        </xs:attribute>
-                                                                       <xs:attribute name="threshstate"
-                                                                               type="xs:int" use="optional">
+                                                                       <xs:attribute name="threshstate" type="xs:int"
+                                                                               use="optional">
                                                                                <xs:annotation>
                                                                                        <xs:documentation>
                                                                                                threshold type for
                                                                                        </xs:documentation>
                                                                                </xs:annotation>
                                                                        </xs:attribute>
-                                                                       <xs:attribute name="max"
-                                                                               type="xs:float" use="optional" />
-                                                                       <xs:attribute name="min"
-                                                                               type="xs:float" use="optional" />
-                                                                       <xs:attribute name="colourByLabel"
-                                                                               type="xs:boolean" use="optional" />
-                                                                       <xs:attribute name="autoScale"
-                                                                               type="xs:boolean" use="optional" />
+                                                                       <xs:attribute name="max" type="xs:float" use="optional" />
+                                                                       <xs:attribute name="min" type="xs:float" use="optional" />
+                                                                       <xs:attribute name="colourByLabel" type="xs:boolean"
+                                                                               use="optional" />
+                                                                       <xs:attribute name="autoScale" type="xs:boolean"
+                                                                               use="optional" />
                                                                </xs:complexType>
                                                        </xs:element>
-                                                       <xs:element name="group" minOccurs="0"
-                                                               maxOccurs="unbounded">
+                                                       <xs:element name="group" minOccurs="0" maxOccurs="unbounded">
                                                                <xs:complexType>
-                                                                       <xs:attribute name="name"
-                                                                               type="xs:string" use="required" />
-                                                                       <xs:attribute name="display"
-                                                                               type="xs:boolean" use="required" />
+                                                                       <xs:attribute name="name" type="xs:string" use="required" />
+                                                                       <xs:attribute name="display" type="xs:boolean"
+                                                                               use="required" />
                                                                </xs:complexType>
                                                        </xs:element>
                                                </xs:sequence>
                <xs:sequence>
                        <xs:element name="otherData" minOccurs="0" maxOccurs="unbounded">
                                <xs:complexType>
-                                       <xs:attribute name="key" type="xs:string" use="required"/>
-                                       <xs:attribute name="value" type="xs:string" use="required"/>
+                                       <xs:attribute name="key" type="xs:string" use="required" />
+                                       <xs:attribute name="value" type="xs:string" use="required" />
                                </xs:complexType>
                        </xs:element>
                </xs:sequence>
-               <xs:attribute name="begin" type="xs:int" use="required"/>
-               <xs:attribute name="end" type="xs:int" use="required"/>
-               <xs:attribute name="type" type="xs:string" use="required"/>
-               <xs:attribute name="description" type="xs:string" use="optional"/>
-               <xs:attribute name="status" type="xs:string" use="optional"/>
-               <xs:attribute name="featureGroup" type="xs:string" use="optional"/>
-               <xs:attribute name="score" type="xs:float" use="optional"/>
+               <xs:attribute name="begin" type="xs:int" use="required" />
+               <xs:attribute name="end" type="xs:int" use="required" />
+               <xs:attribute name="type" type="xs:string" use="required" />
+               <xs:attribute name="description" type="xs:string" use="optional" />
+               <xs:attribute name="status" type="xs:string" use="optional" />
+               <xs:attribute name="featureGroup" type="xs:string" use="optional" />
+               <xs:attribute name="score" type="xs:float" use="optional" />
        </xs:complexType>
        <xs:complexType name="pdbentry">
                <xs:sequence minOccurs="0" maxOccurs="unbounded">
                        <xs:element name="property" minOccurs="0" maxOccurs="unbounded">
                                <xs:complexType>
-                                       <xs:attribute name="name" type="xs:string" use="required"/>
-                                       <xs:attribute name="value" type="xs:string" use="required"/>
+                                       <xs:attribute name="name" type="xs:string" use="required" />
+                                       <xs:attribute name="value" type="xs:string" use="required" />
                                </xs:complexType>
                        </xs:element>
                </xs:sequence>
-               <xs:attribute name="id" type="xs:string" use="required"/>
-               <xs:attribute name="type" type="xs:string" use="optional"/>
-               <xs:attribute name="file" type="xs:string"/>
+               <xs:attribute name="id" type="xs:string" use="required" />
+               <xs:attribute name="type" type="xs:string" use="optional" />
+               <xs:attribute name="file" type="xs:string" />
        </xs:complexType>
-       <!-- 
-       <xs:complexType name="reportWindow">
-       <xs:annotation>
-       <xs:documentation>Generic type for windows containing mime-typed data associated with other jalview windows</xs:documentation>
-       </xs:annotation>
-       <xs:sequence>
-       </xs:sequence>
-    <xs:attribute name="id" type="xs:string" use="required"/>
-    <xs:attribute name="type" type="xs:string" use="optional"/>
-    <xs:attribute name="file" type="xs:string" use="optional"/>
+       <!-- <xs:complexType name="reportWindow"> <xs:annotation> <xs:documentation>Generic 
+               type for windows containing mime-typed data associated with other jalview 
+               windows</xs:documentation> </xs:annotation> <xs:sequence> </xs:sequence> 
+               <xs:attribute name="id" type="xs:string" use="required"/> <xs:attribute name="type" 
+               type="xs:string" use="optional"/> <xs:attribute name="file" type="xs:string" 
+               use="optional"/> </xs:complexType> -->
+       <xs:attributeGroup name="swingwindow">
+               <xs:annotation>
+                       <xs:documentation>
+                               base attributes for windows displayed in Jalview
+                               desktop.
+                       </xs:documentation>
+               </xs:annotation>
+               <xs:attribute name="width" type="xs:int" />
+               <xs:attribute name="height" type="xs:int" />
+               <xs:attribute name="xpos" type="xs:int" />
+               <xs:attribute name="ypos" type="xs:int" />
+       </xs:attributeGroup>
+       <xs:complexType name="AnnotationColourScheme">
+               <xs:attribute name="aboveThreshold" type="xs:int" />
+               <xs:attribute name="annotation" type="xs:string" />
+               <xs:attribute name="minColour" type="xs:int" />
+               <xs:attribute name="maxColour" type="xs:int" />
+               <xs:attribute name="colourScheme" type="xs:string" />
+               <xs:attribute name="threshold" type="xs:float" />
+               <xs:attribute name="perSequence" type="xs:boolean" use="optional" />
+               <xs:attribute name="predefinedColours" type="xs:boolean"
+                       use="optional" />
        </xs:complexType>
- -->
-    <xs:attributeGroup name="swingwindow">
-    <xs:annotation>
-    <xs:documentation>
-      base attributes for windows displayed in Jalview desktop.
-    </xs:documentation>
-    </xs:annotation>
-      <xs:attribute name="width" type="xs:int"/>
-      <xs:attribute name="height" type="xs:int"/>
-      <xs:attribute name="xpos" type="xs:int"/>
-      <xs:attribute name="ypos" type="xs:int"/>
-    </xs:attributeGroup>
-  <xs:complexType name="AnnotationColourScheme">
-       <xs:attribute name="aboveThreshold" type="xs:int" />
-       <xs:attribute name="annotation" type="xs:string" />
-       <xs:attribute name="minColour" type="xs:int" />
-       <xs:attribute name="maxColour" type="xs:int" />
-       <xs:attribute name="colourScheme" type="xs:string" />
-       <xs:attribute name="threshold" type="xs:float" />
-       <xs:attribute name="perSequence" type="xs:boolean" use="optional" />
-       <xs:attribute name="predefinedColours" type="xs:boolean"
-               use="optional" />
-  </xs:complexType>
-  
+
 </xs:schema>
index eaf93c2..075f0d2 100644 (file)
@@ -928,6 +928,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
         aa.visible = visible;
     }
     alignPanel.validateAnnotationDimensions(true);
+    validate();
+    repaint();
   }
 
   private void setAnnotationSortOrder(SequenceAnnotationOrder order)
index 0516533..463c6c3 100644 (file)
  */
 package jalview.appletgui;
 
+import jalview.analysis.AnnotationSorter;
+import jalview.api.AlignViewportI;
+import jalview.api.AlignmentViewPanel;
+import jalview.bin.JalviewLite;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SearchResults;
+import jalview.datamodel.SequenceI;
+import jalview.structure.StructureSelectionManager;
+
 import java.awt.BorderLayout;
 import java.awt.Color;
 import java.awt.Dimension;
@@ -34,15 +43,6 @@ import java.awt.event.ComponentAdapter;
 import java.awt.event.ComponentEvent;
 import java.util.List;
 
-import jalview.analysis.AnnotationSorter;
-import jalview.api.AlignViewportI;
-import jalview.api.AlignmentViewPanel;
-import jalview.bin.JalviewLite;
-import jalview.datamodel.AlignmentI;
-import jalview.datamodel.SearchResults;
-import jalview.datamodel.SequenceI;
-import jalview.structure.StructureSelectionManager;
-
 public class AlignmentPanel extends Panel implements AdjustmentListener,
         AlignmentViewPanel
 {
@@ -552,70 +552,60 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
   }
 
   /**
-   * calculate the annotation dimensions and refresh slider values accordingly.
-   * need to do repaints/notifys afterwards.
+   * Calculate the annotation dimensions and refresh slider values accordingly.
+   * Need to do repaints/notifys afterwards.
    */
   protected void validateAnnotationDimensions(boolean adjustPanelHeight)
   {
-    boolean modified = false;
-    int height = av.calcPanelHeight();
-    int minsize = 0;
-    if (hscroll.isVisible())
-    {
-      height += (minsize = hscroll.getPreferredSize().height);
-    }
-    if (apvscroll.isVisible())
-    {
-      minsize += apvscroll.getPreferredSize().height;
-    }
-    int mheight = height;
-    Dimension d = sequenceHolderPanel.getSize(), e = idPanel.getSize();
-    int seqandannot = d.height - scalePanelHolder.getSize().height;
+    int rowHeight = av.getCharHeight();
+    int alignmentHeight = rowHeight * av.getAlignment().getHeight();
+    int annotationHeight = av.calcPanelHeight();
+
+    int mheight = annotationHeight;
+    Dimension d = sequenceHolderPanel.getSize();
+
+    int availableHeight = d.height - scalePanelHolder.getHeight();
 
     if (adjustPanelHeight)
     {
-      // NOTE: this logic is different in the application. Need a better
-      // algorithm to define behaviour
-      // sets initial preferred height
-      // try and set height according to alignment
-      float sscaling = (float) ((av.getCharHeight() * av.getAlignment()
-              .getHeight()) / (1.0 * mheight));
-      if (sscaling > 0.5)
-      {
-        // if the alignment is too big then
-        // default is 0.5 split
-        height = seqandannot / 2;
-      }
-      else
+      /*
+       * If not enough vertical space, maximize annotation height while keeping
+       * at least two rows of alignment visible
+       */
+      if (annotationHeight + alignmentHeight > availableHeight)
       {
-        // otherwise just set the panel so that one row of sequence is visible
-        height = -av.getCharHeight() * 1
-                + (int) (seqandannot * (1 - sscaling));
+        annotationHeight = Math.min(annotationHeight, availableHeight - 2
+                * rowHeight);
       }
     }
     else
     {
       // maintain same window layout whilst updating sliders
-      height = annotationPanelHolder.getSize().height;
+      annotationHeight = annotationPanelHolder.getSize().height;
     }
 
-    if (seqandannot - height < 5)
+    if (availableHeight - annotationHeight < 5)
     {
-      height = seqandannot;
+      annotationHeight = availableHeight;
     }
-    annotationPanel.setSize(new Dimension(d.width, height));
-    alabels.setSize(new Dimension(e.width, height));
-    annotationSpaceFillerHolder.setSize(new Dimension(e.width, height));
-    annotationPanelHolder.setSize(new Dimension(d.width, height));
+
+    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);
+
+    Dimension e = idPanel.getSize();
+    alabels.setSize(new Dimension(e.width, annotationHeight));
+    annotationSpaceFillerHolder.setSize(new Dimension(e.width,
+            annotationHeight));
+
     int s = apvscroll.getValue();
-    if (s > mheight - height)
+    if (s > mheight - annotationHeight)
     {
       s = 0;
     }
-    apvscroll.setValues(s, height, 0, mheight);
+    apvscroll.setValues(s, annotationHeight, 0, mheight);
     annotationPanel.setScrollOffset(apvscroll.getValue(), false);
     alabels.setScrollOffset(apvscroll.getValue(), false);
   }
index 4c5ea17..322fd54 100755 (executable)
  */
 package jalview.datamodel;
 
-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;
@@ -32,6 +28,10 @@ import java.util.Iterator;
 import java.util.Map;
 import java.util.Map.Entry;
 
+import jalview.analysis.Rna;
+import jalview.analysis.SecStrConsensus.SimpleBP;
+import jalview.analysis.WUSSParseException;
+
 /**
  * DOCUMENT ME!
  * 
@@ -40,6 +40,8 @@ import java.util.Map.Entry;
  */
 public class AlignmentAnnotation
 {
+  private static final String ANNOTATION_ID_PREFIX = "ann";
+
   /*
    * Identifers for different types of profile data
    */
@@ -49,6 +51,8 @@ public class AlignmentAnnotation
 
   public static final int CDNA_PROFILE = 2;
 
+  private static long counter = 0;
+
   /**
    * If true, this annotations is calculated every edit, eg consensus, quality
    * or conservation graphs
@@ -282,6 +286,7 @@ public class AlignmentAnnotation
   public AlignmentAnnotation(String label, String description,
           Annotation[] annotations)
   {
+    setAnnotationId();
     // always editable?
     editable = true;
     this.label = label;
@@ -458,8 +463,6 @@ public class AlignmentAnnotation
         _updateRnaSecStr(new AnnotCharSequence());
       }
     }
-
-    annotationId = this.hashCode() + "";
   }
 
   /**
@@ -565,6 +568,7 @@ public class AlignmentAnnotation
   public AlignmentAnnotation(String label, String description,
           Annotation[] annotations, float min, float max, int graphType)
   {
+    setAnnotationId();
     // graphs are not editable
     editable = graphType == 0;
 
@@ -664,6 +668,7 @@ public class AlignmentAnnotation
    */
   public AlignmentAnnotation(AlignmentAnnotation annotation)
   {
+    setAnnotationId();
     this.label = new String(annotation.label);
     if (annotation.description != null)
     {
@@ -1382,4 +1387,18 @@ public class AlignmentAnnotation
     return sequenceMapping == null ? null : sequenceMapping.get(position);
 
   }
+
+  /**
+   * Set the id to "ann" followed by a counter that increments so as to be
+   * unique for the lifetime of the JVM
+   */
+  protected final void setAnnotationId()
+  {
+    this.annotationId = ANNOTATION_ID_PREFIX + Long.toString(nextId());
+  }
+
+  protected static synchronized long nextId()
+  {
+    return counter++;
+  }
 }
diff --git a/src/jalview/datamodel/RnaViewerModel.java b/src/jalview/datamodel/RnaViewerModel.java
new file mode 100644 (file)
index 0000000..33783ec
--- /dev/null
@@ -0,0 +1,46 @@
+package jalview.datamodel;
+
+
+/**
+ * A data bean class to hold properties of an RNA viewer
+ */
+public class RnaViewerModel
+{
+  public final String viewId;
+
+  public final String title;
+
+  public final int x;
+
+  public final int y;
+
+  public final int width;
+
+  public final int height;
+
+  public final int dividerLocation;
+
+  /**
+   * Constructor
+   * 
+   * @param viewId
+   * @param title
+   * @param xpos
+   * @param ypos
+   * @param width
+   * @param height
+   * @param dividerLocation
+   */
+  public RnaViewerModel(String viewId, String title, int xpos, int ypos,
+          int width,
+ int height, int dividerLocation)
+  {
+    this.viewId = viewId;
+    this.title = title;
+    this.x = xpos;
+    this.y = ypos;
+    this.width = width;
+    this.height = height;
+    this.dividerLocation = dividerLocation;
+  }
+}
index 3f890ba..9c9447e 100644 (file)
  */
 package jalview.datamodel.xdb.embl;
 
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.Vector;
-
 import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.DBRefSource;
 import jalview.datamodel.FeatureProperties;
@@ -33,6 +28,10 @@ import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 
+import java.util.Hashtable;
+import java.util.Map.Entry;
+import java.util.Vector;
+
 /**
  * Data model for one entry returned from an EMBL query, as marshalled by a
  * Castor binding file
@@ -397,7 +396,7 @@ public class EmblEntry
           boolean noPeptide, String sourceDb)
   { // TODO: ensure emblEntry.getSequences behaves correctly for returning all
     // cases of noNa and noPeptide
-    Vector seqs = new Vector();
+    Vector<SequenceI> seqs = new Vector<SequenceI>();
     Sequence dna = null;
     if (!noNa)
     {
@@ -415,26 +414,23 @@ public class EmblEntry
       // TODO: transform EMBL Database refs to canonical form
       if (dbRefs != null)
       {
-        for (Iterator i = dbRefs.iterator(); i.hasNext(); dna
-                .addDBRef((DBRefEntry) i.next()))
+        for (DBRefEntry dbref : dbRefs)
         {
-          ;
+          dna.addDBRef(dbref);
         }
       }
     }
     try
     {
-      for (Iterator i = features.iterator(); i.hasNext();)
+      for (EmblFeature feature: features)
       {
-        EmblFeature feature = (EmblFeature) i.next();
         if (!noNa)
         {
-          if (feature.dbRefs != null && feature.dbRefs.size() > 0)
+          if (feature.dbRefs != null)
           {
-            for (Iterator dbr = feature.dbRefs.iterator(); dbr.hasNext(); dna
-                    .addDBRef((DBRefEntry) dbr.next()))
+            for (DBRefEntry dbref : feature.dbRefs)
             {
-              ;
+              dna.addDBRef(dbref);
             }
           }
         }
@@ -445,14 +441,14 @@ public class EmblEntry
         else
         {
           // General feature type.
+          // TODO this is just duplicated code ??
           if (!noNa)
           {
-            if (feature.dbRefs != null && feature.dbRefs.size() > 0)
+            if (feature.dbRefs != null)
             {
-              for (Iterator dbr = feature.dbRefs.iterator(); dbr.hasNext(); dna
-                      .addDBRef((DBRefEntry) dbr.next()))
+              for (DBRefEntry dbref : feature.dbRefs)
               {
-                ;
+                dna.addDBRef(dbref);
               }
             }
           }
@@ -474,7 +470,7 @@ public class EmblEntry
     SequenceI[] sqs = new SequenceI[seqs.size()];
     for (int i = 0, j = seqs.size(); i < j; i++)
     {
-      sqs[i] = (SequenceI) seqs.elementAt(i);
+      sqs[i] = seqs.elementAt(i);
       seqs.set(i, null);
     }
     return sqs;
@@ -496,19 +492,16 @@ public class EmblEntry
    *          flag for generation of Peptide sequence objects
    */
   private void parseCodingFeature(EmblFeature feature, String sourceDb,
-          Vector seqs, Sequence dna, boolean noPeptide)
+          Vector<SequenceI> seqs, Sequence dna, boolean noPeptide)
   {
     boolean isEmblCdna = sourceDb.equals(DBRefSource.EMBLCDS);
     // extract coding region(s)
     jalview.datamodel.Mapping map = null;
     int[] exon = null;
-    if (feature.locations != null && feature.locations.size() > 0)
+    if (feature.locations != null)
     {
-      for (Enumeration locs = feature.locations.elements(); locs
-              .hasMoreElements();)
+      for (EmblFeatureLocations loc : feature.locations)
       {
-        EmblFeatureLocations loc = (EmblFeatureLocations) locs
-                .nextElement();
         int[] se = loc.getElementRanges(accession);
         if (exon == null)
         {
@@ -526,19 +519,17 @@ public class EmblEntry
     String prseq = null;
     String prname = new String();
     String prid = null;
-    Hashtable vals = new Hashtable();
+    Hashtable<String, String> vals = new Hashtable<String, String>();
     int prstart = 1;
     // get qualifiers
-    if (feature.getQualifiers() != null
-            && feature.getQualifiers().size() > 0)
+    if (feature.getQualifiers() != null)
     {
-      for (Iterator quals = feature.getQualifiers().iterator(); quals
-              .hasNext();)
+      for (Qualifier q : feature.getQualifiers())
       {
-        Qualifier q = (Qualifier) quals.next();
-        if (q.getName().equals("translation"))
+        String qname = q.getName();
+        if (qname.equals("translation"))
         {
-          StringBuffer prsq = new StringBuffer(q.getValues()[0]);
+          StringBuilder prsq = new StringBuilder(q.getValues()[0]);
           int p = prsq.indexOf(" ");
           while (p > -1)
           {
@@ -549,15 +540,15 @@ public class EmblEntry
           prsq = null;
 
         }
-        else if (q.getName().equals("protein_id"))
+        else if (qname.equals("protein_id"))
         {
           prid = q.getValues()[0];
         }
-        else if (q.getName().equals("codon_start"))
+        else if (qname.equals("codon_start"))
         {
           prstart = Integer.parseInt(q.getValues()[0]);
         }
-        else if (q.getName().equals("product"))
+        else if (qname.equals("product"))
         {
           prname = q.getValues()[0];
         }
@@ -565,7 +556,7 @@ public class EmblEntry
         {
           // throw anything else into the additional properties hash
           String[] s = q.getValues();
-          StringBuffer sb = new StringBuffer();
+          StringBuilder sb = new StringBuilder();
           if (s != null)
           {
             for (int i = 0; i < s.length; i++)
@@ -574,15 +565,15 @@ public class EmblEntry
               sb.append("\n");
             }
           }
-          vals.put(q.getName(), sb.toString());
+          vals.put(qname, sb.toString());
         }
       }
     }
     Sequence product = null;
     DBRefEntry protEMBLCDS = null;
     exon = adjustForPrStart(prstart, exon);
-    boolean noProteinDbref=true;
-    
+    boolean noProteinDbref = true;
+
     if (prseq != null && prname != null && prid != null)
     {
       // extract proteins.
@@ -663,9 +654,9 @@ public class EmblEntry
             protEMBLCDS = new DBRefEntry(pcdnaref);
             protEMBLCDS.setSource(DBRefSource.EMBLCDSProduct);
             product.addDBRef(protEMBLCDS);
-            
-          }     
-          
+
+          }
+
         }
       }
       // add cds feature to dna seq - this may include the stop codon
@@ -676,31 +667,25 @@ public class EmblEntry
         sf.setEnd(exon[xint + 1]);
         sf.setType(feature.getName());
         sf.setFeatureGroup(sourceDb);
-        sf.setDescription("Exon " + (1 + xint / 2)
-                + " for protein '" + prname + "' EMBLCDS:" + prid);
+        sf.setDescription("Exon " + (1 + xint / 2) + " for protein '"
+                + prname + "' EMBLCDS:" + prid);
         sf.setValue(FeatureProperties.EXONPOS, new Integer(1 + xint));
         sf.setValue(FeatureProperties.EXONPRODUCT, prname);
-        if (vals != null && vals.size() > 0)
+        if (vals != null)
         {
-          Enumeration kv = vals.keys();
-          while (kv.hasMoreElements())
+          for (Entry<String, String> val : vals.entrySet())
           {
-            Object key = kv.nextElement();
-            if (key != null)
-            {
-              sf.setValue(key.toString(), vals.get(key));
-            }
+            sf.setValue(val.getKey(), val.getValue());
           }
         }
         dna.addSequenceFeature(sf);
       }
     }
     // add dbRefs to sequence
-    if (feature.dbRefs != null && feature.dbRefs.size() > 0)
+    if (feature.dbRefs != null)
     {
-      for (Iterator dbr = feature.dbRefs.iterator(); dbr.hasNext();)
+      for (DBRefEntry ref : feature.dbRefs)
       {
-        DBRefEntry ref = (DBRefEntry) dbr.next();
         ref.setSource(jalview.util.DBRefUtils.getCanonicalName(ref
                 .getSource()));
         // Hard code the kind of protein product accessions that EMBL cite
@@ -755,7 +740,7 @@ public class EmblEntry
                   .setMap(new Mapping(product, map.getMap().getInverse()));
         }
         product.addDBRef(protEMBLCDS);
-          
+
         // Add converse mapping reference
         if (map != null)
         {
diff --git a/src/jalview/ext/varna/RnaModel.java b/src/jalview/ext/varna/RnaModel.java
new file mode 100644 (file)
index 0000000..b39ea94
--- /dev/null
@@ -0,0 +1,32 @@
+package jalview.ext.varna;
+
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.SequenceI;
+
+import fr.orsay.lri.varna.models.rna.RNA;
+
+/**
+ * Data bean wrapping the data items that define one RNA view
+ */
+public class RnaModel
+{
+  public final String title;
+
+  public final AlignmentAnnotation ann;
+
+  public final SequenceI seq;
+
+  public final boolean gapped;
+
+  public final RNA rna;
+
+  public RnaModel(String t, AlignmentAnnotation aa, SequenceI s, RNA r,
+          boolean g)
+  {
+    title = t;
+    ann = aa;
+    seq = s;
+    rna = r;
+    gapped = g;
+  }
+}
\ No newline at end of file
index 8144738..68d7397 100644 (file)
@@ -4861,7 +4861,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
             // temporary flag until SplitFrame is released
             boolean asSplitFrame = Cache.getDefault(
-                    Preferences.ENABLE_SPLIT_FRAME, false);
+                    Preferences.ENABLE_SPLIT_FRAME, true);
             if (asSplitFrame)
             {
               /*
@@ -4993,7 +4993,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
               "label.translation_of_params", new Object[]
               { this.getTitle() });
       af.setTitle(newTitle);
-      if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, false))
+      if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true))
       {
         final SequenceI[] seqs = viewport.getSelectionAsNewSequence();
         viewport.openSplitFrame(af, new Alignment(seqs),
index 9eaee20..c18c989 100644 (file)
@@ -799,7 +799,7 @@ public class AlignViewport extends AlignmentViewport implements
      * If any cDNA/protein mappings can be made between the alignments, offer to
      * open a linked alignment with split frame option.
      */
-    if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, false))
+    if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true))
     {
       if (AlignmentUtils.isMappable(al, getAlignment()))
       {
index 5c3785a..dcb2a7d 100644 (file)
  */
 package jalview.gui;
 
+import jalview.analysis.AlignSeq;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.RnaViewerModel;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.ext.varna.RnaModel;
+import jalview.structure.SecondaryStructureListener;
+import jalview.structure.SelectionListener;
+import jalview.structure.SelectionSource;
+import jalview.structure.StructureSelectionManager;
+import jalview.structure.VamsasSource;
+import jalview.util.Comparison;
+import jalview.util.MessageManager;
+import jalview.util.ShiftList;
+
 import java.awt.BorderLayout;
 import java.awt.Color;
-import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Hashtable;
+import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -35,102 +53,165 @@ import javax.swing.event.InternalFrameEvent;
 
 import fr.orsay.lri.varna.VARNAPanel;
 import fr.orsay.lri.varna.exceptions.ExceptionFileFormatOrSyntax;
+import fr.orsay.lri.varna.exceptions.ExceptionLoadingFailed;
 import fr.orsay.lri.varna.exceptions.ExceptionUnmatchedClosingParentheses;
-import fr.orsay.lri.varna.interfaces.InterfaceVARNAListener;
 import fr.orsay.lri.varna.interfaces.InterfaceVARNASelectionListener;
 import fr.orsay.lri.varna.models.BaseList;
-import fr.orsay.lri.varna.models.VARNAConfig;
+import fr.orsay.lri.varna.models.FullBackup;
 import fr.orsay.lri.varna.models.annotations.HighlightRegionAnnotation;
 import fr.orsay.lri.varna.models.rna.ModeleBase;
 import fr.orsay.lri.varna.models.rna.RNA;
 
-import jalview.bin.Cache;
-import jalview.datamodel.ColumnSelection;
-import jalview.datamodel.SequenceGroup;
-import jalview.datamodel.SequenceI;
-import jalview.structure.SecondaryStructureListener;
-import jalview.structure.SelectionListener;
-import jalview.structure.SelectionSource;
-import jalview.structure.StructureSelectionManager;
-import jalview.structure.VamsasSource;
-import jalview.util.MessageManager;
-import jalview.util.ShiftList;
-
-public class AppVarna extends JInternalFrame implements
-        InterfaceVARNAListener, SelectionListener,
-        SecondaryStructureListener// implements
-                                  // Runnable,SequenceStructureBinding,
-                                  // ViewSetProvider
-        , InterfaceVARNASelectionListener, VamsasSource
-
+public class AppVarna extends JInternalFrame implements SelectionListener,
+        SecondaryStructureListener, InterfaceVARNASelectionListener,
+        VamsasSource
 {
-  AppVarnaBinding vab;
+  private static final Pattern PAIRS_PATTERN = Pattern
+          .compile("[^([{<>}])]");
+
+  private AppVarnaBinding vab;
 
-  VARNAPanel varnaPanel;
+  private AlignmentPanel ap;
 
-  public String name;
+  private String viewId;
 
-  public StructureSelectionManager ssm;
+  private StructureSelectionManager ssm;
 
   /*
-   * public AppVarna(){ vab = new AppVarnaBinding(); initVarna(); }
+   * Lookup for sequence and annotation mapped to each RNA in the viewer. Using
+   * a linked hashmap means that order is preserved when saved to the project.
    */
+  private Map<RNA, RnaModel> models = new LinkedHashMap<RNA, RnaModel>();
 
-  AlignmentPanel ap;
+  private Map<RNA, ShiftList> offsets = new Hashtable<RNA, ShiftList>();
 
-  public AppVarna(String sname, SequenceI seq, String strucseq,
-          String struc, String name, AlignmentPanel ap)
+  private Map<RNA, ShiftList> offsetsInv = new Hashtable<RNA, ShiftList>();
+
+  private JSplitPane split;
+
+  private VarnaHighlighter mouseOverHighlighter = new VarnaHighlighter();
+
+  private VarnaHighlighter selectionHighlighter = new VarnaHighlighter();
+
+  private class VarnaHighlighter
   {
+    private HighlightRegionAnnotation _lastHighlight;
 
-    // System.out.println("1:"+sname);
-    // System.out.println("2:"+seq);
-    // System.out.println("3:"+strucseq);
-    // System.out.println("4:"+struc);
-    // System.out.println("5:"+name);
-    // System.out.println("6:"+ap);
-    this.ap = ap;
-    ArrayList<RNA> rnaList = new ArrayList<RNA>();
-    RNA rna1 = new RNA(name);
-    try
+    private RNA _lastRNAhighlighted = null;
+
+    public VarnaHighlighter()
     {
 
-      rna1.setRNA(strucseq, replaceOddGaps(struc));
-      // System.out.println("The sequence is :"+rna1.getSeq());
-      // System.out.println("The sequence is:"+struc);
-      // System.out.println("The sequence is:"+replaceOddGaps(struc).toString());
-    } catch (ExceptionUnmatchedClosingParentheses e2)
+    }
+
+    /**
+     * Constructor when restoring from Varna session, including any highlight
+     * state
+     * 
+     * @param rna
+     */
+    public VarnaHighlighter(RNA rna)
     {
-      e2.printStackTrace();
-    } catch (ExceptionFileFormatOrSyntax e3)
+      // TODO nice try but doesn't work; do we need a highlighter per model?
+      _lastRNAhighlighted = rna;
+      List<HighlightRegionAnnotation> highlights = rna.getHighlightRegion();
+      if (highlights != null && !highlights.isEmpty())
+      {
+        _lastHighlight = highlights.get(0);
+      }
+    }
+
+    public void highlightRegion(RNA rna, int start, int end)
     {
-      e3.printStackTrace();
+      clearLastSelection();
+      HighlightRegionAnnotation highlight = new HighlightRegionAnnotation(
+              rna.getBasesBetween(start, end));
+      rna.addHighlightRegion(highlight);
+      _lastHighlight = highlight;
+      _lastRNAhighlighted = rna;
     }
-    RNA trim = trimRNA(rna1, "trimmed " + sname);
-    rnaList.add(trim);
-    rnaList.add(rna1);
 
-    rnas.put(seq, rna1);
-    rnas.put(seq, trim);
-    rna1.setName(sname + " (with gaps)");
+    public HighlightRegionAnnotation getLastHighlight()
+    {
+      return _lastHighlight;
+    }
 
+    /**
+     * Clears all structure selection and refreshes the display
+     */
+    public void clearSelection()
     {
-      seqs.put(trim, seq);
-      seqs.put(rna1, seq);
+      if (_lastRNAhighlighted != null)
+      {
+        _lastRNAhighlighted.getHighlightRegion().clear();
+        vab.updateSelectedRNA(_lastRNAhighlighted);
+        _lastRNAhighlighted = null;
+        _lastHighlight = null;
+      }
+    }
 
-      /**
-       * if (false || seq.getStart()!=1) { for (RNA rshift:rnaList) { ShiftList
-       * shift=offsets.get(rshift); if (shift==null) { offsets.put(rshift,
-       * shift=new ShiftList());} shift.addShift(1, seq.getStart()-1);
-       * offsetsInv.put(rshift, shift.getInverse()); } }
-       **/
+    /**
+     * Clear the last structure selection
+     */
+    public void clearLastSelection()
+    {
+      if (_lastRNAhighlighted != null)
+      {
+        _lastRNAhighlighted.removeHighlightRegion(_lastHighlight);
+        _lastRNAhighlighted = null;
+        _lastHighlight = null;
+      }
     }
-    vab = new AppVarnaBinding(rnaList);
-    // vab = new AppVarnaBinding(seq,struc);
-    this.name = sname + " trimmed to " + name;
+  }
+
+  /**
+   * Constructor
+   * 
+   * @param seq
+   *          the RNA sequence
+   * @param aa
+   *          the annotation with the secondary structure string
+   * @param ap
+   *          the AlignmentPanel creating this object
+   */
+  public AppVarna(SequenceI seq, AlignmentAnnotation aa, AlignmentPanel ap)
+  {
+    this(ap);
+
+    String sname = aa.sequenceRef == null ? "secondary structure (alignment)"
+            : seq.getName() + " structure";
+    String theTitle = sname
+            + (aa.sequenceRef == null ? " trimmed to " + seq.getName() : "");
+    theTitle = MessageManager.formatMessage("label.varna_params",
+            new String[]
+            { theTitle });
+    setTitle(theTitle);
+
+    String gappedTitle = sname + " (with gaps)";
+    RnaModel gappedModel = new RnaModel(gappedTitle, aa, seq, null, true);
+    addModel(gappedModel, gappedTitle);
+
+    String trimmedTitle = "trimmed " + sname;
+    RnaModel trimmedModel = new RnaModel(trimmedTitle, aa, seq, null, false);
+    addModel(trimmedModel, trimmedTitle);
+    vab.setSelectedIndex(0);
+  }
+
+
+  /**
+   * Constructor that links the viewer to a parent panel (but has no structures
+   * yet - use addModel to add them)
+   * 
+   * @param ap
+   */
+  protected AppVarna(AlignmentPanel ap)
+  {
+    this.ap = ap;
+    this.viewId = System.currentTimeMillis() + "." + this.hashCode();
+    vab = new AppVarnaBinding();
     initVarna();
 
-    ssm = ap.getStructureSelectionManager();
-    // System.out.println(ssm.toString());
+    this.ssm = ap.getStructureSelectionManager();
     ssm.addStructureViewerListener(this);
     ssm.addSelectionListener(this);
     addInternalFrameListener(new InternalFrameAdapter()
@@ -141,40 +222,59 @@ public class AppVarna extends JInternalFrame implements
         close();
       }
     });
+  }
 
+  /**
+   * Constructor given viewer data read from a saved project file
+   * 
+   * @param model
+   * @param ap
+   *          the (or a) parent alignment panel
+   */
+  public AppVarna(RnaViewerModel model, AlignmentPanel ap)
+  {
+    this(ap);
+    setTitle(model.title);
+    this.viewId = model.viewId;
+    setBounds(model.x, model.y, model.width, model.height);
+    this.split.setDividerLocation(model.dividerLocation);
   }
 
+  /**
+   * Constructs a split pane with an empty selection list and display panel, and
+   * adds it to the desktop
+   */
   public void initVarna()
   {
-
-    // vab.setFinishedInit(false);
-    varnaPanel = vab.get_varnaPanel();
+    VARNAPanel varnaPanel = vab.get_varnaPanel();
     setBackground(Color.white);
-    JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true,
+    split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true,
             vab.getListPanel(), varnaPanel);
     getContentPane().setLayout(new BorderLayout());
     getContentPane().add(split, BorderLayout.CENTER);
-    // getContentPane().add(vab.getTools(), BorderLayout.NORTH);
-    varnaPanel.addVARNAListener(this);
+
     varnaPanel.addSelectionListener(this);
-    jalview.gui.Desktop.addInternalFrame(this,
-            MessageManager.formatMessage("label.varna_params", new String[]
-            { name }), getBounds().width, getBounds().height);
+    jalview.gui.Desktop.addInternalFrame(this, "", getBounds().width,
+            getBounds().height);
     this.pack();
     showPanel(true);
-
   }
 
   public String replaceOddGaps(String oldStr)
   {
-    String patternStr = "[^([{<>}])]";
-    String replacementStr = ".";
-    Pattern pattern = Pattern.compile(patternStr);
-    Matcher matcher = pattern.matcher(oldStr);
-    String newStr = matcher.replaceAll(replacementStr);
+    Matcher matcher = PAIRS_PATTERN.matcher(oldStr);
+    String newStr = matcher.replaceAll(".");
     return newStr;
   }
 
+  /**
+   * Constructs a new RNA model from the given one, without gaps. Also
+   * calculates and saves a 'shift list'
+   * 
+   * @param rna
+   * @param name
+   * @return
+   */
   public RNA trimRNA(RNA rna, String name)
   {
     ShiftList offset = new ShiftList();
@@ -191,19 +291,23 @@ public class AppVarna extends JInternalFrame implements
       e3.printStackTrace();
     }
 
-    StringBuffer seq = new StringBuffer(rnaTrim.getSeq());
-    StringBuffer struc = new StringBuffer(rnaTrim.getStructDBN());
-    int ofstart = -1, sleng = rnaTrim.getSeq().length();
+    String seq = rnaTrim.getSeq();
+    StringBuilder struc = new StringBuilder(256);
+    struc.append(rnaTrim.getStructDBN());
+    int ofstart = -1;
+    int sleng = seq.length();
+
     for (int i = 0; i < sleng; i++)
     {
-      // TODO: Jalview utility for gap detection java.utils.isGap()
-      // TODO: Switch to jalview rna datamodel
-      if (jalview.util.Comparison.isGap(seq.charAt(i)))
+      if (Comparison.isGap(seq.charAt(i)))
       {
         if (ofstart == -1)
         {
           ofstart = i;
         }
+        /*
+         * mark base or base pair in the structure with *
+         */
         if (!rnaTrim.findPair(i).isEmpty())
         {
           int m = rnaTrim.findPair(i).get(1);
@@ -232,35 +336,37 @@ public class AppVarna extends JInternalFrame implements
       offset.addShift(offset.shift(ofstart), ofstart - sleng);
       ofstart = -1;
     }
-    String newSeq = rnaTrim.getSeq().replace("-", "");
-    rnaTrim.getSeq().replace(".", "");
+
+    /*
+     * remove the marked gaps from the structure
+     */
     String newStruc = struc.toString().replace("*", "");
 
+    /*
+     * remove gaps from the sequence
+     */
+    String newSeq = AlignSeq.extractGaps(Comparison.GapChars, seq);
+
     try
     {
       rnaTrim.setRNA(newSeq, newStruc);
       registerOffset(rnaTrim, offset);
     } catch (ExceptionUnmatchedClosingParentheses e)
     {
-      // TODO Auto-generated catch block
       e.printStackTrace();
     } catch (ExceptionFileFormatOrSyntax e)
     {
-      // TODO Auto-generated catch block
       e.printStackTrace();
     }
     return rnaTrim;
   }
 
-  // needs to be many-many
-  Map<RNA, SequenceI> seqs = new Hashtable<RNA, SequenceI>();
-
-  Map<SequenceI, RNA> rnas = new Hashtable<SequenceI, RNA>();
-
-  Map<RNA, ShiftList> offsets = new Hashtable<RNA, ShiftList>();
-
-  Map<RNA, ShiftList> offsetsInv = new Hashtable<RNA, ShiftList>();
-
+  /**
+   * Save the sequence to structure mapping, and also its inverse.
+   * 
+   * @param rnaTrim
+   * @param offset
+   */
   private void registerOffset(RNA rnaTrim, ShiftList offset)
   {
     offsets.put(rnaTrim, offset);
@@ -272,115 +378,37 @@ public class AppVarna extends JInternalFrame implements
     this.setVisible(show);
   }
 
-  private boolean _started = false;
-
-  public void run()
-  {
-    _started = true;
-
-    try
-    {
-      initVarna();
-    } catch (OutOfMemoryError oomerror)
-    {
-      new OOMWarning("When trying to open the Varna viewer!", oomerror);
-    } catch (Exception ex)
-    {
-      Cache.log.error("Couldn't open Varna viewer!", ex);
-    }
-  }
-
-  @Override
-  public void onUINewStructure(VARNAConfig v, RNA r)
-  {
-
-  }
-
-  @Override
-  public void onWarningEmitted(String s)
-  {
-    // TODO Auto-generated method stub
-
-  }
-
-  private class VarnaHighlighter
-  {
-    private HighlightRegionAnnotation _lastHighlight;
-
-    private RNA _lastRNAhighlighted = null;
-
-    public void highlightRegion(RNA rna, int start, int end)
-    {
-      clearSelection(null);
-      HighlightRegionAnnotation highlight = new HighlightRegionAnnotation(
-              rna.getBasesBetween(start, end));
-      rna.addHighlightRegion(highlight);
-      _lastHighlight = highlight;
-      _lastRNAhighlighted = rna;
-
-    }
-
-    public HighlightRegionAnnotation getLastHighlight()
-    {
-      return _lastHighlight;
-    }
-
-    public RNA getLastRNA()
-    {
-      return _lastRNAhighlighted;
-    }
-
-    public void clearSelection(AppVarnaBinding vab)
-    {
-      if (_lastRNAhighlighted != null)
-      {
-        _lastRNAhighlighted.removeHighlightRegion(_lastHighlight);
-        if (vab != null)
-        {
-          vab.updateSelectedRNA(_lastRNAhighlighted);
-        }
-        _lastRNAhighlighted = null;
-        _lastHighlight = null;
-
-      }
-    }
-  }
-
-  VarnaHighlighter mouseOverHighlighter = new VarnaHighlighter(),
-          selectionHighlighter = new VarnaHighlighter();
-
   /**
    * If a mouseOver event from the AlignmentPanel is noticed the currently
    * selected RNA in the VARNA window is highlighted at the specific position.
    * To be able to remove it before the next highlight it is saved in
    * _lastHighlight
+   * 
+   * @param sequence
+   * @param index
+   *          the aligned sequence position (base 0)
+   * @param position
+   *          the dataset sequence position (base 1)
    */
   @Override
-  public void mouseOverSequence(SequenceI sequence, int index)
+  public void mouseOverSequence(SequenceI sequence, final int index,
+          final int position)
   {
     RNA rna = vab.getSelectedRNA();
-    if (seqs.get(rna) == sequence)
+    if (rna == null)
     {
-      ShiftList shift = offsets.get(rna);
-      if (shift != null)
-      {
-        // System.err.print("Orig pos:"+index);
-        index = shift.shift(index);
-        // System.err.println("\nFinal pos:"+index);
-      }
-      mouseOverHighlighter.highlightRegion(rna, index, index);
+      return;
+    }
+    RnaModel rnaModel = models.get(rna);
+    if (rnaModel.seq == sequence)
+    {
+      int highlightPos = rnaModel.gapped ? index : position - 1;
+      mouseOverHighlighter.highlightRegion(rna, highlightPos, highlightPos);
       vab.updateSelectedRNA(rna);
     }
   }
 
   @Override
-  public void onStructureRedrawn()
-  {
-    // TODO Auto-generated method stub
-
-  }
-
-  @Override
   public void selection(SequenceGroup seqsel, ColumnSelection colsel,
           SelectionSource source)
   {
@@ -390,10 +418,14 @@ public class AppVarna extends JInternalFrame implements
       // TODO - reuse many-one panel-view system in jmol viewer
       return;
     }
+    RNA rna = vab.getSelectedRNA();
+    if (rna == null)
+    {
+      return;
+    }
     if (seqsel != null && seqsel.getSize() > 0)
     {
       int start = seqsel.getStartRes(), end = seqsel.getEndRes();
-      RNA rna = vab.getSelectedRNA();
       ShiftList shift = offsets.get(rna);
       if (shift != null)
       {
@@ -408,27 +440,30 @@ public class AppVarna extends JInternalFrame implements
     }
     else
     {
-      selectionHighlighter.clearSelection(vab);
+      selectionHighlighter.clearSelection();
     }
   }
 
+  /**
+   * Respond to a change of the base hovered over in the Varna viewer
+   */
   @Override
-  public void onHoverChanged(ModeleBase arg0, ModeleBase arg1)
+  public void onHoverChanged(ModeleBase previousBase, ModeleBase newBase)
   {
     RNA rna = vab.getSelectedRNA();
     ShiftList shift = offsetsInv.get(rna);
-    SequenceI seq = seqs.get(rna);
-    if (arg1 != null && seq != null)
+    SequenceI seq = models.get(rna).seq;
+    if (newBase != null && seq != null)
     {
       if (shift != null)
       {
-        int i = shift.shift(arg1.getIndex());
+        int i = shift.shift(newBase.getIndex());
         // System.err.println("shifted "+(arg1.getIndex())+" to "+i);
         ssm.mouseOverVamsasSequence(seq, i, this);
       }
       else
       {
-        ssm.mouseOverVamsasSequence(seq, arg1.getIndex(), this);
+        ssm.mouseOverVamsasSequence(seq, newBase.getIndex(), this);
       }
     }
   }
@@ -441,18 +476,56 @@ public class AppVarna extends JInternalFrame implements
 
   }
 
-  @Override
-  public void onTranslationChanged()
+  /**
+   * Returns the path to a temporary file containing a representation of the
+   * state of one Varna display
+   * 
+   * @param rna
+   * 
+   * @return
+   */
+  public String getStateInfo(RNA rna)
   {
-    // TODO Auto-generated method stub
+    return vab.getStateInfo(rna);
+  }
 
+  public AlignmentPanel getAlignmentPanel()
+  {
+    return ap;
   }
 
-  @Override
-  public void onZoomLevelChanged()
+  public String getViewId()
   {
-    // TODO Auto-generated method stub
+    return viewId;
+  }
 
+  /**
+   * Returns true if any of the viewer's models (not necessarily the one
+   * currently displayed) is for the given sequence
+   * 
+   * @param seq
+   * @return
+   */
+  public boolean isListeningFor(SequenceI seq)
+  {
+    for (RnaModel model : models.values())
+    {
+      if (model.seq == seq)
+      {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Returns a value representing the horizontal split divider location
+   * 
+   * @return
+   */
+  public int getDividerLocation()
+  {
+    return split == null ? 0 : split.getDividerLocation();
   }
 
   /**
@@ -461,7 +534,7 @@ public class AppVarna extends JInternalFrame implements
   protected void close()
   {
     /*
-     * Deregister as a listener, to free references to this object
+     * Deregister as a listener, to release references to this object
      */
     if (ssm != null)
     {
@@ -470,4 +543,184 @@ public class AppVarna extends JInternalFrame implements
     }
   }
 
+  /**
+   * Returns the secondary structure annotation that this viewer displays for
+   * the given sequence
+   * 
+   * @return
+   */
+  public AlignmentAnnotation getAnnotation(SequenceI seq)
+  {
+    for (RnaModel model : models.values())
+    {
+      if (model.seq == seq)
+      {
+        return model.ann;
+      }
+    }
+    return null;
+  }
+
+  public int getSelectedIndex()
+  {
+    return this.vab.getSelectedIndex();
+  }
+
+  /**
+   * Returns the set of models shown by the viewer
+   * 
+   * @return
+   */
+  public Collection<RnaModel> getModels()
+  {
+    return models.values();
+  }
+
+  /**
+   * Add a model (e.g. loaded from project file)
+   * 
+   * @param rna
+   * @param modelName
+   */
+  public RNA addModel(RnaModel model, String modelName)
+  {
+    if (!model.ann.isValidStruc())
+    {
+      throw new IllegalArgumentException("Invalid RNA structure annotation");
+    }
+
+    /*
+     * opened on request in Jalview session
+     */
+    RNA rna = new RNA(modelName);
+    String struc = model.ann.getRNAStruc();
+    struc = replaceOddGaps(struc);
+
+    String strucseq = model.seq.getSequenceAsString();
+    try
+    {
+      rna.setRNA(strucseq, struc);
+    } catch (ExceptionUnmatchedClosingParentheses e2)
+    {
+      e2.printStackTrace();
+    } catch (ExceptionFileFormatOrSyntax e3)
+    {
+      e3.printStackTrace();
+    }
+
+    if (!model.gapped)
+    {
+      rna = trimRNA(rna, modelName);
+    }
+    models.put(rna, new RnaModel(modelName, model.ann, model.seq, rna,
+            model.gapped));
+    vab.addStructure(rna);
+    return rna;
+  }
+
+  /**
+   * Constructs a shift list that describes the gaps in the sequence
+   * 
+   * @param seq
+   * @return
+   */
+  protected ShiftList buildOffset(SequenceI seq)
+  {
+    // TODO refactor to avoid duplication with trimRNA()
+    // TODO JAL-1789 bugs in use of ShiftList here
+    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 (ofstart == -1)
+        {
+          ofstart = i;
+        }
+      }
+      else
+      {
+        if (ofstart > -1)
+        {
+          offset.addShift(offset.shift(ofstart), ofstart - i);
+          ofstart = -1;
+        }
+      }
+    }
+    // final gap
+    if (ofstart > -1)
+    {
+      offset.addShift(offset.shift(ofstart), ofstart - sleng);
+      ofstart = -1;
+    }
+    return offset;
+  }
+
+  /**
+   * Set the selected index in the model selection list
+   * 
+   * @param selectedIndex
+   */
+  public void setInitialSelection(final int selectedIndex)
+  {
+    /*
+     * empirically it needs a second for Varna/AWT to finish loading/drawing
+     * models for this to work; SwingUtilities.invokeLater _not_ a solution;
+     * explanation and/or better solution welcome!
+     */
+    synchronized (this)
+    {
+      try
+      {
+        wait(1000);
+      } catch (InterruptedException e)
+      {
+        // meh
+      }
+    }
+    vab.setSelectedIndex(selectedIndex);
+  }
+
+
+  /**
+   * Add a model with associated Varna session file
+   * 
+   * @param rna
+   * @param modelName
+   */
+  public RNA addModelSession(RnaModel model, String modelName,
+          String sessionFile)
+  {
+    if (!model.ann.isValidStruc())
+    {
+      throw new IllegalArgumentException("Invalid RNA structure annotation");
+    }
+
+    try
+    {
+      FullBackup fromSession = vab.vp.loadSession(sessionFile);
+      vab.addStructure(fromSession.rna, fromSession.config);
+      RNA rna = fromSession.rna;
+      // copy the model, but now including the RNA object
+      RnaModel newModel = new RnaModel(model.title, model.ann, model.seq,
+              rna, model.gapped);
+      if (!model.gapped)
+      {
+        registerOffset(rna, buildOffset(model.seq));
+      }
+      models.put(rna, newModel);
+      // capture rna selection state when saved
+      selectionHighlighter = new VarnaHighlighter(rna);
+      return fromSession.rna;
+    } catch (ExceptionLoadingFailed e)
+    {
+      System.err
+              .println("Error restoring Varna session: " + e.getMessage());
+      return null;
+    }
+  }
 }
index 38385f0..25af7d1 100644 (file)
  */
 package jalview.gui;
 
+import jalview.datamodel.SequenceI;
+import jalview.ext.varna.JalviewVarnaBinding;
+import jalview.structure.AtomSpec;
+import jalview.util.MessageManager;
+
 import java.awt.BorderLayout;
 import java.awt.Color;
 import java.awt.Component;
 import java.awt.Dimension;
-import java.awt.Font;
-import java.awt.GridLayout;
 import java.awt.datatransfer.DataFlavor;
 import java.awt.datatransfer.Transferable;
 import java.awt.dnd.DnDConstants;
 import java.awt.dnd.DropTarget;
-import java.awt.dnd.DropTargetDragEvent;
+import java.awt.dnd.DropTargetAdapter;
 import java.awt.dnd.DropTargetDropEvent;
-import java.awt.dnd.DropTargetEvent;
-import java.awt.dnd.DropTargetListener;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.awt.event.ComponentEvent;
+import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
-import java.awt.event.MouseListener;
 import java.io.File;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
 import javax.swing.DefaultListModel;
 import javax.swing.DefaultListSelectionModel;
-import javax.swing.JButton;
 import javax.swing.JLabel;
 import javax.swing.JList;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
-import javax.swing.JTextField;
 import javax.swing.ListModel;
 import javax.swing.ListSelectionModel;
 import javax.swing.event.ListSelectionEvent;
@@ -59,70 +57,17 @@ import javax.swing.event.ListSelectionListener;
 
 import fr.orsay.lri.varna.VARNAPanel;
 import fr.orsay.lri.varna.components.ReorderableJList;
-import fr.orsay.lri.varna.exceptions.ExceptionFileFormatOrSyntax;
 import fr.orsay.lri.varna.exceptions.ExceptionLoadingFailed;
+import fr.orsay.lri.varna.exceptions.ExceptionNAViewAlgorithm;
 import fr.orsay.lri.varna.exceptions.ExceptionNonEqualLength;
-import fr.orsay.lri.varna.exceptions.ExceptionUnmatchedClosingParentheses;
-import fr.orsay.lri.varna.interfaces.InterfaceVARNAListener;
 import fr.orsay.lri.varna.models.FullBackup;
 import fr.orsay.lri.varna.models.VARNAConfig;
-import fr.orsay.lri.varna.models.rna.Mapping;
 import fr.orsay.lri.varna.models.rna.RNA;
 
-import jalview.datamodel.SequenceI;
-import jalview.structure.AtomSpec;
-import jalview.util.MessageManager;
-
-public class AppVarnaBinding extends jalview.ext.varna.JalviewVarnaBinding
-        implements DropTargetListener, InterfaceVARNAListener,
-        MouseListener
+public class AppVarnaBinding extends JalviewVarnaBinding
 {
-
-  /**
-        * 
-        */
-  // private static final long serialVersionUID = -790155708306987257L;
-
-  private String DEFAULT_SEQUENCE = "CAGCACGACACUAGCAGUCAGUGUCAGACUGCAIACAGCACGACACUAGCAGUCAGUGUCAGACUGCAIACAGCACGACACUAGCAGUCAGUGUCAGACUGCAIA";
-
-  private String DEFAULT_STRUCTURE1 = "..(((((...(((((...(((((...(((((.....)))))...))))).....(((((...(((((.....)))))...))))).....)))))...)))))..";
-
-  private String DEFAULT_STRUCTURE2 = "..(((((...(((((...(((((........(((((...(((((.....)))))...)))))..................))))).....)))))...)))))..";
-
   public VARNAPanel vp;
 
-  protected JPanel _tools = new JPanel();
-
-  private JPanel _input = new JPanel();
-
-  private JPanel _seqPanel = new JPanel();
-
-  private JPanel _strPanel = new JPanel();
-
-  private JLabel _info = new JLabel();
-
-  private JTextField _str = new JTextField();
-
-  private JTextField _seq = new JTextField();
-
-  private JLabel _strLabel = new JLabel(
-          MessageManager.getString("label.str"));
-
-  private JLabel _seqLabel = new JLabel(
-          MessageManager.getString("label.seq"));
-
-  private JButton _createButton = new JButton(
-          MessageManager.getString("action.create"));
-
-  private JButton _updateButton = new JButton(
-          MessageManager.getString("action.update"));
-
-  private JButton _deleteButton = new JButton(
-          MessageManager.getString("action.delete"));
-
-  private JButton _duplicateButton = new JButton(
-          MessageManager.getString("action.snapshot"));
-
   protected JPanel _listPanel = new JPanel();
 
   private ReorderableJList _sideList = null;
@@ -141,32 +86,23 @@ public class AppVarnaBinding extends jalview.ext.varna.JalviewVarnaBinding
 
   private BackupHolder _rnaList;
 
-  /*
-   * public AppVarnaBinding() { //super("VARNA in Jalview");
-   * //this.set_seq("ATGC"); //this.set_str(".()."); //RNAPanelDemoInit();
-   * 
-   * //initVarna("ATGCATGATATATATATAT","....((((...))))....");
-   * initVarna(this.DEFAULT_SEQUENCE,this.DEFAULT_STRUCTURE1); }
+  /**
+   * Constructor
    */
-
-  public AppVarnaBinding(String seq, String struc)
-  {
-    // super("VARNA in Jalview");
-    initVarna(seq, struc);
-
-  }
-
-  public AppVarnaBinding(ArrayList<RNA> rnaList)
+  public AppVarnaBinding()
   {
-
-    // super("VARNA in Jalview");
-    initVarnaEdit(rnaList);
+    init();
   }
 
-  private void initVarna(String seq, String str)
+  /**
+   * Constructs the VARNAPanel and an (empty) selection list of structures to
+   * show in it
+   */
+  private void init()
   {
+    DefaultListModel<FullBackup> dlm = new DefaultListModel<FullBackup>();
 
-    DefaultListModel dlm = new DefaultListModel();
+    int marginTools = 40;
 
     DefaultListSelectionModel m = new DefaultListSelectionModel();
     m.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
@@ -174,212 +110,53 @@ public class AppVarnaBinding extends jalview.ext.varna.JalviewVarnaBinding
 
     _sideList = new ReorderableJList();
     _sideList.setModel(dlm);
-    _sideList.addMouseListener(this);
-    _sideList.setSelectionModel(m);
-    _sideList.setPreferredSize(new Dimension(100, 0));
-    _sideList.addListSelectionListener(new ListSelectionListener()
+    _sideList.addMouseListener(new MouseAdapter()
     {
-      public void valueChanged(ListSelectionEvent arg0)
-      {
-        if (!_sideList.isSelectionEmpty() && !arg0.getValueIsAdjusting())
-        {
-          FullBackup sel = (FullBackup) _sideList.getSelectedValue();
-          Mapping map = Mapping.DefaultOutermostMapping(vp.getRNA()
-                  .getSize(), sel.rna.getSize());
-          vp.showRNAInterpolated(sel.rna, sel.config, map);
-          _seq.setText(sel.rna.getSeq());
-          _str.setText(sel.rna.getStructDBN());
-        }
+      @Override
+      public void mouseClicked(MouseEvent e) {
+        AppVarnaBinding.this.mouseClicked(e);
       }
     });
-
-    _rnaList = new BackupHolder(dlm, _sideList);
-    RNA _RNA1 = new RNA("User defined 1");
-
-    try
-    {
-
-      vp = new VARNAPanel("0", ".");
-      _RNA1.setRNA(seq, str);
-      _RNA1.drawRNARadiate(vp.getConfig());
-    } catch (ExceptionNonEqualLength e)
-    {
-      vp.errorDialog(e);
-    } catch (ExceptionUnmatchedClosingParentheses e2)
-    {
-      e2.printStackTrace();
-    } catch (ExceptionFileFormatOrSyntax e3)
-    {
-      e3.printStackTrace();
-    }
-    vp.setPreferredSize(new Dimension(400, 400));
-    _rnaList.add(vp.getConfig().clone(), _RNA1, generateDefaultName(), true);
-
-    // TODO setBackground(_backgroundColor);
-    vp.setBackground(_backgroundColor);
-
-    // TODO getContentPane().setLayout(new BorderLayout());
-    // TODO getContentPane().add(vp, BorderLayout.CENTER);
-
-    // setVisible(true);
-    vp.addVARNAListener(this);
-  }
-
-  private void initVarnaEdit(ArrayList<RNA> rnaInList)
-  {
-
-    DefaultListModel dlm = new DefaultListModel();
-
-    int marginTools = 40;
-
-    DefaultListSelectionModel m = new DefaultListSelectionModel();
-    m.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-    m.setLeadAnchorNotificationEnabled(false);
-
-    _sideList = new ReorderableJList();
-    _sideList.setModel(dlm);
-    _sideList.addMouseListener(this);
     _sideList.setSelectionModel(m);
     _sideList.setPreferredSize(new Dimension(100, 0));
     _sideList.addListSelectionListener(new ListSelectionListener()
     {
-      public void valueChanged(ListSelectionEvent arg0)
+      public void valueChanged(ListSelectionEvent evt)
       {
-        // System.out.println(arg0);
-        if (!_sideList.isSelectionEmpty() && !arg0.getValueIsAdjusting())
-        {
-          FullBackup sel = (FullBackup) _sideList.getSelectedValue();
-          Mapping map = Mapping.DefaultOutermostMapping(vp.getRNA()
-                  .getSize(), sel.rna.getSize());
-          // vp.showRNAInterpolated(sel.rna, sel.config, map);
-          vp.showRNA(sel.rna, sel.config);
-          // _seq.setText(sel.rna.getSeq());
-          _str.setText(sel.rna.getStructDBN());
-        }
+        changeSelectedStructure_actionPerformed(evt);
       }
     });
     _rnaList = new BackupHolder(dlm, _sideList);
 
     try
     {
-
       vp = new VARNAPanel("0", ".");
-      for (int i = 0; i < rnaInList.size(); i++)
-      {
-        rnaInList.get(i).drawRNARadiate(vp.getConfig());
-
-      }
     } catch (ExceptionNonEqualLength e)
     {
       vp.errorDialog(e);
     }
     vp.setPreferredSize(new Dimension(400, 400));
-    for (int i = 0; i < rnaInList.size(); i++)
-    {
-      if (i < rnaInList.size() - 1)
-      {
-        _rnaList.add(vp.getConfig().clone(), rnaInList.get(i), rnaInList
-                .get(i).getName());
-      }
-      else
-      {
-        _rnaList.add(vp.getConfig().clone(), rnaInList.get(i), rnaInList
-                .get(i).getName(), true);
-      }
-    }
-
-    /*
-     * _rnaList.add(vp.getConfig().clone(),_RNA2,generateDefaultName());
-     * _rnaList.add(vp.getConfig().clone(),_RNA1,generateDefaultName(),true);
-     */
 
     JScrollPane listScroller = new JScrollPane(_sideList);
     listScroller.setPreferredSize(new Dimension(150, 0));
 
     vp.setBackground(_backgroundColor);
 
-    Font textFieldsFont = Font.decode("MonoSpaced-PLAIN-12");
-
-    // _seqLabel.setHorizontalTextPosition(JLabel.LEFT);
-    // _seqLabel.setPreferredSize(new Dimension(marginTools, 15));
-    _seq.setFont(textFieldsFont);
-    _seq.setText(rnaInList.get(0).getSeq());
-
-    _updateButton.addActionListener(new ActionListener()
-    {
-      public void actionPerformed(ActionEvent e)
-      {
-        FullBackup sel = (FullBackup) _sideList.getSelectedValue();
-        sel.rna.setSequence("A");
-      }
-    });
-
-    // _seqPanel.setLayout(new BorderLayout());
-    // _seqPanel.add(_seqLabel, BorderLayout.WEST);
-    // _seqPanel.add(_seq, BorderLayout.CENTER);
-
-    _strLabel.setPreferredSize(new Dimension(marginTools, 15));
-    _strLabel.setHorizontalTextPosition(JLabel.LEFT);
-    _str.setFont(textFieldsFont);
-    _strPanel.setLayout(new BorderLayout());
-    _strPanel.add(_strLabel, BorderLayout.WEST);
-    _strPanel.add(_str, BorderLayout.CENTER);
-
-    _input.setLayout(new GridLayout(1, 0));
-    // _input.add(_seqPanel);
-    _input.add(_strPanel);
-
-    JPanel goPanel = new JPanel();
-    goPanel.setLayout(new BorderLayout());
-
-    _tools.setLayout(new BorderLayout());
-    _tools.add(_input, BorderLayout.CENTER);
-    // _tools.add(_info, BorderLayout.SOUTH);
-    _tools.add(goPanel, BorderLayout.EAST);
-
-    /*
-     * _deleteButton.addActionListener(new ActionListener() { public void
-     * actionPerformed(ActionEvent e) { _rnaList.removeSelected(); } });
-     * _duplicateButton.addActionListener(new ActionListener() { public void
-     * actionPerformed(ActionEvent e) {
-     * _rnaList.add((VARNAConfig)vp.getConfig().
-     * clone(),vp.getRNA().clone(),vp.getRNA
-     * ().getName()+"-"+DateFormat.getTimeInstance(DateFormat.LONG).format(new
-     * Date()),true); }});
-     */
-    goPanel.add(_updateButton, BorderLayout.CENTER);
-
-    JPanel ops = new JPanel();
-    ops.setLayout(new GridLayout(1, 2));
-    ops.add(_deleteButton);
-    ops.add(_duplicateButton);
-
     JLabel j = new JLabel(
             MessageManager.getString("label.structures_manager"),
             JLabel.CENTER);
     _listPanel.setLayout(new BorderLayout());
 
-    // _listPanel.add(ops, BorderLayout.SOUTH);
     _listPanel.add(j, BorderLayout.NORTH);
     _listPanel.add(listScroller, BorderLayout.CENTER);
 
-    // JSplitPane split = new
-    // JSplitPane(JSplitPane.HORIZONTAL_SPLIT,true,_listPanel,vp);
-    /**
-     * TODO getContentPane().setLayout(new BorderLayout());
-     * getContentPane().add(split, BorderLayout.CENTER);
-     * getContentPane().add(_tools, BorderLayout.NORTH);
-     */
-
-    // TODO setVisible(true);
-    DropTarget dt = new DropTarget(vp, this);
-
-    vp.addVARNAListener(this);
-  }
-
-  public JPanel getTools()
-  {
-    return _tools;
+    new DropTarget(vp, new DropTargetAdapter() {
+      @Override
+      public void drop(DropTargetDropEvent dtde)
+      {
+        AppVarnaBinding.this.drop(dtde);
+      }
+    });
   }
 
   public JPanel getListPanel()
@@ -388,13 +165,19 @@ public class AppVarnaBinding extends jalview.ext.varna.JalviewVarnaBinding
   }
 
   /**
-   * TODO: Is it effective to transfer the whole RNA?
+   * Returns the currently selected RNA, or null if none selected
    * 
-   * @return Currently selected RNA
+   * @return
    */
   public RNA getSelectedRNA()
   {
-    return _rnaList.getElementAt(_sideList.getSelectedIndex()).rna;
+    int selectedIndex = _sideList.getSelectedIndex();
+    if (selectedIndex < 0)
+    {
+      return null;
+    }
+    FullBackup selected = _rnaList.getElementAt(selectedIndex);
+    return selected.rna;
   }
 
   /**
@@ -408,123 +191,11 @@ public class AppVarnaBinding extends jalview.ext.varna.JalviewVarnaBinding
     vp.showRNA(rnaEdit);
   }
 
-  /*
-   * private void RNAPanelDemoInit() { DefaultListModel dlm = new
-   * DefaultListModel();
-   * 
-   * 
-   * int marginTools = 40;
-   * 
-   * DefaultListSelectionModel m = new DefaultListSelectionModel();
-   * m.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-   * m.setLeadAnchorNotificationEnabled(false);
-   * 
-   * 
-   * _sideList = new ReorderableJList(); _sideList.setModel(dlm);
-   * _sideList.addMouseListener(this); _sideList.setSelectionModel(m);
-   * _sideList.setPreferredSize(new Dimension(100, 0));
-   * _sideList.addListSelectionListener( new ListSelectionListener(){ public
-   * void valueChanged(ListSelectionEvent arg0) { //System.out.println(arg0); if
-   * (!_sideList.isSelectionEmpty() && !arg0.getValueIsAdjusting()) { FullBackup
-   * sel = (FullBackup) _sideList.getSelectedValue(); Mapping map =
-   * Mapping.DefaultOutermostMapping(vp.getRNA().getSize(), sel.rna.getSize());
-   * vp.showRNAInterpolated(sel.rna,sel.config,map);
-   * _seq.setText(sel.rna.getSeq()); _str.setText(sel.rna.getStructDBN()); } }
-   * });
-   * 
-   * _rnaList = new BackupHolder(dlm,_sideList); RNA _RNA1 = new
-   * RNA("User defined 1"); RNA _RNA2 = new RNA("User defined 2"); try { vp =
-   * new VARNAPanel("0","."); _RNA1.setRNA(DEFAULT_SEQUENCE,
-   * DEFAULT_STRUCTURE1); _RNA1.drawRNARadiate(vp.getConfig());
-   * _RNA2.setRNA(DEFAULT_SEQUENCE, DEFAULT_STRUCTURE2);
-   * _RNA2.drawRNARadiate(vp.getConfig()); } catch (ExceptionNonEqualLength e) {
-   * vp.errorDialog(e); } catch (ExceptionUnmatchedClosingParentheses e2) {
-   * e2.printStackTrace(); } catch (ExceptionFileFormatOrSyntax e3) {
-   * e3.printStackTrace(); } vp.setPreferredSize(new Dimension(400, 400));
-   * _rnaList.add(vp.getConfig().clone(),_RNA2,generateDefaultName());
-   * _rnaList.add(vp.getConfig().clone(),_RNA1,generateDefaultName(),true);
-   * 
-   * JScrollPane listScroller = new JScrollPane(_sideList);
-   * listScroller.setPreferredSize(new Dimension(150, 0));
-   * 
-   * setBackground(_backgroundColor); vp.setBackground(_backgroundColor);
-   * 
-   * 
-   * Font textFieldsFont = Font.decode("MonoSpaced-PLAIN-12");
-   * 
-   * _seqLabel.setHorizontalTextPosition(JLabel.LEFT);
-   * _seqLabel.setPreferredSize(new Dimension(marginTools, 15));
-   * _seq.setFont(textFieldsFont); _seq.setText(DEFAULT_SEQUENCE);
-   * 
-   * _createButton.addActionListener(new ActionListener() { public void
-   * actionPerformed(ActionEvent e) { try { RNA nRNA = new
-   * RNA(generateDefaultName()); nRNA.setRNA(_seq.getText(), _str.getText());
-   * nRNA.drawRNARadiate(vp.getConfig()); _rnaList.add(new
-   * VARNAConfig(),nRNA,true); } catch (ExceptionUnmatchedClosingParentheses e1)
-   * { JOptionPane.showMessageDialog(vp, e1.getMessage(),"Error",
-   * JOptionPane.ERROR_MESSAGE); } catch (ExceptionFileFormatOrSyntax e1) {
-   * JOptionPane.showMessageDialog(vp, e1.getMessage(),"Error",
-   * JOptionPane.ERROR_MESSAGE); } } });
-   * 
-   * 
-   * _seqPanel.setLayout(new BorderLayout()); _seqPanel.add(_seqLabel,
-   * BorderLayout.WEST); _seqPanel.add(_seq, BorderLayout.CENTER);
-   * 
-   * _strLabel.setPreferredSize(new Dimension(marginTools, 15));
-   * _strLabel.setHorizontalTextPosition(JLabel.LEFT);
-   * _str.setFont(textFieldsFont); _strPanel.setLayout(new BorderLayout());
-   * _strPanel.add(_strLabel, BorderLayout.WEST); _strPanel.add(_str,
-   * BorderLayout.CENTER);
-   * 
-   * _input.setLayout(new GridLayout(2, 0)); _input.add(_seqPanel);
-   * _input.add(_strPanel);
-   * 
-   * JPanel goPanel = new JPanel(); goPanel.setLayout(new BorderLayout());
-   * 
-   * _tools.setLayout(new BorderLayout()); _tools.add(_input,
-   * BorderLayout.CENTER); _tools.add(_info, BorderLayout.SOUTH);
-   * _tools.add(goPanel, BorderLayout.EAST);
-   * 
-   * _deleteButton.addActionListener(new ActionListener() { public void
-   * actionPerformed(ActionEvent e) { _rnaList.removeSelected(); } });
-   * _duplicateButton.addActionListener(new ActionListener() { public void
-   * actionPerformed(ActionEvent e) {
-   * _rnaList.add((VARNAConfig)vp.getConfig().clone
-   * (),vp.getRNA().clone(),vp.getRNA
-   * ().getName()+"-"+DateFormat.getTimeInstance(DateFormat.LONG).format(new
-   * Date()),true); }});
-   * 
-   * JPanel ops = new JPanel(); ops.setLayout(new GridLayout(1,2));
-   * ops.add(_deleteButton); ops.add(_duplicateButton);
-   * 
-   * JLabel j = new JLabel("Structures Manager",JLabel.CENTER);
-   * _listPanel.setLayout(new BorderLayout());
-   * 
-   * _listPanel.add(ops,BorderLayout.SOUTH);
-   * _listPanel.add(j,BorderLayout.NORTH);
-   * _listPanel.add(listScroller,BorderLayout.CENTER);
-   * 
-   * goPanel.add(_createButton, BorderLayout.CENTER);
-   * 
-   * JSplitPane split = new
-   * JSplitPane(JSplitPane.HORIZONTAL_SPLIT,true,_listPanel,vp);
-   * getContentPane().setLayout(new BorderLayout()); getContentPane().add(split,
-   * BorderLayout.CENTER); getContentPane().add(_tools, BorderLayout.NORTH);
-   * 
-   * setVisible(true); DropTarget dt = new DropTarget(vp, this);
-   * 
-   * vp.addVARNAListener(this); }
-   */
   public static String generateDefaultName()
   {
     return "User file #" + _nextID++;
   }
 
-  public RNA getRNA()
-  {
-    return (RNA) _sideList.getSelectedValue();
-  }
-
   public String[][] getParameterInfo()
   {
     String[][] info =
@@ -537,12 +208,6 @@ public class AppVarnaBinding extends jalview.ext.varna.JalviewVarnaBinding
     return info;
   }
 
-  public void init()
-  {
-    vp.setBackground(_backgroundColor);
-    _error = true;
-  }
-
   @SuppressWarnings("unused")
   private Color getSafeColor(String col, Color def)
   {
@@ -573,60 +238,6 @@ public class AppVarnaBinding extends jalview.ext.varna.JalviewVarnaBinding
     vp = surface;
   }
 
-  public String get_seq()
-  {
-    return _seq.getText();
-  }
-
-  public void set_seq(String _seq)
-  {
-    this._seq.setText(_seq);
-  }
-
-  public String get_str()
-  {
-    return _str.getText();
-  }
-
-  public void set_str(String _str)
-  {
-    this._str.setText(_str);
-  }
-
-  public JLabel get_info()
-  {
-    return _info;
-  }
-
-  public void set_info(JLabel _info)
-  {
-    this._info = _info;
-  }
-
-  /*
-   * public static void main(String[] args) { AppVarnaBinding d = new
-   * AppVarnaBinding(); d.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
-   * d.pack(); d.setVisible(true); }
-   */
-
-  public void dragEnter(DropTargetDragEvent arg0)
-  {
-    // TODO Auto-generated method stub
-
-  }
-
-  public void dragExit(DropTargetEvent arg0)
-  {
-    // TODO Auto-generated method stub
-
-  }
-
-  public void dragOver(DropTargetDragEvent arg0)
-  {
-    // TODO Auto-generated method stub
-
-  }
-
   public void drop(DropTargetDropEvent dtde)
   {
     try
@@ -653,7 +264,7 @@ public class AppVarnaBinding extends jalview.ext.varna.JalviewVarnaBinding
                 if (c instanceof VARNAPanel)
                 {
                   String path = o.toString();
-                  VARNAPanel vp = (VARNAPanel) c;
+                  VARNAPanel varnaPanel = (VARNAPanel) c;
                   try
                   {
                     FullBackup bck = VARNAPanel.importSession(path);
@@ -665,7 +276,7 @@ public class AppVarnaBinding extends jalview.ext.varna.JalviewVarnaBinding
                             .loadSecStr(path);
                     for (RNA r : mdls)
                     {
-                      r.drawRNA(vp.getConfig());
+                      r.drawRNA(varnaPanel.getConfig());
                       String name = r.getName();
                       if (name.equals(""))
                       {
@@ -676,7 +287,7 @@ public class AppVarnaBinding extends jalview.ext.varna.JalviewVarnaBinding
                       {
                         name += " (Model " + mn++ + ")";
                       }
-                      _rnaList.add(vp.getConfig().clone(), r, name, true);
+                      _rnaList.add(varnaPanel.getConfig().clone(), r, name, true);
                     }
                   }
                 }
@@ -698,147 +309,67 @@ public class AppVarnaBinding extends jalview.ext.varna.JalviewVarnaBinding
 
   }
 
-  public void dropActionChanged(DropTargetDragEvent arg0)
-  {
-  }
-
   private class BackupHolder
   {
-    private DefaultListModel _rnaList;
+    private DefaultListModel<FullBackup> _rnalist;
 
-    private ArrayList<RNA> _rnas = new ArrayList<RNA>();
+    private List<RNA> _rnas = new ArrayList<RNA>();
 
     JList _l;
 
-    public BackupHolder(DefaultListModel rnaList, JList l)
+    public BackupHolder(DefaultListModel<FullBackup> rnaList, JList l)
     {
-      _rnaList = rnaList;
+      _rnalist = rnaList;
       _l = l;
     }
 
-    public void add(VARNAConfig c, RNA r)
-    {
-      add(c, r, r.getName(), false);
-    }
-
-    public void add(VARNAConfig c, RNA r, boolean select)
-    {
-      add(c, r, r.getName(), select);
-    }
-
     public void add(VARNAConfig c, RNA r, String name)
     {
       add(c, r, name, false);
     }
 
+    /**
+     * Adds an entry to the end of the selection list and (optionally) sets it
+     * as selected
+     * 
+     * @param c
+     * @param r
+     * @param name
+     * @param select
+     */
     public void add(VARNAConfig c, RNA r, String name, boolean select)
     {
       if (select)
       {
-        _l.removeSelectionInterval(0, _rnaList.size());
+        _l.removeSelectionInterval(0, _rnalist.size());
       }
       if (name.equals(""))
       {
         name = generateDefaultName();
       }
       FullBackup bck = new FullBackup(c, r, name);
-      _rnas.add(0, r);
-      _rnaList.add(0, bck);
+      _rnas.add(r);
+      _rnalist.addElement(bck);
       if (select)
       {
         _l.setSelectedIndex(0);
       }
     }
 
-    public void remove(int i)
-    {
-      _rnas.remove(i);
-      _rnaList.remove(i);
-
-    }
-
-    public DefaultListModel getModel()
-    {
-      return _rnaList;
-    }
-
-    public boolean contains(RNA r)
-    {
-      return _rnas.contains(r);
-    }
-
-    /*
-     * public int getSize() { return _rnaList.getSize(); }
-     */
     public FullBackup getElementAt(int i)
     {
-      return (FullBackup) _rnaList.getElementAt(i);
-    }
-
-    public void removeSelected()
-    {
-      int i = _l.getSelectedIndex();
-      if (i != -1)
-      {
-        if (_rnaList.getSize() == 1)
-        {
-          RNA r = new RNA();
-          try
-          {
-            r.setRNA(" ", ".");
-          } catch (ExceptionUnmatchedClosingParentheses e1)
-          {
-          } catch (ExceptionFileFormatOrSyntax e1)
-          {
-          }
-          vp.showRNA(r);
-          vp.repaint();
-        }
-        else
-        {
-          int newi = i + 1;
-          if (newi == _rnaList.getSize())
-          {
-            newi = _rnaList.getSize() - 2;
-          }
-          FullBackup bck = (FullBackup) _rnaList.getElementAt(newi);
-          _l.setSelectedValue(bck, true);
-        }
-        _rnaList.remove(i);
-      }
-
+      return _rnalist.getElementAt(i);
     }
   }
 
-  public void onLayoutChanged()
-  {
-    // TODO Auto-generated method stub
-
-  }
-
-  public void onUINewStructure(VARNAConfig v, RNA r)
-  {
-    // patch to fix infinite loop
-    // The problem is that onUINewStructure is called when user clicks
-    // check with Yann about whether Jalview should do anything with this event.
-    // e.g. if user has used VARNA's menu to import a structure .. Jalview may
-    // need to be told which structure is displayed.
-
-    // _rnaList.add(v, r, "", true);
-  }
-
-  public void onWarningEmitted(String s)
-  {
-  }
-
   public void mouseClicked(MouseEvent e)
   {
     if (e.getClickCount() == 2)
     {
       int index = _sideList.locationToIndex(e.getPoint());
-      ListModel dlm = _sideList.getModel();
-      FullBackup item = (FullBackup) dlm.getElementAt(index);
-      ;
+      ListModel<FullBackup> dlm = _sideList.getModel();
+      // FullBackup item = dlm.getElementAt(index);
+
       _sideList.ensureIndexIsVisible(index);
       /*
        * TODO Object newName = JOptionPane.showInputDialog( this,
@@ -850,22 +381,6 @@ public class AppVarnaBinding extends jalview.ext.varna.JalviewVarnaBinding
     }
   }
 
-  public void mouseEntered(MouseEvent arg0)
-  {
-  }
-
-  public void mouseExited(MouseEvent arg0)
-  {
-  }
-
-  public void mousePressed(MouseEvent arg0)
-  {
-  }
-
-  public void mouseReleased(MouseEvent arg0)
-  {
-  }
-
   @Override
   public String[] getPdbFile()
   {
@@ -903,28 +418,157 @@ public class AppVarnaBinding extends jalview.ext.varna.JalviewVarnaBinding
   }
 
   @Override
-  public void onStructureRedrawn()
+  public void highlightAtoms(List<AtomSpec> atoms)
   {
   }
 
   @Override
-  public void onZoomLevelChanged()
+  public boolean isListeningFor(SequenceI seq)
   {
+    return true;
   }
 
-  @Override
-  public void onTranslationChanged()
+  /**
+   * Returns the path to a temporary file containing a representation of the
+   * state of the Varna display, or null on any error
+   * 
+   * @param rna
+   * @param jds
+   * 
+   * @return
+   */
+  public String getStateInfo(RNA rna)
   {
+    if (vp == null)
+    {
+      return null;
+    }
+
+    /*
+     * we have to show the RNA we want to save in the viewer; get the currently
+     * displayed model first so we can restore it
+     */
+    FullBackup sel = (FullBackup) _sideList.getSelectedValue();
+
+    FullBackup model = null;
+    ListModel models = _sideList.getModel();
+    for (int i = 0; i < models.getSize(); i++)
+    {
+      model = (FullBackup) models.getElementAt(i);
+      if (model.rna == rna)
+      {
+        break;
+      }
+    }
+    if (model == null)
+    {
+      return null;
+    }
+
+    /*
+     * switch display
+     */
+    vp.showRNA(model.rna, model.config);
+
+    try
+    {
+      File temp;
+      temp = File.createTempFile("varna", null);
+      temp.deleteOnExit();
+      String filePath = temp.getAbsolutePath();
+      vp.toXML(filePath);
+
+      /*
+       * restore the previous display
+       */
+      vp.showRNA(sel.rna, sel.config);
+      
+      return filePath;
+    } catch (IOException e)
+    {
+      return null;
+    }
   }
 
-  @Override
-  public void highlightAtoms(List<AtomSpec> atoms)
+  public int getSelectedIndex()
   {
+    return _sideList.getSelectedIndex();
   }
 
-  @Override
-  public boolean isListeningFor(SequenceI seq)
+  /**
+   * Switch the Varna display to the structure selected in the left hand panel
+   * 
+   * @param evt
+   */
+  protected void changeSelectedStructure_actionPerformed(ListSelectionEvent evt)
   {
-    return true;
+    if (!evt.getValueIsAdjusting())
+    {
+      showSelectedStructure();
+    }
+  }
+
+  /**
+   * 
+   */
+  protected void showSelectedStructure()
+  {
+    FullBackup sel = (FullBackup) _sideList.getSelectedValue();
+    if (sel != null)
+    {
+      vp.showRNA(sel.rna, sel.config);
+    }
+  }
+
+  /**
+   * Set and display the selected item in the list of structures
+   * 
+   * @param selectedRna
+   */
+  public void setSelectedIndex(final int selectedRna)
+  {
+    /*
+     * note this does nothing if, say, selecting item 3 when only 1 has been
+     * added on load
+     */
+    _sideList.setSelectedIndex(selectedRna);
+    // TODO ? need a worker thread to get this to happen properly
+  }
+
+  /**
+   * Add an RNA structure to the selection list
+   * 
+   * @param rna
+   */
+  public void addStructure(RNA rna)
+  {
+    VARNAConfig config = vp.getConfig().clone();
+    addStructure(rna, config);
+  }
+
+  /**
+   * @param rna
+   * @param config
+   */
+  protected void addStructure(final RNA rna, final VARNAConfig config)
+  {
+    drawRna(rna, config);
+    _rnaList.add(config, rna, rna.getName());
+  }
+
+  /**
+   * @param rna
+   * @param config
+   */
+  protected void drawRna(final RNA rna, final VARNAConfig config)
+  {
+    try
+    {
+      rna.drawRNA(rna.getDrawMode(), config);
+    } catch (ExceptionNAViewAlgorithm e)
+    {
+      // only throwable for draw mode = 3 NAView
+      System.err.println("Error drawing RNA: " + e.getMessage());
+    }
   }
 }
index 1e6da78..f644e95 100644 (file)
@@ -1378,11 +1378,10 @@ public class ChimeraViewFrame extends StructureViewerBase
           is.close();
         } catch (IOException e)
         {
-          // ignoreß
+          // ignore
         }
       }
     }
-    // return this.chimeraSessionFile == null ? "" : chimeraSessionFile;
   }
 
   @Override
index e443512..be56292 100644 (file)
  */
 package jalview.gui;
 
-import java.awt.Rectangle;
-import java.io.BufferedReader;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.lang.reflect.InvocationTargetException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.IdentityHashMap;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.StringTokenizer;
-import java.util.Vector;
-import java.util.jar.JarEntry;
-import java.util.jar.JarInputStream;
-import java.util.jar.JarOutputStream;
-
-import javax.swing.JInternalFrame;
-import javax.swing.JOptionPane;
-import javax.swing.SwingUtilities;
-
-import org.exolab.castor.xml.Marshaller;
-import org.exolab.castor.xml.Unmarshaller;
-
 import jalview.api.structures.JalviewStructureDisplayI;
 import jalview.bin.Cache;
 import jalview.datamodel.AlignedCodonFrame;
@@ -66,9 +27,12 @@ import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.PDBEntry;
+import jalview.datamodel.RnaViewerModel;
+import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.datamodel.StructureViewerModel;
 import jalview.datamodel.StructureViewerModel.StructureData;
+import jalview.ext.varna.RnaModel;
 import jalview.gui.StructureViewer.ViewerType;
 import jalview.schemabinding.version2.AlcodMap;
 import jalview.schemabinding.version2.AlcodonFrame;
@@ -92,6 +56,8 @@ import jalview.schemabinding.version2.OtherData;
 import jalview.schemabinding.version2.PdbentryItem;
 import jalview.schemabinding.version2.Pdbids;
 import jalview.schemabinding.version2.Property;
+import jalview.schemabinding.version2.RnaViewer;
+import jalview.schemabinding.version2.SecondaryStructure;
 import jalview.schemabinding.version2.Sequence;
 import jalview.schemabinding.version2.SequenceSet;
 import jalview.schemabinding.version2.SequenceSetProperties;
@@ -123,6 +89,45 @@ import jalview.ws.params.ArgumentI;
 import jalview.ws.params.AutoCalcSetting;
 import jalview.ws.params.WsParamSetI;
 
+import java.awt.Rectangle;
+import java.io.BufferedReader;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+import java.util.jar.JarOutputStream;
+
+import javax.swing.JInternalFrame;
+import javax.swing.JOptionPane;
+import javax.swing.SwingUtilities;
+
+import org.exolab.castor.xml.Marshaller;
+import org.exolab.castor.xml.Unmarshaller;
+
 /**
  * Write out the current jalview desktop state as a Jalview XML stream.
  * 
@@ -135,8 +140,15 @@ import jalview.ws.params.WsParamSetI;
  */
 public class Jalview2XML
 {
+  private static final String VIEWER_PREFIX = "viewer_";
+
+  private static final String RNA_PREFIX = "rna_";
+
   private static final String UTF_8 = "UTF-8";
 
+  // use this with nextCounter() to make unique names for entities
+  private int counter = 0;
+
   /*
    * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
    * of sequence objects are created.
@@ -160,6 +172,12 @@ public class Jalview2XML
    */
   private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<Viewport, AlignFrame>();
 
+  /*
+   * Map from displayed rna structure models to their saved session state jar
+   * entry names
+   */
+  private Map<RnaModel, String> rnaSessions = new HashMap<RnaModel, String>();
+
   /**
    * create/return unique hash string for sq
    * 
@@ -369,7 +387,7 @@ public class Jalview2XML
    */
   public void saveState(JarOutputStream jout)
   {
-    AlignFrame[] frames = Desktop.getAlignFrames(); // Desktop.desktop.getAllFrames();
+    AlignFrame[] frames = Desktop.getAlignFrames();
 
     if (frames == null)
     {
@@ -378,6 +396,13 @@ public class Jalview2XML
 
     Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
 
+    /*
+     * ensure cached data is clear before starting
+     */
+    // todo tidy up seqRefIds, seqsToIds initialisation / reset
+    rnaSessions.clear();
+    splitFrameCandidates.clear();
+
     try
     {
 
@@ -385,6 +410,7 @@ public class Jalview2XML
       // //////////////////////////////////////////////////
 
       List<String> shortNames = new ArrayList<String>();
+      List<String> viewIds = new ArrayList<String>();
 
       // REVERSE ORDER
       for (int i = frames.length - 1; i > -1; i--)
@@ -411,7 +437,7 @@ public class Jalview2XML
             fileName = fileName + ".xml";
           }
 
-          saveState(apanel, fileName, jout);
+          saveState(apanel, fileName, jout, viewIds);
 
           String dssid = getDatasetIdRef(af.getViewport().getAlignment()
                   .getDataset());
@@ -497,6 +523,8 @@ public class Jalview2XML
       FileOutputStream fos = new FileOutputStream(jarFile);
       JarOutputStream jout = new JarOutputStream(fos);
       Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
+      List<String> viewIds = new ArrayList<String>();
+
       for (AlignmentPanel apanel : af.alignPanels)
       {
         String jfileName = apSize == 1 ? fileName : fileName + ap;
@@ -505,7 +533,7 @@ public class Jalview2XML
         {
           jfileName = jfileName + ".xml";
         }
-        saveState(apanel, jfileName, jout);
+        saveState(apanel, jfileName, jout, viewIds);
         String dssid = getDatasetIdRef(af.getViewport().getAlignment()
                 .getDataset());
         if (!dsses.containsKey(dssid))
@@ -543,7 +571,7 @@ public class Jalview2XML
       {
         jfileName = jfileName + ".xml";
       }
-      saveState(_af.alignPanel, jfileName, true, jout);
+      saveState(_af.alignPanel, jfileName, true, jout, null);
     }
   }
 
@@ -557,13 +585,14 @@ public class Jalview2XML
    *          name of alignment panel written to output stream
    * @param jout
    *          jar output stream
+   * @param viewIds
    * @param out
    *          jar entry name
    */
   public JalviewModel saveState(AlignmentPanel ap, String fileName,
-          JarOutputStream jout)
+          JarOutputStream jout, List<String> viewIds)
   {
-    return saveState(ap, fileName, false, jout);
+    return saveState(ap, fileName, false, jout, viewIds);
   }
 
   /**
@@ -583,10 +612,15 @@ public class Jalview2XML
    *          jar entry name
    */
   public JalviewModel saveState(AlignmentPanel ap, String fileName,
-          boolean storeDS, JarOutputStream jout)
+          boolean storeDS, JarOutputStream jout, List<String> viewIds)
   {
+    if (viewIds == null)
+    {
+      viewIds = new ArrayList<String>();
+    }
+
     initSeqRefs();
-    List<String> viewIds = new ArrayList<String>();
+
     List<UserColourScheme> userColours = new ArrayList<UserColourScheme>();
 
     AlignViewport av = ap.av;
@@ -638,14 +672,13 @@ public class Jalview2XML
     Set<String> calcIdSet = new HashSet<String>();
 
     // SAVE SEQUENCES
-    String id = "";
-    jalview.datamodel.SequenceI jds, jdatasq;
     for (int i = 0; i < jal.getHeight(); i++)
     {
-      jds = jal.getSequenceAt(i);
-      jdatasq = jds.getDatasetSequence() == null ? jds : jds
+      final SequenceI jds = jal.getSequenceAt(i);
+      final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
+              : jds
               .getDatasetSequence();
-      id = seqHash(jds);
+      String id = seqHash(jds);
 
       if (seqRefIds.get(id) != null)
       {
@@ -774,8 +807,8 @@ public class Jalview2XML
               matchedFile = saveStructureState(ap, jds, pdb, entry,
                       viewIds, matchedFile, viewFrame);
               /*
-               * Only store each structure viewer's state once in each XML
-               * document. First time through only (storeDS==false)
+               * Only store each structure viewer's state once in the project
+               * jar. First time through only (storeDS==false)
                */
               String viewId = viewFrame.getViewId();
               if (!storeDS && !viewIds.contains(viewId))
@@ -783,8 +816,9 @@ public class Jalview2XML
                 viewIds.add(viewId);
                 try
                 {
+                  String viewerState = viewFrame.getStateInfo();
                   writeJarEntry(jout, getViewerJarEntryName(viewId),
-                          viewFrame.getStateInfo().getBytes());
+                          viewerState.getBytes());
                 } catch (IOException e)
                 {
                   System.err.println("Error saving viewer state: "
@@ -834,6 +868,8 @@ public class Jalview2XML
         }
       }
 
+      saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
+
       jms.addJSeq(jseq);
     }
 
@@ -942,35 +978,17 @@ public class Jalview2XML
       }
     }
 
-    /*
-     * Save associated Varna panels
-     */
-    if (Desktop.desktop != null)
-    {
-      for (JInternalFrame frame : Desktop.desktop.getAllFrames())
-      {
-        if (frame instanceof AppVarna)
-        {
-          AppVarna vp = (AppVarna) frame;
-          if (vp.ap == ap)
-          {
-            // save Varna state
-          }
-        }
-      }
-    }
-
     // SAVE ANNOTATIONS
     /**
      * store forward refs from an annotationRow to any groups
      */
-    IdentityHashMap groupRefs = new IdentityHashMap();
+    IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<SequenceGroup, String>();
     if (storeDS)
     {
       for (SequenceI sq : jal.getSequences())
       {
         // Store annotation on dataset sequences only
-        jalview.datamodel.AlignmentAnnotation[] aa = sq.getAnnotation();
+        AlignmentAnnotation[] aa = sq.getAnnotation();
         if (aa != null && aa.length > 0)
         {
           storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
@@ -983,8 +1001,7 @@ public class Jalview2XML
       if (jal.getAlignmentAnnotation() != null)
       {
         // Store the annotation shown on the alignment.
-        jalview.datamodel.AlignmentAnnotation[] aa = jal
-                .getAlignmentAnnotation();
+        AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
         storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
                 vamsasSet);
       }
@@ -996,70 +1013,69 @@ public class Jalview2XML
       int i = -1;
       for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
       {
-        groups[++i] = new JGroup();
+        JGroup jGroup = new JGroup();
+        groups[++i] = jGroup;
 
-        groups[i].setStart(sg.getStartRes());
-        groups[i].setEnd(sg.getEndRes());
-        groups[i].setName(sg.getName());
+        jGroup.setStart(sg.getStartRes());
+        jGroup.setEnd(sg.getEndRes());
+        jGroup.setName(sg.getName());
         if (groupRefs.containsKey(sg))
         {
-          // group has references so set it's ID field
-          groups[i].setId(groupRefs.get(sg).toString());
+          // group has references so set its ID field
+          jGroup.setId(groupRefs.get(sg));
         }
         if (sg.cs != null)
         {
           if (sg.cs.conservationApplied())
           {
-            groups[i].setConsThreshold(sg.cs.getConservationInc());
+            jGroup.setConsThreshold(sg.cs.getConservationInc());
 
             if (sg.cs instanceof jalview.schemes.UserColourScheme)
             {
-              groups[i].setColour(setUserColourScheme(sg.cs, userColours,
+              jGroup.setColour(setUserColourScheme(sg.cs, userColours,
                       jms));
             }
             else
             {
-              groups[i]
+              jGroup
                       .setColour(ColourSchemeProperty.getColourName(sg.cs));
             }
           }
           else if (sg.cs instanceof jalview.schemes.AnnotationColourGradient)
           {
-            groups[i].setColour("AnnotationColourGradient");
-            groups[i].setAnnotationColours(constructAnnotationColours(
+            jGroup.setColour("AnnotationColourGradient");
+            jGroup.setAnnotationColours(constructAnnotationColours(
                     (jalview.schemes.AnnotationColourGradient) sg.cs,
                     userColours, jms));
           }
           else if (sg.cs instanceof jalview.schemes.UserColourScheme)
           {
-            groups[i]
+            jGroup
                     .setColour(setUserColourScheme(sg.cs, userColours, jms));
           }
           else
           {
-            groups[i].setColour(ColourSchemeProperty.getColourName(sg.cs));
+            jGroup.setColour(ColourSchemeProperty.getColourName(sg.cs));
           }
 
-          groups[i].setPidThreshold(sg.cs.getThreshold());
+          jGroup.setPidThreshold(sg.cs.getThreshold());
         }
 
-        groups[i].setOutlineColour(sg.getOutlineColour().getRGB());
-        groups[i].setDisplayBoxes(sg.getDisplayBoxes());
-        groups[i].setDisplayText(sg.getDisplayText());
-        groups[i].setColourText(sg.getColourText());
-        groups[i].setTextCol1(sg.textColour.getRGB());
-        groups[i].setTextCol2(sg.textColour2.getRGB());
-        groups[i].setTextColThreshold(sg.thresholdTextColour);
-        groups[i].setShowUnconserved(sg.getShowNonconserved());
-        groups[i].setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
-        groups[i].setShowConsensusHistogram(sg.isShowConsensusHistogram());
-        groups[i].setShowSequenceLogo(sg.isShowSequenceLogo());
-        groups[i].setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
-        for (int s = 0; s < sg.getSize(); s++)
-        {
-          jalview.datamodel.Sequence seq = (jalview.datamodel.Sequence) sg
-                  .getSequenceAt(s);
-          groups[i].addSeq(seqHash(seq));
+        jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
+        jGroup.setDisplayBoxes(sg.getDisplayBoxes());
+        jGroup.setDisplayText(sg.getDisplayText());
+        jGroup.setColourText(sg.getColourText());
+        jGroup.setTextCol1(sg.textColour.getRGB());
+        jGroup.setTextCol2(sg.textColour2.getRGB());
+        jGroup.setTextColThreshold(sg.thresholdTextColour);
+        jGroup.setShowUnconserved(sg.getShowNonconserved());
+        jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
+        jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
+        jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
+        jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
+        for (SequenceI seq : sg.getSequences())
+        {
+          jGroup.addSeq(seqHash(seq));
         }
       }
 
@@ -1310,6 +1326,7 @@ public class Jalview2XML
       // using save and then load
       try
       {
+        System.out.println("Writing jar entry " + fileName);
         JarEntry entry = new JarEntry(fileName);
         jout.putNextEntry(entry);
         PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
@@ -1328,14 +1345,109 @@ public class Jalview2XML
   }
 
   /**
-   * Copy the contents of a file to a new file added to the output jar
+   * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
+   * for each viewer, with
+   * <ul>
+   * <li>viewer geometry (position, size, split pane divider location)</li>
+   * <li>index of the selected structure in the viewer (currently shows gapped
+   * or ungapped)</li>
+   * <li>the id of the annotation holding RNA secondary structure</li>
+   * <li>(currently only one SS is shown per viewer, may be more in future)</li>
+   * </ul>
+   * Varna viewer state is also written out (in native Varna XML) to separate
+   * project jar entries. A separate entry is written for each RNA structure
+   * displayed, with the naming convention
+   * <ul>
+   * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
+   * </ul>
+   * 
+   * @param jout
+   * @param jseq
+   * @param jds
+   * @param viewIds
+   * @param ap
+   * @param storeDataset
+   */
+  protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
+          final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
+          boolean storeDataset)
+  {
+    JInternalFrame[] frames = Desktop.desktop.getAllFrames();
+    for (int f = frames.length - 1; f > -1; f--)
+    {
+      if (frames[f] instanceof AppVarna)
+      {
+        AppVarna varna = (AppVarna) frames[f];
+        /*
+         * link the sequence to every viewer that is showing it and is linked to
+         * its alignment panel
+         */
+        if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
+        {
+          String viewId = varna.getViewId();
+          RnaViewer rna = new RnaViewer();
+          rna.setViewId(viewId);
+          rna.setTitle(varna.getTitle());
+          rna.setXpos(varna.getX());
+          rna.setYpos(varna.getY());
+          rna.setWidth(varna.getWidth());
+          rna.setHeight(varna.getHeight());
+          rna.setDividerLocation(varna.getDividerLocation());
+          rna.setSelectedRna(varna.getSelectedIndex());
+          jseq.addRnaViewer(rna);
+
+          /*
+           * Store each Varna panel's state once in the project per sequence.
+           * First time through only (storeDataset==false)
+           */
+          // boolean storeSessions = false;
+          // String sequenceViewId = viewId + seqsToIds.get(jds);
+          // if (!storeDataset && !viewIds.contains(sequenceViewId))
+          // {
+          // viewIds.add(sequenceViewId);
+          // storeSessions = true;
+          // }
+          for (RnaModel model : varna.getModels())
+          {
+            if (model.seq == jds)
+            {
+              /*
+               * VARNA saves each view (sequence or alignment secondary
+               * structure, gapped or trimmed) as a separate XML file
+               */
+              String jarEntryName = rnaSessions.get(model);
+              if (jarEntryName == null)
+              {
+
+                String varnaStateFile = varna.getStateInfo(model.rna);
+                jarEntryName = RNA_PREFIX + viewId + "_"
+                      + nextCounter();
+                copyFileToJar(jout, varnaStateFile, jarEntryName);
+                rnaSessions.put(model, jarEntryName);
+              }
+              SecondaryStructure ss = new SecondaryStructure();
+              String annotationId = varna.getAnnotation(jds).annotationId;
+              ss.setAnnotationId(annotationId);
+              ss.setViewerState(jarEntryName);
+              ss.setGapped(model.gapped);
+              ss.setTitle(model.title);
+              rna.addSecondaryStructure(ss);
+            }
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * Copy the contents of a file to a new entry added to the output jar
    * 
    * @param jout
    * @param infilePath
-   * @param jarfileName
+   * @param jarEntryName
    */
   protected void copyFileToJar(JarOutputStream jout, String infilePath,
-          String jarfileName)
+          String jarEntryName)
   {
     DataInputStream dis = null;
     try
@@ -1346,7 +1458,7 @@ public class Jalview2XML
         dis = new DataInputStream(new FileInputStream(file));
         byte[] data = new byte[(int) file.length()];
         dis.readFully(data);
-        writeJarEntry(jout, jarfileName, data);
+        writeJarEntry(jout, jarEntryName, data);
       }
     } catch (Exception ex)
     {
@@ -1370,16 +1482,17 @@ public class Jalview2XML
    * Write the data to a new entry of given name in the output jar file
    * 
    * @param jout
-   * @param jarfileName
+   * @param jarEntryName
    * @param data
    * @throws IOException
    */
-  protected void writeJarEntry(JarOutputStream jout, String jarfileName,
+  protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
           byte[] data) throws IOException
   {
     if (jout != null)
     {
-      jout.putNextEntry(new JarEntry(jarfileName));
+      System.out.println("Writing jar entry " + jarEntryName);
+      jout.putNextEntry(new JarEntry(jarEntryName));
       DataOutputStream dout = new DataOutputStream(jout);
       dout.write(data, 0, data.length);
       dout.flush();
@@ -1490,7 +1603,8 @@ public class Jalview2XML
   }
 
   private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
-          IdentityHashMap groupRefs, AlignmentViewport av,
+          IdentityHashMap<SequenceGroup, String> groupRefs,
+          AlignmentViewport av,
           Set<String> calcIdSet, boolean storeDS, SequenceSet vamsasSet)
   {
 
@@ -1498,54 +1612,54 @@ public class Jalview2XML
     {
       Annotation an = new Annotation();
 
-      if (aa[i].annotationId != null)
+      AlignmentAnnotation annotation = aa[i];
+      if (annotation.annotationId != null)
       {
-        annotationIds.put(aa[i].annotationId, aa[i]);
+        annotationIds.put(annotation.annotationId, annotation);
       }
 
-      an.setId(aa[i].annotationId);
+      an.setId(annotation.annotationId);
 
-      an.setVisible(aa[i].visible);
+      an.setVisible(annotation.visible);
 
-      an.setDescription(aa[i].description);
+      an.setDescription(annotation.description);
 
-      if (aa[i].sequenceRef != null)
+      if (annotation.sequenceRef != null)
       {
-        // TODO later annotation sequenceRef should be the XML ID of the
-        // sequence rather than its display name
-        an.setSequenceRef(aa[i].sequenceRef.getName());
+        // 2.9 JAL-1781 xref on sequence id rather than name
+        an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
       }
-      if (aa[i].groupRef != null)
+      if (annotation.groupRef != null)
       {
-        Object groupIdr = groupRefs.get(aa[i].groupRef);
+        String groupIdr = groupRefs.get(annotation.groupRef);
         if (groupIdr == null)
         {
           // make a locally unique String
-          groupRefs.put(aa[i].groupRef,
+          groupRefs.put(annotation.groupRef,
                   groupIdr = ("" + System.currentTimeMillis()
-                          + aa[i].groupRef.getName() + groupRefs.size()));
+                          + annotation.groupRef.getName() + groupRefs.size()));
         }
         an.setGroupRef(groupIdr.toString());
       }
 
       // store all visualization attributes for annotation
-      an.setGraphHeight(aa[i].graphHeight);
-      an.setCentreColLabels(aa[i].centreColLabels);
-      an.setScaleColLabels(aa[i].scaleColLabel);
-      an.setShowAllColLabels(aa[i].showAllColLabels);
-      an.setBelowAlignment(aa[i].belowAlignment);
+      an.setGraphHeight(annotation.graphHeight);
+      an.setCentreColLabels(annotation.centreColLabels);
+      an.setScaleColLabels(annotation.scaleColLabel);
+      an.setShowAllColLabels(annotation.showAllColLabels);
+      an.setBelowAlignment(annotation.belowAlignment);
 
-      if (aa[i].graph > 0)
+      if (annotation.graph > 0)
       {
         an.setGraph(true);
-        an.setGraphType(aa[i].graph);
-        an.setGraphGroup(aa[i].graphGroup);
-        if (aa[i].getThreshold() != null)
+        an.setGraphType(annotation.graph);
+        an.setGraphGroup(annotation.graphGroup);
+        if (annotation.getThreshold() != null)
         {
           ThresholdLine line = new ThresholdLine();
-          line.setLabel(aa[i].getThreshold().label);
-          line.setValue(aa[i].getThreshold().value);
-          line.setColour(aa[i].getThreshold().colour.getRGB());
+          line.setLabel(annotation.getThreshold().label);
+          line.setValue(annotation.getThreshold().value);
+          line.setColour(annotation.getThreshold().colour.getRGB());
           an.setThresholdLine(line);
         }
       }
@@ -1554,78 +1668,78 @@ public class Jalview2XML
         an.setGraph(false);
       }
 
-      an.setLabel(aa[i].label);
+      an.setLabel(annotation.label);
 
-      if (aa[i] == av.getAlignmentQualityAnnot()
-              || aa[i] == av.getAlignmentConservationAnnotation()
-              || aa[i] == av.getAlignmentConsensusAnnotation()
-              || aa[i].autoCalculated)
+      if (annotation == av.getAlignmentQualityAnnot()
+              || annotation == av.getAlignmentConservationAnnotation()
+              || annotation == av.getAlignmentConsensusAnnotation()
+              || annotation.autoCalculated)
       {
         // new way of indicating autocalculated annotation -
-        an.setAutoCalculated(aa[i].autoCalculated);
+        an.setAutoCalculated(annotation.autoCalculated);
       }
-      if (aa[i].hasScore())
+      if (annotation.hasScore())
       {
-        an.setScore(aa[i].getScore());
+        an.setScore(annotation.getScore());
       }
 
-      if (aa[i].getCalcId() != null)
+      if (annotation.getCalcId() != null)
       {
-        calcIdSet.add(aa[i].getCalcId());
-        an.setCalcId(aa[i].getCalcId());
+        calcIdSet.add(annotation.getCalcId());
+        an.setCalcId(annotation.getCalcId());
       }
-      if (aa[i].hasProperties())
+      if (annotation.hasProperties())
       {
-        for (String pr : aa[i].getProperties())
+        for (String pr : annotation.getProperties())
         {
           Property prop = new Property();
           prop.setName(pr);
-          prop.setValue(aa[i].getProperty(pr));
+          prop.setValue(annotation.getProperty(pr));
           an.addProperty(prop);
         }
       }
 
       AnnotationElement ae;
-      if (aa[i].annotations != null)
+      if (annotation.annotations != null)
       {
         an.setScoreOnly(false);
-        for (int a = 0; a < aa[i].annotations.length; a++)
+        for (int a = 0; a < annotation.annotations.length; a++)
         {
-          if ((aa[i] == null) || (aa[i].annotations[a] == null))
+          if ((annotation == null) || (annotation.annotations[a] == null))
           {
             continue;
           }
 
           ae = new AnnotationElement();
-          if (aa[i].annotations[a].description != null)
+          if (annotation.annotations[a].description != null)
           {
-            ae.setDescription(aa[i].annotations[a].description);
+            ae.setDescription(annotation.annotations[a].description);
           }
-          if (aa[i].annotations[a].displayCharacter != null)
+          if (annotation.annotations[a].displayCharacter != null)
           {
-            ae.setDisplayCharacter(aa[i].annotations[a].displayCharacter);
+            ae.setDisplayCharacter(annotation.annotations[a].displayCharacter);
           }
 
-          if (!Float.isNaN(aa[i].annotations[a].value))
+          if (!Float.isNaN(annotation.annotations[a].value))
           {
-            ae.setValue(aa[i].annotations[a].value);
+            ae.setValue(annotation.annotations[a].value);
           }
 
           ae.setPosition(a);
-          if (aa[i].annotations[a].secondaryStructure > ' ')
+          if (annotation.annotations[a].secondaryStructure > ' ')
           {
-            ae.setSecondaryStructure(aa[i].annotations[a].secondaryStructure
+            ae.setSecondaryStructure(annotation.annotations[a].secondaryStructure
                     + "");
           }
 
-          if (aa[i].annotations[a].colour != null
-                  && aa[i].annotations[a].colour != java.awt.Color.black)
+          if (annotation.annotations[a].colour != null
+                  && annotation.annotations[a].colour != java.awt.Color.black)
           {
-            ae.setColour(aa[i].annotations[a].colour.getRGB());
+            ae.setColour(annotation.annotations[a].colour.getRGB());
           }
 
           an.addAnnotationElement(ae);
-          if (aa[i].autoCalculated)
+          if (annotation.autoCalculated)
           {
             // only write one non-null entry into the annotation row -
             // sufficient to get the visualization attributes necessary to
@@ -1638,7 +1752,7 @@ public class Jalview2XML
       {
         an.setScoreOnly(true);
       }
-      if (!storeDS || (storeDS && !aa[i].autoCalculated))
+      if (!storeDS || (storeDS && !annotation.autoCalculated))
       {
         // skip autocalculated annotation - these are only provided for
         // alignments
@@ -2058,7 +2172,7 @@ public class Jalview2XML
         });
       } catch (Exception x)
       {
-
+        System.err.println("Error loading alignment: " + x.getMessage());
       }
     }
     return af;
@@ -2174,13 +2288,7 @@ public class Jalview2XML
         }
       } while (jarentry != null);
       resolveFrefedSequences();
-    } catch (java.io.FileNotFoundException ex)
-    {
-      ex.printStackTrace();
-      errorMessage = "Couldn't locate Jalview XML file : " + file;
-      System.err.println("Exception whilst loading jalview XML file : "
-              + ex + "\n");
-    } catch (java.net.UnknownHostException ex)
+    } catch (IOException ex)
     {
       ex.printStackTrace();
       errorMessage = "Couldn't locate Jalview XML file : " + file;
@@ -2740,10 +2848,11 @@ public class Jalview2XML
     // ////////////////////////////////
     // LOAD ANNOTATIONS
     List<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
-    /**
+
+    /*
      * store any annotations which forward reference a group's ID
      */
-    Hashtable<String, ArrayList<jalview.datamodel.AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, ArrayList<jalview.datamodel.AlignmentAnnotation>>();
+    Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, List<AlignmentAnnotation>>();
 
     if (vamsasSet.getAnnotationCount() > 0)
     {
@@ -2751,39 +2860,43 @@ public class Jalview2XML
 
       for (int i = 0; i < an.length; i++)
       {
+        Annotation annotation = an[i];
+
         /**
          * test if annotation is automatically calculated for this view only
          */
         boolean autoForView = false;
-        if (an[i].getLabel().equals("Quality")
-                || an[i].getLabel().equals("Conservation")
-                || an[i].getLabel().equals("Consensus"))
+        if (annotation.getLabel().equals("Quality")
+                || annotation.getLabel().equals("Conservation")
+                || annotation.getLabel().equals("Consensus"))
         {
           // Kludge for pre 2.5 projects which lacked the autocalculated flag
           autoForView = true;
-          if (!an[i].hasAutoCalculated())
+          if (!annotation.hasAutoCalculated())
           {
-            an[i].setAutoCalculated(true);
+            annotation.setAutoCalculated(true);
           }
         }
         if (autoForView
-                || (an[i].hasAutoCalculated() && an[i].isAutoCalculated()))
+                || (annotation.hasAutoCalculated() && annotation
+                        .isAutoCalculated()))
         {
           // remove ID - we don't recover annotation from other views for
           // view-specific annotation
-          an[i].setId(null);
+          annotation.setId(null);
         }
 
         // set visiblity for other annotation in this view
-        if (an[i].getId() != null
-                && annotationIds.containsKey(an[i].getId()))
+        String annotationId = annotation.getId();
+        if (annotationId != null
+                && annotationIds.containsKey(annotationId))
         {
-          AlignmentAnnotation jda = annotationIds.get(an[i].getId());
+          AlignmentAnnotation jda = annotationIds.get(annotationId);
           // in principle Visible should always be true for annotation displayed
           // in multiple views
-          if (an[i].hasVisible())
+          if (annotation.hasVisible())
           {
-            jda.visible = an[i].getVisible();
+            jda.visible = annotation.getVisible();
           }
 
           al.addAnnotation(jda);
@@ -2791,11 +2904,11 @@ public class Jalview2XML
           continue;
         }
         // Construct new annotation from model.
-        AnnotationElement[] ae = an[i].getAnnotationElement();
+        AnnotationElement[] ae = annotation.getAnnotationElement();
         jalview.datamodel.Annotation[] anot = null;
         java.awt.Color firstColour = null;
         int anpos;
-        if (!an[i].getScoreOnly())
+        if (!annotation.getScoreOnly())
         {
           anot = new jalview.datamodel.Annotation[al.getWidth()];
           for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
@@ -2832,27 +2945,27 @@ public class Jalview2XML
         }
         jalview.datamodel.AlignmentAnnotation jaa = null;
 
-        if (an[i].getGraph())
+        if (annotation.getGraph())
         {
           float llim = 0, hlim = 0;
           // if (autoForView || an[i].isAutoCalculated()) {
           // hlim=11f;
           // }
-          jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
-                  an[i].getDescription(), anot, llim, hlim,
-                  an[i].getGraphType());
+          jaa = new jalview.datamodel.AlignmentAnnotation(
+                  annotation.getLabel(), annotation.getDescription(), anot,
+                  llim, hlim, annotation.getGraphType());
 
-          jaa.graphGroup = an[i].getGraphGroup();
+          jaa.graphGroup = annotation.getGraphGroup();
           jaa._linecolour = firstColour;
-          if (an[i].getThresholdLine() != null)
+          if (annotation.getThresholdLine() != null)
           {
-            jaa.setThreshold(new jalview.datamodel.GraphLine(an[i]
-                    .getThresholdLine().getValue(), an[i]
+            jaa.setThreshold(new jalview.datamodel.GraphLine(annotation
+                    .getThresholdLine().getValue(), annotation
                     .getThresholdLine().getLabel(), new java.awt.Color(
-                    an[i].getThresholdLine().getColour())));
+                    annotation.getThresholdLine().getColour())));
 
           }
-          if (autoForView || an[i].isAutoCalculated())
+          if (autoForView || annotation.isAutoCalculated())
           {
             // Hardwire the symbol display line to ensure that labels for
             // histograms are displayed
@@ -2872,19 +2985,26 @@ public class Jalview2XML
           jaa.annotationId = an[i].getId();
         }
         // recover sequence association
-        if (an[i].getSequenceRef() != null)
+        String sequenceRef = an[i].getSequenceRef();
+        if (sequenceRef != null)
         {
-          if (al.findName(an[i].getSequenceRef()) != null)
+          // from 2.9 sequenceRef is to sequence id (JAL-1781)
+          SequenceI sequence = seqRefIds.get(sequenceRef);
+          if (sequence == null)
+          {
+            // in pre-2.9 projects sequence ref is to sequence name
+            sequence = al.findName(sequenceRef);
+          }
+          if (sequence != null)
           {
-            jaa.createSequenceMapping(al.findName(an[i].getSequenceRef()),
-                    1, true);
-            al.findName(an[i].getSequenceRef()).addAlignmentAnnotation(jaa);
+            jaa.createSequenceMapping(sequence, 1, true);
+            sequence.addAlignmentAnnotation(jaa);
           }
         }
         // and make a note of any group association
         if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
         {
-          ArrayList<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
+          List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
                   .get(an[i].getGroupRef());
           if (aal == null)
           {
@@ -2958,37 +3078,37 @@ public class Jalview2XML
       boolean addAnnotSchemeGroup = false;
       for (int i = 0; i < groups.length; i++)
       {
+        JGroup jGroup = groups[i];
         ColourSchemeI cs = null;
-
-        if (groups[i].getColour() != null)
+        if (jGroup.getColour() != null)
         {
-          if (groups[i].getColour().startsWith("ucs"))
+          if (jGroup.getColour().startsWith("ucs"))
           {
-            cs = getUserColourScheme(jms, groups[i].getColour());
+            cs = getUserColourScheme(jms, jGroup.getColour());
           }
-          else if (groups[i].getColour().equals("AnnotationColourGradient")
-                  && groups[i].getAnnotationColours() != null)
+          else if (jGroup.getColour().equals("AnnotationColourGradient")
+                  && jGroup.getAnnotationColours() != null)
           {
             addAnnotSchemeGroup = true;
             cs = null;
           }
           else
           {
-            cs = ColourSchemeProperty.getColour(al, groups[i].getColour());
+            cs = ColourSchemeProperty.getColour(al, jGroup.getColour());
           }
 
           if (cs != null)
           {
-            cs.setThreshold(groups[i].getPidThreshold(), true);
+            cs.setThreshold(jGroup.getPidThreshold(), true);
           }
         }
 
-        Vector seqs = new Vector();
+        Vector<SequenceI> seqs = new Vector<SequenceI>();
 
-        for (int s = 0; s < groups[i].getSeqCount(); s++)
+        for (int s = 0; s < jGroup.getSeqCount(); s++)
         {
-          String seqId = groups[i].getSeq(s) + "";
-          jalview.datamodel.SequenceI ts = seqRefIds.get(seqId);
+          String seqId = jGroup.getSeq(s) + "";
+          SequenceI ts = seqRefIds.get(seqId);
 
           if (ts != null)
           {
@@ -3001,36 +3121,36 @@ public class Jalview2XML
           continue;
         }
 
-        jalview.datamodel.SequenceGroup sg = new jalview.datamodel.SequenceGroup(
-                seqs, groups[i].getName(), cs, groups[i].getDisplayBoxes(),
-                groups[i].getDisplayText(), groups[i].getColourText(),
-                groups[i].getStart(), groups[i].getEnd());
+        SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
+                jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
+                jGroup.getColourText(), jGroup.getStart(),
+                jGroup.getEnd());
 
-        sg.setOutlineColour(new java.awt.Color(groups[i].getOutlineColour()));
+        sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
 
-        sg.textColour = new java.awt.Color(groups[i].getTextCol1());
-        sg.textColour2 = new java.awt.Color(groups[i].getTextCol2());
-        sg.setShowNonconserved(groups[i].hasShowUnconserved() ? groups[i]
+        sg.textColour = new java.awt.Color(jGroup.getTextCol1());
+        sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
+        sg.setShowNonconserved(jGroup.hasShowUnconserved() ? jGroup
                 .isShowUnconserved() : false);
-        sg.thresholdTextColour = groups[i].getTextColThreshold();
-        if (groups[i].hasShowConsensusHistogram())
+        sg.thresholdTextColour = jGroup.getTextColThreshold();
+        if (jGroup.hasShowConsensusHistogram())
         {
-          sg.setShowConsensusHistogram(groups[i].isShowConsensusHistogram());
+          sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
         }
         ;
-        if (groups[i].hasShowSequenceLogo())
+        if (jGroup.hasShowSequenceLogo())
         {
-          sg.setshowSequenceLogo(groups[i].isShowSequenceLogo());
+          sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
         }
-        if (groups[i].hasNormaliseSequenceLogo())
+        if (jGroup.hasNormaliseSequenceLogo())
         {
-          sg.setNormaliseSequenceLogo(groups[i].isNormaliseSequenceLogo());
+          sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
         }
-        if (groups[i].hasIgnoreGapsinConsensus())
+        if (jGroup.hasIgnoreGapsinConsensus())
         {
-          sg.setIgnoreGapsConsensus(groups[i].getIgnoreGapsinConsensus());
+          sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
         }
-        if (groups[i].getConsThreshold() != 0)
+        if (jGroup.getConsThreshold() != 0)
         {
           jalview.analysis.Conservation c = new jalview.analysis.Conservation(
                   "All", ResidueProperties.propHash, 3,
@@ -3040,14 +3160,14 @@ public class Jalview2XML
           sg.cs.setConservation(c);
         }
 
-        if (groups[i].getId() != null && groupAnnotRefs.size() > 0)
+        if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
         {
           // re-instate unique group/annotation row reference
-          ArrayList<jalview.datamodel.AlignmentAnnotation> jaal = groupAnnotRefs
-                  .get(groups[i].getId());
+          List<AlignmentAnnotation> jaal = groupAnnotRefs
+                  .get(jGroup.getId());
           if (jaal != null)
           {
-            for (jalview.datamodel.AlignmentAnnotation jaa : jaal)
+            for (AlignmentAnnotation jaa : jaal)
             {
               jaa.groupRef = sg;
               if (jaa.autoCalculated)
@@ -3073,7 +3193,7 @@ public class Jalview2XML
         {
           // reconstruct the annotation colourscheme
           sg.cs = constructAnnotationColour(
-                  groups[i].getAnnotationColours(), null, al, jms, false);
+                  jGroup.getAnnotationColours(), null, al, jms, false);
         }
       }
     }
@@ -3164,90 +3284,202 @@ public class Jalview2XML
       av = af.viewport;
       ap = af.alignPanel;
     }
-    // LOAD TREES
-    // /////////////////////////////////////
-    if (loadTreesAndStructures && jms.getTreeCount() > 0)
+
+    /*
+     * Load any trees, PDB structures and viewers
+     * 
+     * Not done if flag is false (when this method is used for New View)
+     */
+    if (loadTreesAndStructures)
     {
-      try
+      loadTrees(jms, view, af, av, ap);
+      loadPDBStructures(jprovider, jseqs, af, ap);
+      loadRnaViewers(jprovider, jseqs, ap);
+    }
+    // and finally return.
+    return af;
+  }
+
+  /**
+   * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
+   * panel is restored from separate jar entries, two (gapped and trimmed) per
+   * sequence and secondary structure.
+   * 
+   * Currently each viewer shows just one sequence and structure (gapped and
+   * trimmed), however this method is designed to support multiple sequences or
+   * structures in viewers if wanted in future.
+   * 
+   * @param jprovider
+   * @param jseqs
+   * @param ap
+   */
+  private void loadRnaViewers(jarInputStreamProvider jprovider,
+          JSeq[] jseqs, AlignmentPanel ap)
+  {
+    /*
+     * scan the sequences for references to viewers; create each one the first
+     * time it is referenced, add Rna models to existing viewers
+     */
+    for (JSeq jseq : jseqs)
+    {
+      for (int i = 0; i < jseq.getRnaViewerCount(); i++)
       {
-        for (int t = 0; t < jms.getTreeCount(); t++)
+        RnaViewer viewer = jseq.getRnaViewer(i);
+        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());
 
-          Tree tree = jms.getTree(t);
+          /*
+           * add the structure to the Varna display (with session state copied
+           * from the jar to a temporary file)
+           */
+          boolean gapped = ss.isGapped();
+          String rnaTitle = ss.getTitle();
+          String sessionState = ss.getViewerState();
+          String tempStateFile = copyJarEntry(jprovider, sessionState,
+                  "varna");
+          RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
+          appVarna.addModelSession(rna, rnaTitle, tempStateFile);
+        }
+        appVarna.setInitialSelection(viewer.getSelectedRna());
+      }
+    }
+  }
 
-          TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
-          if (tp == null)
-          {
-            tp = af.ShowNewickTree(
-                    new jalview.io.NewickFile(tree.getNewick()),
-                    tree.getTitle(), tree.getWidth(), tree.getHeight(),
-                    tree.getXpos(), tree.getYpos());
-            if (tree.getId() != null)
-            {
-              // perhaps bind the tree id to something ?
-            }
-          }
-          else
-          {
-            // update local tree attributes ?
-            // 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.av = av; // af.viewport; // TODO: verify 'associate with all
-            // views'
-            // works still
-            tp.treeCanvas.av = av; // af.viewport;
-            tp.treeCanvas.ap = ap; // af.alignPanel;
+  /**
+   * Locate and return an already instantiated matching AppVarna, or create one
+   * if not found
+   * 
+   * @param viewer
+   * @param viewIdSuffix
+   * @param ap
+   * @return
+   */
+  protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
+          String viewIdSuffix, AlignmentPanel ap)
+  {
+    /*
+     * on each load a suffix is appended to the saved viewId, to avoid conflicts
+     * if load is repeated
+     */
+    String postLoadId = viewer.getViewId() + viewIdSuffix;
+    for (JInternalFrame frame : getAllFrames())
+    {
+      if (frame instanceof AppVarna)
+      {
+        AppVarna varna = (AppVarna) frame;
+        if (postLoadId.equals(varna.getViewId()))
+        {
+          // this viewer is already instantiated
+          // could in future here add ap as another 'parent' of the
+          // AppVarna window; currently just 1-to-many
+          return varna;
+        }
+      }
+    }
 
-          }
-          if (tp == null)
-          {
-            warn("There was a problem recovering stored Newick tree: \n"
-                    + tree.getNewick());
-            continue;
-          }
+    /*
+     * viewer not found - make it
+     */
+    RnaViewerModel model = new RnaViewerModel(postLoadId,
+            viewer.getTitle(), viewer.getXpos(),
+            viewer.getYpos(), viewer.getWidth(), viewer.getHeight(),
+            viewer.getDividerLocation());
+    AppVarna varna = new AppVarna(model, ap);
 
-          tp.fitToWindow.setState(tree.getFitToWindow());
-          tp.fitToWindow_actionPerformed(null);
+    return varna;
+  }
 
-          if (tree.getFontName() != null)
-          {
-            tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
-                    .getFontStyle(), tree.getFontSize()));
-          }
-          else
+  /**
+   * Load any saved trees
+   * 
+   * @param jms
+   * @param view
+   * @param af
+   * @param av
+   * @param ap
+   */
+  protected void loadTrees(JalviewModelSequence jms, Viewport view,
+          AlignFrame af, AlignViewport av, AlignmentPanel ap)
+  {
+    // TODO result of automated refactoring - are all these parameters needed?
+    try
+    {
+      for (int t = 0; t < jms.getTreeCount(); t++)
+      {
+
+        Tree tree = jms.getTree(t);
+
+        TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
+        if (tp == null)
+        {
+          tp = af.ShowNewickTree(
+                  new jalview.io.NewickFile(tree.getNewick()),
+                  tree.getTitle(), tree.getWidth(), tree.getHeight(),
+                  tree.getXpos(), tree.getYpos());
+          if (tree.getId() != null)
           {
-            tp.setTreeFont(new java.awt.Font(view.getFontName(), view
-                    .getFontStyle(), tree.getFontSize()));
+            // perhaps bind the tree id to something ?
           }
+        }
+        else
+        {
+          // update local tree attributes ?
+          // 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.av = av; // af.viewport; // TODO: verify 'associate with all
+          // views'
+          // works still
+          tp.treeCanvas.av = av; // af.viewport;
+          tp.treeCanvas.ap = ap; // af.alignPanel;
 
-          tp.showPlaceholders(tree.getMarkUnlinked());
-          tp.showBootstrap(tree.getShowBootstrap());
-          tp.showDistances(tree.getShowDistances());
+        }
+        if (tp == null)
+        {
+          warn("There was a problem recovering stored Newick tree: \n"
+                  + tree.getNewick());
+          continue;
+        }
 
-          tp.treeCanvas.threshold = tree.getThreshold();
+        tp.fitToWindow.setState(tree.getFitToWindow());
+        tp.fitToWindow_actionPerformed(null);
 
-          if (tree.getCurrentTree())
-          {
-            af.viewport.setCurrentTree(tp.getTree());
-          }
+        if (tree.getFontName() != null)
+        {
+          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()));
         }
 
-      } catch (Exception ex)
-      {
-        ex.printStackTrace();
+        tp.showPlaceholders(tree.getMarkUnlinked());
+        tp.showBootstrap(tree.getShowBootstrap());
+        tp.showDistances(tree.getShowDistances());
+
+        tp.treeCanvas.threshold = tree.getThreshold();
+
+        if (tree.getCurrentTree())
+        {
+          af.viewport.setCurrentTree(tp.getTree());
+        }
       }
-    }
 
-    // //LOAD STRUCTURES
-    if (loadTreesAndStructures)
+    } catch (Exception ex)
     {
-      loadStructures(jprovider, jseqs, af, ap);
+      ex.printStackTrace();
     }
-    // and finally return.
-    return af;
   }
 
   /**
@@ -3258,7 +3490,7 @@ public class Jalview2XML
    * @param af
    * @param ap
    */
-  protected void loadStructures(jarInputStreamProvider jprovider,
+  protected void loadPDBStructures(jarInputStreamProvider jprovider,
           JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
   {
     /*
@@ -3452,11 +3684,12 @@ public class Jalview2XML
     /*
      * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
      * 
-     * Note this is the 'saved' viewId as in the project file XML, _not_ the
+     * NB this is the 'saved' viewId as in the project file XML, _not_ the
      * 'uniquified' sviewid used to reconstruct the viewer here
      */
-    chimeraSessionFile = copyJarEntry(jprovider,
-            getViewerJarEntryName(data.getViewId()), "chimera");
+    String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
+    chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
+            "chimera");
 
     Set<Entry<File, StructureData>> fileData = data.getFileData()
             .entrySet();
@@ -3481,6 +3714,7 @@ public class Jalview2XML
     final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs
             .size()][]);
     String newViewId = viewerData.getKey();
+
     ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
             af.alignPanel, pdbArray,
             seqsArray, colourByChimera, colourBySequence, newViewId);
@@ -3653,7 +3887,7 @@ public class Jalview2XML
    */
   protected String getViewerJarEntryName(String viewId)
   {
-    return "viewer_" + viewId;
+    return VIEWER_PREFIX + viewId;
   }
 
   /**
@@ -3794,7 +4028,8 @@ public class Jalview2XML
    * @return true if version is development/null or evaluates to the same or
    *         later X.Y.Z (where X,Y,Z are like [0-9]+b?[0-9]*)
    */
-  private boolean isVersionStringLaterThan(String supported, String version)
+  protected boolean isVersionStringLaterThan(String supported,
+          String version)
   {
     if (version == null || version.equalsIgnoreCase("DEVELOPMENT BUILD")
             || version.equalsIgnoreCase("Test")
@@ -4630,20 +4865,24 @@ public class Jalview2XML
     }
   }
 
-  java.util.Hashtable datasetIds = null;
+  /*
+   * TODO use AlignmentI here and in related methods - needs
+   * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
+   */
+  Hashtable<String, Alignment> datasetIds = null;
 
-  java.util.IdentityHashMap dataset2Ids = null;
+  IdentityHashMap<Alignment, String> dataset2Ids = null;
 
   private Alignment getDatasetFor(String datasetId)
   {
     if (datasetIds == null)
     {
-      datasetIds = new Hashtable();
+      datasetIds = new Hashtable<String, Alignment>();
       return null;
     }
     if (datasetIds.containsKey(datasetId))
     {
-      return (Alignment) datasetIds.get(datasetId);
+      return datasetIds.get(datasetId);
     }
     return null;
   }
@@ -4652,7 +4891,7 @@ public class Jalview2XML
   {
     if (datasetIds == null)
     {
-      datasetIds = new Hashtable();
+      datasetIds = new Hashtable<String, Alignment>();
     }
     datasetIds.put(datasetId, dataset);
   }
@@ -4663,7 +4902,7 @@ public class Jalview2XML
    * @param dataset
    * @return
    */
-  private String getDatasetIdRef(jalview.datamodel.Alignment dataset)
+  private String getDatasetIdRef(Alignment dataset)
   {
     if (dataset.getDataset() != null)
     {
@@ -4675,11 +4914,11 @@ public class Jalview2XML
       // make a new datasetId and record it
       if (dataset2Ids == null)
       {
-        dataset2Ids = new IdentityHashMap();
+        dataset2Ids = new IdentityHashMap<Alignment, String>();
       }
       else
       {
-        datasetId = (String) dataset2Ids.get(dataset);
+        datasetId = dataset2Ids.get(dataset);
       }
       if (datasetId == null)
       {
@@ -4798,8 +5037,7 @@ public class Jalview2XML
           boolean keepSeqRefs)
   {
     initSeqRefs();
-    jalview.schemabinding.version2.JalviewModel jm = saveState(ap, null,
-            null);
+    JalviewModel jm = saveState(ap, null, null, null);
 
     if (!keepSeqRefs)
     {
@@ -5082,4 +5320,14 @@ public class Jalview2XML
   
     return result;
   }
+
+  /**
+   * Returns an incrementing counter (0, 1, 2...)
+   * 
+   * @return
+   */
+  private synchronized int nextCounter()
+  {
+    return counter++;
+  }
 }
index 7d238a0..ad3d6af 100644 (file)
  */
 package jalview.gui;
 
+import java.awt.Color;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Hashtable;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.Vector;
+
+import javax.swing.ButtonGroup;
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JColorChooser;
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JPopupMenu;
+import javax.swing.JRadioButtonMenuItem;
+
 import jalview.analysis.AAFrequency;
 import jalview.analysis.AlignmentAnnotationUtils;
 import jalview.analysis.AlignmentUtils;
@@ -59,27 +80,6 @@ import jalview.util.GroupUrlLink.UrlStringTooLongException;
 import jalview.util.MessageManager;
 import jalview.util.UrlLink;
 
-import java.awt.Color;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Hashtable;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.Vector;
-
-import javax.swing.ButtonGroup;
-import javax.swing.JCheckBoxMenuItem;
-import javax.swing.JColorChooser;
-import javax.swing.JMenu;
-import javax.swing.JMenuItem;
-import javax.swing.JOptionPane;
-import javax.swing.JPopupMenu;
-import javax.swing.JRadioButtonMenuItem;
-
 /**
  * DOCUMENT ME!
  * 
@@ -322,49 +322,54 @@ public class PopupMenu extends JPopupMenu
         makeReferenceSeq.setText("Mark as representative");
       }
 
-      if (ap.av.getAlignment().isNucleotide() == false)
+      if (!ap.av.getAlignment().isNucleotide())
       {
         remove(rnaStructureMenu);
       }
-
-      if (ap.av.getAlignment().isNucleotide() == true)
+      else
       {
-        AlignmentAnnotation[] aa = ap.av.getAlignment()
+        /*
+         * add menu items to 2D-render any alignment or sequence secondary
+         * structure annotation
+         */
+        AlignmentAnnotation[] aas = ap.av.getAlignment()
                 .getAlignmentAnnotation();
-        for (int i = 0; aa != null && i < aa.length; i++)
+        if (aas != null)
         {
-          if (aa[i].isValidStruc() && aa[i].sequenceRef == null)
+          for (final AlignmentAnnotation aa : aas)
           {
-            final String rnastruc = aa[i].getRNAStruc();
-            final String structureLine = aa[i].label + " (alignment)";
-            menuItem = new JMenuItem();
-            menuItem.setText(MessageManager.formatMessage(
-                    "label.2d_rna_structure_line", new Object[]
-                    { structureLine }));
-            menuItem.addActionListener(new java.awt.event.ActionListener()
+            if (aa.isValidStruc() && aa.sequenceRef == null)
             {
-              @Override
-              public void actionPerformed(ActionEvent e)
+              /*
+               * valid alignment RNA secondary structure annotation
+               */
+              menuItem = new JMenuItem();
+              menuItem.setText(MessageManager.formatMessage(
+                      "label.2d_rna_structure_line", new Object[]
+                      { aa.label }));
+              menuItem.addActionListener(new java.awt.event.ActionListener()
               {
-                new AppVarna(structureLine, seq, seq.getSequenceAsString(),
-                        rnastruc, seq.getName(), ap);
-                System.out.println("end");
-              }
-            });
-            rnaStructureMenu.add(menuItem);
+                @Override
+                public void actionPerformed(ActionEvent e)
+                {
+                  new AppVarna(seq, aa, ap);
+                }
+              });
+              rnaStructureMenu.add(menuItem);
+            }
           }
         }
 
-
         if (seq.getAnnotation() != null)
         {
-          AlignmentAnnotation seqAnno[] = seq.getAnnotation();
-          for (int i = 0; i < seqAnno.length; i++)
+          AlignmentAnnotation seqAnns[] = seq.getAnnotation();
+          for (final AlignmentAnnotation aa : seqAnns)
           {
-            if (seqAnno[i].isValidStruc())
+            if (aa.isValidStruc())
             {
-              final String rnastruc = seqAnno[i].getRNAStruc();
-
+              /*
+               * valid sequence RNA secondary structure annotation
+               */
               // TODO: make rnastrucF a bit more nice
               menuItem = new JMenuItem();
               menuItem.setText(MessageManager.formatMessage(
@@ -376,10 +381,7 @@ public class PopupMenu extends JPopupMenu
                 public void actionPerformed(ActionEvent e)
                 {
                   // TODO: VARNA does'nt print gaps in the sequence
-
-                  new AppVarna(seq.getName() + " structure", seq, seq
-                          .getSequenceAsString(), rnastruc, seq.getName(),
-                          ap);
+                  new AppVarna(seq, aa, ap);
                 }
               });
               rnaStructureMenu.add(menuItem);
index 65150f6..2b8e4b5 100644 (file)
@@ -1,4 +1,4 @@
-#Wed Jun 10 11:15:53 BST 2015
+#Wed Jun 17 15:04:02 BST 2015
 jalview.schemabinding.version2.ThresholdLine=jalview.schemabinding.version2.descriptors.ThresholdLineDescriptor
 jalview.schemabinding.version2.SequenceSetProperties=jalview.schemabinding.version2.descriptors.SequenceSetPropertiesDescriptor
 jalview.schemabinding.version2.StructureState=jalview.schemabinding.version2.descriptors.StructureStateDescriptor
@@ -10,8 +10,10 @@ jalview.schemabinding.version2.OtherData=jalview.schemabinding.version2.descript
 jalview.schemabinding.version2.Setting=jalview.schemabinding.version2.descriptors.SettingDescriptor
 jalview.schemabinding.version2.AlcodonFrame=jalview.schemabinding.version2.descriptors.AlcodonFrameDescriptor
 jalview.schemabinding.version2.AnnotationElement=jalview.schemabinding.version2.descriptors.AnnotationElementDescriptor
+jalview.schemabinding.version2.SecondaryStructure=jalview.schemabinding.version2.descriptors.SecondaryStructureDescriptor
 jalview.schemabinding.version2.SequenceSet=jalview.schemabinding.version2.descriptors.SequenceSetDescriptor
 jalview.schemabinding.version2.Viewport=jalview.schemabinding.version2.descriptors.ViewportDescriptor
+jalview.schemabinding.version2.RnaViewer=jalview.schemabinding.version2.descriptors.RnaViewerDescriptor
 jalview.schemabinding.version2.MapListType=jalview.schemabinding.version2.descriptors.MapListTypeDescriptor
 jalview.schemabinding.version2.Property=jalview.schemabinding.version2.descriptors.PropertyDescriptor
 jalview.schemabinding.version2.UserColourScheme=jalview.schemabinding.version2.descriptors.UserColourSchemeDescriptor
index d5eda07..193b005 100644 (file)
@@ -86,6 +86,17 @@ public class JSeq implements java.io.Serializable {
      */
     private java.util.Vector _hiddenSequencesList;
 
+    /**
+     * Reference to a viewer showing RNA structure
+     *  for this sequence. Schema supports one viewer showing
+     * multiple
+     *  annotations for multiple sequences, though currently only
+     * one
+     *  annotation for one sequence (gapped or trimmed) is used
+     *  
+     */
+    private java.util.Vector _rnaViewerList;
+
 
       //----------------/
      //- Constructors -/
@@ -96,6 +107,7 @@ public class JSeq implements java.io.Serializable {
         this._featuresList = new java.util.Vector();
         this._pdbidsList = new java.util.Vector();
         this._hiddenSequencesList = new java.util.Vector();
+        this._rnaViewerList = new java.util.Vector();
     }
 
 
@@ -188,6 +200,34 @@ public class JSeq implements java.io.Serializable {
     }
 
     /**
+     * 
+     * 
+     * @param vRnaViewer
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     */
+    public void addRnaViewer(
+            final jalview.schemabinding.version2.RnaViewer vRnaViewer)
+    throws java.lang.IndexOutOfBoundsException {
+        this._rnaViewerList.addElement(vRnaViewer);
+    }
+
+    /**
+     * 
+     * 
+     * @param index
+     * @param vRnaViewer
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     */
+    public void addRnaViewer(
+            final int index,
+            final jalview.schemabinding.version2.RnaViewer vRnaViewer)
+    throws java.lang.IndexOutOfBoundsException {
+        this._rnaViewerList.add(index, vRnaViewer);
+    }
+
+    /**
      */
     public void deleteColour(
     ) {
@@ -248,6 +288,17 @@ public class JSeq implements java.io.Serializable {
     }
 
     /**
+     * Method enumerateRnaViewer.
+     * 
+     * @return an Enumeration over all
+     * jalview.schemabinding.version2.RnaViewer elements
+     */
+    public java.util.Enumeration enumerateRnaViewer(
+    ) {
+        return this._rnaViewerList.elements();
+    }
+
+    /**
      * Returns the value of field 'colour'.
      * 
      * @return the value of field 'Colour'.
@@ -424,6 +475,51 @@ public class JSeq implements java.io.Serializable {
     }
 
     /**
+     * Method getRnaViewer.
+     * 
+     * @param index
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     * @return the value of the
+     * jalview.schemabinding.version2.RnaViewer at the given index
+     */
+    public jalview.schemabinding.version2.RnaViewer getRnaViewer(
+            final int index)
+    throws java.lang.IndexOutOfBoundsException {
+        // check bounds for index
+        if (index < 0 || index >= this._rnaViewerList.size()) {
+            throw new IndexOutOfBoundsException("getRnaViewer: Index value '" + index + "' not in range [0.." + (this._rnaViewerList.size() - 1) + "]");
+        }
+        
+        return (jalview.schemabinding.version2.RnaViewer) _rnaViewerList.get(index);
+    }
+
+    /**
+     * Method getRnaViewer.Returns the contents of the collection
+     * in an Array.  <p>Note:  Just in case the collection contents
+     * are changing in another thread, we pass a 0-length Array of
+     * the correct type into the API call.  This way we <i>know</i>
+     * that the Array returned is of exactly the correct length.
+     * 
+     * @return this collection as an Array
+     */
+    public jalview.schemabinding.version2.RnaViewer[] getRnaViewer(
+    ) {
+        jalview.schemabinding.version2.RnaViewer[] array = new jalview.schemabinding.version2.RnaViewer[0];
+        return (jalview.schemabinding.version2.RnaViewer[]) this._rnaViewerList.toArray(array);
+    }
+
+    /**
+     * Method getRnaViewerCount.
+     * 
+     * @return the size of this collection
+     */
+    public int getRnaViewerCount(
+    ) {
+        return this._rnaViewerList.size();
+    }
+
+    /**
      * Returns the value of field 'start'.
      * 
      * @return the value of field 'Start'.
@@ -552,6 +648,13 @@ public class JSeq implements java.io.Serializable {
     }
 
     /**
+     */
+    public void removeAllRnaViewer(
+    ) {
+        this._rnaViewerList.clear();
+    }
+
+    /**
      * Method removeFeatures.
      * 
      * @param vFeatures
@@ -624,6 +727,30 @@ public class JSeq implements java.io.Serializable {
     }
 
     /**
+     * Method removeRnaViewer.
+     * 
+     * @param vRnaViewer
+     * @return true if the object was removed from the collection.
+     */
+    public boolean removeRnaViewer(
+            final jalview.schemabinding.version2.RnaViewer vRnaViewer) {
+        boolean removed = _rnaViewerList.remove(vRnaViewer);
+        return removed;
+    }
+
+    /**
+     * Method removeRnaViewerAt.
+     * 
+     * @param index
+     * @return the element removed from the collection
+     */
+    public jalview.schemabinding.version2.RnaViewer removeRnaViewerAt(
+            final int index) {
+        java.lang.Object obj = this._rnaViewerList.remove(index);
+        return (jalview.schemabinding.version2.RnaViewer) obj;
+    }
+
+    /**
      * Sets the value of field 'colour'.
      * 
      * @param colour the value of field 'colour'.
@@ -772,6 +899,41 @@ public class JSeq implements java.io.Serializable {
     }
 
     /**
+     * 
+     * 
+     * @param index
+     * @param vRnaViewer
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     */
+    public void setRnaViewer(
+            final int index,
+            final jalview.schemabinding.version2.RnaViewer vRnaViewer)
+    throws java.lang.IndexOutOfBoundsException {
+        // check bounds for index
+        if (index < 0 || index >= this._rnaViewerList.size()) {
+            throw new IndexOutOfBoundsException("setRnaViewer: Index value '" + index + "' not in range [0.." + (this._rnaViewerList.size() - 1) + "]");
+        }
+        
+        this._rnaViewerList.set(index, vRnaViewer);
+    }
+
+    /**
+     * 
+     * 
+     * @param vRnaViewerArray
+     */
+    public void setRnaViewer(
+            final jalview.schemabinding.version2.RnaViewer[] vRnaViewerArray) {
+        //-- copy array
+        _rnaViewerList.clear();
+        
+        for (int i = 0; i < vRnaViewerArray.length; i++) {
+                this._rnaViewerList.add(vRnaViewerArray[i]);
+        }
+    }
+
+    /**
      * Sets the value of field 'start'.
      * 
      * @param start the value of field 'start'.
diff --git a/src/jalview/schemabinding/version2/RnaViewer.java b/src/jalview/schemabinding/version2/RnaViewer.java
new file mode 100644 (file)
index 0000000..96c4195
--- /dev/null
@@ -0,0 +1,643 @@
+/*
+ * This class was automatically generated with 
+ * <a href="http://www.castor.org">Castor 1.1</a>, using an XML
+ * Schema.
+ * $Id$
+ */
+
+package jalview.schemabinding.version2;
+
+  //---------------------------------/
+ //- Imported classes and packages -/
+//---------------------------------/
+
+import org.exolab.castor.xml.Marshaller;
+import org.exolab.castor.xml.Unmarshaller;
+
+/**
+ * Reference to a viewer showing RNA structure
+ *  for this sequence. Schema supports one viewer showing multiple
+ *  annotations for multiple sequences, though currently only one
+ *  annotation for one sequence (gapped or trimmed) is used
+ *  
+ * 
+ * @version $Revision$ $Date$
+ */
+public class RnaViewer implements java.io.Serializable {
+
+
+      //--------------------------/
+     //- Class/Member Variables -/
+    //--------------------------/
+
+    /**
+     * Field _title.
+     */
+    private java.lang.String _title;
+
+    /**
+     * An id unique to the RNA viewer panel
+     *  
+     */
+    private java.lang.String _viewId;
+
+    /**
+     * horizontal position of split pane divider
+     *  
+     */
+    private int _dividerLocation;
+
+    /**
+     * keeps track of state for field: _dividerLocation
+     */
+    private boolean _has_dividerLocation;
+
+    /**
+     * Index of the selected structure in the
+     *  viewer panel
+     *  
+     */
+    private int _selectedRna;
+
+    /**
+     * keeps track of state for field: _selectedRna
+     */
+    private boolean _has_selectedRna;
+
+    /**
+     * Field _width.
+     */
+    private int _width;
+
+    /**
+     * keeps track of state for field: _width
+     */
+    private boolean _has_width;
+
+    /**
+     * Field _height.
+     */
+    private int _height;
+
+    /**
+     * keeps track of state for field: _height
+     */
+    private boolean _has_height;
+
+    /**
+     * Field _xpos.
+     */
+    private int _xpos;
+
+    /**
+     * keeps track of state for field: _xpos
+     */
+    private boolean _has_xpos;
+
+    /**
+     * Field _ypos.
+     */
+    private int _ypos;
+
+    /**
+     * keeps track of state for field: _ypos
+     */
+    private boolean _has_ypos;
+
+    /**
+     * Field _secondaryStructureList.
+     */
+    private java.util.Vector _secondaryStructureList;
+
+
+      //----------------/
+     //- Constructors -/
+    //----------------/
+
+    public RnaViewer() {
+        super();
+        this._secondaryStructureList = new java.util.Vector();
+    }
+
+
+      //-----------/
+     //- Methods -/
+    //-----------/
+
+    /**
+     * 
+     * 
+     * @param vSecondaryStructure
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     */
+    public void addSecondaryStructure(
+            final jalview.schemabinding.version2.SecondaryStructure vSecondaryStructure)
+    throws java.lang.IndexOutOfBoundsException {
+        this._secondaryStructureList.addElement(vSecondaryStructure);
+    }
+
+    /**
+     * 
+     * 
+     * @param index
+     * @param vSecondaryStructure
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     */
+    public void addSecondaryStructure(
+            final int index,
+            final jalview.schemabinding.version2.SecondaryStructure vSecondaryStructure)
+    throws java.lang.IndexOutOfBoundsException {
+        this._secondaryStructureList.add(index, vSecondaryStructure);
+    }
+
+    /**
+     */
+    public void deleteDividerLocation(
+    ) {
+        this._has_dividerLocation= false;
+    }
+
+    /**
+     */
+    public void deleteHeight(
+    ) {
+        this._has_height= false;
+    }
+
+    /**
+     */
+    public void deleteSelectedRna(
+    ) {
+        this._has_selectedRna= false;
+    }
+
+    /**
+     */
+    public void deleteWidth(
+    ) {
+        this._has_width= false;
+    }
+
+    /**
+     */
+    public void deleteXpos(
+    ) {
+        this._has_xpos= false;
+    }
+
+    /**
+     */
+    public void deleteYpos(
+    ) {
+        this._has_ypos= false;
+    }
+
+    /**
+     * Method enumerateSecondaryStructure.
+     * 
+     * @return an Enumeration over all
+     * jalview.schemabinding.version2.SecondaryStructure elements
+     */
+    public java.util.Enumeration enumerateSecondaryStructure(
+    ) {
+        return this._secondaryStructureList.elements();
+    }
+
+    /**
+     * Returns the value of field 'dividerLocation'. The field
+     * 'dividerLocation' has the following description: horizontal
+     * position of split pane divider
+     *  
+     * 
+     * @return the value of field 'DividerLocation'.
+     */
+    public int getDividerLocation(
+    ) {
+        return this._dividerLocation;
+    }
+
+    /**
+     * Returns the value of field 'height'.
+     * 
+     * @return the value of field 'Height'.
+     */
+    public int getHeight(
+    ) {
+        return this._height;
+    }
+
+    /**
+     * Method getSecondaryStructure.
+     * 
+     * @param index
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     * @return the value of the
+     * jalview.schemabinding.version2.SecondaryStructure at the
+     * given index
+     */
+    public jalview.schemabinding.version2.SecondaryStructure getSecondaryStructure(
+            final int index)
+    throws java.lang.IndexOutOfBoundsException {
+        // check bounds for index
+        if (index < 0 || index >= this._secondaryStructureList.size()) {
+            throw new IndexOutOfBoundsException("getSecondaryStructure: Index value '" + index + "' not in range [0.." + (this._secondaryStructureList.size() - 1) + "]");
+        }
+        
+        return (jalview.schemabinding.version2.SecondaryStructure) _secondaryStructureList.get(index);
+    }
+
+    /**
+     * Method getSecondaryStructure.Returns the contents of the
+     * collection in an Array.  <p>Note:  Just in case the
+     * collection contents are changing in another thread, we pass
+     * a 0-length Array of the correct type into the API call. 
+     * This way we <i>know</i> that the Array returned is of
+     * exactly the correct length.
+     * 
+     * @return this collection as an Array
+     */
+    public jalview.schemabinding.version2.SecondaryStructure[] getSecondaryStructure(
+    ) {
+        jalview.schemabinding.version2.SecondaryStructure[] array = new jalview.schemabinding.version2.SecondaryStructure[0];
+        return (jalview.schemabinding.version2.SecondaryStructure[]) this._secondaryStructureList.toArray(array);
+    }
+
+    /**
+     * Method getSecondaryStructureCount.
+     * 
+     * @return the size of this collection
+     */
+    public int getSecondaryStructureCount(
+    ) {
+        return this._secondaryStructureList.size();
+    }
+
+    /**
+     * Returns the value of field 'selectedRna'. The field
+     * 'selectedRna' has the following description: Index of the
+     * selected structure in the
+     *  viewer panel
+     *  
+     * 
+     * @return the value of field 'SelectedRna'.
+     */
+    public int getSelectedRna(
+    ) {
+        return this._selectedRna;
+    }
+
+    /**
+     * Returns the value of field 'title'.
+     * 
+     * @return the value of field 'Title'.
+     */
+    public java.lang.String getTitle(
+    ) {
+        return this._title;
+    }
+
+    /**
+     * Returns the value of field 'viewId'. The field 'viewId' has
+     * the following description: An id unique to the RNA viewer
+     * panel
+     *  
+     * 
+     * @return the value of field 'ViewId'.
+     */
+    public java.lang.String getViewId(
+    ) {
+        return this._viewId;
+    }
+
+    /**
+     * Returns the value of field 'width'.
+     * 
+     * @return the value of field 'Width'.
+     */
+    public int getWidth(
+    ) {
+        return this._width;
+    }
+
+    /**
+     * Returns the value of field 'xpos'.
+     * 
+     * @return the value of field 'Xpos'.
+     */
+    public int getXpos(
+    ) {
+        return this._xpos;
+    }
+
+    /**
+     * Returns the value of field 'ypos'.
+     * 
+     * @return the value of field 'Ypos'.
+     */
+    public int getYpos(
+    ) {
+        return this._ypos;
+    }
+
+    /**
+     * Method hasDividerLocation.
+     * 
+     * @return true if at least one DividerLocation has been added
+     */
+    public boolean hasDividerLocation(
+    ) {
+        return this._has_dividerLocation;
+    }
+
+    /**
+     * Method hasHeight.
+     * 
+     * @return true if at least one Height has been added
+     */
+    public boolean hasHeight(
+    ) {
+        return this._has_height;
+    }
+
+    /**
+     * Method hasSelectedRna.
+     * 
+     * @return true if at least one SelectedRna has been added
+     */
+    public boolean hasSelectedRna(
+    ) {
+        return this._has_selectedRna;
+    }
+
+    /**
+     * Method hasWidth.
+     * 
+     * @return true if at least one Width has been added
+     */
+    public boolean hasWidth(
+    ) {
+        return this._has_width;
+    }
+
+    /**
+     * Method hasXpos.
+     * 
+     * @return true if at least one Xpos has been added
+     */
+    public boolean hasXpos(
+    ) {
+        return this._has_xpos;
+    }
+
+    /**
+     * Method hasYpos.
+     * 
+     * @return true if at least one Ypos has been added
+     */
+    public boolean hasYpos(
+    ) {
+        return this._has_ypos;
+    }
+
+    /**
+     * Method isValid.
+     * 
+     * @return true if this object is valid according to the schema
+     */
+    public boolean isValid(
+    ) {
+        try {
+            validate();
+        } catch (org.exolab.castor.xml.ValidationException vex) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 
+     * 
+     * @param out
+     * @throws org.exolab.castor.xml.MarshalException if object is
+     * null or if any SAXException is thrown during marshaling
+     * @throws org.exolab.castor.xml.ValidationException if this
+     * object is an invalid instance according to the schema
+     */
+    public void marshal(
+            final java.io.Writer out)
+    throws org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException {
+        Marshaller.marshal(this, out);
+    }
+
+    /**
+     * 
+     * 
+     * @param handler
+     * @throws java.io.IOException if an IOException occurs during
+     * marshaling
+     * @throws org.exolab.castor.xml.ValidationException if this
+     * object is an invalid instance according to the schema
+     * @throws org.exolab.castor.xml.MarshalException if object is
+     * null or if any SAXException is thrown during marshaling
+     */
+    public void marshal(
+            final org.xml.sax.ContentHandler handler)
+    throws java.io.IOException, org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException {
+        Marshaller.marshal(this, handler);
+    }
+
+    /**
+     */
+    public void removeAllSecondaryStructure(
+    ) {
+        this._secondaryStructureList.clear();
+    }
+
+    /**
+     * Method removeSecondaryStructure.
+     * 
+     * @param vSecondaryStructure
+     * @return true if the object was removed from the collection.
+     */
+    public boolean removeSecondaryStructure(
+            final jalview.schemabinding.version2.SecondaryStructure vSecondaryStructure) {
+        boolean removed = _secondaryStructureList.remove(vSecondaryStructure);
+        return removed;
+    }
+
+    /**
+     * Method removeSecondaryStructureAt.
+     * 
+     * @param index
+     * @return the element removed from the collection
+     */
+    public jalview.schemabinding.version2.SecondaryStructure removeSecondaryStructureAt(
+            final int index) {
+        java.lang.Object obj = this._secondaryStructureList.remove(index);
+        return (jalview.schemabinding.version2.SecondaryStructure) obj;
+    }
+
+    /**
+     * Sets the value of field 'dividerLocation'. The field
+     * 'dividerLocation' has the following description: horizontal
+     * position of split pane divider
+     *  
+     * 
+     * @param dividerLocation the value of field 'dividerLocation'.
+     */
+    public void setDividerLocation(
+            final int dividerLocation) {
+        this._dividerLocation = dividerLocation;
+        this._has_dividerLocation = true;
+    }
+
+    /**
+     * Sets the value of field 'height'.
+     * 
+     * @param height the value of field 'height'.
+     */
+    public void setHeight(
+            final int height) {
+        this._height = height;
+        this._has_height = true;
+    }
+
+    /**
+     * 
+     * 
+     * @param index
+     * @param vSecondaryStructure
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     */
+    public void setSecondaryStructure(
+            final int index,
+            final jalview.schemabinding.version2.SecondaryStructure vSecondaryStructure)
+    throws java.lang.IndexOutOfBoundsException {
+        // check bounds for index
+        if (index < 0 || index >= this._secondaryStructureList.size()) {
+            throw new IndexOutOfBoundsException("setSecondaryStructure: Index value '" + index + "' not in range [0.." + (this._secondaryStructureList.size() - 1) + "]");
+        }
+        
+        this._secondaryStructureList.set(index, vSecondaryStructure);
+    }
+
+    /**
+     * 
+     * 
+     * @param vSecondaryStructureArray
+     */
+    public void setSecondaryStructure(
+            final jalview.schemabinding.version2.SecondaryStructure[] vSecondaryStructureArray) {
+        //-- copy array
+        _secondaryStructureList.clear();
+        
+        for (int i = 0; i < vSecondaryStructureArray.length; i++) {
+                this._secondaryStructureList.add(vSecondaryStructureArray[i]);
+        }
+    }
+
+    /**
+     * Sets the value of field 'selectedRna'. The field
+     * 'selectedRna' has the following description: Index of the
+     * selected structure in the
+     *  viewer panel
+     *  
+     * 
+     * @param selectedRna the value of field 'selectedRna'.
+     */
+    public void setSelectedRna(
+            final int selectedRna) {
+        this._selectedRna = selectedRna;
+        this._has_selectedRna = true;
+    }
+
+    /**
+     * Sets the value of field 'title'.
+     * 
+     * @param title the value of field 'title'.
+     */
+    public void setTitle(
+            final java.lang.String title) {
+        this._title = title;
+    }
+
+    /**
+     * Sets the value of field 'viewId'. The field 'viewId' has the
+     * following description: An id unique to the RNA viewer panel
+     *  
+     * 
+     * @param viewId the value of field 'viewId'.
+     */
+    public void setViewId(
+            final java.lang.String viewId) {
+        this._viewId = viewId;
+    }
+
+    /**
+     * Sets the value of field 'width'.
+     * 
+     * @param width the value of field 'width'.
+     */
+    public void setWidth(
+            final int width) {
+        this._width = width;
+        this._has_width = true;
+    }
+
+    /**
+     * Sets the value of field 'xpos'.
+     * 
+     * @param xpos the value of field 'xpos'.
+     */
+    public void setXpos(
+            final int xpos) {
+        this._xpos = xpos;
+        this._has_xpos = true;
+    }
+
+    /**
+     * Sets the value of field 'ypos'.
+     * 
+     * @param ypos the value of field 'ypos'.
+     */
+    public void setYpos(
+            final int ypos) {
+        this._ypos = ypos;
+        this._has_ypos = true;
+    }
+
+    /**
+     * Method unmarshal.
+     * 
+     * @param reader
+     * @throws org.exolab.castor.xml.MarshalException if object is
+     * null or if any SAXException is thrown during marshaling
+     * @throws org.exolab.castor.xml.ValidationException if this
+     * object is an invalid instance according to the schema
+     * @return the unmarshaled
+     * jalview.schemabinding.version2.RnaViewer
+     */
+    public static jalview.schemabinding.version2.RnaViewer unmarshal(
+            final java.io.Reader reader)
+    throws org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException {
+        return (jalview.schemabinding.version2.RnaViewer) Unmarshaller.unmarshal(jalview.schemabinding.version2.RnaViewer.class, reader);
+    }
+
+    /**
+     * 
+     * 
+     * @throws org.exolab.castor.xml.ValidationException if this
+     * object is an invalid instance according to the schema
+     */
+    public void validate(
+    )
+    throws org.exolab.castor.xml.ValidationException {
+        org.exolab.castor.xml.Validator validator = new org.exolab.castor.xml.Validator();
+        validator.validate(this);
+    }
+
+}
diff --git a/src/jalview/schemabinding/version2/SecondaryStructure.java b/src/jalview/schemabinding/version2/SecondaryStructure.java
new file mode 100644 (file)
index 0000000..d2f97fb
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * This class was automatically generated with 
+ * <a href="http://www.castor.org">Castor 1.1</a>, using an XML
+ * Schema.
+ * $Id$
+ */
+
+package jalview.schemabinding.version2;
+
+  //---------------------------------/
+ //- Imported classes and packages -/
+//---------------------------------/
+
+import org.exolab.castor.xml.Marshaller;
+import org.exolab.castor.xml.Unmarshaller;
+
+/**
+ * Class SecondaryStructure.
+ * 
+ * @version $Revision$ $Date$
+ */
+public class SecondaryStructure implements java.io.Serializable {
+
+
+      //--------------------------/
+     //- Class/Member Variables -/
+    //--------------------------/
+
+    /**
+     * Field _title.
+     */
+    private java.lang.String _title;
+
+    /**
+     * id attribute of Annotation in
+     *  vamsasModel for
+     *  the secondary structure annotation shown
+     *  in the viewer
+     *  
+     */
+    private java.lang.String _annotationId;
+
+    /**
+     * if true the RNA structure is shown with gaps, if false
+     * without
+     *  
+     */
+    private boolean _gapped;
+
+    /**
+     * keeps track of state for field: _gapped
+     */
+    private boolean _has_gapped;
+
+    /**
+     * name of the project jar entry that holds
+     *  the VARNA viewer state for the structure
+     *  
+     */
+    private java.lang.String _viewerState;
+
+
+      //----------------/
+     //- Constructors -/
+    //----------------/
+
+    public SecondaryStructure() {
+        super();
+    }
+
+
+      //-----------/
+     //- Methods -/
+    //-----------/
+
+    /**
+     */
+    public void deleteGapped(
+    ) {
+        this._has_gapped= false;
+    }
+
+    /**
+     * Returns the value of field 'annotationId'. The field
+     * 'annotationId' has the following description: id attribute
+     * of Annotation in
+     *  vamsasModel for
+     *  the secondary structure annotation shown
+     *  in the viewer
+     *  
+     * 
+     * @return the value of field 'AnnotationId'.
+     */
+    public java.lang.String getAnnotationId(
+    ) {
+        return this._annotationId;
+    }
+
+    /**
+     * Returns the value of field 'gapped'. The field 'gapped' has
+     * the following description: if true the RNA structure is
+     * shown with gaps, if false without
+     *  
+     * 
+     * @return the value of field 'Gapped'.
+     */
+    public boolean getGapped(
+    ) {
+        return this._gapped;
+    }
+
+    /**
+     * Returns the value of field 'title'.
+     * 
+     * @return the value of field 'Title'.
+     */
+    public java.lang.String getTitle(
+    ) {
+        return this._title;
+    }
+
+    /**
+     * Returns the value of field 'viewerState'. The field
+     * 'viewerState' has the following description: name of the
+     * project jar entry that holds
+     *  the VARNA viewer state for the structure
+     *  
+     * 
+     * @return the value of field 'ViewerState'.
+     */
+    public java.lang.String getViewerState(
+    ) {
+        return this._viewerState;
+    }
+
+    /**
+     * Method hasGapped.
+     * 
+     * @return true if at least one Gapped has been added
+     */
+    public boolean hasGapped(
+    ) {
+        return this._has_gapped;
+    }
+
+    /**
+     * Returns the value of field 'gapped'. The field 'gapped' has
+     * the following description: if true the RNA structure is
+     * shown with gaps, if false without
+     *  
+     * 
+     * @return the value of field 'Gapped'.
+     */
+    public boolean isGapped(
+    ) {
+        return this._gapped;
+    }
+
+    /**
+     * Method isValid.
+     * 
+     * @return true if this object is valid according to the schema
+     */
+    public boolean isValid(
+    ) {
+        try {
+            validate();
+        } catch (org.exolab.castor.xml.ValidationException vex) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 
+     * 
+     * @param out
+     * @throws org.exolab.castor.xml.MarshalException if object is
+     * null or if any SAXException is thrown during marshaling
+     * @throws org.exolab.castor.xml.ValidationException if this
+     * object is an invalid instance according to the schema
+     */
+    public void marshal(
+            final java.io.Writer out)
+    throws org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException {
+        Marshaller.marshal(this, out);
+    }
+
+    /**
+     * 
+     * 
+     * @param handler
+     * @throws java.io.IOException if an IOException occurs during
+     * marshaling
+     * @throws org.exolab.castor.xml.ValidationException if this
+     * object is an invalid instance according to the schema
+     * @throws org.exolab.castor.xml.MarshalException if object is
+     * null or if any SAXException is thrown during marshaling
+     */
+    public void marshal(
+            final org.xml.sax.ContentHandler handler)
+    throws java.io.IOException, org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException {
+        Marshaller.marshal(this, handler);
+    }
+
+    /**
+     * Sets the value of field 'annotationId'. The field
+     * 'annotationId' has the following description: id attribute
+     * of Annotation in
+     *  vamsasModel for
+     *  the secondary structure annotation shown
+     *  in the viewer
+     *  
+     * 
+     * @param annotationId the value of field 'annotationId'.
+     */
+    public void setAnnotationId(
+            final java.lang.String annotationId) {
+        this._annotationId = annotationId;
+    }
+
+    /**
+     * Sets the value of field 'gapped'. The field 'gapped' has the
+     * following description: if true the RNA structure is shown
+     * with gaps, if false without
+     *  
+     * 
+     * @param gapped the value of field 'gapped'.
+     */
+    public void setGapped(
+            final boolean gapped) {
+        this._gapped = gapped;
+        this._has_gapped = true;
+    }
+
+    /**
+     * Sets the value of field 'title'.
+     * 
+     * @param title the value of field 'title'.
+     */
+    public void setTitle(
+            final java.lang.String title) {
+        this._title = title;
+    }
+
+    /**
+     * Sets the value of field 'viewerState'. The field
+     * 'viewerState' has the following description: name of the
+     * project jar entry that holds
+     *  the VARNA viewer state for the structure
+     *  
+     * 
+     * @param viewerState the value of field 'viewerState'.
+     */
+    public void setViewerState(
+            final java.lang.String viewerState) {
+        this._viewerState = viewerState;
+    }
+
+    /**
+     * Method unmarshal.
+     * 
+     * @param reader
+     * @throws org.exolab.castor.xml.MarshalException if object is
+     * null or if any SAXException is thrown during marshaling
+     * @throws org.exolab.castor.xml.ValidationException if this
+     * object is an invalid instance according to the schema
+     * @return the unmarshaled
+     * jalview.schemabinding.version2.SecondaryStructure
+     */
+    public static jalview.schemabinding.version2.SecondaryStructure unmarshal(
+            final java.io.Reader reader)
+    throws org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException {
+        return (jalview.schemabinding.version2.SecondaryStructure) Unmarshaller.unmarshal(jalview.schemabinding.version2.SecondaryStructure.class, reader);
+    }
+
+    /**
+     * 
+     * 
+     * @throws org.exolab.castor.xml.ValidationException if this
+     * object is an invalid instance according to the schema
+     */
+    public void validate(
+    )
+    throws org.exolab.castor.xml.ValidationException {
+        org.exolab.castor.xml.Validator validator = new org.exolab.castor.xml.Validator();
+        validator.validate(this);
+    }
+
+}
index ab0eaaf..44c8caf 100644 (file)
@@ -408,6 +408,48 @@ public class JSeqDescriptor extends org.exolab.castor.xml.util.XMLClassDescripto
             typeValidator.setMaxInclusive(2147483647);
         }
         desc.setValidator(fieldValidator);
+        //-- _rnaViewerList
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(jalview.schemabinding.version2.RnaViewer.class, "_rnaViewerList", "rnaViewer", org.exolab.castor.xml.NodeType.Element);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                JSeq target = (JSeq) object;
+                return target.getRnaViewer();
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    JSeq target = (JSeq) object;
+                    target.addRnaViewer( (jalview.schemabinding.version2.RnaViewer) value);
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public void resetValue(Object object) throws IllegalStateException, IllegalArgumentException {
+                try {
+                    JSeq target = (JSeq) object;
+                    target.removeAllRnaViewer();
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return new jalview.schemabinding.version2.RnaViewer();
+            }
+        };
+        desc.setHandler(handler);
+        desc.setNameSpaceURI("www.jalview.org");
+        desc.setMultivalued(true);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _rnaViewerList
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        fieldValidator.setMinOccurs(0);
+        { //-- local scope
+        }
+        desc.setValidator(fieldValidator);
     }
 
 
diff --git a/src/jalview/schemabinding/version2/descriptors/RnaViewerDescriptor.java b/src/jalview/schemabinding/version2/descriptors/RnaViewerDescriptor.java
new file mode 100644 (file)
index 0000000..fd824a1
--- /dev/null
@@ -0,0 +1,535 @@
+/*
+ * This class was automatically generated with 
+ * <a href="http://www.castor.org">Castor 1.1</a>, using an XML
+ * Schema.
+ * $Id$
+ */
+
+package jalview.schemabinding.version2.descriptors;
+
+  //---------------------------------/
+ //- Imported classes and packages -/
+//---------------------------------/
+
+import jalview.schemabinding.version2.RnaViewer;
+
+/**
+ * Class RnaViewerDescriptor.
+ * 
+ * @version $Revision$ $Date$
+ */
+public class RnaViewerDescriptor extends org.exolab.castor.xml.util.XMLClassDescriptorImpl {
+
+
+      //--------------------------/
+     //- Class/Member Variables -/
+    //--------------------------/
+
+    /**
+     * Field _elementDefinition.
+     */
+    private boolean _elementDefinition;
+
+    /**
+     * Field _nsPrefix.
+     */
+    private java.lang.String _nsPrefix;
+
+    /**
+     * Field _nsURI.
+     */
+    private java.lang.String _nsURI;
+
+    /**
+     * Field _xmlName.
+     */
+    private java.lang.String _xmlName;
+
+
+      //----------------/
+     //- Constructors -/
+    //----------------/
+
+    public RnaViewerDescriptor() {
+        super();
+        _nsURI = "www.jalview.org";
+        _xmlName = "rnaViewer";
+        _elementDefinition = true;
+        
+        //-- set grouping compositor
+        setCompositorAsSequence();
+        org.exolab.castor.xml.util.XMLFieldDescriptorImpl  desc           = null;
+        org.exolab.castor.mapping.FieldHandler             handler        = null;
+        org.exolab.castor.xml.FieldValidator               fieldValidator = null;
+        //-- initialize attribute descriptors
+        
+        //-- _title
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(java.lang.String.class, "_title", "title", org.exolab.castor.xml.NodeType.Attribute);
+        desc.setImmutable(true);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                RnaViewer target = (RnaViewer) object;
+                return target.getTitle();
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    RnaViewer target = (RnaViewer) object;
+                    target.setTitle( (java.lang.String) value);
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return null;
+            }
+        };
+        desc.setHandler(handler);
+        desc.setMultivalued(false);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _title
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        { //-- local scope
+            org.exolab.castor.xml.validators.StringValidator typeValidator;
+            typeValidator = new org.exolab.castor.xml.validators.StringValidator();
+            fieldValidator.setValidator(typeValidator);
+            typeValidator.setWhiteSpace("preserve");
+        }
+        desc.setValidator(fieldValidator);
+        //-- _viewId
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(java.lang.String.class, "_viewId", "viewId", org.exolab.castor.xml.NodeType.Attribute);
+        desc.setImmutable(true);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                RnaViewer target = (RnaViewer) object;
+                return target.getViewId();
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    RnaViewer target = (RnaViewer) object;
+                    target.setViewId( (java.lang.String) value);
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return null;
+            }
+        };
+        desc.setHandler(handler);
+        desc.setMultivalued(false);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _viewId
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        { //-- local scope
+            org.exolab.castor.xml.validators.StringValidator typeValidator;
+            typeValidator = new org.exolab.castor.xml.validators.StringValidator();
+            fieldValidator.setValidator(typeValidator);
+            typeValidator.setWhiteSpace("preserve");
+        }
+        desc.setValidator(fieldValidator);
+        //-- _dividerLocation
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(java.lang.Integer.TYPE, "_dividerLocation", "dividerLocation", org.exolab.castor.xml.NodeType.Attribute);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                RnaViewer target = (RnaViewer) object;
+                if (!target.hasDividerLocation()) { return null; }
+                return new java.lang.Integer(target.getDividerLocation());
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    RnaViewer target = (RnaViewer) object;
+                    // if null, use delete method for optional primitives 
+                    if (value == null) {
+                        target.deleteDividerLocation();
+                        return;
+                    }
+                    target.setDividerLocation( ((java.lang.Integer) value).intValue());
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return null;
+            }
+        };
+        desc.setHandler(handler);
+        desc.setMultivalued(false);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _dividerLocation
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        { //-- local scope
+            org.exolab.castor.xml.validators.IntValidator typeValidator;
+            typeValidator = new org.exolab.castor.xml.validators.IntValidator();
+            fieldValidator.setValidator(typeValidator);
+            typeValidator.setMinInclusive(-2147483648);
+            typeValidator.setMaxInclusive(2147483647);
+        }
+        desc.setValidator(fieldValidator);
+        //-- _selectedRna
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(java.lang.Integer.TYPE, "_selectedRna", "selectedRna", org.exolab.castor.xml.NodeType.Attribute);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                RnaViewer target = (RnaViewer) object;
+                if (!target.hasSelectedRna()) { return null; }
+                return new java.lang.Integer(target.getSelectedRna());
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    RnaViewer target = (RnaViewer) object;
+                    // if null, use delete method for optional primitives 
+                    if (value == null) {
+                        target.deleteSelectedRna();
+                        return;
+                    }
+                    target.setSelectedRna( ((java.lang.Integer) value).intValue());
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return null;
+            }
+        };
+        desc.setHandler(handler);
+        desc.setMultivalued(false);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _selectedRna
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        { //-- local scope
+            org.exolab.castor.xml.validators.IntValidator typeValidator;
+            typeValidator = new org.exolab.castor.xml.validators.IntValidator();
+            fieldValidator.setValidator(typeValidator);
+            typeValidator.setMinInclusive(-2147483648);
+            typeValidator.setMaxInclusive(2147483647);
+        }
+        desc.setValidator(fieldValidator);
+        //-- _width
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(java.lang.Integer.TYPE, "_width", "width", org.exolab.castor.xml.NodeType.Attribute);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                RnaViewer target = (RnaViewer) object;
+                if (!target.hasWidth()) { return null; }
+                return new java.lang.Integer(target.getWidth());
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    RnaViewer target = (RnaViewer) object;
+                    // if null, use delete method for optional primitives 
+                    if (value == null) {
+                        target.deleteWidth();
+                        return;
+                    }
+                    target.setWidth( ((java.lang.Integer) value).intValue());
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return null;
+            }
+        };
+        desc.setHandler(handler);
+        desc.setMultivalued(false);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _width
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        { //-- local scope
+            org.exolab.castor.xml.validators.IntValidator typeValidator;
+            typeValidator = new org.exolab.castor.xml.validators.IntValidator();
+            fieldValidator.setValidator(typeValidator);
+            typeValidator.setMinInclusive(-2147483648);
+            typeValidator.setMaxInclusive(2147483647);
+        }
+        desc.setValidator(fieldValidator);
+        //-- _height
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(java.lang.Integer.TYPE, "_height", "height", org.exolab.castor.xml.NodeType.Attribute);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                RnaViewer target = (RnaViewer) object;
+                if (!target.hasHeight()) { return null; }
+                return new java.lang.Integer(target.getHeight());
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    RnaViewer target = (RnaViewer) object;
+                    // if null, use delete method for optional primitives 
+                    if (value == null) {
+                        target.deleteHeight();
+                        return;
+                    }
+                    target.setHeight( ((java.lang.Integer) value).intValue());
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return null;
+            }
+        };
+        desc.setHandler(handler);
+        desc.setMultivalued(false);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _height
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        { //-- local scope
+            org.exolab.castor.xml.validators.IntValidator typeValidator;
+            typeValidator = new org.exolab.castor.xml.validators.IntValidator();
+            fieldValidator.setValidator(typeValidator);
+            typeValidator.setMinInclusive(-2147483648);
+            typeValidator.setMaxInclusive(2147483647);
+        }
+        desc.setValidator(fieldValidator);
+        //-- _xpos
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(java.lang.Integer.TYPE, "_xpos", "xpos", org.exolab.castor.xml.NodeType.Attribute);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                RnaViewer target = (RnaViewer) object;
+                if (!target.hasXpos()) { return null; }
+                return new java.lang.Integer(target.getXpos());
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    RnaViewer target = (RnaViewer) object;
+                    // if null, use delete method for optional primitives 
+                    if (value == null) {
+                        target.deleteXpos();
+                        return;
+                    }
+                    target.setXpos( ((java.lang.Integer) value).intValue());
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return null;
+            }
+        };
+        desc.setHandler(handler);
+        desc.setMultivalued(false);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _xpos
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        { //-- local scope
+            org.exolab.castor.xml.validators.IntValidator typeValidator;
+            typeValidator = new org.exolab.castor.xml.validators.IntValidator();
+            fieldValidator.setValidator(typeValidator);
+            typeValidator.setMinInclusive(-2147483648);
+            typeValidator.setMaxInclusive(2147483647);
+        }
+        desc.setValidator(fieldValidator);
+        //-- _ypos
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(java.lang.Integer.TYPE, "_ypos", "ypos", org.exolab.castor.xml.NodeType.Attribute);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                RnaViewer target = (RnaViewer) object;
+                if (!target.hasYpos()) { return null; }
+                return new java.lang.Integer(target.getYpos());
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    RnaViewer target = (RnaViewer) object;
+                    // if null, use delete method for optional primitives 
+                    if (value == null) {
+                        target.deleteYpos();
+                        return;
+                    }
+                    target.setYpos( ((java.lang.Integer) value).intValue());
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return null;
+            }
+        };
+        desc.setHandler(handler);
+        desc.setMultivalued(false);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _ypos
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        { //-- local scope
+            org.exolab.castor.xml.validators.IntValidator typeValidator;
+            typeValidator = new org.exolab.castor.xml.validators.IntValidator();
+            fieldValidator.setValidator(typeValidator);
+            typeValidator.setMinInclusive(-2147483648);
+            typeValidator.setMaxInclusive(2147483647);
+        }
+        desc.setValidator(fieldValidator);
+        //-- initialize element descriptors
+        
+        //-- _secondaryStructureList
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(jalview.schemabinding.version2.SecondaryStructure.class, "_secondaryStructureList", "secondaryStructure", org.exolab.castor.xml.NodeType.Element);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                RnaViewer target = (RnaViewer) object;
+                return target.getSecondaryStructure();
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    RnaViewer target = (RnaViewer) object;
+                    target.addSecondaryStructure( (jalview.schemabinding.version2.SecondaryStructure) value);
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public void resetValue(Object object) throws IllegalStateException, IllegalArgumentException {
+                try {
+                    RnaViewer target = (RnaViewer) object;
+                    target.removeAllSecondaryStructure();
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return new jalview.schemabinding.version2.SecondaryStructure();
+            }
+        };
+        desc.setHandler(handler);
+        desc.setNameSpaceURI("www.jalview.org");
+        desc.setRequired(true);
+        desc.setMultivalued(true);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _secondaryStructureList
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        fieldValidator.setMinOccurs(1);
+        { //-- local scope
+        }
+        desc.setValidator(fieldValidator);
+    }
+
+
+      //-----------/
+     //- Methods -/
+    //-----------/
+
+    /**
+     * Method getAccessMode.
+     * 
+     * @return the access mode specified for this class.
+     */
+    public org.exolab.castor.mapping.AccessMode getAccessMode(
+    ) {
+        return null;
+    }
+
+    /**
+     * Method getIdentity.
+     * 
+     * @return the identity field, null if this class has no
+     * identity.
+     */
+    public org.exolab.castor.mapping.FieldDescriptor getIdentity(
+    ) {
+        return super.getIdentity();
+    }
+
+    /**
+     * Method getJavaClass.
+     * 
+     * @return the Java class represented by this descriptor.
+     */
+    public java.lang.Class getJavaClass(
+    ) {
+        return jalview.schemabinding.version2.RnaViewer.class;
+    }
+
+    /**
+     * Method getNameSpacePrefix.
+     * 
+     * @return the namespace prefix to use when marshaling as XML.
+     */
+    public java.lang.String getNameSpacePrefix(
+    ) {
+        return _nsPrefix;
+    }
+
+    /**
+     * Method getNameSpaceURI.
+     * 
+     * @return the namespace URI used when marshaling and
+     * unmarshaling as XML.
+     */
+    public java.lang.String getNameSpaceURI(
+    ) {
+        return _nsURI;
+    }
+
+    /**
+     * Method getValidator.
+     * 
+     * @return a specific validator for the class described by this
+     * ClassDescriptor.
+     */
+    public org.exolab.castor.xml.TypeValidator getValidator(
+    ) {
+        return this;
+    }
+
+    /**
+     * Method getXMLName.
+     * 
+     * @return the XML Name for the Class being described.
+     */
+    public java.lang.String getXMLName(
+    ) {
+        return _xmlName;
+    }
+
+    /**
+     * Method isElementDefinition.
+     * 
+     * @return true if XML schema definition of this Class is that
+     * of a global
+     * element or element with anonymous type definition.
+     */
+    public boolean isElementDefinition(
+    ) {
+        return _elementDefinition;
+    }
+
+}
diff --git a/src/jalview/schemabinding/version2/descriptors/SecondaryStructureDescriptor.java b/src/jalview/schemabinding/version2/descriptors/SecondaryStructureDescriptor.java
new file mode 100644 (file)
index 0000000..bc7e4ac
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ * This class was automatically generated with 
+ * <a href="http://www.castor.org">Castor 1.1</a>, using an XML
+ * Schema.
+ * $Id$
+ */
+
+package jalview.schemabinding.version2.descriptors;
+
+  //---------------------------------/
+ //- Imported classes and packages -/
+//---------------------------------/
+
+import jalview.schemabinding.version2.SecondaryStructure;
+
+/**
+ * Class SecondaryStructureDescriptor.
+ * 
+ * @version $Revision$ $Date$
+ */
+public class SecondaryStructureDescriptor extends org.exolab.castor.xml.util.XMLClassDescriptorImpl {
+
+
+      //--------------------------/
+     //- Class/Member Variables -/
+    //--------------------------/
+
+    /**
+     * Field _elementDefinition.
+     */
+    private boolean _elementDefinition;
+
+    /**
+     * Field _nsPrefix.
+     */
+    private java.lang.String _nsPrefix;
+
+    /**
+     * Field _nsURI.
+     */
+    private java.lang.String _nsURI;
+
+    /**
+     * Field _xmlName.
+     */
+    private java.lang.String _xmlName;
+
+
+      //----------------/
+     //- Constructors -/
+    //----------------/
+
+    public SecondaryStructureDescriptor() {
+        super();
+        _nsURI = "www.jalview.org";
+        _xmlName = "secondaryStructure";
+        _elementDefinition = true;
+        org.exolab.castor.xml.util.XMLFieldDescriptorImpl  desc           = null;
+        org.exolab.castor.mapping.FieldHandler             handler        = null;
+        org.exolab.castor.xml.FieldValidator               fieldValidator = null;
+        //-- initialize attribute descriptors
+        
+        //-- _title
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(java.lang.String.class, "_title", "title", org.exolab.castor.xml.NodeType.Attribute);
+        desc.setImmutable(true);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                SecondaryStructure target = (SecondaryStructure) object;
+                return target.getTitle();
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    SecondaryStructure target = (SecondaryStructure) object;
+                    target.setTitle( (java.lang.String) value);
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return null;
+            }
+        };
+        desc.setHandler(handler);
+        desc.setMultivalued(false);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _title
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        { //-- local scope
+            org.exolab.castor.xml.validators.StringValidator typeValidator;
+            typeValidator = new org.exolab.castor.xml.validators.StringValidator();
+            fieldValidator.setValidator(typeValidator);
+            typeValidator.setWhiteSpace("preserve");
+        }
+        desc.setValidator(fieldValidator);
+        //-- _annotationId
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(java.lang.String.class, "_annotationId", "annotationId", org.exolab.castor.xml.NodeType.Attribute);
+        desc.setImmutable(true);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                SecondaryStructure target = (SecondaryStructure) object;
+                return target.getAnnotationId();
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    SecondaryStructure target = (SecondaryStructure) object;
+                    target.setAnnotationId( (java.lang.String) value);
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return null;
+            }
+        };
+        desc.setHandler(handler);
+        desc.setRequired(true);
+        desc.setMultivalued(false);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _annotationId
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        fieldValidator.setMinOccurs(1);
+        { //-- local scope
+            org.exolab.castor.xml.validators.StringValidator typeValidator;
+            typeValidator = new org.exolab.castor.xml.validators.StringValidator();
+            fieldValidator.setValidator(typeValidator);
+            typeValidator.setWhiteSpace("preserve");
+        }
+        desc.setValidator(fieldValidator);
+        //-- _gapped
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(java.lang.Boolean.TYPE, "_gapped", "gapped", org.exolab.castor.xml.NodeType.Attribute);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                SecondaryStructure target = (SecondaryStructure) object;
+                if (!target.hasGapped()) { return null; }
+                return (target.getGapped() ? java.lang.Boolean.TRUE : java.lang.Boolean.FALSE);
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    SecondaryStructure target = (SecondaryStructure) object;
+                    // if null, use delete method for optional primitives 
+                    if (value == null) {
+                        target.deleteGapped();
+                        return;
+                    }
+                    target.setGapped( ((java.lang.Boolean) value).booleanValue());
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return null;
+            }
+        };
+        desc.setHandler(handler);
+        desc.setMultivalued(false);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _gapped
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        { //-- local scope
+            org.exolab.castor.xml.validators.BooleanValidator typeValidator;
+            typeValidator = new org.exolab.castor.xml.validators.BooleanValidator();
+            fieldValidator.setValidator(typeValidator);
+        }
+        desc.setValidator(fieldValidator);
+        //-- _viewerState
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(java.lang.String.class, "_viewerState", "viewerState", org.exolab.castor.xml.NodeType.Attribute);
+        desc.setImmutable(true);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                SecondaryStructure target = (SecondaryStructure) object;
+                return target.getViewerState();
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    SecondaryStructure target = (SecondaryStructure) object;
+                    target.setViewerState( (java.lang.String) value);
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return null;
+            }
+        };
+        desc.setHandler(handler);
+        desc.setMultivalued(false);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _viewerState
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        { //-- local scope
+            org.exolab.castor.xml.validators.StringValidator typeValidator;
+            typeValidator = new org.exolab.castor.xml.validators.StringValidator();
+            fieldValidator.setValidator(typeValidator);
+            typeValidator.setWhiteSpace("preserve");
+        }
+        desc.setValidator(fieldValidator);
+        //-- initialize element descriptors
+        
+    }
+
+
+      //-----------/
+     //- Methods -/
+    //-----------/
+
+    /**
+     * Method getAccessMode.
+     * 
+     * @return the access mode specified for this class.
+     */
+    public org.exolab.castor.mapping.AccessMode getAccessMode(
+    ) {
+        return null;
+    }
+
+    /**
+     * Method getIdentity.
+     * 
+     * @return the identity field, null if this class has no
+     * identity.
+     */
+    public org.exolab.castor.mapping.FieldDescriptor getIdentity(
+    ) {
+        return super.getIdentity();
+    }
+
+    /**
+     * Method getJavaClass.
+     * 
+     * @return the Java class represented by this descriptor.
+     */
+    public java.lang.Class getJavaClass(
+    ) {
+        return jalview.schemabinding.version2.SecondaryStructure.class;
+    }
+
+    /**
+     * Method getNameSpacePrefix.
+     * 
+     * @return the namespace prefix to use when marshaling as XML.
+     */
+    public java.lang.String getNameSpacePrefix(
+    ) {
+        return _nsPrefix;
+    }
+
+    /**
+     * Method getNameSpaceURI.
+     * 
+     * @return the namespace URI used when marshaling and
+     * unmarshaling as XML.
+     */
+    public java.lang.String getNameSpaceURI(
+    ) {
+        return _nsURI;
+    }
+
+    /**
+     * Method getValidator.
+     * 
+     * @return a specific validator for the class described by this
+     * ClassDescriptor.
+     */
+    public org.exolab.castor.xml.TypeValidator getValidator(
+    ) {
+        return this;
+    }
+
+    /**
+     * Method getXMLName.
+     * 
+     * @return the XML Name for the Class being described.
+     */
+    public java.lang.String getXMLName(
+    ) {
+        return _xmlName;
+    }
+
+    /**
+     * Method isElementDefinition.
+     * 
+     * @return true if XML schema definition of this Class is that
+     * of a global
+     * element or element with anonymous type definition.
+     */
+    public boolean isElementDefinition(
+    ) {
+        return _elementDefinition;
+    }
+
+}
index 5d5d880..a7384f8 100644 (file)
  */
 package jalview.structure;
 
-import jalview.datamodel.*;
+import jalview.datamodel.SequenceI;
 
 public interface SecondaryStructureListener
 {
   // TODO - redefine to allow RNA mouseovers to be passed back correctly to
   // listeners
-  public void mouseOverSequence(SequenceI sequence, int index);
+  /**
+   * act on a mouseover event
+   * 
+   * @param sequence
+   * @param index
+   *          the aligned sequence position (base 0)
+   * @param position
+   *          the dataset sequence position (base 1)
+   */
+  public void mouseOverSequence(SequenceI sequence, int index, int position);
 }
index 0253a7e..ac14b52 100644 (file)
@@ -739,7 +739,7 @@ public class StructureSelectionManager
         else if (listener instanceof SecondaryStructureListener)
         {
           ((SecondaryStructureListener) listener).mouseOverSequence(seq,
-                  indexpos);
+                  indexpos, index);
         }
       }
     }
index 0df7851..07f9bd5 100644 (file)
@@ -16,19 +16,27 @@ import jalview.schemes.TaylorColourScheme;
 import java.awt.Color;
 import java.util.Vector;
 
+import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 public class PDBChainTest
 {
-  PDBChain c = new PDBChain("1GAQ", "A");
+  PDBChain c;
 
-  Atom a1 = new Atom(1f, 2f, 3f);
+  final Atom a1 = new Atom(1f, 2f, 3f);
 
-  Atom a2 = new Atom(5f, 6f, 4f);
+  final Atom a2 = new Atom(5f, 6f, 4f);
 
-  Atom a3 = new Atom(2f, 5f, 6f);
+  final Atom a3 = new Atom(2f, 5f, 6f);
 
-  Atom a4 = new Atom(2f, 1f, 7f);
+  final Atom a4 = new Atom(2f, 1f, 7f);
+
+  @BeforeMethod
+  public void setUp()
+  {
+    System.out.println("setup");
+    c = new PDBChain("1GAQ", "A");
+  }
 
   @Test
   public void testGetNewlineString()
diff --git a/test/jalview/analysis/AlignSeqTest.java b/test/jalview/analysis/AlignSeqTest.java
new file mode 100644 (file)
index 0000000..ed686a7
--- /dev/null
@@ -0,0 +1,23 @@
+package jalview.analysis;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+
+public class AlignSeqTest
+{
+  @Test
+  public void testExtractGaps()
+  {
+    assertNull(AlignSeq.extractGaps(null, null));
+    assertNull(AlignSeq.extractGaps(null, "ACG"));
+    assertNull(AlignSeq.extractGaps("-. ", null));
+
+    assertEquals(" AC-G.T", AlignSeq.extractGaps("", " AC-G.T"));
+    assertEquals("AC-G.T", AlignSeq.extractGaps(" ", " AC-G.T"));
+    assertEquals("ACG.T", AlignSeq.extractGaps(" -", " AC-G.T"));
+    assertEquals("ACGT", AlignSeq.extractGaps(" -.", " AC-G.T ."));
+    assertEquals(" ACG.T", AlignSeq.extractGaps("-", " AC-G.T"));
+  }
+}
index 8c3489b..6149048 100644 (file)
@@ -242,23 +242,23 @@ public class AnnotationSorterTest
    */
   private void testTiming_presorted(final int numSeqs, final int numAnns)
   {
-    al = buildAlignment(numSeqs);
-    anns = buildAnnotations(numAnns);
+    Alignment alignment = buildAlignment(numSeqs);
+    AlignmentAnnotation[] annotations = buildAnnotations(numAnns);
 
     /*
      * Set the annotations presorted by label
      */
     Random r = new Random();
-    final SequenceI[] sequences = al.getSequencesArray();
-    for (int i = 0; i < anns.length; i++)
+    final SequenceI[] sequences = alignment.getSequencesArray();
+    for (int i = 0; i < annotations.length; i++)
     {
       SequenceI randomSequenceRef = sequences[r.nextInt(sequences.length)];
-      anns[i].sequenceRef = randomSequenceRef;
-      anns[i].label = "label" + i;
+      annotations[i].sequenceRef = randomSequenceRef;
+      annotations[i].label = "label" + i;
     }
     long startTime = System.currentTimeMillis();
-    AnnotationSorter testee = new AnnotationSorter(al, false);
-    testee.sort(anns, SequenceAnnotationOrder.LABEL_AND_SEQUENCE);
+    AnnotationSorter testee = new AnnotationSorter(alignment, false);
+    testee.sort(annotations, SequenceAnnotationOrder.LABEL_AND_SEQUENCE);
     long endTime = System.currentTimeMillis();
     final long elapsed = endTime - startTime;
     System.out.println("Timing test for presorted " + numSeqs
@@ -286,23 +286,23 @@ public class AnnotationSorterTest
    */
   private void testTiming_unsorted(final int numSeqs, final int numAnns)
   {
-    al = buildAlignment(numSeqs);
-    anns = buildAnnotations(numAnns);
+    Alignment alignment = buildAlignment(numSeqs);
+    AlignmentAnnotation[] annotations = buildAnnotations(numAnns);
 
     /*
      * Set the annotations in random order with respect to the sequences
      */
     Random r = new Random();
-    final SequenceI[] sequences = al.getSequencesArray();
-    for (int i = 0; i < anns.length; i++)
+    final SequenceI[] sequences = alignment.getSequencesArray();
+    for (int i = 0; i < annotations.length; i++)
     {
       SequenceI randomSequenceRef = sequences[r.nextInt(sequences.length)];
-      anns[i].sequenceRef = randomSequenceRef;
-      anns[i].label = "label" + i;
+      annotations[i].sequenceRef = randomSequenceRef;
+      annotations[i].label = "label" + i;
     }
     long startTime = System.currentTimeMillis();
-    AnnotationSorter testee = new AnnotationSorter(al, false);
-    testee.sort(anns, SequenceAnnotationOrder.SEQUENCE_AND_LABEL);
+    AnnotationSorter testee = new AnnotationSorter(alignment, false);
+    testee.sort(annotations, SequenceAnnotationOrder.SEQUENCE_AND_LABEL);
     long endTime = System.currentTimeMillis();
     final long elapsed = endTime - startTime;
     System.out.println("Timing test for unsorted " + numSeqs
@@ -336,8 +336,8 @@ public class AnnotationSorterTest
    */
   private void testTiming_semiSorted(final int numSeqs, final int numAnns)
   {
-    al = buildAlignment(numSeqs);
-    anns = buildAnnotations(numAnns);
+    Alignment alignment = buildAlignment(numSeqs);
+    AlignmentAnnotation[] annotations = buildAnnotations(numAnns);
 
     String[] labels = new String[]
     { "label1", "label2", "label3", "label4", "label5", "label6" };
@@ -346,16 +346,16 @@ public class AnnotationSorterTest
      * Set the annotations in sequence order with randomly assigned labels.
      */
     Random r = new Random();
-    final SequenceI[] sequences = al.getSequencesArray();
-    for (int i = 0; i < anns.length; i++)
+    final SequenceI[] sequences = alignment.getSequencesArray();
+    for (int i = 0; i < annotations.length; i++)
     {
       SequenceI sequenceRef = sequences[i % sequences.length];
-      anns[i].sequenceRef = sequenceRef;
-      anns[i].label = labels[r.nextInt(labels.length)];
+      annotations[i].sequenceRef = sequenceRef;
+      annotations[i].label = labels[r.nextInt(labels.length)];
     }
     long startTime = System.currentTimeMillis();
-    AnnotationSorter testee = new AnnotationSorter(al, false);
-    testee.sort(anns, SequenceAnnotationOrder.LABEL_AND_SEQUENCE);
+    AnnotationSorter testee = new AnnotationSorter(alignment, false);
+    testee.sort(annotations, SequenceAnnotationOrder.LABEL_AND_SEQUENCE);
     long endTime = System.currentTimeMillis();
     long elapsed = endTime - startTime;
     System.out.println("Sort by label for semisorted " + numSeqs
@@ -364,7 +364,7 @@ public class AnnotationSorterTest
 
     // now resort by sequence
     startTime = System.currentTimeMillis();
-    testee.sort(anns, SequenceAnnotationOrder.SEQUENCE_AND_LABEL);
+    testee.sort(annotations, SequenceAnnotationOrder.SEQUENCE_AND_LABEL);
     endTime = System.currentTimeMillis();
     elapsed = endTime - startTime;
     System.out.println("Resort by sequence for semisorted " + numSeqs
@@ -373,7 +373,7 @@ public class AnnotationSorterTest
 
     // now resort by label
     startTime = System.currentTimeMillis();
-    testee.sort(anns, SequenceAnnotationOrder.LABEL_AND_SEQUENCE);
+    testee.sort(annotations, SequenceAnnotationOrder.LABEL_AND_SEQUENCE);
     endTime = System.currentTimeMillis();
     elapsed = endTime - startTime;
     System.out.println("Resort by label for semisorted " + numSeqs
diff --git a/test/jalview/analysis/RnaTest.java b/test/jalview/analysis/RnaTest.java
new file mode 100644 (file)
index 0000000..165192c
--- /dev/null
@@ -0,0 +1,58 @@
+package jalview.analysis;
+
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.fail;
+
+import jalview.analysis.SecStrConsensus.SimpleBP;
+
+import java.util.Vector;
+
+import org.testng.annotations.Test;
+public class RnaTest
+{
+  @Test
+  public void testGetSimpleBPs() throws WUSSParseException
+  {
+    String rna = "([{})]"; // JAL-1081 example
+    Vector<SimpleBP> bps = Rna.GetSimpleBPs(rna);
+    assertEquals(3, bps.size());
+
+    /*
+     * the base pairs are added in the order in which the matching base is found
+     */
+    assertEquals(2, bps.get(0).bp5); // {
+    assertEquals(3, bps.get(0).bp3); // }
+    assertEquals(0, bps.get(1).bp5); // (
+    assertEquals(4, bps.get(1).bp3); // )
+    assertEquals(1, bps.get(2).bp5); // [
+    assertEquals(5, bps.get(2).bp3); // ]
+  }
+
+  @Test
+  public void testGetSimpleBPs_unmatchedOpener()
+  {
+    String rna = "(([{})]";
+    try
+    {
+      Rna.GetSimpleBPs(rna);
+      fail("expected exception");
+    } catch (WUSSParseException e)
+    {
+      // expected
+    }
+  }
+
+  @Test
+  public void testGetSimpleBPs_unmatchedCloser()
+  {
+    String rna = "([{})]]";
+    try
+    {
+      Rna.GetSimpleBPs(rna);
+      fail("expected exception");
+    } catch (WUSSParseException e)
+    {
+      // expected
+    }
+  }
+}
index 64f42cd..6402019 100755 (executable)
@@ -1840,7 +1840,7 @@ and any path to a file to save to the file]]></string>
                                                                <string><![CDATA[664]]></string>
                                                        </property>
                                                        <property name="sourceName">
-                                                               <string><![CDATA[VARNAv3-91.jar]]></string>
+                                                               <string><![CDATA[VARNAv3-93.jar]]></string>
                                                        </property>
                                                        <property name="overrideUnixPermissions">
                                                                <boolean>false</boolean>
@@ -1858,7 +1858,7 @@ and any path to a file to save to the file]]></string>
                                                                <boolean>true</boolean>
                                                        </property>
                                                        <property name="destinationName">
-                                                               <string><![CDATA[VARNAv3-91.jar]]></string>
+                                                               <string><![CDATA[VARNAv3-93.jar]]></string>
                                                        </property>
                                                        <property name="fileSize">
                                                                <long>663408</long>